From 94e86ffc912f1fbc12e7845d8ca3a19425e82f9d Mon Sep 17 00:00:00 2001 From: mrholek Date: Thu, 24 Jul 2025 01:15:17 +0200 Subject: [PATCH 1/5] feat(Autocomplete): initial commit --- docs/assets/js/partials/snippets.js | 110 +++ docs/content/forms/autocomplete.md | 368 +++++++++ docs/data/sidebar.yml | 4 + docs/layouts/partials/stylesheet.html | 2 +- js/index.esm.js | 1 + js/index.umd.js | 2 + js/src/autocomplete.js | 962 ++++++++++++++++++++++ js/tests/unit/autocomplete.spec.js | 1058 +++++++++++++++++++++++++ scss/_autocomplete.import.scss | 1 + scss/_autocomplete.scss | 343 ++++++++ scss/_variables.scss | 108 +++ scss/coreui.scss | 1 + 12 files changed, 2959 insertions(+), 1 deletion(-) create mode 100644 docs/content/forms/autocomplete.md create mode 100644 js/src/autocomplete.js create mode 100644 js/tests/unit/autocomplete.spec.js create mode 100644 scss/_autocomplete.import.scss create mode 100644 scss/_autocomplete.scss diff --git a/docs/assets/js/partials/snippets.js b/docs/assets/js/partials/snippets.js index 249a13b2e..d7c132bdd 100644 --- a/docs/assets/js/partials/snippets.js +++ b/docs/assets/js/partials/snippets.js @@ -167,6 +167,116 @@ export default () => { }) } + // ------------------------------- + // Aurocomplete + // ------------------------------- + // 'Autocomplete components' example in docs only + // js-docs-start autocomplete-array-data + const myAutoComplete = document.getElementById('myAutoComplete') + + if (myAutoComplete) { + new coreui.Autocomplete(myAutoComplete, { + name: 'autocomplete', + options: [ + 'Angular', + 'Bootstrap', + { + label: 'React.js', + disabled: true + }, + 'Vue.js', + { + label: 'backend', + options: ['Django', 'Laravel', 'Node.js'] + } + ], + value: 'Laravel' + }) + } + // js-docs-end autocomplete-array-data + + // js-docs-start autocomplete-grouped-data + const myAutoCompleteGrouped = document.getElementById('myAutoCompleteGrouped') + + if (myAutoCompleteGrouped) { + new coreui.Autocomplete(myAutoCompleteGrouped, { + name: 'autocomplete-grouped', + options: [ + 'Angular', + { + label: 'Bootstrap', + selected: true + }, + { + label: 'React.js', + disabled: true + }, + 'Vue.js', + { + label: 'backend', + options: ['Django', 'Laravel', 'Node.js'] + } + ] + }) + } + // js-docs-end autocomplete-grouped-data + + // js-docs-start autocomplete-external-data + const myAutoCompleteExternalData = document.getElementById('myAutoCompleteExternalData') + + if (myAutoCompleteExternalData) { + const getUsers = async (name = '') => { + try { + const response = await fetch(`https://apitest.coreui.io/demos/users?first_name=${name}&limit=10`) + const users = await response.json() + + return users.records.map(user => ({ + value: user.id, + label: user.first_name + })) + } catch (error) { + // eslint-disable-next-line no-console + console.error('Error fetching users:', error) + } + } + + const autocomplete = new coreui.Autocomplete(myAutoCompleteExternalData, { + cleaner: true, + highlightOptionsOnSearch: true, + name: 'autocomplete-external', + options: [], + placeholder: 'Search names...', + search: ['external', 'global'], // 🔴 'external' is required for external search + showHints: true + }) + + let lastQuery = null + let debounceTimer = null + + myAutoCompleteExternalData.addEventListener('show.coreui.autocomplete', async () => { + const users = await getUsers() + autocomplete.update({ options: users }) + }) + + myAutoCompleteExternalData.addEventListener('input.coreui.autocomplete', event => { + const query = event.value + + if (query === lastQuery) { + return + } + + lastQuery = query + + clearTimeout(debounceTimer) + + debounceTimer = setTimeout(async () => { + const users = await getUsers(query) + autocomplete.update({ options: users }) + }, 200) + }) + } + // js-docs-end autocomplete-external-data + // ------------------------------- // Multi Selects // ------------------------------- diff --git a/docs/content/forms/autocomplete.md b/docs/content/forms/autocomplete.md new file mode 100644 index 000000000..ec746ee2b --- /dev/null +++ b/docs/content/forms/autocomplete.md @@ -0,0 +1,368 @@ +--- +layout: docs +title: Autocomplete +description: Create intelligent, responsive input fields using the Bootstrap Autocomplete plugin. This component enhances user input with dynamic dropdown suggestions, flexible data providers, and callback support. +group: forms +toc: true +bootstrap: true +pro_component: true +--- + +## Overview + +The **Bootstrap Autocomplete Dropdown** component is a powerful autocomplete dropdown plugin that enhances form control usability by suggesting completions as the user types. Whether you're integrating with local JavaScript arrays or fetching live server responses via AJAX, this plugin enables rich, dynamic user interactions. + +## Basic example + +A straightforward demonstration of how to implement a basic Bootstrap Autocomplete input field, highlighting essential attributes and configurations. + +{{< example stackblitz_pro="true" >}} +
+{{< /example >}} + +## Data source + +Learn how to populate the autocomplete component with data from various sources, including arrays and objects, for dynamic content integration. + +### Array data + +To dynamically populate an autocomplete input with suggestions from an array, use JavaScript to configure the component with predefined options. + +{{< example stackblitz_pro="true" stackblitz_add_js="true">}} +
+{{< /example >}} + +We use the following JavaScript to set up our autocomplete: + +{{< js-docs name="autocomplete-array-data" file="docs/assets/js/partials/snippets.js" >}} + +### Object data with groups + +You can organize suggestions into groups using optgroups for better categorization and user experience. + +{{< example stackblitz_pro="true" stackblitz_add_js="true">}} +
+{{< /example >}} + +{{< js-docs name="autocomplete-grouped-data" file="docs/assets/js/partials/snippets.js" >}} + +### External data + +You can configure CoreUI's AutoComplete component to fetch and display options dynamically from an external API. This is useful when you need to autocomplete data that changes frequently or is too large to preload. + +This example shows how to connect the AutoComplete to a remote API to search users by first name. + +{{< example stackblitz_pro="true" >}} +
+{{< /example >}} + +To fetch data from an external source, you must set the search option to `'external'` or `['external', 'global']`. +This disables internal filtering and allows you to provide custom data (e.g., from an API) based on user input. + +{{< js-docs name="autocomplete-external-data" file="docs/assets/js/partials/snippets.js" >}} + +## Search functionality + +Configure the search behavior within the component. The `data-coreui-search` option determines how the search input operates and provides different search modes. + +By default, search applies only while the input field is focused: + +{{< example stackblitz_pro="true" >}} +
+{{< /example >}} + +### Global search + +Enable global search functionality that works across the entire component, regardless of focus position: + +{{< example stackblitz_pro="true" >}} + +
+{{< /example >}} + +### External search + +Use external search mode to fetch data dynamically from a server or API. This disables internal filtering and delegates the search logic entirely to your application via JavaScript: + +```html +
+``` + +```js +const autocomplete = new coreui.AutoComplete(myAutoCompleteExternalDataExample, { + search: 'external', // Required for remote data sources + options: [], + placeholder: 'Search technologies...' +}) + +myAutoCompleteExternalDataExample.addEventListener('input.coreui.autocomplete', async event => { + const query = event.value + const response = await fetch(`https://example.com/api?q=${query}`) + const results = await response.json() + + autocomplete.update({ + options: results.map(item => ({ + value: item.id, + label: item.name + })) + }) +}) +``` + +{{< callout info >}} +When `search: 'external'` is used, the component no longer filters options internally — you must handle all data fetching and filtering logic manually. + +You can combine it with `'global'` (e.g. search: `['external', 'global']`) to allow search input even when focus is not in the text field. +{{< /callout >}} + +## Restricted selection + +Restrict users to only select from predefined options by setting `data-coreui-allow-only-defined-options="true"`: + +{{< example stackblitz_pro="true" >}} +
+{{< /example >}} + +## Hints and completion + +Enable intelligent hints and auto-completion features to improve user experience. + +### Show hints + +Display completion hints as users type: + +{{< example stackblitz_pro="true" >}} +
+{{< /example >}} + +### Highlight matching text + +Highlight matching portions of suggestions during search: + +{{< example stackblitz_pro="true" >}} +
+{{< /example >}} + +## Validation states + +Apply validation styling to indicate input validity. + +{{< example stackblitz_pro="true" >}} +
+{{< /example >}} + +{{< example stackblitz_pro="true" >}} +
+{{< /example >}} + +## Disabled state + +Add the `data-coreui-disabled="true"` attribute to disable the component: + +{{< example stackblitz_pro="true" >}} +
+{{< /example >}} + +## Sizing + +You may also choose from small and large auto completes to match our similarly sized text inputs. + +{{< example class="d-flex flex-column gap-3" stackblitz_pro="true" >}} +
+
+
+{{< /example >}} + +## Cleaner functionality + +Enable a cleaner button to quickly clear input element: + +{{< example stackblitz_pro="true" >}} +
+{{< /example >}} + +## Usage + +{{< bootstrap-compatibility >}} + +### Via data attributes + +Add `autocomplete` class to a container element with an input field: + +```html +
+``` + +### Via JavaScript + +Initialize the autocomplete component via JavaScript: + +```html +
+``` + +```js +const autoCompleteElementList = Array.prototype.slice.call(document.querySelectorAll('.autocomplete')) +const autoCompleteList = autoCompleteElementList.map(autoCompleteEl => { + return new coreui.Autocomplete(autoCompleteEl, { + options: [ + 'JavaScript', + 'TypeScript', + 'React', + 'Vue.js', + 'Angular' + ], + search: 'global' + }) +}) +``` + +### Options + +{{< markdown >}} +{{< partial "js-data-attributes.md" >}} +{{< /markdown >}} + +{{< bs-table >}} +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `allowOnlyDefinedOptions` | boolean | `false` | Restricts selection to only predefined options when set to `true`. | +| `ariaCleanerLabel` | string | `'Clear selection'` | Accessible label for the cleaner button, read by screen readers. | +| `ariaIndicatorLabel` | string | `'Toggle visibility of options menu'` | Accessible label for the indicator button, read by screen readers. | +| `cleaner` | boolean | `false` | Enables the selection cleaner button. | +| `clearSearchOnSelect` | boolean | `true` | Clears the search input when an option is selected. | +| `container` | string, element, boolean | `false` | Appends the dropdown to a specific element. Example: `container: 'body'`. | +| `disabled` | boolean | `false` | Disables the component when set to `true`. | +| `highlightOptionsOnSearch` | boolean | `true` | Highlights matching text in options during search. | +| `indicator` | boolean | `false` | Enables the selection indicator button. | +| `invalid` | boolean | `false` | Applies invalid styling to the component. | +| `name` | string, null | `null` | Sets the name attribute for the input element. | +| `options` | boolean, array | `false` | Array of options or option objects to populate the dropdown. | +| `optionsMaxHeight` | number, string | `'auto'` | Sets the maximum height of the options dropdown. | +| `placeholder` | string, null | `null` | Placeholder text displayed in the input field. | +| `required` | boolean | `false` | Makes the input field required for form validation. | +| `search` | array, string, null | `null` | Enables search functionality. Use `'global'` for global search across the component and `'external'` when options are provided from external sources. | +| `searchNoResultsLabel` | string | `false` | Text displayed when no search results are found. | +| `showHints` | boolean | `false` | Shows completion hints as users type. | +| `valid` | boolean | `false` | Applies valid styling to the component. | +| `value` | number, string, null | `null` | Sets the initial value of the component. | +{{< /bs-table >}} + +### Methods + +{{< bs-table >}} +| Method | Description | +| --- | --- | +| `show` | Shows the Bootstrap autocomplete dropdown options. | +| `hide` | Hides the Bootstrap autocomplete dropdown options. | +| `toggle` | Toggles the visibility of the dropdown options. | +| `search` | Performs a search with the provided text parameter. | +| `update` | Updates the component configuration and rebuilds the interface. | +| `deselectAll` | Deselects all currently selected options. | +| `dispose` | Destroys the component instance and removes stored data. | +| `getInstance` | Static method to get the Bootstrap autocomplete instance associated with a DOM element. | +{{< /bs-table >}} + +### Events + +The Autocomplete component exposes several events for integrating with application logic. + +{{< bs-table >}} +| Event | Description | +| --- | --- | +| `changed.coreui.autocomplete` | Fires when an option is selected or the input value changes. | +| `show.coreui.autocomplete` | Event fires immediately when the show method is called. | +| `shown.coreui.autocomplete` | Fired when the dropdown has been made visible and CSS transitions completed. | +| `hide.coreui.autocomplete` | Event fires immediately when the hide method is called. | +| `hidden.coreui.autocomplete` | Fired when the dropdown has been hidden and CSS transitions completed. | +| `input.coreui.autocomplete` | Fires when the search input value changes. | +{{< /bs-table >}} + +```js +const myAutocomplete = document.getElementById('myAutocomplete') +myAutocomplete.addEventListener('changed.coreui.autocomplete', event => { + // Get the selected value + const selectedValue = event.value + // Your callback function to handle change + // eslint-disable-next-line no-console + console.log('Selected:', selectedValue) +}) + +myAutocomplete.addEventListener('input.coreui.autocomplete', event => { + // Get the current input value + const inputValue = event.value + // Your callback function to handle input + // eslint-disable-next-line no-console + console.log('Input changed:', inputValue) +}) +``` + +## Accessibility + +The Autocomplete component includes several accessibility features: + +- **ARIA attributes**: Proper `role`, `aria-expanded`, `aria-haspopup`, and `aria-autocomplete` attributes +- **Screen reader support**: Descriptive labels and announcements for state changes +- **Keyboard navigation**: Full keyboard support with arrow keys, Enter, Escape, and Tab +- **Focus management**: Proper focus handling and visual focus indicators +- **Semantic markup**: Uses appropriate HTML elements and structure + +### Keyboard shortcuts + +{{< bs-table >}} +| Key | Action | +| --- | --- | +| `Arrow Down` | Navigate to the next option or open dropdown | +| `Arrow Up` | Navigate to the previous option | +| `Enter` | Select the highlighted option | +| `Escape` | Close the dropdown and clear focus | +| `Tab` | Accept hint completion (when hints are enabled) | +| `Backspace/Delete` | Clear input and trigger search | +{{< /bs-table >}} + +## Customizing + +### CSS variables + +Autocomplete components use local CSS variables on `.autocomplete` for enhanced real-time customization. Values for the CSS variables are set via Sass, so Sass customization is still supported. + +{{< scss-docs name="autocomplete-css-vars" file="scss/_autocomplete.scss" >}} + +### SASS variables + +{{< scss-docs name="autocomplete-variables" file="scss/_variables.scss" >}} diff --git a/docs/data/sidebar.yml b/docs/data/sidebar.yml index 12b8f0515..4428f4118 100644 --- a/docs/data/sidebar.yml +++ b/docs/data/sidebar.yml @@ -69,6 +69,10 @@ text: PRO - title: Input group - title: Floating labels + - title: Autocomplete + badge: + color: danger + text: PRO - title: Date Picker badge: color: danger diff --git a/docs/layouts/partials/stylesheet.html b/docs/layouts/partials/stylesheet.html index b0f3c0595..9f1c09bcd 100644 --- a/docs/layouts/partials/stylesheet.html +++ b/docs/layouts/partials/stylesheet.html @@ -21,7 +21,7 @@ {{- $docsCss := resources.Get "scss/docs.scss" | toCSS (merge (dict "targetPath" $targetDocsCssPath) $sassOptions) | postCSS $postcssOptions -}} {{- $searchCss := resources.Get "scss/search.scss" | toCSS (merge (dict "targetPath" $targetSearchCssPath) $sassOptions) | postCSS $postcssOptions -}} -{{- $stylePickers := resources.Get "scss/docs-pickers.scss" | toCSS | postCSS $postcssOptions }} +{{- $stylePickers := resources.Get "scss/docs-pickers.scss" | toCSS (merge (dict "targetPath" $targetSearchCssPath) $sassOptions) | postCSS $postcssOptions -}} diff --git a/js/index.esm.js b/js/index.esm.js index 1a70d150c..7f969f924 100644 --- a/js/index.esm.js +++ b/js/index.esm.js @@ -6,6 +6,7 @@ */ export { default as Alert } from './src/alert.js' +export { default as Autocomplete } from './src/autocomplete.js' export { default as Button } from './src/button.js' export { default as Calendar } from './src/calendar.js' export { default as Carousel } from './src/carousel.js' diff --git a/js/index.umd.js b/js/index.umd.js index 53f14e2ed..188d3149e 100644 --- a/js/index.umd.js +++ b/js/index.umd.js @@ -6,6 +6,7 @@ */ import Alert from './src/alert.js' +import Autocomplete from './src/autocomplete.js' import Button from './src/button.js' import Calendar from './src/calendar.js' import Carousel from './src/carousel.js' @@ -32,6 +33,7 @@ import Tooltip from './src/tooltip.js' export default { Alert, + Autocomplete, Button, Calendar, Carousel, diff --git a/js/src/autocomplete.js b/js/src/autocomplete.js new file mode 100644 index 000000000..5b46fa423 --- /dev/null +++ b/js/src/autocomplete.js @@ -0,0 +1,962 @@ +/** + * -------------------------------------------------------------------------- + * CoreUI PRO autocomplete.js + * License (https://coreui.io/pro/license/) + * -------------------------------------------------------------------------- + */ + +import * as Popper from '@popperjs/core' +import BaseComponent from './base-component.js' +import Data from './dom/data.js' +import EventHandler from './dom/event-handler.js' +import SelectorEngine from './dom/selector-engine.js' +import { + defineJQueryPlugin, + getNextActiveElement, + getElement, + getUID, + isVisible, + isRTL +} from './util/index.js' + +/** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + +const NAME = 'autocomplete' +const DATA_KEY = 'coreui.autocomplete' +const EVENT_KEY = `.${DATA_KEY}` +const DATA_API_KEY = '.data-api' + +const ARROW_UP_KEY = 'ArrowUp' +const ARROW_DOWN_KEY = 'ArrowDown' +const BACKSPACE_KEY = 'Backspace' +const DELETE_KEY = 'Delete' +const ENTER_KEY = 'Enter' +const ESCAPE_KEY = 'Escape' +const TAB_KEY = 'Tab' +const RIGHT_MOUSE_BUTTON = 2 // MouseEvent.button value for the secondary button, usually the right button + +const EVENT_BLUR = `blur${EVENT_KEY}` +const EVENT_CHANGED = `changed${EVENT_KEY}` +const EVENT_CLICK = `click${EVENT_KEY}` +const EVENT_HIDE = `hide${EVENT_KEY}` +const EVENT_HIDDEN = `hidden${EVENT_KEY}` +const EVENT_INPUT = `input${EVENT_KEY}` +const EVENT_KEYDOWN = `keydown${EVENT_KEY}` +const EVENT_KEYUP = `keyup${EVENT_KEY}` +const EVENT_SHOW = `show${EVENT_KEY}` +const EVENT_SHOWN = `shown${EVENT_KEY}` +const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}` +const EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY}${DATA_API_KEY}` +const EVENT_LOAD_DATA_API = `load${EVENT_KEY}${DATA_API_KEY}` + +const CLASS_NAME_AUTOCOMPLETE = 'autocomplete' +const CLASS_NAME_AUTOCOMPLETE_DROPDOWN = 'autocomplete-dropdown' +const CLASS_NAME_CLEANER = 'autocomplete-cleaner' +const CLASS_NAME_DISABLED = 'disabled' +const CLASS_NAME_INPUT_GROUP = 'autocomplete-input-group' +const CLASS_NAME_LABEL = 'label' +const CLASS_NAME_OPTGROUP = 'autocomplete-optgroup' +const CLASS_NAME_OPTGROUP_LABEL = 'autocomplete-optgroup-label' +const CLASS_NAME_OPTION = 'autocomplete-option' +const CLASS_NAME_OPTIONS = 'autocomplete-options' +const CLASS_NAME_OPTIONS_EMPTY = 'autocomplete-options-empty' +const CLASS_NAME_SELECTED = 'selected' +const CLASS_NAME_SHOW = 'show' + +const SELECTOR_DATA_TOGGLE = '[data-coreui-toggle="autocomplete"]:not(.disabled)' +const SELECTOR_DATA_TOGGLE_SHOWN = `${SELECTOR_DATA_TOGGLE}.${CLASS_NAME_SHOW}` +const SELECTOR_OPTGROUP = '.autocomplete-optgroup' +const SELECTOR_OPTION = '.autocomplete-option' +const SELECTOR_OPTIONS = '.autocomplete-options' +const SELECTOR_OPTIONS_EMPTY = '.autocomplete-options-empty' +const SELECTOR_VISIBLE_ITEMS = '.autocomplete-options .autocomplete-option:not(.disabled):not(:disabled)' + +const Default = { + allowOnlyDefinedOptions: false, + ariaCleanerLabel: 'Clear selection', + ariaIndicatorLabel: 'Toggle visibility of options menu', + cleaner: false, + clearSearchOnSelect: true, + container: false, + disabled: false, + highlightOptionsOnSearch: false, + id: null, + indicator: false, + invalid: false, + name: null, + options: false, + optionsMaxHeight: 'auto', + placeholder: null, + required: false, + search: null, + searchNoResultsLabel: false, + showHints: false, + valid: false, + value: null +} + +const DefaultType = { + allowOnlyDefinedOptions: 'boolean', + ariaCleanerLabel: 'string', + ariaIndicatorLabel: 'string', + cleaner: 'boolean', + clearSearchOnSelect: 'boolean', + container: '(string|element|boolean)', + disabled: 'boolean', + highlightOptionsOnSearch: 'boolean', + id: '(string|null)', + indicator: 'boolean', + invalid: 'boolean', + name: '(string|null)', + options: '(array|null)', + optionsMaxHeight: '(number|string)', + placeholder: '(string|null)', + required: 'boolean', + search: '(array|string|null)', + searchNoResultsLabel: ('boolean|string'), + showHints: 'boolean', + valid: 'boolean', + value: '(number|string|null)' +} + +/** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + +class Autocomplete extends BaseComponent { + constructor(element, config) { + super(element, config) + + this._uniqueId = this._config.id ?? getUID(`${this.constructor.NAME}`) + this._indicatorElement = null + this._inputElement = null + this._inputHintElement = null + this._togglerElement = null + this._optionsElement = null + + this._menu = null + this._selected = [] + this._options = this._getOptionsFromConfig() + this._popper = null + this._search = '' + + this._createAutocomplete() + this._addEventListeners() + + Data.set(this._element, DATA_KEY, this) + } + + // Getters + + static get Default() { + return Default + } + + static get DefaultType() { + return DefaultType + } + + static get NAME() { + return NAME + } + + // Public + + toggle() { + return this._isShown() ? this.hide() : this.show() + } + + show() { + if (this._config.disabled || this._isShown()) { + return + } + + if ( + !this._config.searchNoResultsLabel && + this._flattenOptions().filter(option => option.label.toLowerCase().includes(this._search.toLowerCase())).length === 0) { + return + } + + EventHandler.trigger(this._element, EVENT_SHOW) + this._element.classList.add(CLASS_NAME_SHOW) + this._element.setAttribute('aria-expanded', true) + + if (this._config.container) { + this._menu.style.minWidth = `${this._element.offsetWidth}px` + this._menu.classList.add(CLASS_NAME_SHOW) + } + + EventHandler.trigger(this._element, EVENT_SHOWN) + + this._createPopper() + } + + hide() { + EventHandler.trigger(this._element, EVENT_HIDE) + + if (this._popper) { + this._popper.destroy() + } + + this._element.classList.remove(CLASS_NAME_SHOW) + this._element.setAttribute('aria-expanded', 'false') + + if (this._config.container) { + this._menu.classList.remove(CLASS_NAME_SHOW) + } + + if (this._inputHintElement) { + this._inputHintElement.value = '' + } + + EventHandler.trigger(this._element, EVENT_HIDDEN) + } + + dispose() { + if (this._popper) { + this._popper.destroy() + } + + super.dispose() + } + + clear() { + this.deselectAll() + this.search('') + this._filterOptionsList() + this._inputElement.value = '' + } + + search(label) { + this._search = label.length > 0 ? label.toLowerCase() : '' + if (!this._isExternalSearch()) { + this._filterOptionsList() + } + + EventHandler.trigger(this._element, EVENT_INPUT, { + value: label + }) + } + + update(config) { + if (config.value) { + this.deselectAll() + } + + this._config = { ...this._config, ...this._configAfterMerge(config) } + this._options = this._getOptionsFromConfig() + this._optionsElement.innerHTML = '' + this._createOptions(this._optionsElement, this._options) + } + + deselectAll(options = this._selected) { + for (const option of options) { + if (option.disabled) { + continue + } + + if (Array.isArray(option.options)) { + this.deselectAll(option.options) + continue + } + + this._deselectOption(option.value) + this._updateSelectionCleaner() + } + } + + // Helpers + + _flattenOptions(options = this._options, flat = []) { + for (const opt of options) { + if (opt && Array.isArray(opt.options)) { + this._flattenOptions(opt.options, flat) + continue + } + + flat.push(opt) + } + + return flat + } + + _getClassNames() { + return this._element.classList.value.split(' ') + } + + _highlightOption(label) { + const regex = new RegExp(this._search, 'gi') + return label.replace(regex, string => `${string}`) + } + + _isExternalSearch() { + return Array.isArray(this._config.search) && this._config.search.includes('external') + } + + _isGlobalSearch() { + return Array.isArray(this._config.search) && this._config.search.includes('global') + } + + _isVisible(element) { + const style = window.getComputedStyle(element) + return (style.display !== 'none') + } + + _isShown() { + return this._element.classList.contains(CLASS_NAME_SHOW) + } + + // Private + + _addEventListeners() { + EventHandler.on(this._element, EVENT_CLICK, () => { + if (!this._config.disabled) { + this.show() + } + }) + + EventHandler.on(this._element, EVENT_KEYDOWN, event => { + if (event.key === ESCAPE_KEY) { + this.hide() + if (this._config.allowOnlyDefinedOptions && this._selected.length === 0) { + this.search('') + this._inputElement.value = '' + } + + return + } + + if (this._isGlobalSearch() && (event.key.length === 1 || event.key === BACKSPACE_KEY || event.key === DELETE_KEY)) { + this._inputElement.focus() + } + }) + + EventHandler.on(this._menu, EVENT_KEYDOWN, event => { + if (this._isGlobalSearch() && (event.key.length === 1 || event.key === BACKSPACE_KEY || event.key === DELETE_KEY)) { + this._inputElement.focus() + } + }) + + EventHandler.on(this._togglerElement, EVENT_KEYDOWN, event => { + if (!this._isShown() && (event.key === ENTER_KEY || event.key === ARROW_DOWN_KEY)) { + event.preventDefault() + this.show() + return + } + + if (this._isShown() && event.key === ARROW_DOWN_KEY) { + event.preventDefault() + this._selectMenuItem(event) + } + }) + + EventHandler.on(this._indicatorElement, EVENT_CLICK, event => { + event.preventDefault() + event.stopPropagation() + this.toggle() + }) + + EventHandler.on(this._inputElement, EVENT_BLUR, () => { + const options = this._flattenOptions().filter(option => option.label.toLowerCase().startsWith(this._inputElement.value.toLowerCase())) + if (this._config.allowOnlyDefinedOptions && this._selected.length === 0 && options.length === 0) { + this.clear() + } + }) + + EventHandler.on(this._inputElement, EVENT_KEYDOWN, event => { + if (!this._isShown() && event.key !== TAB_KEY) { + this.show() + } + + if (event.key === ARROW_DOWN_KEY && this._inputElement.value.length === this._inputElement.selectionStart) { + this._selectMenuItem(event) + return + } + + if (event.key === TAB_KEY && this._config.showHints && this._inputElement.value.length > 0) { + if (this._inputHintElement.value) { + event.preventDefault() + event.stopPropagation() + } + + const options = this._flattenOptions().filter(option => option.label.toLowerCase().startsWith(this._inputElement.value.toLowerCase())) + + if (options.length > 0) { + this._selectOption(options[0]) + } + } + + if (event.key === ENTER_KEY) { + event.preventDefault() + event.stopPropagation() + + if (this._inputElement.value.length === 0) { + return + } + + const options = this._flattenOptions().filter(option => option.label.toLowerCase() === this._inputElement.value.toLowerCase()) + + if (options.length > 0) { + this._selectOption(options[0]) + } + + if (options.length === 0 && !this._config.allowOnlyDefinedOptions) { + EventHandler.trigger(this._element, EVENT_CHANGED, { + value: this._inputElement.value + }) + + this.hide() + + if (this._config.clearSearchOnSelect) { + this.search('') + } + } + } + }) + + EventHandler.on(this._inputElement, EVENT_KEYUP, event => { + if (event.key.length === 1 || event.key === BACKSPACE_KEY || event.key === DELETE_KEY) { + const { value } = event.target + this.deselectAll() + this.search(value) + if (this._config.showHints) { + const options = value ? + this._flattenOptions().filter(option => option.label.toLowerCase().startsWith(value.toLowerCase())) : + [] + this._inputHintElement.value = options.length > 0 ? `${value}${options[0].label.slice(value.length)}` : '' + } + } + }) + + EventHandler.on(this._optionsElement, EVENT_CLICK, event => { + event.preventDefault() + event.stopPropagation() + this._onOptionsClick(event.target) + }) + + EventHandler.on(this._selectionCleanerElement, EVENT_CLICK, event => { + if (!this._config.disabled) { + event.preventDefault() + event.stopPropagation() + this.clear() + } + }) + + EventHandler.on(this._optionsElement, EVENT_KEYDOWN, event => { + if (event.key === ENTER_KEY) { + this._onOptionsClick(event.target) + } + + if ([ARROW_UP_KEY, ARROW_DOWN_KEY].includes(event.key)) { + event.preventDefault() + this._selectMenuItem(event) + } + }) + } + + _getOptionsFromConfig(options = this._config.options) { + if (!options || !Array.isArray(options)) { + return [] + } + + const _options = [] + for (const option of options) { + if (option.options && Array.isArray(option.options)) { + _options.push({ + label: option.label, + options: this._getOptionsFromConfig(option.options) + }) + continue + } + + const label = typeof option === 'string' ? option : option.label + const value = option.value ?? (typeof option === 'string' ? option : option.label) + const isSelected = option.selected || (this._config.value && this._config.value === value) + + _options.push({ + label, + value, + ...isSelected && { selected: true }, + ...option.disabled && { disabled: true } + }) + + if (isSelected) { + this._selected.push({ + label: option.label, + value: String(option.label) + }) + } + } + + return _options + } + + _createAutocomplete() { + this._element.classList.add(CLASS_NAME_AUTOCOMPLETE) + this._element.classList.toggle('is-invalid', this._config.invalid) + this._element.classList.toggle('is-valid', this._config.valid) + + if (this._config.disabled) { + this._element.classList.add(CLASS_NAME_DISABLED) + } + + for (const className of this._getClassNames()) { + this._element.classList.add(className) + } + + this._createSelection() + this._createButtons() + this._createOptionsContainer() + this._updateOptionsList() + } + + _createSelection() { + const togglerEl = document.createElement('div') + togglerEl.classList.add(CLASS_NAME_INPUT_GROUP) + this._togglerElement = togglerEl + + if (!this._config.search && !this._config.disabled) { + togglerEl.tabIndex = -1 + } + + if (!this._config.disabled && this._config.showHints) { + const inputHintEl = document.createElement('input') + inputHintEl.classList.add('form-control', 'autocomplete-selection', 'autocomplete-selection-hint') + inputHintEl.setAttribute('name', (this._config.name || `${this._uniqueId}-hint`).toString()) + inputHintEl.autocomplete = 'off' + inputHintEl.readOnly = true + inputHintEl.tabIndex = -1 + inputHintEl.setAttribute('aria-hidden', true) + + togglerEl.append(inputHintEl) + this._inputHintElement = inputHintEl + } + + const inputEl = document.createElement('input') + inputEl.classList.add('form-control', 'autocomplete-selection') + inputEl.id = this._uniqueId + inputEl.setAttribute('name', (this._config.name || this._uniqueId).toString()) + inputEl.autocomplete = 'off' + inputEl.placeholder = this._config.placeholder ?? '' + inputEl.role = 'combobox' + inputEl.setAttribute('aria-autocomplete', 'list') + inputEl.setAttribute('aria-expanded', 'false') + inputEl.setAttribute('aria-haspopup', 'listbox') + + if (this._config.disabled) { + inputEl.setAttribute('disabled', true) + inputEl.tabIndex = -1 + } + + if (this._config.required) { + inputEl.setAttribute('required', true) + } + + togglerEl.append(inputEl) + this._inputElement = inputEl + + this._element.append(togglerEl) + } + + _createButtons() { + if (!this._config.cleaner && !this._config.indicator) { + return + } + + const buttons = document.createElement('div') + buttons.classList.add('autocomplete-buttons') + + if (!this._config.disabled && this._config.cleaner) { + const cleaner = document.createElement('button') + cleaner.type = 'button' + cleaner.classList.add(CLASS_NAME_CLEANER) + cleaner.style.display = 'none' + cleaner.setAttribute('aria-label', this._config.ariaCleanerLabel) + + buttons.append(cleaner) + this._selectionCleanerElement = cleaner + } + + if (this._config.indicator) { + const indicator = document.createElement('button') + indicator.type = 'button' + indicator.classList.add('autocomplete-indicator') + indicator.setAttribute('aria-label', this._config.ariaIndicatorLabel) + + if (this._config.disabled) { + indicator.tabIndex = -1 + } + + buttons.append(indicator) + this._indicatorElement = indicator + this._indicatorElement = indicator + } + + this._togglerElement.append(buttons) + this._updateSelectionCleaner() + } + + _createPopper() { + if (typeof Popper === 'undefined') { + throw new TypeError('CoreUI\'s Auto Complete component require Popper (https://popper.js.org)') + } + + const popperConfig = { + modifiers: [{ + name: 'preventOverflow', + options: { + boundary: 'clippingParents' + } + }, + { + name: 'offset', + options: { + offset: [0, 2] + } + }], + placement: isRTL() ? 'bottom-end' : 'bottom-start' + } + + this._popper = Popper.createPopper(this._togglerElement, this._menu, popperConfig) + } + + _createOptionsContainer() { + const dropdownDiv = document.createElement('div') + dropdownDiv.classList.add(CLASS_NAME_AUTOCOMPLETE_DROPDOWN) + dropdownDiv.role = 'listbox' + dropdownDiv.setAttribute('aria-labelledby', this._uniqueId) + + const optionsDiv = document.createElement('div') + optionsDiv.classList.add(CLASS_NAME_OPTIONS) + + if (this._config.optionsMaxHeight !== 'auto') { + optionsDiv.style.maxHeight = `${this._config.optionsMaxHeight}px` + optionsDiv.style.overflow = 'auto' + } + + dropdownDiv.append(optionsDiv) + + const { container } = this._config + if (container) { + container.append(dropdownDiv) + } else { + this._element.append(dropdownDiv) + } + + this._createOptions(optionsDiv, this._options) + this._optionsElement = optionsDiv + this._menu = dropdownDiv + } + + _createOptions(parentElement, options) { + for (const option of options) { + if (Array.isArray(option.options)) { + const optgroup = document.createElement('div') + optgroup.classList.add(CLASS_NAME_OPTGROUP) + optgroup.setAttribute('role', 'group') + + const optgrouplabel = document.createElement('div') + optgrouplabel.textContent = option.label + optgrouplabel.classList.add(CLASS_NAME_OPTGROUP_LABEL) + optgroup.append(optgrouplabel) + + this._createOptions(optgroup, option.options) + parentElement.append(optgroup) + + return + } + + const optionDiv = document.createElement('div') + optionDiv.classList.add(CLASS_NAME_OPTION) + + if (option.disabled) { + optionDiv.classList.add(CLASS_NAME_DISABLED) + optionDiv.setAttribute('aria-disabled', 'true') + } + + optionDiv.dataset.value = option.value + optionDiv.tabIndex = 0 + if (this._isExternalSearch() && this._config.highlightOptionsOnSearch && this._search) { + optionDiv.innerHTML = this._highlightOption(option.label) + } else { + optionDiv.textContent = option.label + } + + parentElement.append(optionDiv) + } + } + + _onOptionsClick(element) { + if (!element.classList.contains(CLASS_NAME_OPTION) || element.classList.contains(CLASS_NAME_LABEL)) { + return + } + + const value = String(element.dataset.value) + const foundOption = this._findOptionByValue(value) + + if (foundOption) { + this._selectOption(foundOption) + } + } + + _findOptionByValue(value, options = this._options) { + for (const option of options) { + if (option.value === value) { + return option + } + + if (option.options && Array.isArray(option.options)) { + const found = this._findOptionByValue(value, option.options) + if (found) { + return found + } + } + } + + return null + } + + _selectOption(option) { + this.deselectAll() + + if (this._selected.filter(selectedOption => selectedOption.value === option.value).length === 0) { + this._selected.push(option) + } + + const foundOption = SelectorEngine.findOne(`[data-value="${option.value}"]`, this._optionsElement) + if (foundOption) { + foundOption.classList.add(CLASS_NAME_SELECTED) + foundOption.setAttribute('aria-selected', true) + } + + EventHandler.trigger(this._element, EVENT_CHANGED, { + value: option + }) + + this._inputElement.value = option.label + + if (this._config.showHints) { + this._inputHintElement.value = '' + } + + this.hide() + + if (this._config.clearSearchOnSelect) { + this.search('') + } + + this._inputElement.focus() + this._updateSelectionCleaner() + } + + _deselectOption(value) { + this._selected = this._selected.filter(option => option.value !== String(value)) + + const option = SelectorEngine.findOne(`[data-value="${value}"]`, this._optionsElement) + if (option) { + option.classList.remove(CLASS_NAME_SELECTED) + option.setAttribute('aria-selected', false) + } + + EventHandler.trigger(this._element, EVENT_CHANGED, { + value: this._selected + }) + } + + _updateSelectionCleaner() { + if (!this._config.cleaner || this._selectionCleanerElement === null) { + return + } + + if (this._selected.length > 0) { + this._selectionCleanerElement.style.removeProperty('display') + return + } + + this._selectionCleanerElement.style.display = 'none' + } + + _updateOptionsList(options = this._options) { + for (const option of options) { + if (Array.isArray(option.options)) { + this._updateOptionsList(option.options) + continue + } + + if (option.selected) { + this._selectOption(option) + } + } + } + + _filterOptionsList() { + const options = SelectorEngine.find(SELECTOR_OPTION, this._menu) + let visibleOptions = 0 + + for (const option of options) { + // eslint-disable-next-line unicorn/prefer-includes + if (option.textContent.toLowerCase().indexOf(this._search) === -1) { + option.style.display = 'none' + } else { + if (this._config.highlightOptionsOnSearch) { + option.innerHTML = this._highlightOption(option.textContent) + } + + option.style.removeProperty('display') + visibleOptions++ + } + + const optgroup = option.closest(SELECTOR_OPTGROUP) + if (optgroup) { + // eslint-disable-next-line unicorn/prefer-array-some + if (SelectorEngine.children(optgroup, SELECTOR_OPTION).filter(element => this._isVisible(element)).length > 0) { + optgroup.style.removeProperty('display') + } else { + optgroup.style.display = 'none' + } + } + } + + if (visibleOptions > 0) { + if (SelectorEngine.findOne(SELECTOR_OPTIONS_EMPTY, this._menu)) { + SelectorEngine.findOne(SELECTOR_OPTIONS_EMPTY, this._menu).remove() + } + + return + } + + if (visibleOptions === 0) { + if (this._config.searchNoResultsLabel) { + const placeholder = document.createElement('div') + placeholder.classList.add(CLASS_NAME_OPTIONS_EMPTY) + placeholder.innerHTML = this._config.searchNoResultsLabel + + if (!SelectorEngine.findOne(SELECTOR_OPTIONS_EMPTY, this._menu)) { + SelectorEngine.findOne(SELECTOR_OPTIONS, this._menu).append(placeholder) + } + + return + } + + this.hide() + } + } + + _selectMenuItem({ key, target }) { + const items = SelectorEngine.find(SELECTOR_VISIBLE_ITEMS, this._menu).filter(element => isVisible(element)) + + if (!items.length) { + return + } + + // if target isn't included in items (e.g. when expanding the dropdown) + // allow cycling to get the last item in case key equals ARROW_UP_KEY + getNextActiveElement(items, target, key === ARROW_DOWN_KEY, !items.includes(target)).focus() + } + + _configAfterMerge(config) { + if (config.container === true) { + config.container = document.body + } + + if (typeof config.container === 'object' || typeof config.container === 'string') { + config.container = getElement(config.container) + } + + if (typeof config.options === 'string') { + config.options = config.options.split(/,\s*/).map(String) + } + + if (typeof config.search === 'string') { + config.search = config.search.split(/,\s*/).map(String) + } + + return config + } + + // Static + + static autocompleteInterface(element, config) { + const data = Autocomplete.getOrCreateInstance(element, config) + + if (typeof config === 'string') { + if (typeof data[config] === 'undefined') { + throw new TypeError(`No method named "${config}"`) + } + + data[config]() + } + } + + static jQueryInterface(config) { + return this.each(function () { + Autocomplete.autocompleteInterface(this, config) + }) + } + + static clearMenus(event) { + if (event && (event.button === RIGHT_MOUSE_BUTTON || + (event.type === 'keyup' && event.key !== TAB_KEY))) { + return + } + + const autocompletes = SelectorEngine.find(SELECTOR_DATA_TOGGLE_SHOWN) + + for (let i = 0, len = autocompletes.length; i < len; i++) { + const context = Data.get(autocompletes[i], DATA_KEY) + const relatedTarget = { + relatedTarget: autocompletes[i] + } + + if (event && event.type === 'click') { + relatedTarget.clickEvent = event + } + + if (!context) { + continue + } + + if (!context._element.classList.contains(CLASS_NAME_SHOW)) { + continue + } + + if (context._element.contains(event.target)) { + continue + } + + context.hide() + context.search('') + if (context._config.allowOnlyDefinedOptions && context._selected.length === 0) { + context._inputElement.value = '' + } + + EventHandler.trigger(context._element, EVENT_HIDDEN) + } + } +} + +/** + * Data API implementation + */ + +EventHandler.on(window, EVENT_LOAD_DATA_API, () => { + for (const autocomplete of SelectorEngine.find(SELECTOR_DATA_TOGGLE)) { + Autocomplete.autocompleteInterface(autocomplete) + } +}) +EventHandler.on(document, EVENT_CLICK_DATA_API, Autocomplete.clearMenus) +EventHandler.on(document, EVENT_KEYUP_DATA_API, Autocomplete.clearMenus) + +/** + * jQuery + */ + +defineJQueryPlugin(Autocomplete) + +export default Autocomplete diff --git a/js/tests/unit/autocomplete.spec.js b/js/tests/unit/autocomplete.spec.js new file mode 100644 index 000000000..5e65ca1cd --- /dev/null +++ b/js/tests/unit/autocomplete.spec.js @@ -0,0 +1,1058 @@ +import Autocomplete from '../../src/autocomplete.js' +import { + clearFixture, createEvent, getFixture, jQueryMock +} from '../helpers/fixture.js' + +describe('Autocomplete', () => { + let fixtureEl + + beforeAll(() => { + fixtureEl = getFixture() + }) + + afterEach(() => { + clearFixture() + }) + + describe('VERSION', () => { + it('should return plugin version', () => { + expect(Autocomplete.VERSION).toEqual(jasmine.any(String)) + }) + }) + + describe('Default', () => { + it('should return plugin default config', () => { + expect(Autocomplete.Default).toEqual(jasmine.any(Object)) + }) + }) + + describe('DefaultType', () => { + it('should return plugin default type config', () => { + expect(Autocomplete.DefaultType).toEqual(jasmine.any(Object)) + }) + }) + + describe('DATA_KEY', () => { + it('should return plugin data key', () => { + expect(Autocomplete.DATA_KEY).toEqual('coreui.autocomplete') + }) + }) + + describe('constructor', () => { + it('should take care of element either passed as a CSS selector or DOM element', () => { + fixtureEl.innerHTML = [ + '
', + '
' + ].join('') + + const autocompleteEl = fixtureEl.querySelector('[data-coreui-toggle="autocomplete"]') + const autocompleteBySelector = new Autocomplete('[data-coreui-toggle="autocomplete"]', { options: [] }) + const autocompleteByElement = new Autocomplete(autocompleteEl, { options: [] }) + + expect(autocompleteBySelector._element).toEqual(autocompleteEl) + expect(autocompleteByElement._element).toEqual(autocompleteEl) + }) + + it('should create autocomplete with default options', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { options: [] }) + + expect(autocomplete._config.allowOnlyDefinedOptions).toBe(false) + expect(autocomplete._config.cleaner).toBe(false) + expect(autocomplete._config.disabled).toBe(false) + expect(autocomplete._config.options).toEqual([]) + expect(autocomplete._config.placeholder).toBe(null) + }) + + it('should create autocomplete with custom options', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const config = { + allowOnlyDefinedOptions: true, + cleaner: true, + disabled: false, + placeholder: 'Select an option', + options: [ + { label: 'Option 1', value: '1' }, + { label: 'Option 2', value: '2' } + ] + } + const autocomplete = new Autocomplete(autocompleteEl, config) + + expect(autocomplete._config.allowOnlyDefinedOptions).toBe(true) + expect(autocomplete._config.cleaner).toBe(true) + expect(autocomplete._config.disabled).toBe(false) + expect(autocomplete._config.placeholder).toBe('Select an option') + expect(autocomplete._config.options).toEqual(config.options) + }) + + it('should create autocomplete structure with input element', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { options: [] }) + + expect(autocompleteEl.classList.contains('autocomplete')).toBe(true) + expect(autocomplete._inputElement).toBeTruthy() + expect(autocomplete._inputElement.tagName).toBe('INPUT') + expect(autocomplete._inputElement.getAttribute('role')).toBe('combobox') + expect(autocomplete._inputElement.getAttribute('aria-autocomplete')).toBe('list') + expect(autocomplete._inputElement.getAttribute('aria-haspopup')).toBe('listbox') + }) + + it('should create autocomplete with cleaner button when cleaner option is true', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { cleaner: true, options: [] }) + + expect(autocomplete._selectionCleanerElement).toBeTruthy() + expect(autocomplete._selectionCleanerElement.classList.contains('autocomplete-cleaner')).toBe(true) + }) + + it('should create autocomplete with indicator button when indicator option is true', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { indicator: true, options: [] }) + + expect(autocomplete._indicatorElement).toBeTruthy() + expect(autocomplete._indicatorElement.classList.contains('autocomplete-indicator')).toBe(true) + }) + + it('should create autocomplete with options', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const options = [ + { label: 'Option 1', value: '1' }, + { label: 'Option 2', value: '2' } + ] + const autocomplete = new Autocomplete(autocompleteEl, { options }) + + expect(autocomplete._options).toEqual(options) + expect(autocomplete._optionsElement).toBeTruthy() + expect(autocomplete._optionsElement.classList.contains('autocomplete-options')).toBe(true) + }) + }) + + describe('toggle', () => { + it('should toggle autocomplete visibility', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + options: [{ label: 'Option 1', value: '1' }] + }) + + expect(autocomplete._isShown()).toBe(false) + autocomplete.toggle() + expect(autocomplete._isShown()).toBe(true) + autocomplete.toggle() + expect(autocomplete._isShown()).toBe(false) + }) + + it('should not toggle if disabled', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + disabled: true, + options: [{ label: 'Option 1', value: '1' }] + }) + + autocomplete.toggle() + expect(autocomplete._isShown()).toBe(false) + }) + }) + + describe('show', () => { + it('should show the autocomplete dropdown', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + options: [{ label: 'Option 1', value: '1' }] + }) + + autocompleteEl.addEventListener('shown.coreui.autocomplete', () => { + expect(autocomplete._isShown()).toBe(true) + expect(autocompleteEl.classList.contains('show')).toBe(true) + expect(autocompleteEl.getAttribute('aria-expanded')).toBe('true') + resolve() + }) + + autocomplete.show() + }) + }) + + it('should trigger show event', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + options: [{ label: 'Option 1', value: '1' }] + }) + + autocompleteEl.addEventListener('show.coreui.autocomplete', () => { + expect().nothing() + resolve() + }) + + autocomplete.show() + }) + }) + + it('should not show if disabled', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + disabled: true, + options: [{ label: 'Option 1', value: '1' }] + }) + + autocomplete.show() + expect(autocomplete._isShown()).toBe(false) + }) + + it('should not show if already shown', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + options: [{ label: 'Option 1', value: '1' }] + }) + + autocomplete.show() + const isShown = autocomplete._isShown() + autocomplete.show() + expect(autocomplete._isShown()).toBe(isShown) + }) + + it('should not show if no matching options and no searchNoResultsLabel', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + options: [{ label: 'Option 1', value: '1' }] + }) + + autocomplete._search = 'nonexistent' + autocomplete.show() + expect(autocomplete._isShown()).toBe(false) + }) + }) + + describe('hide', () => { + it('should hide the autocomplete dropdown', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + options: [{ label: 'Option 1', value: '1' }] + }) + + autocompleteEl.addEventListener('shown.coreui.autocomplete', () => { + autocomplete.hide() + }) + + autocompleteEl.addEventListener('hidden.coreui.autocomplete', () => { + expect(autocomplete._isShown()).toBe(false) + expect(autocompleteEl.classList.contains('show')).toBe(false) + expect(autocompleteEl.getAttribute('aria-expanded')).toBe('false') + resolve() + }) + + autocomplete.show() + }) + }) + + it('should trigger hide event', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + options: [{ label: 'Option 1', value: '1' }] + }) + + autocompleteEl.addEventListener('shown.coreui.autocomplete', () => { + autocomplete.hide() + }) + + autocompleteEl.addEventListener('hide.coreui.autocomplete', () => { + expect().nothing() + resolve() + }) + + autocomplete.show() + }) + }) + + it('should clear input hint element when hiding', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + showHints: true, + options: [{ label: 'Option 1', value: '1' }] + }) + + autocomplete.show() + autocomplete._inputHintElement.value = 'hint text' + autocomplete.hide() + expect(autocomplete._inputHintElement.value).toBe('') + }) + }) + + describe('clear', () => { + it('should clear all selections and input', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + options: [{ label: 'Option 1', value: '1' }], + value: '1' + }) + + autocomplete._inputElement.value = 'some text' + autocomplete._selected.push({ label: 'Option 1', value: '1' }) + + autocomplete.clear() + + expect(autocomplete._selected).toEqual([]) + expect(autocomplete._inputElement.value).toBe('') + expect(autocomplete._search).toBe('') + }) + }) + + describe('search', () => { + it('should set search term and trigger input event', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + options: [{ label: 'Option 1', value: '1' }] + }) + + autocompleteEl.addEventListener('input.coreui.autocomplete', event => { + expect(event.value).toBe('test') + resolve() + }) + + autocomplete.search('test') + expect(autocomplete._search).toBe('test') + }) + }) + + it('should convert search term to lowercase', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + options: [{ label: 'Option 1', value: '1' }] + }) + + autocomplete.search('TEST') + expect(autocomplete._search).toBe('test') + }) + + it('should set empty search for empty input', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + options: [{ label: 'Option 1', value: '1' }] + }) + + autocomplete.search('') + expect(autocomplete._search).toBe('') + }) + }) + + describe('update', () => { + it('should update configuration and options', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + options: [{ label: 'Option 1', value: '1' }] + }) + + const newOptions = [ + { label: 'New Option 1', value: 'new1' }, + { label: 'New Option 2', value: 'new2' } + ] + + autocomplete.update({ options: newOptions }) + + expect(autocomplete._options).toEqual(newOptions) + }) + + it('should deselect all when value is updated', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + options: [{ label: 'Option 1', value: '1' }], + value: '1' + }) + + autocomplete._selected.push({ label: 'Option 1', value: '1' }) + + autocomplete.update({ value: '2' }) + + expect(autocomplete._selected).toEqual([]) + }) + }) + + describe('deselectAll', () => { + it('should deselect all selected options', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + options: [ + { label: 'Option 1', value: '1' }, + { label: 'Option 2', value: '2' } + ] + }) + + autocomplete._selected = [ + { label: 'Option 1', value: '1' }, + { label: 'Option 2', value: '2' } + ] + + autocomplete.deselectAll() + + expect(autocomplete._selected).toEqual([]) + }) + + it('should skip disabled options when deselecting', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + options: [ + { label: 'Option 1', value: '1' }, + { label: 'Option 2', value: '2', disabled: true } + ] + }) + + autocomplete._selected = [ + { label: 'Option 1', value: '1' }, + { label: 'Option 2', value: '2', disabled: true } + ] + + autocomplete.deselectAll() + + expect(autocomplete._selected).toEqual([{ label: 'Option 2', value: '2', disabled: true }]) + }) + }) + + describe('_flattenOptions', () => { + it('should flatten nested options', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const options = [ + { label: 'Option 1', value: '1' }, + { + label: 'Group 1', + options: [ + { label: 'Option 2', value: '2' }, + { label: 'Option 3', value: '3' } + ] + } + ] + const autocomplete = new Autocomplete(autocompleteEl, { options }) + + const flattened = autocomplete._flattenOptions() + + expect(flattened).toEqual([ + { label: 'Option 1', value: '1' }, + { label: 'Option 2', value: '2' }, + { label: 'Option 3', value: '3' } + ]) + }) + }) + + describe('_highlightOption', () => { + it('should highlight matching text in options', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { options: [] }) + + autocomplete._search = 'opt' + const highlighted = autocomplete._highlightOption('Option 1') + + expect(highlighted).toBe('Option 1') + }) + + it('should highlight multiple matches', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { options: [] }) + + autocomplete._search = 'o' + const highlighted = autocomplete._highlightOption('Option One') + + expect(highlighted).toBe('Option One') + }) + }) + + describe('_isExternalSearch', () => { + it('should return true when search includes external', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + search: ['external'], + options: [] + }) + + expect(autocomplete._isExternalSearch()).toBe(true) + }) + + it('should return false when search does not include external', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + search: ['internal'], + options: [] + }) + + expect(autocomplete._isExternalSearch()).toBe(false) + }) + }) + + describe('_isGlobalSearch', () => { + it('should return true when search includes global', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + search: ['global'], + options: [] + }) + + expect(autocomplete._isGlobalSearch()).toBe(true) + }) + + it('should return false when search does not include global', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + search: ['local'], + options: [] + }) + + expect(autocomplete._isGlobalSearch()).toBe(false) + }) + }) + + describe('keyboard navigation', () => { + it('should open dropdown on ArrowDown key', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + options: [{ label: 'Option 1', value: '1' }] + }) + + autocompleteEl.addEventListener('shown.coreui.autocomplete', () => { + expect(autocomplete._isShown()).toBe(true) + resolve() + }) + + const keydownEvent = createEvent('keydown') + keydownEvent.key = 'ArrowDown' + autocomplete._togglerElement.dispatchEvent(keydownEvent) + }) + }) + + it('should open dropdown on Enter key', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + options: [{ label: 'Option 1', value: '1' }] + }) + + autocompleteEl.addEventListener('shown.coreui.autocomplete', () => { + expect(autocomplete._isShown()).toBe(true) + resolve() + }) + + const keydownEvent = createEvent('keydown') + keydownEvent.key = 'Enter' + autocomplete._togglerElement.dispatchEvent(keydownEvent) + }) + }) + + it('should close dropdown on Escape key', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + options: [{ label: 'Option 1', value: '1' }] + }) + + autocompleteEl.addEventListener('shown.coreui.autocomplete', () => { + const keydownEvent = createEvent('keydown') + keydownEvent.key = 'Escape' + autocompleteEl.dispatchEvent(keydownEvent) + }) + + autocompleteEl.addEventListener('hidden.coreui.autocomplete', () => { + expect(autocomplete._isShown()).toBe(false) + resolve() + }) + + autocomplete.show() + }) + }) + + it('should handle Tab key for hint completion', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + showHints: true, + options: [{ label: 'Option 1', value: '1' }] + }) + + autocomplete._inputElement.value = 'Opt' + autocomplete._inputHintElement.value = 'Option 1' + + const keydownEvent = createEvent('keydown') + keydownEvent.key = 'Tab' + + const spy = spyOn(keydownEvent, 'preventDefault') + const spyStop = spyOn(keydownEvent, 'stopPropagation') + + autocomplete._inputElement.dispatchEvent(keydownEvent) + + expect(spy).toHaveBeenCalled() + expect(spyStop).toHaveBeenCalled() + }) + }) + + describe('option selection', () => { + it('should select option on click', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + options: [{ label: 'Option 1', value: '1' }] + }) + + autocompleteEl.addEventListener('changed.coreui.autocomplete', event => { + expect(event.value.label).toBe('Option 1') + expect(event.value.value).toBe('1') + resolve() + }) + + // Manually test the selection instead of relying on DOM interaction + const option = { label: 'Option 1', value: '1' } + autocomplete._selectOption(option) + }) + }) + + it('should select option on Enter key', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + options: [{ label: 'Option 1', value: '1' }] + }) + + autocompleteEl.addEventListener('changed.coreui.autocomplete', event => { + expect(event.value.label).toBe('Option 1') + expect(event.value.value).toBe('1') + resolve() + }) + + // Manually test the selection instead of relying on DOM interaction + const option = { label: 'Option 1', value: '1' } + autocomplete._selectOption(option) + }) + }) + + it('should update input value when option is selected', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + options: [{ label: 'Option 1', value: '1' }] + }) + + const option = { label: 'Option 1', value: '1' } + autocomplete._selectOption(option) + + expect(autocomplete._inputElement.value).toBe('Option 1') + expect(autocomplete._selected).toContain(option) + }) + + it('should hide dropdown after selection', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + options: [{ label: 'Option 1', value: '1' }] + }) + + autocomplete.show() + const option = { label: 'Option 1', value: '1' } + autocomplete._selectOption(option) + + expect(autocomplete._isShown()).toBe(false) + }) + + it('should clear search after selection when clearSearchOnSelect is true', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + clearSearchOnSelect: true, + options: [{ label: 'Option 1', value: '1' }] + }) + + autocomplete._search = 'test' + const option = { label: 'Option 1', value: '1' } + autocomplete._selectOption(option) + + expect(autocomplete._search).toBe('') + }) + }) + + describe('filtering', () => { + it('should filter options based on search term', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + options: [ + { label: 'Apple', value: 'apple' }, + { label: 'Banana', value: 'banana' }, + { label: 'Cherry', value: 'cherry' } + ] + }) + + autocomplete.show() + autocomplete._search = 'app' + autocomplete._filterOptionsList() + + const visibleOptions = Array.from(autocomplete._optionsElement.querySelectorAll('.autocomplete-option')) + .filter(option => option.style.display !== 'none') + + expect(visibleOptions).toHaveSize(1) + expect(visibleOptions[0].textContent).toBe('Apple') + }) + + it('should show "no results" message when no options match', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + searchNoResultsLabel: 'No results found', + options: [ + { label: 'Apple', value: 'apple' }, + { label: 'Banana', value: 'banana' } + ] + }) + + autocomplete.show() + autocomplete._search = 'xyz' + autocomplete._filterOptionsList() + + const emptyMessage = autocomplete._menu.querySelector('.autocomplete-options-empty') + expect(emptyMessage).toBeTruthy() + expect(emptyMessage.innerHTML).toBe('No results found') + }) + + it('should hide dropdown when no options match and no searchNoResultsLabel', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + options: [ + { label: 'Apple', value: 'apple' }, + { label: 'Banana', value: 'banana' } + ] + }) + + autocomplete.show() + autocomplete._search = 'xyz' + autocomplete._filterOptionsList() + + expect(autocomplete._isShown()).toBe(false) + }) + }) + + describe('cleaner functionality', () => { + it('should clear selection when cleaner button is clicked', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + cleaner: true, + options: [{ label: 'Option 1', value: '1' }] + }) + + autocomplete._inputElement.value = 'test' + autocomplete._selected.push({ label: 'Option 1', value: '1' }) + + autocomplete._selectionCleanerElement.click() + + expect(autocomplete._inputElement.value).toBe('') + expect(autocomplete._selected).toEqual([]) + }) + + it('should show cleaner button when there are selections', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + cleaner: true, + options: [{ label: 'Option 1', value: '1' }] + }) + + autocomplete._selected.push({ label: 'Option 1', value: '1' }) + autocomplete._updateSelectionCleaner() + + expect(autocomplete._selectionCleanerElement.style.display).not.toBe('none') + }) + + it('should hide cleaner button when there are no selections', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + cleaner: true, + options: [{ label: 'Option 1', value: '1' }] + }) + + autocomplete._selected = [] + autocomplete._updateSelectionCleaner() + + expect(autocomplete._selectionCleanerElement.style.display).toBe('none') + }) + }) + + describe('dispose', () => { + it('should dispose autocomplete', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { options: [] }) + + expect(autocomplete._element).not.toBeNull() + + autocomplete.dispose() + + expect(autocomplete._element).toBeNull() + }) + + it('should destroy popper when disposing', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + options: [{ label: 'Option 1', value: '1' }] + }) + + autocomplete.show() + expect(autocomplete._popper).not.toBeNull() + + const spy = spyOn(autocomplete._popper, 'destroy') + autocomplete.dispose() + + expect(spy).toHaveBeenCalled() + }) + }) + + describe('static methods', () => { + describe('autocompleteInterface', () => { + it('should create instance and call method', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + + Autocomplete.autocompleteInterface(autocompleteEl, { + options: [{ label: 'Option 1', value: '1' }] + }) + + expect(Autocomplete.getInstance(autocompleteEl)).toBeInstanceOf(Autocomplete) + }) + + it('should call method on existing instance', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + options: [{ label: 'Option 1', value: '1' }] + }) + + const spy = spyOn(autocomplete, 'show') + + Autocomplete.autocompleteInterface(autocompleteEl, 'show') + + expect(spy).toHaveBeenCalled() + }) + + it('should throw error for undefined method', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + + // First create instance with proper configuration + const autocomplete = new Autocomplete(autocompleteEl, { options: [] }) + + expect(() => { + Autocomplete.autocompleteInterface(autocompleteEl, 'undefinedMethod') + }).toThrowError(TypeError, 'No method named "undefinedMethod"') + + // Clean up + autocomplete.dispose() + }) + }) + + describe('jQueryInterface', () => { + it('should create autocomplete', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + + jQueryMock.fn.autocomplete = Autocomplete.jQueryInterface + jQueryMock.elements = [autocompleteEl] + + jQueryMock.fn.autocomplete.call(jQueryMock, { options: [] }) + + expect(Autocomplete.getInstance(autocompleteEl)).not.toBeNull() + }) + + it('should not re-create autocomplete', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { options: [] }) + + jQueryMock.fn.autocomplete = Autocomplete.jQueryInterface + jQueryMock.elements = [autocompleteEl] + + jQueryMock.fn.autocomplete.call(jQueryMock, { options: [] }) + + expect(Autocomplete.getInstance(autocompleteEl)).toEqual(autocomplete) + }) + + it('should throw error on undefined method', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + + // First create instance with proper configuration + const autocomplete = new Autocomplete(autocompleteEl, { options: [] }) + + jQueryMock.fn.autocomplete = Autocomplete.jQueryInterface + jQueryMock.elements = [autocompleteEl] + + expect(() => { + jQueryMock.fn.autocomplete.call(jQueryMock, 'undefinedMethod') + }).toThrowError(TypeError, 'No method named "undefinedMethod"') + + // Clean up + autocomplete.dispose() + }) + }) + + describe('getInstance', () => { + it('should return autocomplete instance', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { options: [] }) + + expect(Autocomplete.getInstance(autocompleteEl)).toEqual(autocomplete) + expect(Autocomplete.getInstance(autocompleteEl)).toBeInstanceOf(Autocomplete) + }) + + it('should return null when there is no autocomplete instance', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + + expect(Autocomplete.getInstance(autocompleteEl)).toBeNull() + }) + }) + }) + + describe('data-api', () => { + it('should initialize autocomplete on data-api elements', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('[data-coreui-toggle="autocomplete"]') + + // Manually initialize since the data-api might not work in test environment + const _autocomplete = new Autocomplete(autocompleteEl, { options: [{ label: 'Test', value: '1' }] }) + + expect(Autocomplete.getInstance(autocompleteEl)).toBeInstanceOf(Autocomplete) + }) + + it('should close autocomplete when clicking outside', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + options: [{ label: 'Option 1', value: '1' }] + }) + + autocompleteEl.addEventListener('shown.coreui.autocomplete', () => { + document.body.click() + }) + + autocompleteEl.addEventListener('hidden.coreui.autocomplete', () => { + expect(autocomplete._isShown()).toBe(false) + resolve() + }) + + autocomplete.show() + }) + }) + }) + + describe('hint functionality', () => { + it('should show hint when typing and showHints is true', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + showHints: true, + options: [{ label: 'Option 1', value: '1' }] + }) + + autocomplete._inputElement.value = 'Opt' + + const keyupEvent = createEvent('keyup') + keyupEvent.key = 'p' + Object.defineProperty(keyupEvent, 'target', { + value: autocomplete._inputElement, + enumerable: true + }) + autocomplete._inputElement.dispatchEvent(keyupEvent) + + expect(autocomplete._inputHintElement.value).toBe('Option 1') + }) + + it('should clear hint when no matching options', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + showHints: true, + options: [{ label: 'Option 1', value: '1' }] + }) + + autocomplete._inputElement.value = 'xyz' + + const keyupEvent = createEvent('keyup') + keyupEvent.key = 'z' + Object.defineProperty(keyupEvent, 'target', { + value: autocomplete._inputElement, + enumerable: true + }) + autocomplete._inputElement.dispatchEvent(keyupEvent) + + expect(autocomplete._inputHintElement.value).toBe('') + }) + }) + + describe('allowOnlyDefinedOptions', () => { + it('should clear input on blur when allowOnlyDefinedOptions is true and no selection', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + allowOnlyDefinedOptions: true, + options: [{ label: 'Option 1', value: '1' }] + }) + + autocomplete._inputElement.value = 'invalid' + autocomplete._inputElement.dispatchEvent(createEvent('blur')) + + expect(autocomplete._inputElement.value).toBe('') + }) + + it('should not clear input on blur when there is a selection', () => { + fixtureEl.innerHTML = '
' + const autocompleteEl = fixtureEl.querySelector('.autocomplete') + const autocomplete = new Autocomplete(autocompleteEl, { + allowOnlyDefinedOptions: true, + options: [{ label: 'Option 1', value: '1' }] + }) + + autocomplete._selected.push({ label: 'Option 1', value: '1' }) + autocomplete._inputElement.value = 'Option 1' + autocomplete._inputElement.dispatchEvent(createEvent('blur')) + + expect(autocomplete._inputElement.value).toBe('Option 1') + }) + }) +}) diff --git a/scss/_autocomplete.import.scss b/scss/_autocomplete.import.scss new file mode 100644 index 000000000..cb59f3e85 --- /dev/null +++ b/scss/_autocomplete.import.scss @@ -0,0 +1 @@ +@forward "autocomplete"; diff --git a/scss/_autocomplete.scss b/scss/_autocomplete.scss new file mode 100644 index 000000000..a7b4c702f --- /dev/null +++ b/scss/_autocomplete.scss @@ -0,0 +1,343 @@ +@use "functions/escape-svg" as *; +@use "mixins/border-radius" as *; +@use "mixins/box-shadow" as *; +@use "mixins/elevation" as *; +@use "mixins/transition" as *; +@use "vendor/rfs" as *; +@use "variables" as *; + + +.autocomplete, +*:not(.autocomplete) > .autocomplete-dropdown { + // scss-docs-start autocomplete-css-vars + --#{$prefix}autocomplete-zindex: #{$autocomplete-zindex}; + --#{$prefix}autocomplete-font-family: #{$autocomplete-font-family}; + --#{$prefix}autocomplete-font-size: #{$autocomplete-font-size}; + --#{$prefix}autocomplete-font-weight: #{$autocomplete-font-weight}; + --#{$prefix}autocomplete-line-height: #{$autocomplete-line-height}; + --#{$prefix}autocomplete-color: #{$autocomplete-color}; + --#{$prefix}autocomplete-bg: #{$autocomplete-bg}; + --#{$prefix}autocomplete-box-shadow: #{$autocomplete-box-shadow}; + --#{$prefix}autocomplete-border-width: #{$autocomplete-border-width}; + --#{$prefix}autocomplete-border-color: #{$autocomplete-border-color}; + --#{$prefix}autocomplete-border-radius: #{$autocomplete-border-radius}; + --#{$prefix}autocomplete-disabled-color: #{$autocomplete-disabled-color}; + --#{$prefix}autocomplete-disabled-bg: #{$autocomplete-disabled-bg}; + --#{$prefix}autocomplete-disabled-border-color: #{$autocomplete-disabled-border-color}; + --#{$prefix}autocomplete-focus-color: #{$autocomplete-focus-color}; + --#{$prefix}autocomplete-focus-bg: #{$autocomplete-focus-bg}; + --#{$prefix}autocomplete-focus-border-color: #{$autocomplete-focus-border-color}; + --#{$prefix}autocomplete-focus-box-shadow: #{$autocomplete-focus-box-shadow}; + --#{$prefix}autocomplete-selection-padding-y: #{$autocomplete-selection-padding-y}; + --#{$prefix}autocomplete-selection-padding-x: #{$autocomplete-selection-padding-x}; + --#{$prefix}autocomplete-cleaner-width: #{$autocomplete-cleaner-width}; + --#{$prefix}autocomplete-cleaner-height: #{$autocomplete-cleaner-height}; + --#{$prefix}autocomplete-cleaner-padding-y: #{$autocomplete-cleaner-padding-y}; + --#{$prefix}autocomplete-cleaner-padding-x: #{$autocomplete-cleaner-padding-x}; + --#{$prefix}autocomplete-cleaner-icon: #{escape-svg($autocomplete-cleaner-icon)}; + --#{$prefix}autocomplete-cleaner-icon-color: #{$autocomplete-cleaner-icon-color}; + --#{$prefix}autocomplete-cleaner-icon-hover-color: #{$autocomplete-cleaner-icon-hover-color}; + --#{$prefix}autocomplete-cleaner-icon-size: #{$autocomplete-cleaner-icon-size}; + --#{$prefix}autocomplete-indicator-width: #{$autocomplete-indicator-width}; + --#{$prefix}autocomplete-indicator-height: #{$autocomplete-indicator-height}; + --#{$prefix}autocomplete-indicator-padding-y: #{$autocomplete-indicator-padding-y}; + --#{$prefix}autocomplete-indicator-padding-x: #{$autocomplete-indicator-padding-x}; + --#{$prefix}autocomplete-indicator-icon: #{escape-svg($autocomplete-indicator-icon)}; + --#{$prefix}autocomplete-indicator-icon-color: #{$autocomplete-indicator-icon-color}; + --#{$prefix}autocomplete-indicator-icon-hover-color: #{$autocomplete-indicator-icon-hover-color}; + --#{$prefix}autocomplete-indicator-icon-size: #{$autocomplete-indicator-icon-size}; + --#{$prefix}autocomplete-dropdown-min-width: #{$autocomplete-dropdown-min-width}; + --#{$prefix}autocomplete-dropdown-bg: #{$autocomplete-dropdown-bg}; + --#{$prefix}autocomplete-dropdown-border-width: #{$autocomplete-dropdown-border-width}; + --#{$prefix}autocomplete-dropdown-border-color: #{$autocomplete-dropdown-border-color}; + --#{$prefix}autocomplete-dropdown-border-radius: #{$autocomplete-dropdown-border-radius}; + --#{$prefix}autocomplete-dropdown-box-shadow: #{$autocomplete-dropdown-box-shadow}; + --#{$prefix}autocomplete-options-padding-y: #{$autocomplete-options-padding-y}; + --#{$prefix}autocomplete-options-padding-x: #{$autocomplete-options-padding-x}; + --#{$prefix}autocomplete-options-font-size: #{$autocomplete-options-font-size}; + --#{$prefix}autocomplete-options-font-weight: #{$autocomplete-options-font-weight}; + --#{$prefix}autocomplete-options-color: #{$autocomplete-options-color}; + --#{$prefix}autocomplete-optgroup-label-padding-y: #{$autocomplete-optgroup-label-padding-y}; + --#{$prefix}autocomplete-optgroup-label-padding-x: #{$autocomplete-optgroup-label-padding-x}; + --#{$prefix}autocomplete-optgroup-label-font-size: #{$autocomplete-optgroup-label-font-size}; + --#{$prefix}autocomplete-optgroup-label-font-weight: #{$autocomplete-optgroup-label-font-weight}; + --#{$prefix}autocomplete-optgroup-label-color: #{$autocomplete-optgroup-label-color}; + --#{$prefix}autocomplete-optgroup-label-text-transform: #{$autocomplete-optgroup-label-text-transform}; + --#{$prefix}autocomplete-option-padding-y: #{$autocomplete-option-padding-y}; + --#{$prefix}autocomplete-option-padding-x: #{$autocomplete-option-padding-x}; + --#{$prefix}autocomplete-option-margin-y: #{$autocomplete-option-margin-y}; + --#{$prefix}autocomplete-option-margin-x: #{$autocomplete-option-margin-x}; + --#{$prefix}autocomplete-option-border-width: #{$autocomplete-option-border-width}; + --#{$prefix}autocomplete-option-border-color: #{$autocomplete-option-border-color}; + --#{$prefix}autocomplete-option-border-radius: #{$autocomplete-option-border-radius}; + --#{$prefix}autocomplete-option-box-shadow: #{$autocomplete-option-box-shadow}; + --#{$prefix}autocomplete-option-hover-color: #{$autocomplete-option-hover-color}; + --#{$prefix}autocomplete-option-hover-bg: #{$autocomplete-option-hover-bg}; + --#{$prefix}autocomplete-option-focus-box-shadow: #{$autocomplete-option-focus-box-shadow}; + --#{$prefix}autocomplete-option-disabled-color: #{$autocomplete-option-disabled-color}; + --#{$prefix}autocomplete-option-indicator-width: #{$autocomplete-option-indicator-width}; + --#{$prefix}autocomplete-option-indicator-bg: #{$autocomplete-option-indicator-bg}; + --#{$prefix}autocomplete-option-indicator-border: #{$autocomplete-option-indicator-border}; + --#{$prefix}autocomplete-option-indicator-border-radius: #{$autocomplete-option-indicator-border-radius}; + --#{$prefix}autocomplete-option-selected-bg: #{$autocomplete-option-selected-bg}; + --#{$prefix}autocomplete-option-selected-indicator-bg: #{$autocomplete-option-selected-indicator-bg}; + --#{$prefix}autocomplete-option-selected-indicator-bg-image: #{escape-svg($autocomplete-option-selected-indicator-bg-image)}; + --#{$prefix}autocomplete-option-selected-indicator-border-color: #{$autocomplete-option-selected-indicator-border-color}; + // scss-docs-end autocomplete-css-vars + + position: relative; + + .was-validated .autocomplete:invalid + &, + &.is-invalid { + $focus-box-shadow: 0 0 $input-btn-focus-blur $input-focus-width rgba($autocomplete-invalid-border-color, $input-btn-focus-color-opacity); + + --#{$prefix}autocomplete-border-color: #{$autocomplete-invalid-border-color}; + --#{$prefix}autocomplete-focus-border-color: #{$autocomplete-invalid-border-color}; + --#{$prefix}autocomplete-focus-box-shadow: #{$focus-box-shadow} !important; // stylelint-disable-line declaration-no-important + + } + + .was-validated .autocomplete:valid + &, + &.is-valid { + $focus-box-shadow: 0 0 $input-btn-focus-blur $input-focus-width rgba($autocomplete-valid-border-color, $input-btn-focus-color-opacity); + + --#{$prefix}autocomplete-border-color: #{$autocomplete-valid-border-color}; + --#{$prefix}autocomplete-focus-border-color: #{$autocomplete-valid-border-color}; + --#{$prefix}autocomplete-focus-box-shadow: #{$focus-box-shadow} !important; // stylelint-disable-line declaration-no-important + } +} + +.autocomplete-input-group { + position: relative; + display: flex; + flex-wrap: wrap; + align-items: stretch; + width: 100%; + font-family: var(--#{$prefix}autocomplete-font-family); + @include font-size(var(--#{$prefix}autocomplete-font-size)); + font-weight: var(--#{$prefix}autocomplete-font-weight); + line-height: var(--#{$prefix}autocomplete-line-height); + color: var(--#{$prefix}autocomplete-color); + background-color: var(--#{$prefix}autocomplete-bg); + background-clip: padding-box; + border: var(--#{$prefix}autocomplete-border-width) solid var(--#{$prefix}autocomplete-border-color); + @include border-radius(var(--#{$prefix}autocomplete-border-radius)); + + .autocomplete & { + @include transition($input-transition); + } + + .autocomplete.disabled & { + color: var(--#{$prefix}autocomplete-disabled-color); + background-color: var(--#{$prefix}autocomplete-disabled-bg); + border-color: $input-disabled-border-color; + } + + .autocomplete.show &, + &:has(*:focus), + &:focus { + color: var(--#{$prefix}autocomplete-focus-color); + background-color: var(--#{$prefix}autocomplete-focus-bg); + border-color: var(--#{$prefix}autocomplete-focus-border-color); + outline: 0; + @if $enable-shadows { + box-shadow: var(--#{$prefix}autocomplete-box-shadow), var(--#{$prefix}autocomplete-focus-box-shadow); + } @else { + box-shadow: var(--#{$prefix}autocomplete-focus-box-shadow); + } + } +} + +.autocomplete-selection { + position: relative; + display: flex; + flex: 1 1 auto; + flex-wrap: wrap; + width: 1%; + min-width: 0; + padding: var(--#{$prefix}autocomplete-selection-padding-y) var(--#{$prefix}autocomplete-selection-padding-x); + background-color: transparent; + border: 0; + + &:focus { + background-color: transparent; + box-shadow: none; + } +} + +.autocomplete-selection-hint { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + pointer-events: none; + opacity: .5; +} + +.autocomplete-buttons { + display: flex; + align-items: center; + min-height: calc(2 * var(--#{$prefix}autocomplete-selection-padding-y) + calc(var(--#{$prefix}autocomplete-font-size) * var(--#{$prefix}autocomplete-line-height))); // stylelint-disable-line function-disallowed-list + padding: 0 var(--#{$prefix}autocomplete-selection-padding-y); +} + +.autocomplete-cleaner, +.autocomplete-indicator { + position: relative; + z-index: 2; + box-sizing: content-box; + background-color: transparent; + background-repeat: no-repeat; + background-position: center; + border: 0; + + &:focus { + z-index: 5; + outline: 0; + box-shadow: var(--#{$prefix}focus-ring-x, 0) var(--#{$prefix}focus-ring-y, 0) var(--#{$prefix}focus-ring-blur, 0) var(--#{$prefix}focus-ring-width) var(--#{$prefix}focus-ring-color); + @include border-radius($border-radius); + } + + &::before { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + content: ""; + } +} + +.autocomplete-cleaner { + width: var(--#{$prefix}autocomplete-cleaner-width); + height: var(--#{$prefix}autocomplete-cleaner-height); + padding: var(--#{$prefix}autocomplete-cleaner-padding-y) var(--#{$prefix}autocomplete-cleaner-padding-x); + + &::before { + background-color: var(--#{$prefix}autocomplete-cleaner-icon-color); + mask: var(--#{$prefix}autocomplete-cleaner-icon) center / var(--#{$prefix}autocomplete-cleaner-icon-size) no-repeat; + } + + &:focus::before, + &:hover::before { + background-color: var(--#{$prefix}autocomplete-cleaner-icon-hover-color); + } +} + +.autocomplete-indicator { + width: var(--#{$prefix}autocomplete-indicator-width); + height: var(--#{$prefix}autocomplete-indicator-height); + padding: var(--#{$prefix}autocomplete-indicator-padding-y) var(--#{$prefix}autocomplete-indicator-padding-x); + @include transition(transform .15s ease-in-out); + + &::before { + background-color: var(--#{$prefix}autocomplete-indicator-icon-color); + mask: var(--#{$prefix}autocomplete-indicator-icon) center / var(--#{$prefix}autocomplete-indicator-icon-size) no-repeat; + } + + &:focus::before, + &:hover::before { + background-color: var(--#{$prefix}autocomplete-indicator-icon-hover-color); + } + + .autocomplete.show & { + transform: rotate(180deg); + } +} + +.autocomplete-dropdown { + position: absolute; + z-index: var(--#{$prefix}autocomplete-zindex); + display: none; // none by default, but block on "open" of the menu + min-width: var(--#{$prefix}autocomplete-dropdown-min-width); + background-color: var(--#{$prefix}autocomplete-dropdown-bg); + background-clip: padding-box; + border: var(--#{$prefix}autocomplete-dropdown-border-width) solid var(--#{$prefix}autocomplete-dropdown-border-color); + @include border-radius(var(--#{$prefix}autocomplete-dropdown-border-radius)); + @include box-shadow(var(--#{$prefix}autocomplete-dropdown-box-shadow)); + @include elevation(4); + + .autocomplete.show &, + &.show { + display: block; + } +} + +.autocomplete-options { + padding: var(--#{$prefix}autocomplete-options-padding-y) var(--#{$prefix}autocomplete-options-padding-x); + font-size: var(--#{$prefix}autocomplete-options-font-size); + font-weight: var(--#{$prefix}autocomplete-options-font-weight); + color: var(--#{$prefix}autocomplete-options-color); +} + +.autocomplete-option { + position: relative; + z-index: 2; + padding: var(--#{$prefix}autocomplete-option-padding-y) var(--#{$prefix}autocomplete-option-padding-x); + margin: var(--#{$prefix}autocomplete-option-margin-y) var(--#{$prefix}autocomplete-option-margin-x); + cursor: pointer; + border: var(--#{$prefix}autocomplete-option-border-width) solid var(--#{$prefix}autocomplete-option-border-color); + @include border-radius(var(--#{$prefix}autocomplete-option-border-radius), 0); + + &:hover, + &:focus { + color: var(--#{$prefix}autocomplete-option-hover-color); + text-decoration: none; + background-color: var(--#{$prefix}autocomplete-option-hover-bg); + } + + &:focus { + z-index: 5; + border-color: var(--#{$prefix}input-focus-border-color, $input-focus-border-color); + outline: 0; + @if $enable-shadows { + box-shadow: var(--#{$prefix}autocomplete-box-shadow), var(--#{$prefix}autocomplete-focus-box-shadow); + } @else { + box-shadow: var(--#{$prefix}autocomplete-focus-box-shadow); + } + } + + &.disabled { + color: var(--#{$prefix}autocomplete-option-disabled-color); + pointer-events: none; + background-color: transparent; + } + + &.selected { + background-color: var(--#{$prefix}autocomplete-option-selected-bg); + + &::before { + background-color: var(--#{$prefix}autocomplete-option-selected-indicator-bg); + background-image: var(--#{$prefix}autocomplete-option-selected-indicator-bg-image); + border-color: var(--#{$prefix}autocomplete-option-selected-indicator-border-color); + } + } +} + +.autocomplete-optgroup-label { + padding: var(--#{$prefix}autocomplete-options-padding-y) var(--#{$prefix}autocomplete-options-padding-x); + font-size: var(--#{$prefix}autocomplete-optgroup-label-font-size); + font-weight: var(--#{$prefix}autocomplete-optgroup-label-font-weight); + color: var(--#{$prefix}autocomplete-optgroup-label-color); + text-transform: var(--#{$prefix}autocomplete-optgroup-label-text-transform); +} + +.autocomplete-options-empty { + padding: var(--#{$prefix}autocomplete-option-padding-y) var(--#{$prefix}autocomplete-option-padding-x); +} + + +.autocomplete-sm { + --#{$prefix}autocomplete-selection-padding-y: #{$autocomplete-selection-padding-y-sm}; + --#{$prefix}autocomplete-selection-padding-x: #{$autocomplete-selection-padding-x-sm}; + --#{$prefix}autocomplete-font-size: #{$autocomplete-font-size-sm}; + --#{$prefix}autocomplete-border-radius: #{$autocomplete-border-radius-sm}; +} + +.autocomplete-lg { + --#{$prefix}autocomplete-selection-padding-y: #{$autocomplete-selection-padding-y-lg}; + --#{$prefix}autocomplete-selection-padding-x: #{$autocomplete-selection-padding-x-lg}; + --#{$prefix}autocomplete-font-size: #{$autocomplete-font-size-lg}; + --#{$prefix}autocomplete-border-radius: #{$autocomplete-border-radius-lg}; +} diff --git a/scss/_variables.scss b/scss/_variables.scss index 575ece4cd..72cc22eac 100644 --- a/scss/_variables.scss +++ b/scss/_variables.scss @@ -2187,6 +2187,114 @@ $nested-kbd-font-weight: null !default; // Deprecated in v4.2.6, remo $pre-color: null !default; + +// Auto Complete + +// scss-docs-start autocomplete-variables +$autocomplete-zindex: 1000 !default; +$autocomplete-font-family: $input-font-family !default; +$autocomplete-font-size: $input-font-size !default; +$autocomplete-font-weight: $input-font-weight !default; +$autocomplete-line-height: $input-line-height !default; +$autocomplete-color: $input-color !default; +$autocomplete-bg: $input-bg !default; +$autocomplete-box-shadow: $box-shadow-inset !default; + +$autocomplete-border-width: $input-border-width !default; +$autocomplete-border-color: $input-border-color !default; +$autocomplete-border-radius: $input-border-radius !default; +$autocomplete-border-radius-sm: $input-border-radius-sm !default; +$autocomplete-border-radius-lg: $input-border-radius-lg !default; + +$autocomplete-disabled-color: $input-disabled-color !default; +$autocomplete-disabled-bg: $input-disabled-bg !default; +$autocomplete-disabled-border-color: $input-disabled-border-color !default; + +$autocomplete-focus-color: $input-focus-color !default; +$autocomplete-focus-bg: $input-focus-bg !default; +$autocomplete-focus-border-color: $input-focus-border-color !default; +$autocomplete-focus-box-shadow: $input-btn-focus-box-shadow !default; + +$autocomplete-invalid-border-color: $form-invalid-border-color !default; +$autocomplete-valid-border-color: $form-valid-border-color !default; + +$autocomplete-selection-padding-y: $input-padding-y !default; +$autocomplete-selection-padding-x: $input-padding-x !default; + +$autocomplete-cleaner-width: 1.5rem !default; +$autocomplete-cleaner-height: 1.5rem !default; +$autocomplete-cleaner-padding-x: 0 !default; +$autocomplete-cleaner-padding-y: 0 !default; +$autocomplete-cleaner-icon: url("data:image/svg+xml,") !default; +$autocomplete-cleaner-icon-color: var(--#{$prefix}tertiary-color) !default; +$autocomplete-cleaner-icon-hover-color: var(--#{$prefix}body-color) !default; +$autocomplete-cleaner-icon-size: .625rem !default; + +$autocomplete-indicator-width: 1.5rem !default; +$autocomplete-indicator-height: 1.5rem !default; +$autocomplete-indicator-padding-x: 0 !default; +$autocomplete-indicator-padding-y: 0 !default; +$autocomplete-indicator-icon: url("data:image/svg+xml,") !default; +$autocomplete-indicator-icon-color: var(--#{$prefix}tertiary-color) !default; +$autocomplete-indicator-icon-hover-color: var(--#{$prefix}body-color) !default; +$autocomplete-indicator-icon-size: .75rem !default; + +$autocomplete-dropdown-min-width: 100% !default; +$autocomplete-dropdown-bg: var(--#{$prefix}body-bg) !default; +$autocomplete-dropdown-border-color: var(--#{$prefix}border-color) !default; +$autocomplete-dropdown-border-width: var(--#{$prefix}border-width) !default; +$autocomplete-dropdown-border-radius: var(--#{$prefix}border-radius) !default; +$autocomplete-dropdown-box-shadow: var(--#{$prefix}box-shadow) !default; + +$autocomplete-options-padding-y: .5rem !default; +$autocomplete-options-padding-x: .5rem !default; +$autocomplete-options-font-size: $font-size-base !default; +$autocomplete-options-font-weight: $font-weight-normal !default; +$autocomplete-options-color: var(--#{$prefix}body-color) !default; + +$autocomplete-optgroup-label-padding-y: .5rem !default; +$autocomplete-optgroup-label-padding-x: .625rem !default; +$autocomplete-optgroup-label-font-size: 80% !default; +$autocomplete-optgroup-label-font-weight: $font-weight-bold !default; +$autocomplete-optgroup-label-color: var(--#{$prefix}tertiary-color) !default; +$autocomplete-optgroup-label-text-transform: uppercase !default; + +$autocomplete-option-padding-y: .5rem !default; +$autocomplete-option-padding-x: .75rem !default; +$autocomplete-option-margin-y: 1px !default; +$autocomplete-option-margin-x: 0 !default; +$autocomplete-option-border-width: $input-border-width !default; +$autocomplete-option-border-color: transparent !default; +$autocomplete-option-border-radius: var(--#{$prefix}border-radius) !default; +$autocomplete-option-box-shadow: $box-shadow-inset !default; + +$autocomplete-option-hover-color: var(--#{$prefix}body-color) !default; +$autocomplete-option-hover-bg: var(--#{$prefix}tertiary-bg) !default; + +$autocomplete-option-focus-box-shadow: $input-btn-focus-box-shadow !default; + +$autocomplete-option-indicator-width: 1em !default; +$autocomplete-option-indicator-bg: $form-check-input-bg !default; +$autocomplete-option-indicator-border: $form-check-input-border !default; +$autocomplete-option-indicator-border-radius: .25em !default; + +$autocomplete-option-selected-bg: var(--#{$prefix}secondary-bg) !default; +$autocomplete-option-selected-indicator-bg: $form-check-input-checked-bg-color !default; +$autocomplete-option-selected-indicator-bg-image: $form-check-input-checked-bg-image !default; +$autocomplete-option-selected-indicator-border-color: $autocomplete-option-selected-indicator-bg !default; + +$autocomplete-option-disabled-color: var(--#{$prefix}secondary-color) !default; + +$autocomplete-font-size-lg: $input-font-size-lg !default; +$autocomplete-selection-padding-y-lg: $input-padding-y-lg !default; +$autocomplete-selection-padding-x-lg: $input-padding-x-lg !default; + +$autocomplete-font-size-sm: $input-font-size-sm !default; +$autocomplete-selection-padding-y-sm: $input-padding-y-sm !default; +$autocomplete-selection-padding-x-sm: $input-padding-x-sm !default; +// scss-docs-end autocomplete-variables + + // Calendar & Date & Time Pickers // Calendar diff --git a/scss/coreui.scss b/scss/coreui.scss index 96e718cf8..fae52ead1 100644 --- a/scss/coreui.scss +++ b/scss/coreui.scss @@ -40,6 +40,7 @@ @forward "offcanvas"; @forward "placeholders"; +@forward "autocomplete"; @forward "avatar"; @forward "calendar"; @forward "callout"; From cffb26c599c78ff5399bb303088e92d3f360e998 Mon Sep 17 00:00:00 2001 From: mrholek Date: Sat, 26 Jul 2025 16:38:52 +0200 Subject: [PATCH 2/5] feat(Autocomplete): add custom templates support --- docs/assets/js/partials/snippets.js | 108 ++++++++++++++++++++++++++++ docs/content/forms/autocomplete.md | 28 +++++++- js/src/autocomplete.js | 53 ++++++++++++-- 3 files changed, 184 insertions(+), 5 deletions(-) diff --git a/docs/assets/js/partials/snippets.js b/docs/assets/js/partials/snippets.js index d7c132bdd..5feb3d112 100644 --- a/docs/assets/js/partials/snippets.js +++ b/docs/assets/js/partials/snippets.js @@ -277,6 +277,114 @@ export default () => { } // js-docs-end autocomplete-external-data + // js-docs-start autocomplete-custom-options + const myAutocompleteCountries = document.getElementById('myAutocompleteCountries') + const myAutocompleteCountriesAndCities = document.getElementById('myAutocompleteCountriesAndCities') + + if (myAutocompleteCountries && myAutocompleteCountriesAndCities) { + const countries = [ + { + value: 'pl', + label: 'Poland', + flag: '🇵🇱' + }, + { + value: 'de', + label: 'Germany', + flag: '🇩🇪' + }, + { + value: 'us', + label: 'United States', + flag: '🇺🇸' + }, + { + value: 'es', + label: 'Spain', + flag: '🇪🇸' + }, + { + value: 'gb', + label: 'United Kingdom', + flag: '🇬🇧' + } + ] + + const cities = [ + { + label: 'United States', + code: 'us', + flag: '🇺🇸', + options: [ + { + value: 'au', + label: 'Austin' + }, + { + value: 'ch', + label: 'Chicago' + }, + { + value: 'la', + label: 'Los Angeles' + }, + { + value: 'ny', + label: 'New York' + }, + { + value: 'sa', + label: 'San Jose' + } + ] + }, + { + label: 'United Kingdom', + code: 'gb', + flag: '🇬🇧', + options: [ + { + value: 'li', + label: 'Liverpool' + }, + { + value: 'lo', + label: 'London' + }, + { + value: 'ma', + label: 'Manchester' + } + ] + } + ] + + new coreui.Autocomplete(myAutocompleteCountries, { + cleaner: true, + indicator: true, + options: countries, + optionsTemplate(option) { + return `
${option.flag}${option.label}
` + }, + placeholder: 'Select country', + showHints: true, + search: 'global' + }) + + new coreui.Autocomplete(myAutocompleteCountriesAndCities, { + cleaner: true, + indicator: true, + options: cities, + optionsGroupsTemplate(optionGroup) { + return `
${optionGroup.flag}${optionGroup.label}
` + }, + placeholder: 'Select city', + showHints: true, + search: 'global' + }) + } + // js-docs-end autocomplete-custom-options + // ------------------------------- // Multi Selects // ------------------------------- diff --git a/docs/content/forms/autocomplete.md b/docs/content/forms/autocomplete.md index ec746ee2b..519cc7c9c 100644 --- a/docs/content/forms/autocomplete.md +++ b/docs/content/forms/autocomplete.md @@ -216,6 +216,26 @@ Enable a cleaner button to quickly clear input element:
{{< /example >}} +## Custom templates + +The CoreUI Bootstrap Autocomplete Component provides the flexibility to personalize options and group labels by utilizing custom templates. You can easily customize the options using the `optionsTemplate`, and for groups, you can use `optionsGroupsTemplate`, as demonstrated in the examples below: + +{{< example stackblitz_pro="true" stackblitz_add_js="true">}} +
+
+
+
+
+
+
+
+{{< /example >}} + +We use the following JavaScript to set up our autocomplete: + +{{< js-docs name="autocomplete-custom-options" file="docs/assets/js/partials/snippets.js" >}} + + ## Usage {{< bootstrap-compatibility >}} @@ -261,6 +281,7 @@ const autoCompleteList = autoCompleteElementList.map(autoCompleteEl => { {{< bs-table >}} | Name | Type | Default | Description | | --- | --- | --- | --- | +| `allowList` | object | `DefaultAllowlist` | Object containing allowed tags and attributes for HTML sanitization when using custom templates. | | `allowOnlyDefinedOptions` | boolean | `false` | Restricts selection to only predefined options when set to `true`. | | `ariaCleanerLabel` | string | `'Clear selection'` | Accessible label for the cleaner button, read by screen readers. | | `ariaIndicatorLabel` | string | `'Toggle visibility of options menu'` | Accessible label for the indicator button, read by screen readers. | @@ -268,14 +289,19 @@ const autoCompleteList = autoCompleteElementList.map(autoCompleteEl => { | `clearSearchOnSelect` | boolean | `true` | Clears the search input when an option is selected. | | `container` | string, element, boolean | `false` | Appends the dropdown to a specific element. Example: `container: 'body'`. | | `disabled` | boolean | `false` | Disables the component when set to `true`. | -| `highlightOptionsOnSearch` | boolean | `true` | Highlights matching text in options during search. | +| `highlightOptionsOnSearch` | boolean | `false` | Highlights matching text in options during search. | +| `id` | string, null | `null` | Sets a custom ID for the component. If not provided, a unique ID is auto-generated. | | `indicator` | boolean | `false` | Enables the selection indicator button. | | `invalid` | boolean | `false` | Applies invalid styling to the component. | | `name` | string, null | `null` | Sets the name attribute for the input element. | | `options` | boolean, array | `false` | Array of options or option objects to populate the dropdown. | +| `optionsGroupsTemplate` | function, null | `null` | Custom template function for rendering option group labels. Receives the group object as parameter. | | `optionsMaxHeight` | number, string | `'auto'` | Sets the maximum height of the options dropdown. | +| `optionsTemplate` | function, null | `null` | Custom template function for rendering individual options. Receives the option object as parameter. | | `placeholder` | string, null | `null` | Placeholder text displayed in the input field. | | `required` | boolean | `false` | Makes the input field required for form validation. | +| `sanitize` | boolean | `true` | Enables HTML sanitization for custom templates to prevent XSS attacks. | +| `sanitizeFn` | function, null | `null` | Custom sanitization function. If provided, it will be used instead of the built-in sanitizer. | | `search` | array, string, null | `null` | Enables search functionality. Use `'global'` for global search across the component and `'external'` when options are provided from external sources. | | `searchNoResultsLabel` | string | `false` | Text displayed when no search results are found. | | `showHints` | boolean | `false` | Shows completion hints as users type. | diff --git a/js/src/autocomplete.js b/js/src/autocomplete.js index 5b46fa423..301fce9f0 100644 --- a/js/src/autocomplete.js +++ b/js/src/autocomplete.js @@ -10,6 +10,7 @@ import BaseComponent from './base-component.js' import Data from './dom/data.js' import EventHandler from './dom/event-handler.js' import SelectorEngine from './dom/selector-engine.js' +import { DefaultAllowlist, sanitizeHtml } from './util/sanitizer.js' import { defineJQueryPlugin, getNextActiveElement, @@ -76,6 +77,7 @@ const SELECTOR_OPTIONS_EMPTY = '.autocomplete-options-empty' const SELECTOR_VISIBLE_ITEMS = '.autocomplete-options .autocomplete-option:not(.disabled):not(:disabled)' const Default = { + allowList: DefaultAllowlist, allowOnlyDefinedOptions: false, ariaCleanerLabel: 'Clear selection', ariaIndicatorLabel: 'Toggle visibility of options menu', @@ -89,9 +91,13 @@ const Default = { invalid: false, name: null, options: false, + optionsGroupsTemplate: null, optionsMaxHeight: 'auto', + optionsTemplate: null, placeholder: null, required: false, + sanitize: true, + sanitizeFn: null, search: null, searchNoResultsLabel: false, showHints: false, @@ -100,6 +106,7 @@ const Default = { } const DefaultType = { + allowList: 'object', allowOnlyDefinedOptions: 'boolean', ariaCleanerLabel: 'string', ariaIndicatorLabel: 'string', @@ -113,9 +120,13 @@ const DefaultType = { invalid: 'boolean', name: '(string|null)', options: '(array|null)', + optionsGroupsTemplate: '(function|null)', optionsMaxHeight: '(number|string)', + optionsTemplate: '(function|null)', placeholder: '(string|null)', required: 'boolean', + sanitize: 'boolean', + sanitizeFn: '(null|function)', search: '(array|string|null)', searchNoResultsLabel: ('boolean|string'), showHints: 'boolean', @@ -468,10 +479,17 @@ class Autocomplete extends BaseComponent { const _options = [] for (const option of options) { if (option.options && Array.isArray(option.options)) { + const customGroupProperties = { ...option } + + delete customGroupProperties.label + delete customGroupProperties.options + _options.push({ + ...customGroupProperties, label: option.label, options: this._getOptionsFromConfig(option.options) }) + continue } @@ -479,7 +497,15 @@ class Autocomplete extends BaseComponent { const value = option.value ?? (typeof option === 'string' ? option : option.label) const isSelected = option.selected || (this._config.value && this._config.value === value) + const customProperties = typeof option === 'object' ? { ...option } : {} + + delete customProperties.label + delete customProperties.value + delete customProperties.selected + delete customProperties.disabled + _options.push({ + ...customProperties, label, value, ...isSelected && { selected: true }, @@ -662,14 +688,21 @@ class Autocomplete extends BaseComponent { optgroup.setAttribute('role', 'group') const optgrouplabel = document.createElement('div') - optgrouplabel.textContent = option.label + if (this._config.optionsGroupsTemplate && typeof this._config.optionsGroupsTemplate === 'function') { + optgrouplabel.innerHTML = this._config.sanitize ? + sanitizeHtml(this._config.optionsGroupsTemplate(option), this._config.allowList, this._config.sanitizeFn) : + this._config.optionsGroupsTemplate(option) + } else { + optgrouplabel.textContent = option.label + } + optgrouplabel.classList.add(CLASS_NAME_OPTGROUP_LABEL) optgroup.append(optgrouplabel) this._createOptions(optgroup, option.options) parentElement.append(optgroup) - return + continue } const optionDiv = document.createElement('div') @@ -684,6 +717,10 @@ class Autocomplete extends BaseComponent { optionDiv.tabIndex = 0 if (this._isExternalSearch() && this._config.highlightOptionsOnSearch && this._search) { optionDiv.innerHTML = this._highlightOption(option.label) + } else if (this._config.optionsTemplate && typeof this._config.optionsTemplate === 'function') { + optionDiv.innerHTML = this._config.sanitize ? + sanitizeHtml(this._config.optionsTemplate(option), this._config.allowList, this._config.sanitizeFn) : + this._config.optionsTemplate(option) } else { optionDiv.textContent = option.label } @@ -693,10 +730,18 @@ class Autocomplete extends BaseComponent { } _onOptionsClick(element) { - if (!element.classList.contains(CLASS_NAME_OPTION) || element.classList.contains(CLASS_NAME_LABEL)) { + if (element.classList.contains(CLASS_NAME_LABEL)) { return } + if (!element.classList.contains(CLASS_NAME_OPTION)) { + element = element.closest(SELECTOR_OPTION) + + if (!element) { + return + } + } + const value = String(element.dataset.value) const foundOption = this._findOptionByValue(value) @@ -804,7 +849,7 @@ class Autocomplete extends BaseComponent { if (option.textContent.toLowerCase().indexOf(this._search) === -1) { option.style.display = 'none' } else { - if (this._config.highlightOptionsOnSearch) { + if (this._config.highlightOptionsOnSearch && !this._config.optionsTemplate) { option.innerHTML = this._highlightOption(option.textContent) } From 1c62bb98e1346aee536f3875462694de846921b8 Mon Sep 17 00:00:00 2001 From: mrholek Date: Sat, 26 Jul 2025 18:56:19 +0200 Subject: [PATCH 3/5] refactor(Autocomplete): improve class names, `clearMenus`, input group support --- docs/content/forms/autocomplete.md | 11 ++-- js/src/autocomplete.js | 81 +++++++++++++++--------------- scss/_autocomplete.scss | 56 ++++++++++++--------- scss/_variables.scss | 15 +++--- scss/forms/_input-group.scss | 4 ++ scss/mixins/_forms.scss | 1 + 6 files changed, 95 insertions(+), 73 deletions(-) diff --git a/docs/content/forms/autocomplete.md b/docs/content/forms/autocomplete.md index 519cc7c9c..79e48e151 100644 --- a/docs/content/forms/autocomplete.md +++ b/docs/content/forms/autocomplete.md @@ -180,31 +180,36 @@ You may also choose from small and large auto completes to match our similarly s {{< example class="d-flex flex-column gap-3" stackblitz_pro="true" >}}
{{< /example >}} diff --git a/js/src/autocomplete.js b/js/src/autocomplete.js index 301fce9f0..8f44a77a0 100644 --- a/js/src/autocomplete.js +++ b/js/src/autocomplete.js @@ -55,9 +55,13 @@ const EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY}${DATA_API_KEY}` const EVENT_LOAD_DATA_API = `load${EVENT_KEY}${DATA_API_KEY}` const CLASS_NAME_AUTOCOMPLETE = 'autocomplete' -const CLASS_NAME_AUTOCOMPLETE_DROPDOWN = 'autocomplete-dropdown' +const CLASS_NAME_BUTTONS = 'autocomplete-buttons' const CLASS_NAME_CLEANER = 'autocomplete-cleaner' const CLASS_NAME_DISABLED = 'disabled' +const CLASS_NAME_DROPDOWN = 'autocomplete-dropdown' +const CLASS_NAME_INDICATOR = 'autocomplete-indicator' +const CLASS_NAME_INPUT = 'autocomplete-input' +const CLASS_NAME_INPUT_HINT = 'autocomplete-input-hint' const CLASS_NAME_INPUT_GROUP = 'autocomplete-input-group' const CLASS_NAME_LABEL = 'label' const CLASS_NAME_OPTGROUP = 'autocomplete-optgroup' @@ -69,7 +73,8 @@ const CLASS_NAME_SELECTED = 'selected' const CLASS_NAME_SHOW = 'show' const SELECTOR_DATA_TOGGLE = '[data-coreui-toggle="autocomplete"]:not(.disabled)' -const SELECTOR_DATA_TOGGLE_SHOWN = `${SELECTOR_DATA_TOGGLE}.${CLASS_NAME_SHOW}` +const SELECTOR_DATA_TOGGLE_SHOWN = `.autocomplete:not(.disabled).${CLASS_NAME_SHOW}` +const SELECTOR_INDICATOR = '.autocomplete-indicator' const SELECTOR_OPTGROUP = '.autocomplete-optgroup' const SELECTOR_OPTION = '.autocomplete-option' const SELECTOR_OPTIONS = '.autocomplete-options' @@ -196,7 +201,7 @@ class Autocomplete extends BaseComponent { EventHandler.trigger(this._element, EVENT_SHOW) this._element.classList.add(CLASS_NAME_SHOW) - this._element.setAttribute('aria-expanded', true) + this._inputElement.setAttribute('aria-expanded', true) if (this._config.container) { this._menu.style.minWidth = `${this._element.offsetWidth}px` @@ -216,7 +221,7 @@ class Autocomplete extends BaseComponent { } this._element.classList.remove(CLASS_NAME_SHOW) - this._element.setAttribute('aria-expanded', 'false') + this._inputElement.setAttribute('aria-expanded', 'false') if (this._config.container) { this._menu.classList.remove(CLASS_NAME_SHOW) @@ -278,7 +283,7 @@ class Autocomplete extends BaseComponent { } this._deselectOption(option.value) - this._updateSelectionCleaner() + this._updateCleaner() } } @@ -326,8 +331,8 @@ class Autocomplete extends BaseComponent { // Private _addEventListeners() { - EventHandler.on(this._element, EVENT_CLICK, () => { - if (!this._config.disabled) { + EventHandler.on(this._element, EVENT_CLICK, event => { + if (!this._config.disabled && !event.target.closest(SELECTOR_INDICATOR)) { this.show() } }) @@ -369,7 +374,7 @@ class Autocomplete extends BaseComponent { EventHandler.on(this._indicatorElement, EVENT_CLICK, event => { event.preventDefault() - event.stopPropagation() + // event.stopPropagation() this.toggle() }) @@ -451,7 +456,7 @@ class Autocomplete extends BaseComponent { this._onOptionsClick(event.target) }) - EventHandler.on(this._selectionCleanerElement, EVENT_CLICK, event => { + EventHandler.on(this._cleanerElement, EVENT_CLICK, event => { if (!this._config.disabled) { event.preventDefault() event.stopPropagation() @@ -536,13 +541,13 @@ class Autocomplete extends BaseComponent { this._element.classList.add(className) } - this._createSelection() + this._createInputGroup() this._createButtons() this._createOptionsContainer() this._updateOptionsList() } - _createSelection() { + _createInputGroup() { const togglerEl = document.createElement('div') togglerEl.classList.add(CLASS_NAME_INPUT_GROUP) this._togglerElement = togglerEl @@ -553,7 +558,7 @@ class Autocomplete extends BaseComponent { if (!this._config.disabled && this._config.showHints) { const inputHintEl = document.createElement('input') - inputHintEl.classList.add('form-control', 'autocomplete-selection', 'autocomplete-selection-hint') + inputHintEl.classList.add(CLASS_NAME_INPUT, CLASS_NAME_INPUT_HINT) inputHintEl.setAttribute('name', (this._config.name || `${this._uniqueId}-hint`).toString()) inputHintEl.autocomplete = 'off' inputHintEl.readOnly = true @@ -565,7 +570,7 @@ class Autocomplete extends BaseComponent { } const inputEl = document.createElement('input') - inputEl.classList.add('form-control', 'autocomplete-selection') + inputEl.classList.add(CLASS_NAME_INPUT) inputEl.id = this._uniqueId inputEl.setAttribute('name', (this._config.name || this._uniqueId).toString()) inputEl.autocomplete = 'off' @@ -596,7 +601,7 @@ class Autocomplete extends BaseComponent { } const buttons = document.createElement('div') - buttons.classList.add('autocomplete-buttons') + buttons.classList.add(CLASS_NAME_BUTTONS) if (!this._config.disabled && this._config.cleaner) { const cleaner = document.createElement('button') @@ -606,13 +611,13 @@ class Autocomplete extends BaseComponent { cleaner.setAttribute('aria-label', this._config.ariaCleanerLabel) buttons.append(cleaner) - this._selectionCleanerElement = cleaner + this._cleanerElement = cleaner } if (this._config.indicator) { const indicator = document.createElement('button') indicator.type = 'button' - indicator.classList.add('autocomplete-indicator') + indicator.classList.add(CLASS_NAME_INDICATOR) indicator.setAttribute('aria-label', this._config.ariaIndicatorLabel) if (this._config.disabled) { @@ -625,7 +630,7 @@ class Autocomplete extends BaseComponent { } this._togglerElement.append(buttons) - this._updateSelectionCleaner() + this._updateCleaner() } _createPopper() { @@ -654,7 +659,7 @@ class Autocomplete extends BaseComponent { _createOptionsContainer() { const dropdownDiv = document.createElement('div') - dropdownDiv.classList.add(CLASS_NAME_AUTOCOMPLETE_DROPDOWN) + dropdownDiv.classList.add(CLASS_NAME_DROPDOWN) dropdownDiv.role = 'listbox' dropdownDiv.setAttribute('aria-labelledby', this._uniqueId) @@ -797,7 +802,7 @@ class Autocomplete extends BaseComponent { } this._inputElement.focus() - this._updateSelectionCleaner() + this._updateCleaner() } _deselectOption(value) { @@ -814,17 +819,17 @@ class Autocomplete extends BaseComponent { }) } - _updateSelectionCleaner() { - if (!this._config.cleaner || this._selectionCleanerElement === null) { + _updateCleaner() { + if (!this._config.cleaner || this._cleanerElement === null) { return } if (this._selected.length > 0) { - this._selectionCleanerElement.style.removeProperty('display') + this._cleanerElement.style.removeProperty('display') return } - this._selectionCleanerElement.style.display = 'none' + this._cleanerElement.style.display = 'none' } _updateOptionsList(options = this._options) { @@ -946,33 +951,31 @@ class Autocomplete extends BaseComponent { } static clearMenus(event) { - if (event && (event.button === RIGHT_MOUSE_BUTTON || - (event.type === 'keyup' && event.key !== TAB_KEY))) { + if (event.button === RIGHT_MOUSE_BUTTON || (event.type === 'keyup' && event.key !== TAB_KEY)) { return } - const autocompletes = SelectorEngine.find(SELECTOR_DATA_TOGGLE_SHOWN) - - for (let i = 0, len = autocompletes.length; i < len; i++) { - const context = Data.get(autocompletes[i], DATA_KEY) - const relatedTarget = { - relatedTarget: autocompletes[i] - } + const openToggles = SelectorEngine.find(SELECTOR_DATA_TOGGLE_SHOWN) - if (event && event.type === 'click') { - relatedTarget.clickEvent = event - } + for (const toggle of openToggles) { + const context = Autocomplete.getInstance(toggle) if (!context) { continue } - if (!context._element.classList.contains(CLASS_NAME_SHOW)) { + const composedPath = event.composedPath() + + if ( + composedPath.includes(context._element) + ) { continue } - if (context._element.contains(event.target)) { - continue + const relatedTarget = { relatedTarget: context._element } + + if (event.type === 'click') { + relatedTarget.clickEvent = event } context.hide() @@ -980,8 +983,6 @@ class Autocomplete extends BaseComponent { if (context._config.allowOnlyDefinedOptions && context._selected.length === 0) { context._inputElement.value = '' } - - EventHandler.trigger(context._element, EVENT_HIDDEN) } } } diff --git a/scss/_autocomplete.scss b/scss/_autocomplete.scss index a7b4c702f..e23c6a4d5 100644 --- a/scss/_autocomplete.scss +++ b/scss/_autocomplete.scss @@ -28,8 +28,9 @@ --#{$prefix}autocomplete-focus-bg: #{$autocomplete-focus-bg}; --#{$prefix}autocomplete-focus-border-color: #{$autocomplete-focus-border-color}; --#{$prefix}autocomplete-focus-box-shadow: #{$autocomplete-focus-box-shadow}; - --#{$prefix}autocomplete-selection-padding-y: #{$autocomplete-selection-padding-y}; - --#{$prefix}autocomplete-selection-padding-x: #{$autocomplete-selection-padding-x}; + --#{$prefix}autocomplete-placeholder-color: #{$autocomplete-placeholder-color}; + --#{$prefix}autocomplete-padding-y: #{$autocomplete-padding-y}; + --#{$prefix}autocomplete-padding-x: #{$autocomplete-padding-x}; --#{$prefix}autocomplete-cleaner-width: #{$autocomplete-cleaner-width}; --#{$prefix}autocomplete-cleaner-height: #{$autocomplete-cleaner-height}; --#{$prefix}autocomplete-cleaner-padding-y: #{$autocomplete-cleaner-padding-y}; @@ -113,11 +114,6 @@ flex-wrap: wrap; align-items: stretch; width: 100%; - font-family: var(--#{$prefix}autocomplete-font-family); - @include font-size(var(--#{$prefix}autocomplete-font-size)); - font-weight: var(--#{$prefix}autocomplete-font-weight); - line-height: var(--#{$prefix}autocomplete-line-height); - color: var(--#{$prefix}autocomplete-color); background-color: var(--#{$prefix}autocomplete-bg); background-clip: padding-box; border: var(--#{$prefix}autocomplete-border-width) solid var(--#{$prefix}autocomplete-border-color); @@ -128,7 +124,6 @@ } .autocomplete.disabled & { - color: var(--#{$prefix}autocomplete-disabled-color); background-color: var(--#{$prefix}autocomplete-disabled-bg); border-color: $input-disabled-border-color; } @@ -136,10 +131,8 @@ .autocomplete.show &, &:has(*:focus), &:focus { - color: var(--#{$prefix}autocomplete-focus-color); background-color: var(--#{$prefix}autocomplete-focus-bg); border-color: var(--#{$prefix}autocomplete-focus-border-color); - outline: 0; @if $enable-shadows { box-shadow: var(--#{$prefix}autocomplete-box-shadow), var(--#{$prefix}autocomplete-focus-box-shadow); } @else { @@ -148,24 +141,41 @@ } } -.autocomplete-selection { +.autocomplete-input { position: relative; - display: flex; flex: 1 1 auto; - flex-wrap: wrap; width: 1%; min-width: 0; - padding: var(--#{$prefix}autocomplete-selection-padding-y) var(--#{$prefix}autocomplete-selection-padding-x); + padding: var(--#{$prefix}autocomplete-padding-y) var(--#{$prefix}autocomplete-padding-x); + font-family: var(--#{$prefix}autocomplete-font-family); + @include font-size(var(--#{$prefix}autocomplete-font-size)); + font-weight: var(--#{$prefix}autocomplete-font-weight); + line-height: var(--#{$prefix}autocomplete-line-height); + color: var(--#{$prefix}autocomplete-color); + appearance: none; background-color: transparent; border: 0; + .autocomplete.show & { + color: var(--#{$prefix}autocomplete-focus-color); + } + + &:disabled { + color: var(--#{$prefix}autocomplete-disabled-color); + } + &:focus { - background-color: transparent; - box-shadow: none; + color: var(--#{$prefix}autocomplete-focus-color); + outline: 0; + } + + &::placeholder { + color: var(--#{$prefix}autocomplete-placeholder-color); + opacity: 1; } } -.autocomplete-selection-hint { +.autocomplete-input-hint { position: absolute; top: 0; left: 0; @@ -178,8 +188,8 @@ .autocomplete-buttons { display: flex; align-items: center; - min-height: calc(2 * var(--#{$prefix}autocomplete-selection-padding-y) + calc(var(--#{$prefix}autocomplete-font-size) * var(--#{$prefix}autocomplete-line-height))); // stylelint-disable-line function-disallowed-list - padding: 0 var(--#{$prefix}autocomplete-selection-padding-y); + min-height: calc(2 * var(--#{$prefix}autocomplete-padding-y) + calc(var(--#{$prefix}autocomplete-font-size) * var(--#{$prefix}autocomplete-line-height))); // stylelint-disable-line function-disallowed-list + padding: 0 var(--#{$prefix}autocomplete-padding-y); } .autocomplete-cleaner, @@ -329,15 +339,15 @@ .autocomplete-sm { - --#{$prefix}autocomplete-selection-padding-y: #{$autocomplete-selection-padding-y-sm}; - --#{$prefix}autocomplete-selection-padding-x: #{$autocomplete-selection-padding-x-sm}; + --#{$prefix}autocomplete-padding-y: #{$autocomplete-padding-y-sm}; + --#{$prefix}autocomplete-padding-x: #{$autocomplete-padding-x-sm}; --#{$prefix}autocomplete-font-size: #{$autocomplete-font-size-sm}; --#{$prefix}autocomplete-border-radius: #{$autocomplete-border-radius-sm}; } .autocomplete-lg { - --#{$prefix}autocomplete-selection-padding-y: #{$autocomplete-selection-padding-y-lg}; - --#{$prefix}autocomplete-selection-padding-x: #{$autocomplete-selection-padding-x-lg}; + --#{$prefix}autocomplete-padding-y: #{$autocomplete-padding-y-lg}; + --#{$prefix}autocomplete-padding-x: #{$autocomplete-padding-x-lg}; --#{$prefix}autocomplete-font-size: #{$autocomplete-font-size-lg}; --#{$prefix}autocomplete-border-radius: #{$autocomplete-border-radius-lg}; } diff --git a/scss/_variables.scss b/scss/_variables.scss index 72cc22eac..29612df09 100644 --- a/scss/_variables.scss +++ b/scss/_variables.scss @@ -2196,6 +2196,8 @@ $autocomplete-font-family: $input-font-family !default; $autocomplete-font-size: $input-font-size !default; $autocomplete-font-weight: $input-font-weight !default; $autocomplete-line-height: $input-line-height !default; +$autocomplete-padding-y: $input-padding-y !default; +$autocomplete-padding-x: $input-padding-x !default; $autocomplete-color: $input-color !default; $autocomplete-bg: $input-bg !default; $autocomplete-box-shadow: $box-shadow-inset !default; @@ -2215,12 +2217,11 @@ $autocomplete-focus-bg: $input-focus-bg !default; $autocomplete-focus-border-color: $input-focus-border-color !default; $autocomplete-focus-box-shadow: $input-btn-focus-box-shadow !default; +$autocomplete-placeholder-color: var(--#{$prefix}secondary-color) !default; + $autocomplete-invalid-border-color: $form-invalid-border-color !default; $autocomplete-valid-border-color: $form-valid-border-color !default; -$autocomplete-selection-padding-y: $input-padding-y !default; -$autocomplete-selection-padding-x: $input-padding-x !default; - $autocomplete-cleaner-width: 1.5rem !default; $autocomplete-cleaner-height: 1.5rem !default; $autocomplete-cleaner-padding-x: 0 !default; @@ -2286,12 +2287,12 @@ $autocomplete-option-selected-indicator-border-color: $autocomplete-option-sele $autocomplete-option-disabled-color: var(--#{$prefix}secondary-color) !default; $autocomplete-font-size-lg: $input-font-size-lg !default; -$autocomplete-selection-padding-y-lg: $input-padding-y-lg !default; -$autocomplete-selection-padding-x-lg: $input-padding-x-lg !default; +$autocomplete-padding-y-lg: $input-padding-y-lg !default; +$autocomplete-padding-x-lg: $input-padding-x-lg !default; $autocomplete-font-size-sm: $input-font-size-sm !default; -$autocomplete-selection-padding-y-sm: $input-padding-y-sm !default; -$autocomplete-selection-padding-x-sm: $input-padding-x-sm !default; +$autocomplete-padding-y-sm: $input-padding-y-sm !default; +$autocomplete-padding-x-sm: $input-padding-x-sm !default; // scss-docs-end autocomplete-variables diff --git a/scss/forms/_input-group.scss b/scss/forms/_input-group.scss index eaaad8cf4..697b94a58 100644 --- a/scss/forms/_input-group.scss +++ b/scss/forms/_input-group.scss @@ -25,6 +25,7 @@ } // Bring the "active" form control to the top of surrounding elements + > .autocomplete:focus-within, > .date-picker:focus-within, > .time-picker:focus-within, > .form-multi-select:focus-within, @@ -108,6 +109,7 @@ // stylelint-disable-next-line no-duplicate-selectors .input-group { &:not(.has-validation) { + > .autocomplete:not(:last-child) > .autocomplete-input-group, > .date-picker:not(:last-child) > .date-picker-input-group, > .time-picker:not(:last-child) > .time-picker-input-group, > .form-multi-select:not(:last-child) > .form-multi-select-input-group, @@ -121,6 +123,7 @@ } &.has-validation { + > .autocomplete > .autocomplete-input-group, > .date-picker > .date-picker-input-group, > .time-picker > .time-picker-input-group, > .form-multi-select > .form-multi-select-input-group, @@ -143,6 +146,7 @@ @include border-start-radius(0); } + > .autocomplete:not(:first-child) > .autocomplete-input-group, > .date-picker:not(:first-child) > .date-picker-input-group, > .time-picker:not(:first-child) > .time-picker-input-group, > .form-multi-select:not(:first-child) > .form-multi-select .form-multi-select-input-group, diff --git a/scss/mixins/_forms.scss b/scss/mixins/_forms.scss index 5d638147f..c53ad1257 100644 --- a/scss/mixins/_forms.scss +++ b/scss/mixins/_forms.scss @@ -168,6 +168,7 @@ } .input-group { + > .autocomplete:focus-within, > .date-picker:focus-within, > .time-picker:focus-within, > .form-multi-select:focus-within, From 000eaeca385358f2a15f2f3eb282fce1180ee15e Mon Sep 17 00:00:00 2001 From: mrholek Date: Sun, 27 Jul 2025 14:01:36 +0200 Subject: [PATCH 4/5] chore: clean-up --- js/dist/auto-complete copy.js | 884 ++++++++++++++++++++++++++++++ js/dist/auto-complete copy.js.map | 1 + js/dist/auto-complete.js | 818 +++++++++++++++++++++++++++ js/dist/auto-complete.js.map | 1 + js/dist/autocomplete.js | 867 +++++++++++++++++++++++++++++ js/dist/autocomplete.js.map | 1 + js/src/autocomplete.js | 1 - 7 files changed, 2572 insertions(+), 1 deletion(-) create mode 100644 js/dist/auto-complete copy.js create mode 100644 js/dist/auto-complete copy.js.map create mode 100644 js/dist/auto-complete.js create mode 100644 js/dist/auto-complete.js.map create mode 100644 js/dist/autocomplete.js create mode 100644 js/dist/autocomplete.js.map diff --git a/js/dist/auto-complete copy.js b/js/dist/auto-complete copy.js new file mode 100644 index 000000000..3d5427213 --- /dev/null +++ b/js/dist/auto-complete copy.js @@ -0,0 +1,884 @@ +/*! + * CoreUI auto-complete copy.js v5.15.0 (https://coreui.io) + * Copyright 2025 The CoreUI Team (https://github.com/orgs/coreui/people) + * Licensed under MIT (https://github.com/coreui/coreui/blob/main/LICENSE) + */ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('@popperjs/core'), require('./base-component.js'), require('./dom/data.js'), require('./dom/event-handler.js'), require('./dom/selector-engine.js'), require('./util/index.js')) : + typeof define === 'function' && define.amd ? define(['@popperjs/core', './base-component', './dom/data', './dom/event-handler', './dom/selector-engine', './util/index'], factory) : + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global["AutoComplete copy"] = factory(global["@popperjs/core"], global.BaseComponent, global.Data, global.EventHandler, global.SelectorEngine, global.Index)); +})(this, (function (Popper, BaseComponent, Data, EventHandler, SelectorEngine, index_js) { 'use strict'; + + function _interopNamespaceDefault(e) { + const n = Object.create(null, { [Symbol.toStringTag]: { value: 'Module' } }); + if (e) { + for (const k in e) { + if (k !== 'default') { + const d = Object.getOwnPropertyDescriptor(e, k); + Object.defineProperty(n, k, d.get ? d : { + enumerable: true, + get: () => e[k] + }); + } + } + } + n.default = e; + return Object.freeze(n); + } + + const Popper__namespace = /*#__PURE__*/_interopNamespaceDefault(Popper); + + /** + * -------------------------------------------------------------------------- + * CoreUI PRO auto-complete.js + * License (https://coreui.io/pro/license/) + * -------------------------------------------------------------------------- + */ + + + /** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + + const NAME = 'auto-complete'; + const DATA_KEY = 'coreui.auto-complete'; + const EVENT_KEY = `.${DATA_KEY}`; + const DATA_API_KEY = '.data-api'; + + // Keys + const ARROW_UP_KEY = 'ArrowUp'; + const ARROW_DOWN_KEY = 'ArrowDown'; + // const ARROW_LEFT_KEY = 'ArrowLeft' + const ARROW_RIGHT_KEY = 'ArrowRight'; + const BACKSPACE_KEY = 'Backspace'; + const DELETE_KEY = 'Delete'; + const ENTER_KEY = 'Enter'; + const ESCAPE_KEY = 'Escape'; + const TAB_KEY = 'Tab'; + const RIGHT_MOUSE_BUTTON = 2; + + // Selectors + const SELECTOR_AC = '.auto-complete'; + // const SELECTOR_AC_INPUT_GROUP = '.auto-complete-input-group' + // const SELECTOR_AC_SELECTION = '.auto-complete-selection' + // const SELECTOR_AC_HINT = '.auto-complete-selection-hint' + // const SELECTOR_AC_CLEANER = '.auto-complete-cleaner' + // const SELECTOR_AC_INDICATOR = '.auto-complete-indicator' + // const SELECTOR_AC_DROPDOWN = '.auto-complete-dropdown' + const SELECTOR_AC_OPTIONS = '.auto-complete-options'; + const SELECTOR_AC_OPTION = '.auto-complete-option'; + const SELECTOR_AC_OPTIONS_EMPTY = '.auto-complete-options-empty'; + const SELECTOR_AC_VISIBLE_ITEMS = '.auto-complete-options .auto-complete-option:not(.disabled):not(:disabled)'; + + // Events + const EVENT_CHANGED = `changed${EVENT_KEY}`; // { value: Option | null } + const EVENT_INPUT = `input${EVENT_KEY}`; // when user types search text + const EVENT_SEARCH = `search${EVENT_KEY}`; // after internal filter applied + const EVENT_SHOW = `show${EVENT_KEY}`; + const EVENT_SHOWN = `shown${EVENT_KEY}`; + const EVENT_HIDE = `hide${EVENT_KEY}`; + const EVENT_HIDDEN = `hidden${EVENT_KEY}`; + const EVENT_CLICK = `click${EVENT_KEY}`; + const EVENT_KEYDOWN = `keydown${EVENT_KEY}`; + // const EVENT_KEYUP = `keyup${EVENT_KEY}` + const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`; + const EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY}${DATA_API_KEY}`; + const EVENT_LOAD_DATA_API = `load${EVENT_KEY}${DATA_API_KEY}`; + + // Class names + const CLASS_NAME_AC = 'auto-complete'; + const CLASS_NAME_INPUT_GROUP = 'auto-complete-input-group'; + const CLASS_NAME_HINT = 'auto-complete-selection-hint'; + const CLASS_NAME_SELECTION = 'auto-complete-selection'; + const CLASS_NAME_DROPDOWN = 'auto-complete-dropdown'; + const CLASS_NAME_OPTIONS = 'auto-complete-options'; + const CLASS_NAME_OPTION = 'auto-complete-option'; + const CLASS_NAME_OPTIONS_EMPTY = 'auto-complete-options-empty'; + const CLASS_NAME_DISABLED = 'disabled'; + const CLASS_NAME_SHOW = 'show'; + const CLASS_NAME_CLEANER = 'auto-complete-cleaner'; + const CLASS_NAME_INDICATOR = 'auto-complete-indicator'; + const CLASS_NAME_IS_INVALID = 'is-invalid'; + const CLASS_NAME_IS_VALID = 'is-valid'; + + // Default config mirrors CAutoComplete props where meaningful. + const Default = { + allowCreateOptions: false, + allowOnlyDefinedOptions: false, + cleaner: true, + clearSearchOnSelect: true, + container: false, + // false | element | selector | true (-> body) + disabled: false, + globalSearch: true, + hightlightOptionsOnSearch: true, + id: null, + invalid: false, + loading: false, + name: null, + options: [], + // array of Option | OptionsGroup | string + optionsMaxHeight: 'auto', + optionsTemplate: null, + // fn(option) => HTML + optionsGroupsTemplate: null, + // fn(group) => HTML + placeholder: '', + readOnly: false, + required: false, + resetSelectionOnOptionsChange: false, + search: true, + // true | 'external' + searchNoResultsLabel: 'No results found', + showHints: true, + size: null, + // 'sm' | 'lg' + valid: false, + value: null, + // initial string value + // virtualScroller: false, // not implemented in vanilla; reserved + visible: false, + visibleItems: 10 + }; + + // Type hints (string descriptors for BaseComponent._typeCheckConfig if used) + const DefaultType = { + allowCreateOptions: 'boolean', + allowOnlyDefinedOptions: 'boolean', + cleaner: 'boolean', + clearSearchOnSelect: 'boolean', + container: '(string|element|boolean)', + disabled: 'boolean', + globalSearch: 'boolean', + hightlightOptionsOnSearch: 'boolean', + id: '(string|null)', + invalid: 'boolean', + loading: 'boolean', + name: '(string|null)', + options: 'array', + optionsMaxHeight: '(number|string)', + optionsTemplate: '(function|null)', + optionsGroupsTemplate: '(function|null)', + placeholder: 'string', + readOnly: 'boolean', + required: 'boolean', + resetSelectionOnOptionsChange: 'boolean', + search: '(boolean|string)', + searchNoResultsLabel: '(boolean|string)', + showHints: 'boolean', + size: '(string|null)', + valid: 'boolean', + value: '(string|null)', + // virtualScroller: 'boolean', + visible: 'boolean', + visibleItems: 'number' + }; + + // ------------------------------------------------------------------------ + // Helpers for options dataset + // ------------------------------------------------------------------------ + + function normalizeOption(raw) { + var _ref, _raw$label; + // Accept string shorthand: 'foo' => { value: 'foo', label: 'foo' } + if (typeof raw === 'string') { + return { + value: raw, + label: raw + }; + } + + // Group test + if (raw && Array.isArray(raw.options)) { + return { + label: raw.label, + options: raw.options.map(normalizeOption) + }; + } + + // Single option + const value = String(raw.value); + return { + value, + label: (_ref = (_raw$label = raw.label) != null ? _raw$label : raw.text) != null ? _ref : value, + disabled: Boolean(raw.disabled), + selected: Boolean(raw.selected) + }; + } + function flattenOptions(options, flat = []) { + for (const opt of options) { + if (opt && Array.isArray(opt.options)) { + flattenOptions(opt.options, flat); + continue; + } + flat.push(opt); + } + return flat; + } + function getOptionLabel(opt) { + var _ref2, _opt$label; + return typeof opt === 'string' ? opt : (_ref2 = (_opt$label = opt.label) != null ? _opt$label : opt.text) != null ? _ref2 : String(opt.value); + } + function isOptionDisabled(opt) { + return Boolean(opt && typeof opt === 'object' && opt.disabled); + } + + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + + class AutoComplete extends BaseComponent { + constructor(element, config) { + super(element); + this._config = this._getConfig(config); + this._indicatorElement = null; + this._cleanerElement = null; + this._dropdownElement = null; + this._optionsElement = null; + this._hintInputElement = null; + this._inputElement = null; + this._togglerElement = null; + this._popper = null; + this._options = this._getOptionsFromConfig(this._config.options); + this._userOptions = []; + this._selected = []; + this._search = ''; + this._visible = this._config.visible; + this._hint = null; + this._createAutoComplete(); + this._addEventListeners(); + Data.set(this._element, DATA_KEY, this); + + // Initial value resolution (string or preselected flag) + this._initInitialValue(); + } + + // Getters ----------------------------------------------------------------- + static get NAME() { + return NAME; + } + static get Default() { + return Default; + } + static get DefaultType() { + return DefaultType; + } + + // Public API --------------------------------------------------------------- + toggle() { + return this._isShown() ? this.hide() : this.show(); + } + show() { + var _this$_inputElement; + if (this._config.disabled || this._isShown()) { + return; + } + if (this._filteredOptions().length === 0 && this._config.searchNoResultsLabel === false) { + return; + } + EventHandler.trigger(this._element, EVENT_SHOW); + this._clone.classList.add(CLASS_NAME_SHOW); + this._clone.setAttribute('aria-expanded', true); + if (this._config.container) { + this._dropdownElement.style.minWidth = `${this._clone.offsetWidth}px`; + this._dropdownElement.classList.add(CLASS_NAME_SHOW); + } + EventHandler.trigger(this._element, EVENT_SHOWN); + this._createPopper(); + (_this$_inputElement = this._inputElement) == null || _this$_inputElement.focus(); + } + hide() { + EventHandler.trigger(this._element, EVENT_HIDE); + if (this._popper) { + this._popper.destroy(); + } + this._clone.classList.remove(CLASS_NAME_SHOW); + this._clone.setAttribute('aria-expanded', 'false'); + if (this._config.container) { + this._dropdownElement.classList.remove(CLASS_NAME_SHOW); + } + EventHandler.trigger(this._element, EVENT_HIDDEN); + } + dispose() { + if (this._popper) { + this._popper.destroy(); + } + super.dispose(); + } + update(config) { + const reset = config && config.value !== undefined; + this._config = { + ...this._config, + ...this._configAfterMerge(config) + }; + this._options = this._getOptionsFromConfig(this._config.options); + if (reset || this._config.resetSelectionOnOptionsChange) { + this._selected = []; + } + this._clone.remove(); + this._element.innerHTML = ''; + this._createAutoComplete(); + this._addEventListeners(); + } + getValue() { + return this._selected.length ? this._selected[0] : null; + } + + // Private ------------------------------------------------------------------ + + _addEventListeners() { + // toggle show when clicking group wrapper + EventHandler.on(this._clone, EVENT_CLICK, () => { + if (!this._config.disabled) { + this.show(); + } + }); + + // keyboard from wrapper (globalSearch behaviour) + EventHandler.on(this._clone, EVENT_KEYDOWN, event => { + if (event.key === ESCAPE_KEY) { + this.hide(); + return; + } + if (this._config.globalSearch && (event.key.length === 1 || event.key === BACKSPACE_KEY || event.key === DELETE_KEY)) { + var _this$_inputElement2; + (_this$_inputElement2 = this._inputElement) == null || _this$_inputElement2.focus(); + } + }); + + // indicator button explicit toggle + EventHandler.on(this._indicatorElement, EVENT_CLICK, event => { + event.preventDefault(); + event.stopPropagation(); + this.toggle(); + }); + + // cleaner button + if (this._cleanerElement) { + EventHandler.on(this._cleanerElement, EVENT_CLICK, event => { + event.preventDefault(); + event.stopPropagation(); + this._clearSelection(); + }); + } + + // input typing + EventHandler.on(this._inputElement, EVENT_INPUT, event => { + const { + value + } = event.target; + this._onInputChange(value); + }); + EventHandler.on(this._inputElement, EVENT_KEYDOWN, event => this._onInputKeyDown(event)); + + // options click delegate + EventHandler.on(this._optionsElement, EVENT_CLICK, event => { + event.preventDefault(); + event.stopPropagation(); + this._onOptionsClick(event.target); + }); + + // options keyboard + EventHandler.on(this._optionsElement, EVENT_KEYDOWN, event => { + if (event.key === ENTER_KEY) { + this._onOptionsClick(event.target); + } + if ([ARROW_UP_KEY, ARROW_DOWN_KEY].includes(event.key)) { + event.preventDefault(); + this._selectMenuItem(event); + } + }); + } + _onInputChange(text) { + this._search = text; + EventHandler.trigger(this._element, EVENT_INPUT, { + value: text + }); + this._filterOptionsList(); + this._updateHint(); + EventHandler.trigger(this._element, EVENT_SEARCH); + } + _onInputKeyDown(event) { + if (event.key === ESCAPE_KEY) { + this._getOrCreateOption(); + this.hide(); + return; + } + if (event.key === ARROW_DOWN_KEY) { + event.preventDefault(); + this.show(); + const first = SelectorEngine.findOne(SELECTOR_AC_OPTION, this._optionsElement); + if (first) { + first.focus(); + } + return; + } + if (this._config.showHints && this._hint && (event.key === ARROW_RIGHT_KEY || event.key === TAB_KEY)) { + event.preventDefault(); + this._selectOption(this._hint); + return; + } + if (event.key === ENTER_KEY) { + this._getOrCreateOption(); + return; + } + if (event.key === BACKSPACE_KEY || event.key === DELETE_KEY) { + this._clearSelection(); + } + } + _onOptionsClick(element) { + if (!element.classList.contains(CLASS_NAME_OPTION)) { + return; + } + const { + value + } = element.dataset; + const opt = this._findOptionByValue(value); + if (opt && isOptionDisabled(opt)) { + return; + } + this._selectOption(opt || { + value, + label: value + }); + if (this._config.clearSearchOnSelect) { + this._onInputChange(''); + this._inputElement.value = ''; + this._inputElement.focus(); + } + this.hide(); + } + _selectMenuItem({ + key, + target + }) { + const items = SelectorEngine.find(SELECTOR_AC_VISIBLE_ITEMS, this._dropdownElement).filter(el => index_js.isVisible(el)); + if (!items.length) { + return; + } + index_js.getNextActiveElement(items, target, key === ARROW_DOWN_KEY, !items.includes(target)).focus(); + } + _getOptionsFromConfig(options = []) { + return options.map(normalizeOption); + } + _filteredOptions() { + const all = [...this._options, ...this._userOptions]; + if (!this._search) { + return all; + } + const s = this._search.toLowerCase(); + return all.filter(opt => { + if (opt.options) { + // group: include groups where any child matches + return opt.options.some(o => getOptionLabel(o).toLowerCase().includes(s)); + } + return getOptionLabel(opt).toLowerCase().includes(s); + }); + } + _filteredFlatOptions() { + return flattenOptions(this._filteredOptions()); + } + _updateHint() { + if (!this._config.showHints || !this._hintInputElement) { + return; + } + const s = this._search; + if (!s) { + this._hint = null; + this._hintInputElement.value = ''; + return; + } + const flat = this._filteredFlatOptions(); + const found = flat.find(opt => getOptionLabel(opt).toLowerCase().startsWith(s.toLowerCase())); + this._hint = found || null; + this._hintInputElement.value = found ? `${s}${getOptionLabel(found).slice(s.length)}` : ''; + } + _getOrCreateOption() { + const s = this._search.trim(); + if (s === '') { + return; + } + const flat = this._filteredFlatOptions(); + const found = flat.find(opt => getOptionLabel(opt).toLowerCase() === s.toLowerCase()); + if (found && isOptionDisabled(found)) { + return; + } + if (!found && this._config.allowOnlyDefinedOptions) { + return; + } + if (found) { + this._selectOption(found); + return; + } + if (this._config.allowCreateOptions) { + const userOpt = { + value: s, + label: s + }; + this._userOptions.push(userOpt); + this._selectOption(userOpt); + return; + } + this._selectOption({ + value: s, + label: s + }); + } + _selectOption(opt) { + if (opt && opt.disabled) { + return; + } + this._selected = opt ? [opt] : []; + if (this._inputElement) { + this._inputElement.value = opt ? getOptionLabel(opt) : ''; + } + this._updateCleanerVisibility(); + EventHandler.trigger(this._element, EVENT_CHANGED, { + value: this.getValue() + }); + } + _clearSelection() { + this._selectOption(null); + } + _findOptionByValue(value, options = [...this._options, ...this._userOptions]) { + for (const opt of options) { + if (opt && Array.isArray(opt.options)) { + const found = this._findOptionByValue(value, opt.options); + if (found) { + return found; + } + continue; + } + if (String(opt.value) === String(value)) { + return opt; + } + } + return null; + } + _filterOptionsList() { + const s = this._search.toLowerCase(); + const options = SelectorEngine.find(SELECTOR_AC_OPTION, this._dropdownElement); + let visibleOptions = 0; + for (const option of options) { + const match = option.textContent.toLowerCase().includes(s); + if (match) { + option.style.removeProperty('display'); + visibleOptions++; + } else { + option.style.display = 'none'; + } + } + if (visibleOptions > 0) { + const empty = SelectorEngine.findOne(SELECTOR_AC_OPTIONS_EMPTY, this._dropdownElement); + if (empty) { + empty.remove(); + } + return; + } + if (visibleOptions === 0) { + const placeholder = document.createElement('div'); + placeholder.classList.add(CLASS_NAME_OPTIONS_EMPTY); + placeholder.innerHTML = this._config.searchNoResultsLabel; + const container = SelectorEngine.findOne(SELECTOR_AC_OPTIONS, this._dropdownElement); + if (container && !SelectorEngine.findOne(SELECTOR_AC_OPTIONS_EMPTY, container)) { + container.append(placeholder); + } + } + } + _createAutoComplete() { + // root clone + const acEl = document.createElement('div'); + acEl.classList.add(CLASS_NAME_AC); + acEl.classList.toggle(CLASS_NAME_IS_INVALID, this._config.invalid); + acEl.classList.toggle(CLASS_NAME_IS_VALID, this._config.valid); + acEl.setAttribute('aria-expanded', 'false'); + if (this._config.disabled) { + acEl.classList.add(CLASS_NAME_DISABLED); + } + if (this._config.size) { + acEl.classList.add(`${CLASS_NAME_AC}-${this._config.size}`); + } + + // copy any extra classes from source element + for (const className of this._element.classList) { + acEl.classList.add(className); + } + this._clone = acEl; + this._element.parentNode.insertBefore(acEl, this._element.nextSibling); + + // input group + const inputGroupEl = document.createElement('div'); + inputGroupEl.classList.add(CLASS_NAME_INPUT_GROUP); + this._togglerElement = inputGroupEl; + acEl.append(inputGroupEl); + + // hint input (readonly overlay) if enabled + if (this._config.showHints) { + const hintEl = document.createElement('input'); + hintEl.classList.add('form-control', CLASS_NAME_SELECTION, CLASS_NAME_HINT); + hintEl.autocomplete = 'off'; + hintEl.readOnly = true; + hintEl.tabIndex = -1; + inputGroupEl.append(hintEl); + this._hintInputElement = hintEl; + } + + // main text input + const inputEl = document.createElement('input'); + inputEl.type = 'text'; + inputEl.classList.add('form-control', CLASS_NAME_SELECTION); + if (this._config.disabled) { + inputEl.disabled = true; + } + if (this._config.id) { + inputEl.id = this._config.id; + } + if (this._config.name) { + inputEl.name = this._config.name; + } + if (this._config.placeholder) { + inputEl.placeholder = this._config.placeholder; + } + inputEl.autocomplete = 'off'; + inputEl.required = Boolean(this._config.required); + inputEl.readOnly = Boolean(this._config.readOnly); + inputEl.setAttribute('aria-autocomplete', 'list'); + inputEl.setAttribute('role', 'combobox'); + inputGroupEl.append(inputEl); + this._inputElement = inputEl; + + // buttons + const buttonsEl = document.createElement('div'); + buttonsEl.classList.add('auto-complete-buttons'); + inputGroupEl.append(buttonsEl); + if (!this._config.disabled && !this._config.readOnly && this._config.cleaner) { + const cleanerEl = document.createElement('button'); + cleanerEl.type = 'button'; + cleanerEl.classList.add(CLASS_NAME_CLEANER); + buttonsEl.append(cleanerEl); + this._cleanerElement = cleanerEl; + } + const indicatorEl = document.createElement('button'); + indicatorEl.type = 'button'; + indicatorEl.classList.add(CLASS_NAME_INDICATOR); + if (this._config.disabled) { + indicatorEl.tabIndex = -1; + } + buttonsEl.append(indicatorEl); + this._indicatorElement = indicatorEl; + + // dropdown container + const dropdownEl = document.createElement('div'); + dropdownEl.classList.add(CLASS_NAME_DROPDOWN); + dropdownEl.setAttribute('role', 'menu'); + if (this._config.container) ; else { + acEl.append(dropdownEl); + } + this._dropdownElement = dropdownEl; + + // options container + const optionsEl = document.createElement('div'); + optionsEl.classList.add(CLASS_NAME_OPTIONS); + if (this._config.optionsMaxHeight !== 'auto') { + optionsEl.style.maxHeight = `${this._config.optionsMaxHeight}px`; + optionsEl.style.overflow = 'auto'; + } + dropdownEl.append(optionsEl); + this._optionsElement = optionsEl; + + // create options markup + this._createOptions(optionsEl, this._options); + + // hide source element (if etc.)\n this._hideNativeElement()\n\n // ensure container\n const { container } = this._config\n if (container) {\n const _container = container === true ? document.body : getElement(container)\n _container.append(dropdownEl)\n }\n\n // reflect initial show state if configured\n if (this._visible) {\n this.show()\n }\n\n this._updateCleanerVisibility()\n }\n\n _createOptions(parent, options) {\n for (const opt of options) {\n if (Array.isArray(opt.options)) {\n const labelEl = document.createElement('div')\n labelEl.classList.add('auto-complete-optgroup-label')\n labelEl.innerHTML = opt.label\n parent.append(labelEl)\n this._createOptions(parent, opt.options)\n continue\n }\n\n const optEl = document.createElement('div')\n optEl.classList.add(CLASS_NAME_OPTION)\n if (opt.disabled) {\n optEl.classList.add(CLASS_NAME_DISABLED)\n }\n\n optEl.dataset.value = String(opt.value)\n optEl.tabIndex = 0\n optEl.innerHTML = this._renderOptionContent(opt)\n parent.append(optEl)\n }\n }\n\n _renderOptionContent(opt) {\n if (this._config.optionsTemplate) {\n try {\n return this._config.optionsTemplate(opt)\n } catch {/* ignore */}\n }\n\n if (this._config.hightlightOptionsOnSearch && this._search) {\n const label = getOptionLabel(opt)\n const idx = label.toLowerCase().indexOf(this._search.toLowerCase())\n if (idx !== -1) {\n const before = label.slice(0, idx)\n const match = label.slice(idx, idx + this._search.length)\n const after = label.slice(idx + this._search.length)\n return `${before}${match}${after}`\n }\n\n return label\n }\n\n return getOptionLabel(opt)\n }\n\n _hideNativeElement() {\n this._element.tabIndex = -1\n this._element.style.display = 'none'\n }\n\n _initInitialValue() {\n const cfgVal = this._config.value\n if (cfgVal && typeof cfgVal === 'string') {\n const found = this._findOptionByValue(cfgVal) || { value: cfgVal, label: cfgVal }\n this._selectOption(found)\n return\n }\n\n // look for preselected in options\n const flat = flattenOptions(this._options)\n const pre = flat.find(o => o.selected)\n if (pre) {\n this._selectOption(pre)\n }\n }\n\n _updateCleanerVisibility() {\n if (!this._cleanerElement) {\n return\n }\n\n if (this._selected.length > 0) {\n this._cleanerElement.style.removeProperty('display')\n return\n }\n\n this._cleanerElement.style.display = 'none'\n }\n\n _createPopper() {\n if (typeof Popper === 'undefined') {\n throw new TypeError('CoreUI\\'s auto complete require Popper (https://popper.js.org)')\n }\n\n const popperConfig = {\n modifiers: [{\n name: 'preventOverflow',\n options: { boundary: 'clippingParents' }\n }, {\n name: 'offset',\n options: { offset: [0, 2] }\n }],\n placement: isRTL() ? 'bottom-end' : 'bottom-start'\n }\n this._popper = Popper.createPopper(this._togglerElement, this._dropdownElement, popperConfig)\n }\n\n _isShown() {\n return this._clone.classList.contains(CLASS_NAME_SHOW)\n }\n\n _configAfterMerge(config = {}) {\n if (config.container === true) {\n config.container = document.body\n }\n\n if (typeof config.container === 'object' || typeof config.container === 'string') {\n config.container = getElement(config.container)\n }\n\n if (typeof config.options === 'string') {\n config.options = config.options.split(/,\\s*/).map(String)\n }\n\n return config\n }\n}\n\n// ------------------------------------------------------------------------\n// Data API implementation ----------------------------------------------------\n// ------------------------------------------------------------------------\n\nEventHandler.on(window, EVENT_LOAD_DATA_API, () => {\n for (const ac of SelectorEngine.find(SELECTOR_AC)) {\n if (ac.tabIndex !== -1) {\n AutoComplete.autoCompleteInterface(ac)\n }\n }\n})\nEventHandler.on(document, EVENT_CLICK_DATA_API, clearMenus)\nEventHandler.on(document, EVENT_KEYUP_DATA_API, clearMenus)\n\nfunction clearMenus(event) {\n if (event && (event.button === RIGHT_MOUSE_BUTTON || (event.type === 'keyup' && event.key !== TAB_KEY))) {\n return\n }\n\n const acs = SelectorEngine.find(SELECTOR_AC)\n for (const el of acs) {\n const context = Data.get(el, DATA_KEY)\n const relatedTarget = { relatedTarget: el }\n if (event && event.type === 'click') {\n relatedTarget.clickEvent = event\n }\n\n if (!context) {\n continue\n }\n\n if (!context._clone.classList.contains(CLASS_NAME_SHOW)) {\n continue\n }\n\n if (context._clone.contains(event.target)) {\n continue\n }\n\n context.hide()\n EventHandler.trigger(context._element, EVENT_HIDDEN, relatedTarget)\n }\n}\n\n// Static interface + jQuery bridge ------------------------------------------\n\nAutoComplete.autoCompleteInterface = function (element, config) {\n const data = AutoComplete.getOrCreateInstance(element, config)\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n\n data[config]()\n }\n}\n\nAutoComplete.jQueryInterface = function (config) {\n return this.each(function () {\n AutoComplete.autoCompleteInterface(this, config)\n })\n}\n\ndefineJQueryPlugin(AutoComplete)\n\nexport default AutoComplete\n"],"names":["NAME","DATA_KEY","EVENT_KEY","DATA_API_KEY","ARROW_UP_KEY","ARROW_DOWN_KEY","ARROW_RIGHT_KEY","BACKSPACE_KEY","DELETE_KEY","ENTER_KEY","ESCAPE_KEY","TAB_KEY","RIGHT_MOUSE_BUTTON","SELECTOR_AC","SELECTOR_AC_OPTIONS","SELECTOR_AC_OPTION","SELECTOR_AC_OPTIONS_EMPTY","SELECTOR_AC_VISIBLE_ITEMS","EVENT_CHANGED","EVENT_INPUT","EVENT_SEARCH","EVENT_SHOW","EVENT_SHOWN","EVENT_HIDE","EVENT_HIDDEN","EVENT_CLICK","EVENT_KEYDOWN","EVENT_CLICK_DATA_API","EVENT_KEYUP_DATA_API","EVENT_LOAD_DATA_API","CLASS_NAME_AC","CLASS_NAME_INPUT_GROUP","CLASS_NAME_HINT","CLASS_NAME_SELECTION","CLASS_NAME_DROPDOWN","CLASS_NAME_OPTIONS","CLASS_NAME_OPTION","CLASS_NAME_OPTIONS_EMPTY","CLASS_NAME_DISABLED","CLASS_NAME_SHOW","CLASS_NAME_CLEANER","CLASS_NAME_INDICATOR","CLASS_NAME_IS_INVALID","CLASS_NAME_IS_VALID","Default","allowCreateOptions","allowOnlyDefinedOptions","cleaner","clearSearchOnSelect","container","disabled","globalSearch","hightlightOptionsOnSearch","id","invalid","loading","name","options","optionsMaxHeight","optionsTemplate","optionsGroupsTemplate","placeholder","readOnly","required","resetSelectionOnOptionsChange","search","searchNoResultsLabel","showHints","size","valid","value","visible","visibleItems","DefaultType","normalizeOption","raw","_ref","_raw$label","label","Array","isArray","map","String","text","Boolean","selected","flattenOptions","flat","opt","push","getOptionLabel","_ref2","_opt$label","isOptionDisabled","AutoComplete","BaseComponent","constructor","element","config","_config","_getConfig","_indicatorElement","_cleanerElement","_dropdownElement","_optionsElement","_hintInputElement","_inputElement","_togglerElement","_popper","_options","_getOptionsFromConfig","_userOptions","_selected","_search","_visible","_hint","_createAutoComplete","_addEventListeners","Data","set","_element","_initInitialValue","toggle","_isShown","hide","show","_this$_inputElement","_filteredOptions","length","EventHandler","trigger","_clone","classList","add","setAttribute","style","minWidth","offsetWidth","_createPopper","focus","destroy","remove","dispose","update","reset","undefined","_configAfterMerge","innerHTML","getValue","on","event","key","_this$_inputElement2","preventDefault","stopPropagation","_clearSelection","target","_onInputChange","_onInputKeyDown","_onOptionsClick","includes","_selectMenuItem","_filterOptionsList","_updateHint","_getOrCreateOption","first","SelectorEngine","findOne","_selectOption","contains","dataset","_findOptionByValue","items","find","filter","el","isVisible","getNextActiveElement","all","s","toLowerCase","some","o","_filteredFlatOptions","found","startsWith","slice","trim","userOpt","_updateCleanerVisibility","visibleOptions","option","match","textContent","removeProperty","display","empty","document","createElement","append","acEl","className","parentNode","insertBefore","nextSibling","inputGroupEl","hintEl","autocomplete","tabIndex","inputEl","type","buttonsEl","cleanerEl","indicatorEl","dropdownEl","optionsEl","maxHeight","overflow","_createOptions","_hideNativeElement","_container","body","getElement","parent","labelEl","optEl","_renderOptionContent","_unused","idx","indexOf","before","after","cfgVal","pre","Popper","TypeError","popperConfig","modifiers","boundary","offset","placement","isRTL","createPopper","split","window","ac","autoCompleteInterface","clearMenus","button","acs","context","get","relatedTarget","clickEvent","data","getOrCreateInstance","jQueryInterface","each","defineJQueryPlugin"],"mappings":"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"} \ No newline at end of file diff --git a/js/dist/auto-complete.js b/js/dist/auto-complete.js new file mode 100644 index 000000000..926e2b7ba --- /dev/null +++ b/js/dist/auto-complete.js @@ -0,0 +1,818 @@ +/*! + * CoreUI auto-complete.js v5.15.0 (https://coreui.io) + * Copyright 2025 The CoreUI Team (https://github.com/orgs/coreui/people) + * Licensed under MIT (https://github.com/coreui/coreui/blob/main/LICENSE) + */ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('@popperjs/core'), require('./base-component.js'), require('./dom/data.js'), require('./dom/event-handler.js'), require('./dom/selector-engine.js'), require('./util/index.js')) : + typeof define === 'function' && define.amd ? define(['@popperjs/core', './base-component', './dom/data', './dom/event-handler', './dom/selector-engine', './util/index'], factory) : + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.AutoComplete = factory(global["@popperjs/core"], global.BaseComponent, global.Data, global.EventHandler, global.SelectorEngine, global.Index)); +})(this, (function (Popper, BaseComponent, Data, EventHandler, SelectorEngine, index_js) { 'use strict'; + + function _interopNamespaceDefault(e) { + const n = Object.create(null, { [Symbol.toStringTag]: { value: 'Module' } }); + if (e) { + for (const k in e) { + if (k !== 'default') { + const d = Object.getOwnPropertyDescriptor(e, k); + Object.defineProperty(n, k, d.get ? d : { + enumerable: true, + get: () => e[k] + }); + } + } + } + n.default = e; + return Object.freeze(n); + } + + const Popper__namespace = /*#__PURE__*/_interopNamespaceDefault(Popper); + + /** + * -------------------------------------------------------------------------- + * CoreUI PRO auto-complete.js + * License (https://coreui.io/pro/license/) + * -------------------------------------------------------------------------- + */ + + + /** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + + const NAME = 'auto-complete'; + const DATA_KEY = 'coreui.auto-complete'; + const EVENT_KEY = `.${DATA_KEY}`; + const DATA_API_KEY = '.data-api'; + const ARROW_UP_KEY = 'ArrowUp'; + const ARROW_DOWN_KEY = 'ArrowDown'; + const BACKSPACE_KEY = 'Backspace'; + const DELETE_KEY = 'Delete'; + const ENTER_KEY = 'Enter'; + const ESCAPE_KEY = 'Escape'; + const TAB_KEY = 'Tab'; + const RIGHT_MOUSE_BUTTON = 2; // MouseEvent.button value for the secondary button, usually the right button + + const SELECTOR_OPTGROUP = '.auto-complete-optgroup'; + const SELECTOR_OPTION = '.auto-complete-option'; + const SELECTOR_OPTIONS = '.auto-complete-options'; + const SELECTOR_OPTIONS_EMPTY = '.auto-complete-options-empty'; + const SELECTOR_AUTO_COMPLETE = '.auto-complete'; + const SELECTOR_VISIBLE_ITEMS = '.auto-complete-options .auto-complete-option:not(.disabled):not(:disabled)'; + const EVENT_CHANGED = `changed${EVENT_KEY}`; + const EVENT_CLICK = `click${EVENT_KEY}`; + const EVENT_HIDE = `hide${EVENT_KEY}`; + const EVENT_HIDDEN = `hidden${EVENT_KEY}`; + const EVENT_INPUT = `input${EVENT_KEY}`; + const EVENT_KEYDOWN = `keydown${EVENT_KEY}`; + const EVENT_KEYUP = `keyup${EVENT_KEY}`; + const EVENT_SHOW = `show${EVENT_KEY}`; + const EVENT_SHOWN = `shown${EVENT_KEY}`; + const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`; + const EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY}${DATA_API_KEY}`; + const EVENT_LOAD_DATA_API = `load${EVENT_KEY}${DATA_API_KEY}`; + const CLASS_NAME_AUTO_COMPLETE = 'auto-complete'; + const CLASS_NAME_AUTO_COMPLETE_DROPDOWN = 'auto-complete-dropdown'; + const CLASS_NAME_CLEANER = 'auto-complete-cleaner'; + const CLASS_NAME_DISABLED = 'disabled'; + const CLASS_NAME_INPUT_GROUP = 'auto-complete-input-group'; + const CLASS_NAME_LABEL = 'label'; + const CLASS_NAME_OPTGROUP = 'auto-complete-optgroup'; + const CLASS_NAME_OPTGROUP_LABEL = 'auto-complete-optgroup-label'; + const CLASS_NAME_OPTION = 'auto-complete-option'; + const CLASS_NAME_OPTIONS = 'auto-complete-options'; + const CLASS_NAME_OPTIONS_EMPTY = 'auto-complete-options-empty'; + const CLASS_NAME_SELECTED = 'selected'; + const CLASS_NAME_SHOW = 'show'; + const Default = { + allowOnlyDefinedOptions: false, + ariaCleanerLabel: 'Clear all selections', + ariaIndicatorLabel: 'Toggle dropdown', + cleaner: false, + clearSearchOnSelect: true, + container: false, + disabled: false, + highlightOptionsOnSearch: false, + indicator: true, + invalid: false, + name: null, + options: false, + optionsMaxHeight: 'auto', + placeholder: null, + required: false, + search: null, + searchNoResultsLabel: 'No results found', + showHints: false, + valid: false, + value: null + }; + const DefaultType = { + allowOnlyDefinedOptions: 'boolean', + ariaCleanerLabel: 'string', + ariaIndicatorLabel: 'string', + cleaner: 'boolean', + clearSearchOnSelect: 'boolean', + container: '(string|element|boolean)', + disabled: 'boolean', + highlightOptionsOnSearch: 'boolean', + indicator: 'boolean', + invalid: 'boolean', + name: '(string|null)', + options: '(array|null)', + optionsMaxHeight: '(number|string)', + placeholder: '(string|null)', + required: 'boolean', + search: '(array|string|null)', + searchNoResultsLabel: 'boolean|string', + showHints: 'boolean', + valid: 'boolean', + value: '(number|string|null)' + }; + + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + + class AutoComplete extends BaseComponent { + constructor(element, config) { + super(element, config); + this._indicatorElement = null; + this._inputElement = null; + this._inputHintElement = null; + this._togglerElement = null; + this._optionsElement = null; + this._menu = null; + this._selected = []; + this._options = this._getOptionsFromConfig(); + this._popper = null; + this._search = ''; + this._createAutoComplete(); + this._addEventListeners(); + Data.set(this._element, DATA_KEY, this); + } + + // Getters + + static get Default() { + return Default; + } + static get DefaultType() { + return DefaultType; + } + static get NAME() { + return NAME; + } + + // Public + + toggle() { + return this._isShown() ? this.hide() : this.show(); + } + show() { + if (this._config.disabled || this._isShown()) { + return; + } + if (!this._config.searchNoResultsLabel && this._flattenOptions().filter(option => option.label.toLowerCase().includes(this._search.toLowerCase())).length === 0) { + return; + } + EventHandler.trigger(this._element, EVENT_SHOW); + this._element.classList.add(CLASS_NAME_SHOW); + this._element.setAttribute('aria-expanded', true); + if (this._config.container) { + this._menu.style.minWidth = `${this._element.offsetWidth}px`; + this._menu.classList.add(CLASS_NAME_SHOW); + } + EventHandler.trigger(this._element, EVENT_SHOWN); + this._createPopper(); + } + hide() { + EventHandler.trigger(this._element, EVENT_HIDE); + if (this._popper) { + this._popper.destroy(); + } + + // TODO: move outside of hide method + // if (this._config.allowOnlyDefinedOptions && this._selected.length === 0) { + // this._inputElement.value = '' + // } + + this._element.classList.remove(CLASS_NAME_SHOW); + this._element.setAttribute('aria-expanded', 'false'); + if (this._config.container) { + this._menu.classList.remove(CLASS_NAME_SHOW); + } + EventHandler.trigger(this._element, EVENT_HIDDEN); + } + dispose() { + if (this._popper) { + this._popper.destroy(); + } + super.dispose(); + } + clear() { + this.deselectAll(); + this.search(''); + this._filterOptionsList(); + this._inputElement.value = ''; + } + search(label) { + this._search = label.length > 0 ? label.toLowerCase() : ''; + if (!this._isExternalSearch()) { + this._filterOptionsList(); + } + EventHandler.trigger(this._element, EVENT_INPUT, { + value: label + }); + } + update(config) { + if (config.value) { + this.deselectAll(); + } + this._config = { + ...this._config, + ...this._configAfterMerge(config) + }; + this._options = this._getOptionsFromConfig(); + this._optionsElement.innerHTML = ''; + this._createOptions(this._optionsElement, this._options); + } + deselectAll(options = this._selected) { + for (const option of options) { + if (option.disabled) { + continue; + } + if (Array.isArray(option.options)) { + this.deselectAll(option.options); + continue; + } + this._deselectOption(option.value); + this._updateSelectionCleaner(); + } + } + + // Helpers + + _flattenOptions(options = this._options, flat = []) { + for (const opt of options) { + if (opt && Array.isArray(opt.options)) { + this._flattenOptions(opt.options, flat); + continue; + } + flat.push(opt); + } + return flat; + } + _getClassNames() { + return this._element.classList.value.split(' '); + } + _highlightOption(label) { + const regex = new RegExp(this._search, 'gi'); + return label.replace(regex, string => `${string}`); + } + _isExternalSearch() { + return Array.isArray(this._config.search) && this._config.search.includes('external'); + } + _isGlobalSearch() { + return Array.isArray(this._config.search) && this._config.search.includes('global'); + } + _isVisible(element) { + const style = window.getComputedStyle(element); + return style.display !== 'none'; + } + _isShown() { + return this._element.classList.contains(CLASS_NAME_SHOW); + } + + // Private + + _addEventListeners() { + EventHandler.on(this._element, EVENT_CLICK, () => { + if (!this._config.disabled) { + this.show(); + } + }); + EventHandler.on(this._element, EVENT_KEYDOWN, event => { + if (event.key === ESCAPE_KEY) { + this.hide(); + if (this._config.allowOnlyDefinedOptions && this._selected.length === 0) { + this.search(''); + this._inputElement.value = ''; + } + return; + } + if (this._isGlobalSearch() && (event.key.length === 1 || event.key === BACKSPACE_KEY || event.key === DELETE_KEY)) { + this._inputElement.focus(); + } + }); + EventHandler.on(this._menu, EVENT_KEYDOWN, event => { + if (this._isGlobalSearch() && (event.key.length === 1 || event.key === BACKSPACE_KEY || event.key === DELETE_KEY)) { + this._inputElement.focus(); + } + }); + EventHandler.on(this._togglerElement, EVENT_KEYDOWN, event => { + if (!this._isShown() && (event.key === ENTER_KEY || event.key === ARROW_DOWN_KEY)) { + event.preventDefault(); + this.show(); + return; + } + if (this._isShown() && event.key === ARROW_DOWN_KEY) { + event.preventDefault(); + this._selectMenuItem(event); + } + }); + EventHandler.on(this._indicatorElement, EVENT_CLICK, event => { + event.preventDefault(); + event.stopPropagation(); + this.toggle(); + }); + EventHandler.on(this._inputElement, EVENT_KEYUP, event => { + if (event.key.length === 1 || event.key === BACKSPACE_KEY || event.key === DELETE_KEY) { + const { + value + } = event.target; + this.deselectAll(); + this.search(value); + if (this._config.showHints) { + const options = value ? this._flattenOptions().filter(option => option.label.toLowerCase().startsWith(value.toLowerCase())) : []; + this._inputHintElement.value = options.length > 0 ? `${value}${options[0].label.slice(value.length)}` : ''; + } + } + }); + EventHandler.on(this._inputElement, EVENT_KEYDOWN, event => { + if (!this._isShown() && event.key !== TAB_KEY) { + this.show(); + } + if (event.key === ARROW_DOWN_KEY && this._inputElement.value.length === this._inputElement.selectionStart) { + this._selectMenuItem(event); + return; + } + if (event.key === TAB_KEY && this._config.showHints && this._inputElement.value.length > 0) { + if (this._inputHintElement.value) { + event.preventDefault(); + event.stopPropagation(); + } + const options = this._flattenOptions().filter(option => option.label.toLowerCase().startsWith(this._inputElement.value.toLowerCase())); + if (options.length > 0) { + this._selectOption(options[0]); + } + } + if (event.key === ENTER_KEY) { + event.preventDefault(); + event.stopPropagation(); + if (this._inputElement.value.length === 0) { + return; + } + const options = this._flattenOptions().filter(option => option.label.toLowerCase() === this._inputElement.value.toLowerCase()); + if (options.length > 0) { + this._selectOption(options[0]); + } + if (options.length === 0 && !this._config.allowOnlyDefinedOptions) { + EventHandler.trigger(this._element, EVENT_CHANGED, { + value: this._inputElement.value + }); + this.hide(); + if (this._config.clearSearchOnSelect) { + this.search(''); + } + } + } + }); + EventHandler.on(this._optionsElement, EVENT_CLICK, event => { + event.preventDefault(); + event.stopPropagation(); + this._onOptionsClick(event.target); + }); + EventHandler.on(this._selectionCleanerElement, EVENT_CLICK, event => { + if (!this._config.disabled) { + event.preventDefault(); + event.stopPropagation(); + this.clear(); + } + }); + EventHandler.on(this._optionsElement, EVENT_KEYDOWN, event => { + if (event.key === ENTER_KEY) { + this._onOptionsClick(event.target); + } + if ([ARROW_UP_KEY, ARROW_DOWN_KEY].includes(event.key)) { + event.preventDefault(); + this._selectMenuItem(event); + } + }); + } + _getOptionsFromConfig(options = this._config.options) { + if (!options || !Array.isArray(options)) { + return []; + } + const _options = []; + for (const option of options) { + var _option$value; + if (option.options && Array.isArray(option.options)) { + _options.push({ + label: option.label, + options: this._getOptionsFromConfig(option.options) + }); + continue; + } + const label = typeof option === 'string' ? option : option.label; + const value = (_option$value = option.value) != null ? _option$value : typeof option === 'string' ? option : option.label; + const isSelected = option.selected || this._config.value && this._config.value === value; + _options.push({ + label, + value, + ...(isSelected && { + selected: true + }), + ...(option.disabled && { + disabled: true + }) + }); + if (isSelected) { + this._selected.push({ + label: option.label, + value: String(option.label) + }); + } + } + return _options; + } + _createAutoComplete() { + this._element.classList.add(CLASS_NAME_AUTO_COMPLETE); + this._element.classList.toggle('is-invalid', this._config.invalid); + this._element.classList.toggle('is-valid', this._config.valid); + this._element.setAttribute('aria-expanded', 'false'); + if (this._config.disabled) { + this._element.classList.add(CLASS_NAME_DISABLED); + } + for (const className of this._getClassNames()) { + this._element.classList.add(className); + } + this._createSelection(); + this._createButtons(); + this._createOptionsContainer(); + this._updateOptionsList(); + } + _createSelection() { + var _this$_config$placeho; + const togglerEl = document.createElement('div'); + togglerEl.classList.add(CLASS_NAME_INPUT_GROUP); + this._togglerElement = togglerEl; + if (!this._config.search && !this._config.disabled) { + togglerEl.tabIndex = -1; + } + if (!this._config.disabled && this._config.showHints) { + const inputHintEl = document.createElement('input'); + inputHintEl.classList.add('form-control', 'auto-complete-selection', 'auto-complete-selection-hint'); + inputHintEl.setAttribute('name', this._config.name || index_js.getUID(`${this.constructor.NAME}-hint`).toString()); + inputHintEl.autocomplete = 'off'; + inputHintEl.readOnly = true; + inputHintEl.tabIndex = -1; + inputHintEl.setAttribute('aria-hidden', true); + togglerEl.append(inputHintEl); + this._inputHintElement = inputHintEl; + } + const inputEl = document.createElement('input'); + inputEl.classList.add('form-control', 'auto-complete-selection'); + inputEl.setAttribute('name', this._config.name || index_js.getUID(`${this.constructor.NAME}`).toString()); + inputEl.autocomplete = 'off'; + inputEl.placeholder = (_this$_config$placeho = this._config.placeholder) != null ? _this$_config$placeho : ''; + inputEl.role = 'combobox'; + inputEl.setAttribute('aria-autocomplete', 'list'); + inputEl.setAttribute('aria-haspopup', 'listbox'); + if (this._config.disabled) { + inputEl.setAttribute('disabled', true); + inputEl.tabIndex = -1; + } + if (this._config.required) { + inputEl.setAttribute('required', true); + } + togglerEl.append(inputEl); + this._inputElement = inputEl; + this._element.append(togglerEl); + } + _createButtons() { + if (!this._config.cleaner && !this._config.indicator) { + return; + } + const buttons = document.createElement('div'); + buttons.classList.add('auto-complete-buttons'); + if (!this._config.disabled && this._config.cleaner) { + const cleaner = document.createElement('button'); + cleaner.type = 'button'; + cleaner.classList.add(CLASS_NAME_CLEANER); + cleaner.style.display = 'none'; + cleaner.setAttribute('aria-label', this._config.ariaCleanerLabel); + buttons.append(cleaner); + this._selectionCleanerElement = cleaner; + } + if (this._config.indicator) { + const indicator = document.createElement('button'); + indicator.type = 'button'; + indicator.classList.add('auto-complete-indicator'); + indicator.setAttribute('aria-label', this._config.ariaIndicatorLabel); + if (this._config.disabled) { + indicator.tabIndex = -1; + } + buttons.append(indicator); + this._indicatorElement = indicator; + this._indicatorElement = indicator; + } + this._togglerElement.append(buttons); + this._updateSelectionCleaner(); + } + _createPopper() { + if (typeof Popper__namespace === 'undefined') { + throw new TypeError('CoreUI\'s Auto Complete component require Popper (https://popper.js.org)'); + } + const popperConfig = { + modifiers: [{ + name: 'preventOverflow', + options: { + boundary: 'clippingParents' + } + }, { + name: 'offset', + options: { + offset: [0, 2] + } + }], + placement: index_js.isRTL() ? 'bottom-end' : 'bottom-start' + }; + this._popper = Popper__namespace.createPopper(this._togglerElement, this._menu, popperConfig); + } + _createOptionsContainer() { + const dropdownDiv = document.createElement('div'); + dropdownDiv.classList.add(CLASS_NAME_AUTO_COMPLETE_DROPDOWN); + const optionsDiv = document.createElement('div'); + optionsDiv.classList.add(CLASS_NAME_OPTIONS); + optionsDiv.setAttribute('role', 'listbox'); + if (this._config.optionsMaxHeight !== 'auto') { + optionsDiv.style.maxHeight = `${this._config.optionsMaxHeight}px`; + optionsDiv.style.overflow = 'auto'; + } + dropdownDiv.append(optionsDiv); + const { + container + } = this._config; + if (container) { + container.append(dropdownDiv); + } else { + this._element.append(dropdownDiv); + } + this._createOptions(optionsDiv, this._options); + this._optionsElement = optionsDiv; + this._menu = dropdownDiv; + } + _createOptions(parentElement, options) { + for (const option of options) { + if (Array.isArray(option.options)) { + const optgroup = document.createElement('div'); + optgroup.classList.add(CLASS_NAME_OPTGROUP); + optgroup.setAttribute('role', 'group'); + const optgrouplabel = document.createElement('div'); + optgrouplabel.textContent = option.label; + optgrouplabel.classList.add(CLASS_NAME_OPTGROUP_LABEL); + optgroup.append(optgrouplabel); + this._createOptions(optgroup, option.options); + parentElement.append(optgroup); + return; + } + const optionDiv = document.createElement('div'); + optionDiv.classList.add(CLASS_NAME_OPTION); + if (option.disabled) { + optionDiv.classList.add(CLASS_NAME_DISABLED); + optionDiv.setAttribute('aria-disabled', 'true'); + } + optionDiv.dataset.value = option.value; + optionDiv.tabIndex = 0; + if (this._isExternalSearch() && this._config.highlightOptionsOnSearch && this._search) { + optionDiv.innerHTML = this._highlightOption(option.label); + } else { + optionDiv.textContent = option.label; + } + parentElement.append(optionDiv); + } + } + _onOptionsClick(element) { + if (!element.classList.contains(CLASS_NAME_OPTION) || element.classList.contains(CLASS_NAME_LABEL)) { + return; + } + const value = String(element.dataset.value); + const foundOption = this._findOptionByValue(value); + if (foundOption) { + this._selectOption(foundOption); + } + } + _findOptionByValue(value, options = this._options) { + for (const option of options) { + if (option.value === value) { + return option; + } + if (option.options && Array.isArray(option.options)) { + const found = this._findOptionByValue(value, option.options); + if (found) { + return found; + } + } + } + return null; + } + _selectOption(option) { + this.deselectAll(); + if (this._selected.filter(selectedOption => selectedOption.value === option.value).length === 0) { + this._selected.push(option); + } + const foundOption = SelectorEngine.findOne(`[data-value="${option.value}"]`, this._optionsElement); + if (foundOption) { + foundOption.classList.add(CLASS_NAME_SELECTED); + foundOption.setAttribute('aria-selected', true); + } + EventHandler.trigger(this._element, EVENT_CHANGED, { + value: option + }); + this._inputElement.value = option.label; + if (this._config.showHints) { + this._inputHintElement.value = ''; + } + this.hide(); + if (this._config.clearSearchOnSelect) { + this.search(''); + } + this._inputElement.focus(); + this._updateSelectionCleaner(); + } + _deselectOption(value) { + this._selected = this._selected.filter(option => option.value !== String(value)); + const option = SelectorEngine.findOne(`[data-value="${value}"]`, this._optionsElement); + if (option) { + option.classList.remove(CLASS_NAME_SELECTED); + option.setAttribute('aria-selected', false); + } + EventHandler.trigger(this._element, EVENT_CHANGED, { + value: this._selected + }); + } + _updateSelectionCleaner() { + if (!this._config.cleaner || this._selectionCleanerElement === null) { + return; + } + if (this._selected.length > 0) { + this._selectionCleanerElement.style.removeProperty('display'); + return; + } + this._selectionCleanerElement.style.display = 'none'; + } + _updateOptionsList(options = this._options) { + for (const option of options) { + if (Array.isArray(option.options)) { + this._updateOptionsList(option.options); + continue; + } + if (option.selected) { + this._selectOption(option); + } + } + } + _filterOptionsList() { + const options = SelectorEngine.find(SELECTOR_OPTION, this._menu); + let visibleOptions = 0; + for (const option of options) { + // eslint-disable-next-line unicorn/prefer-includes + if (option.textContent.toLowerCase().indexOf(this._search) === -1) { + option.style.display = 'none'; + } else { + if (this._config.highlightOptionsOnSearch) { + option.innerHTML = this._highlightOption(option.textContent); + } + option.style.removeProperty('display'); + visibleOptions++; + } + const optgroup = option.closest(SELECTOR_OPTGROUP); + if (optgroup) { + // eslint-disable-next-line unicorn/prefer-array-some + if (SelectorEngine.children(optgroup, SELECTOR_OPTION).filter(element => this._isVisible(element)).length > 0) { + optgroup.style.removeProperty('display'); + } else { + optgroup.style.display = 'none'; + } + } + } + if (visibleOptions > 0) { + if (SelectorEngine.findOne(SELECTOR_OPTIONS_EMPTY, this._menu)) { + SelectorEngine.findOne(SELECTOR_OPTIONS_EMPTY, this._menu).remove(); + } + return; + } + if (visibleOptions === 0) { + if (this._config.searchNoResultsLabel) { + const placeholder = document.createElement('div'); + placeholder.classList.add(CLASS_NAME_OPTIONS_EMPTY); + placeholder.innerHTML = this._config.searchNoResultsLabel; + if (!SelectorEngine.findOne(SELECTOR_OPTIONS_EMPTY, this._menu)) { + SelectorEngine.findOne(SELECTOR_OPTIONS, this._menu).append(placeholder); + } + return; + } + this.hide(); + } + } + _selectMenuItem({ + key, + target + }) { + const items = SelectorEngine.find(SELECTOR_VISIBLE_ITEMS, this._menu).filter(element => index_js.isVisible(element)); + if (!items.length) { + return; + } + + // if target isn't included in items (e.g. when expanding the dropdown) + // allow cycling to get the last item in case key equals ARROW_UP_KEY + index_js.getNextActiveElement(items, target, key === ARROW_DOWN_KEY, !items.includes(target)).focus(); + } + _configAfterMerge(config) { + if (config.container === true) { + config.container = document.body; + } + if (typeof config.container === 'object' || typeof config.container === 'string') { + config.container = index_js.getElement(config.container); + } + if (typeof config.options === 'string') { + config.options = config.options.split(/,\s*/).map(String); + } + if (typeof config.search === 'string') { + config.search = config.search.split(/,\s*/).map(String); + } + return config; + } + + // Static + + static AutoCompleteInterface(element, config) { + const data = AutoComplete.getOrCreateInstance(element, config); + if (typeof config === 'string') { + if (typeof data[config] === 'undefined') { + throw new TypeError(`No method named "${config}"`); + } + data[config](); + } + } + static jQueryInterface(config) { + return this.each(function () { + AutoComplete.AutoCompleteInterface(this, config); + }); + } + static clearMenus(event) { + if (event && (event.button === RIGHT_MOUSE_BUTTON || event.type === 'keyup' && event.key !== TAB_KEY)) { + return; + } + const selects = SelectorEngine.find(SELECTOR_AUTO_COMPLETE); + for (let i = 0, len = selects.length; i < len; i++) { + const context = Data.get(selects[i], DATA_KEY); + ({ + relatedTarget: selects[i] + }); + if (event && event.type === 'click') ; + if (!context) { + continue; + } + if (!context._element.classList.contains(CLASS_NAME_SHOW)) { + continue; + } + if (context._element.contains(event.target)) { + continue; + } + context.hide(); + context.search(''); + if (context._config.allowOnlyDefinedOptions && context._selected.length === 0) { + context._inputElement.value = ''; + } + EventHandler.trigger(context._element, EVENT_HIDDEN); + } + } + } + + /** + * Data API implementation + */ + + EventHandler.on(window, EVENT_LOAD_DATA_API, () => { + for (const ac of SelectorEngine.find(SELECTOR_AUTO_COMPLETE)) { + AutoComplete.AutoCompleteInterface(ac); + } + }); + EventHandler.on(document, EVENT_CLICK_DATA_API, AutoComplete.clearMenus); + EventHandler.on(document, EVENT_KEYUP_DATA_API, AutoComplete.clearMenus); + + /** + * jQuery + */ + + index_js.defineJQueryPlugin(AutoComplete); + + return AutoComplete; + +})); +//# sourceMappingURL=auto-complete.js.map diff --git a/js/dist/auto-complete.js.map b/js/dist/auto-complete.js.map new file mode 100644 index 000000000..29f45bf1c --- /dev/null +++ b/js/dist/auto-complete.js.map @@ -0,0 +1 @@ +{"version":3,"file":"auto-complete.js","sources":["../src/auto-complete.js"],"sourcesContent":["/**\n * --------------------------------------------------------------------------\n * CoreUI PRO auto-complete.js\n * License (https://coreui.io/pro/license/)\n * --------------------------------------------------------------------------\n */\n\nimport * as Popper from '@popperjs/core'\nimport BaseComponent from './base-component.js'\nimport Data from './dom/data.js'\nimport EventHandler from './dom/event-handler.js'\nimport SelectorEngine from './dom/selector-engine.js'\nimport {\n defineJQueryPlugin,\n getNextActiveElement,\n getElement,\n getUID,\n isVisible,\n isRTL\n} from './util/index.js'\n\n/**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\nconst NAME = 'auto-complete'\nconst DATA_KEY = 'coreui.auto-complete'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst DATA_API_KEY = '.data-api'\n\nconst ARROW_UP_KEY = 'ArrowUp'\nconst ARROW_DOWN_KEY = 'ArrowDown'\nconst BACKSPACE_KEY = 'Backspace'\nconst DELETE_KEY = 'Delete'\nconst ENTER_KEY = 'Enter'\nconst ESCAPE_KEY = 'Escape'\nconst TAB_KEY = 'Tab'\nconst RIGHT_MOUSE_BUTTON = 2 // MouseEvent.button value for the secondary button, usually the right button\n\nconst SELECTOR_OPTGROUP = '.auto-complete-optgroup'\nconst SELECTOR_OPTION = '.auto-complete-option'\nconst SELECTOR_OPTIONS = '.auto-complete-options'\nconst SELECTOR_OPTIONS_EMPTY = '.auto-complete-options-empty'\nconst SELECTOR_AUTO_COMPLETE = '.auto-complete'\nconst SELECTOR_VISIBLE_ITEMS = '.auto-complete-options .auto-complete-option:not(.disabled):not(:disabled)'\n\nconst EVENT_CHANGED = `changed${EVENT_KEY}`\nconst EVENT_CLICK = `click${EVENT_KEY}`\nconst EVENT_HIDE = `hide${EVENT_KEY}`\nconst EVENT_HIDDEN = `hidden${EVENT_KEY}`\nconst EVENT_INPUT = `input${EVENT_KEY}`\nconst EVENT_KEYDOWN = `keydown${EVENT_KEY}`\nconst EVENT_KEYUP = `keyup${EVENT_KEY}`\nconst EVENT_SHOW = `show${EVENT_KEY}`\nconst EVENT_SHOWN = `shown${EVENT_KEY}`\nconst EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`\nconst EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY}${DATA_API_KEY}`\nconst EVENT_LOAD_DATA_API = `load${EVENT_KEY}${DATA_API_KEY}`\n\nconst CLASS_NAME_AUTO_COMPLETE = 'auto-complete'\nconst CLASS_NAME_AUTO_COMPLETE_DROPDOWN = 'auto-complete-dropdown'\nconst CLASS_NAME_CLEANER = 'auto-complete-cleaner'\nconst CLASS_NAME_DISABLED = 'disabled'\nconst CLASS_NAME_INPUT_GROUP = 'auto-complete-input-group'\nconst CLASS_NAME_LABEL = 'label'\nconst CLASS_NAME_OPTGROUP = 'auto-complete-optgroup'\nconst CLASS_NAME_OPTGROUP_LABEL = 'auto-complete-optgroup-label'\nconst CLASS_NAME_OPTION = 'auto-complete-option'\nconst CLASS_NAME_OPTIONS = 'auto-complete-options'\nconst CLASS_NAME_OPTIONS_EMPTY = 'auto-complete-options-empty'\nconst CLASS_NAME_SELECTED = 'selected'\nconst CLASS_NAME_SHOW = 'show'\n\nconst Default = {\n allowOnlyDefinedOptions: false,\n ariaCleanerLabel: 'Clear all selections',\n ariaIndicatorLabel: 'Toggle dropdown',\n cleaner: false,\n clearSearchOnSelect: true,\n container: false,\n disabled: false,\n highlightOptionsOnSearch: false,\n indicator: true,\n invalid: false,\n name: null,\n options: false,\n optionsMaxHeight: 'auto',\n placeholder: null,\n required: false,\n search: null,\n searchNoResultsLabel: 'No results found',\n showHints: false,\n valid: false,\n value: null\n}\n\nconst DefaultType = {\n allowOnlyDefinedOptions: 'boolean',\n ariaCleanerLabel: 'string',\n ariaIndicatorLabel: 'string',\n cleaner: 'boolean',\n clearSearchOnSelect: 'boolean',\n container: '(string|element|boolean)',\n disabled: 'boolean',\n highlightOptionsOnSearch: 'boolean',\n indicator: 'boolean',\n invalid: 'boolean',\n name: '(string|null)',\n options: '(array|null)',\n optionsMaxHeight: '(number|string)',\n placeholder: '(string|null)',\n required: 'boolean',\n search: '(array|string|null)',\n searchNoResultsLabel: ('boolean|string'),\n showHints: 'boolean',\n valid: 'boolean',\n value: '(number|string|null)'\n}\n\n/**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\nclass AutoComplete extends BaseComponent {\n constructor(element, config) {\n super(element, config)\n\n this._indicatorElement = null\n this._inputElement = null\n this._inputHintElement = null\n this._togglerElement = null\n this._optionsElement = null\n\n this._menu = null\n this._selected = []\n this._options = this._getOptionsFromConfig()\n this._popper = null\n this._search = ''\n\n this._createAutoComplete()\n this._addEventListeners()\n Data.set(this._element, DATA_KEY, this)\n }\n\n // Getters\n\n static get Default() {\n return Default\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n static get NAME() {\n return NAME\n }\n\n // Public\n\n toggle() {\n return this._isShown() ? this.hide() : this.show()\n }\n\n show() {\n if (this._config.disabled || this._isShown()) {\n return\n }\n\n if (\n !this._config.searchNoResultsLabel &&\n this._flattenOptions().filter(option => option.label.toLowerCase().includes(this._search.toLowerCase())).length === 0) {\n return\n }\n\n EventHandler.trigger(this._element, EVENT_SHOW)\n this._element.classList.add(CLASS_NAME_SHOW)\n this._element.setAttribute('aria-expanded', true)\n\n if (this._config.container) {\n this._menu.style.minWidth = `${this._element.offsetWidth}px`\n this._menu.classList.add(CLASS_NAME_SHOW)\n }\n\n EventHandler.trigger(this._element, EVENT_SHOWN)\n\n this._createPopper()\n }\n\n hide() {\n EventHandler.trigger(this._element, EVENT_HIDE)\n\n if (this._popper) {\n this._popper.destroy()\n }\n\n // TODO: move outside of hide method\n // if (this._config.allowOnlyDefinedOptions && this._selected.length === 0) {\n // this._inputElement.value = ''\n // }\n\n this._element.classList.remove(CLASS_NAME_SHOW)\n this._element.setAttribute('aria-expanded', 'false')\n\n if (this._config.container) {\n this._menu.classList.remove(CLASS_NAME_SHOW)\n }\n\n EventHandler.trigger(this._element, EVENT_HIDDEN)\n }\n\n dispose() {\n if (this._popper) {\n this._popper.destroy()\n }\n\n super.dispose()\n }\n\n clear() {\n this.deselectAll()\n this.search('')\n this._filterOptionsList()\n this._inputElement.value = ''\n }\n\n search(label) {\n this._search = label.length > 0 ? label.toLowerCase() : ''\n if (!this._isExternalSearch()) {\n this._filterOptionsList()\n }\n\n EventHandler.trigger(this._element, EVENT_INPUT, {\n value: label\n })\n }\n\n update(config) {\n if (config.value) {\n this.deselectAll()\n }\n\n this._config = { ...this._config, ...this._configAfterMerge(config) }\n this._options = this._getOptionsFromConfig()\n this._optionsElement.innerHTML = ''\n this._createOptions(this._optionsElement, this._options)\n }\n\n deselectAll(options = this._selected) {\n for (const option of options) {\n if (option.disabled) {\n continue\n }\n\n if (Array.isArray(option.options)) {\n this.deselectAll(option.options)\n continue\n }\n\n this._deselectOption(option.value)\n this._updateSelectionCleaner()\n }\n }\n\n // Helpers\n\n _flattenOptions(options = this._options, flat = []) {\n for (const opt of options) {\n if (opt && Array.isArray(opt.options)) {\n this._flattenOptions(opt.options, flat)\n continue\n }\n\n flat.push(opt)\n }\n\n return flat\n }\n\n _getClassNames() {\n return this._element.classList.value.split(' ')\n }\n\n _highlightOption(label) {\n const regex = new RegExp(this._search, 'gi')\n return label.replace(regex, string => `${string}`)\n }\n\n _isExternalSearch() {\n return Array.isArray(this._config.search) && this._config.search.includes('external')\n }\n\n _isGlobalSearch() {\n return Array.isArray(this._config.search) && this._config.search.includes('global')\n }\n\n _isVisible(element) {\n const style = window.getComputedStyle(element)\n return (style.display !== 'none')\n }\n\n _isShown() {\n return this._element.classList.contains(CLASS_NAME_SHOW)\n }\n\n // Private\n\n _addEventListeners() {\n EventHandler.on(this._element, EVENT_CLICK, () => {\n if (!this._config.disabled) {\n this.show()\n }\n })\n\n EventHandler.on(this._element, EVENT_KEYDOWN, event => {\n if (event.key === ESCAPE_KEY) {\n this.hide()\n if (this._config.allowOnlyDefinedOptions && this._selected.length === 0) {\n this.search('')\n this._inputElement.value = ''\n }\n\n return\n }\n\n if (this._isGlobalSearch() && (event.key.length === 1 || event.key === BACKSPACE_KEY || event.key === DELETE_KEY)) {\n this._inputElement.focus()\n }\n })\n\n EventHandler.on(this._menu, EVENT_KEYDOWN, event => {\n if (this._isGlobalSearch() && (event.key.length === 1 || event.key === BACKSPACE_KEY || event.key === DELETE_KEY)) {\n this._inputElement.focus()\n }\n })\n\n EventHandler.on(this._togglerElement, EVENT_KEYDOWN, event => {\n if (!this._isShown() && (event.key === ENTER_KEY || event.key === ARROW_DOWN_KEY)) {\n event.preventDefault()\n this.show()\n return\n }\n\n if (this._isShown() && event.key === ARROW_DOWN_KEY) {\n event.preventDefault()\n this._selectMenuItem(event)\n }\n })\n\n EventHandler.on(this._indicatorElement, EVENT_CLICK, event => {\n event.preventDefault()\n event.stopPropagation()\n this.toggle()\n })\n\n EventHandler.on(this._inputElement, EVENT_KEYUP, event => {\n if (event.key.length === 1 || event.key === BACKSPACE_KEY || event.key === DELETE_KEY) {\n const { value } = event.target\n this.deselectAll()\n this.search(value)\n if (this._config.showHints) {\n const options = value ?\n this._flattenOptions().filter(option => option.label.toLowerCase().startsWith(value.toLowerCase())) :\n []\n this._inputHintElement.value = options.length > 0 ? `${value}${options[0].label.slice(value.length)}` : ''\n }\n }\n })\n\n EventHandler.on(this._inputElement, EVENT_KEYDOWN, event => {\n if (!this._isShown() && event.key !== TAB_KEY) {\n this.show()\n }\n\n if (event.key === ARROW_DOWN_KEY && this._inputElement.value.length === this._inputElement.selectionStart) {\n this._selectMenuItem(event)\n return\n }\n\n if (event.key === TAB_KEY && this._config.showHints && this._inputElement.value.length > 0) {\n if (this._inputHintElement.value) {\n event.preventDefault()\n event.stopPropagation()\n }\n\n const options = this._flattenOptions().filter(option => option.label.toLowerCase().startsWith(this._inputElement.value.toLowerCase()))\n\n if (options.length > 0) {\n this._selectOption(options[0])\n }\n }\n\n if (event.key === ENTER_KEY) {\n event.preventDefault()\n event.stopPropagation()\n\n if (this._inputElement.value.length === 0) {\n return\n }\n\n const options = this._flattenOptions().filter(option => option.label.toLowerCase() === this._inputElement.value.toLowerCase())\n\n if (options.length > 0) {\n this._selectOption(options[0])\n }\n\n if (options.length === 0 && !this._config.allowOnlyDefinedOptions) {\n EventHandler.trigger(this._element, EVENT_CHANGED, {\n value: this._inputElement.value\n })\n\n this.hide()\n\n if (this._config.clearSearchOnSelect) {\n this.search('')\n }\n }\n }\n })\n\n EventHandler.on(this._optionsElement, EVENT_CLICK, event => {\n event.preventDefault()\n event.stopPropagation()\n this._onOptionsClick(event.target)\n })\n\n EventHandler.on(this._selectionCleanerElement, EVENT_CLICK, event => {\n if (!this._config.disabled) {\n event.preventDefault()\n event.stopPropagation()\n this.clear()\n }\n })\n\n EventHandler.on(this._optionsElement, EVENT_KEYDOWN, event => {\n if (event.key === ENTER_KEY) {\n this._onOptionsClick(event.target)\n }\n\n if ([ARROW_UP_KEY, ARROW_DOWN_KEY].includes(event.key)) {\n event.preventDefault()\n this._selectMenuItem(event)\n }\n })\n }\n\n _getOptionsFromConfig(options = this._config.options) {\n if (!options || !Array.isArray(options)) {\n return []\n }\n\n const _options = []\n for (const option of options) {\n if (option.options && Array.isArray(option.options)) {\n _options.push({\n label: option.label,\n options: this._getOptionsFromConfig(option.options)\n })\n continue\n }\n\n const label = typeof option === 'string' ? option : option.label\n const value = option.value ?? (typeof option === 'string' ? option : option.label)\n const isSelected = option.selected || (this._config.value && this._config.value === value)\n\n _options.push({\n label,\n value,\n ...isSelected && { selected: true },\n ...option.disabled && { disabled: true }\n })\n\n if (isSelected) {\n this._selected.push({\n label: option.label,\n value: String(option.label)\n })\n }\n }\n\n return _options\n }\n\n _createAutoComplete() {\n this._element.classList.add(CLASS_NAME_AUTO_COMPLETE)\n this._element.classList.toggle('is-invalid', this._config.invalid)\n this._element.classList.toggle('is-valid', this._config.valid)\n this._element.setAttribute('aria-expanded', 'false')\n\n if (this._config.disabled) {\n this._element.classList.add(CLASS_NAME_DISABLED)\n }\n\n for (const className of this._getClassNames()) {\n this._element.classList.add(className)\n }\n\n this._createSelection()\n this._createButtons()\n this._createOptionsContainer()\n this._updateOptionsList()\n }\n\n _createSelection() {\n const togglerEl = document.createElement('div')\n togglerEl.classList.add(CLASS_NAME_INPUT_GROUP)\n this._togglerElement = togglerEl\n\n if (!this._config.search && !this._config.disabled) {\n togglerEl.tabIndex = -1\n }\n\n if (!this._config.disabled && this._config.showHints) {\n const inputHintEl = document.createElement('input')\n inputHintEl.classList.add('form-control', 'auto-complete-selection', 'auto-complete-selection-hint')\n inputHintEl.setAttribute('name', (this._config.name || getUID(`${this.constructor.NAME}-hint`).toString()))\n inputHintEl.autocomplete = 'off'\n inputHintEl.readOnly = true\n inputHintEl.tabIndex = -1\n inputHintEl.setAttribute('aria-hidden', true)\n\n togglerEl.append(inputHintEl)\n this._inputHintElement = inputHintEl\n }\n\n const inputEl = document.createElement('input')\n inputEl.classList.add('form-control', 'auto-complete-selection')\n inputEl.setAttribute('name', (this._config.name || getUID(`${this.constructor.NAME}`).toString()))\n inputEl.autocomplete = 'off'\n inputEl.placeholder = this._config.placeholder ?? ''\n inputEl.role = 'combobox'\n inputEl.setAttribute('aria-autocomplete', 'list')\n inputEl.setAttribute('aria-haspopup', 'listbox')\n\n if (this._config.disabled) {\n inputEl.setAttribute('disabled', true)\n inputEl.tabIndex = -1\n }\n\n if (this._config.required) {\n inputEl.setAttribute('required', true)\n }\n\n togglerEl.append(inputEl)\n this._inputElement = inputEl\n\n this._element.append(togglerEl)\n }\n\n _createButtons() {\n if (!this._config.cleaner && !this._config.indicator) {\n return\n }\n\n const buttons = document.createElement('div')\n buttons.classList.add('auto-complete-buttons')\n\n if (!this._config.disabled && this._config.cleaner) {\n const cleaner = document.createElement('button')\n cleaner.type = 'button'\n cleaner.classList.add(CLASS_NAME_CLEANER)\n cleaner.style.display = 'none'\n cleaner.setAttribute('aria-label', this._config.ariaCleanerLabel)\n\n buttons.append(cleaner)\n this._selectionCleanerElement = cleaner\n }\n\n if (this._config.indicator) {\n const indicator = document.createElement('button')\n indicator.type = 'button'\n indicator.classList.add('auto-complete-indicator')\n indicator.setAttribute('aria-label', this._config.ariaIndicatorLabel)\n\n if (this._config.disabled) {\n indicator.tabIndex = -1\n }\n\n buttons.append(indicator)\n this._indicatorElement = indicator\n this._indicatorElement = indicator\n }\n\n this._togglerElement.append(buttons)\n this._updateSelectionCleaner()\n }\n\n _createPopper() {\n if (typeof Popper === 'undefined') {\n throw new TypeError('CoreUI\\'s Auto Complete component require Popper (https://popper.js.org)')\n }\n\n const popperConfig = {\n modifiers: [{\n name: 'preventOverflow',\n options: {\n boundary: 'clippingParents'\n }\n },\n {\n name: 'offset',\n options: {\n offset: [0, 2]\n }\n }],\n placement: isRTL() ? 'bottom-end' : 'bottom-start'\n }\n\n this._popper = Popper.createPopper(this._togglerElement, this._menu, popperConfig)\n }\n\n _createOptionsContainer() {\n const dropdownDiv = document.createElement('div')\n dropdownDiv.classList.add(CLASS_NAME_AUTO_COMPLETE_DROPDOWN)\n\n const optionsDiv = document.createElement('div')\n optionsDiv.classList.add(CLASS_NAME_OPTIONS)\n optionsDiv.setAttribute('role', 'listbox')\n\n if (this._config.optionsMaxHeight !== 'auto') {\n optionsDiv.style.maxHeight = `${this._config.optionsMaxHeight}px`\n optionsDiv.style.overflow = 'auto'\n }\n\n dropdownDiv.append(optionsDiv)\n\n const { container } = this._config\n if (container) {\n container.append(dropdownDiv)\n } else {\n this._element.append(dropdownDiv)\n }\n\n this._createOptions(optionsDiv, this._options)\n this._optionsElement = optionsDiv\n this._menu = dropdownDiv\n }\n\n _createOptions(parentElement, options) {\n for (const option of options) {\n if (Array.isArray(option.options)) {\n const optgroup = document.createElement('div')\n optgroup.classList.add(CLASS_NAME_OPTGROUP)\n optgroup.setAttribute('role', 'group')\n\n const optgrouplabel = document.createElement('div')\n optgrouplabel.textContent = option.label\n optgrouplabel.classList.add(CLASS_NAME_OPTGROUP_LABEL)\n optgroup.append(optgrouplabel)\n\n this._createOptions(optgroup, option.options)\n parentElement.append(optgroup)\n\n return\n }\n\n const optionDiv = document.createElement('div')\n optionDiv.classList.add(CLASS_NAME_OPTION)\n\n if (option.disabled) {\n optionDiv.classList.add(CLASS_NAME_DISABLED)\n optionDiv.setAttribute('aria-disabled', 'true')\n }\n\n optionDiv.dataset.value = option.value\n optionDiv.tabIndex = 0\n if (this._isExternalSearch() && this._config.highlightOptionsOnSearch && this._search) {\n optionDiv.innerHTML = this._highlightOption(option.label)\n } else {\n optionDiv.textContent = option.label\n }\n\n parentElement.append(optionDiv)\n }\n }\n\n _onOptionsClick(element) {\n if (!element.classList.contains(CLASS_NAME_OPTION) || element.classList.contains(CLASS_NAME_LABEL)) {\n return\n }\n\n const value = String(element.dataset.value)\n const foundOption = this._findOptionByValue(value)\n\n if (foundOption) {\n this._selectOption(foundOption)\n }\n }\n\n _findOptionByValue(value, options = this._options) {\n for (const option of options) {\n if (option.value === value) {\n return option\n }\n\n if (option.options && Array.isArray(option.options)) {\n const found = this._findOptionByValue(value, option.options)\n if (found) {\n return found\n }\n }\n }\n\n return null\n }\n\n _selectOption(option) {\n this.deselectAll()\n\n if (this._selected.filter(selectedOption => selectedOption.value === option.value).length === 0) {\n this._selected.push(option)\n }\n\n const foundOption = SelectorEngine.findOne(`[data-value=\"${option.value}\"]`, this._optionsElement)\n if (foundOption) {\n foundOption.classList.add(CLASS_NAME_SELECTED)\n foundOption.setAttribute('aria-selected', true)\n }\n\n EventHandler.trigger(this._element, EVENT_CHANGED, {\n value: option\n })\n\n this._inputElement.value = option.label\n\n if (this._config.showHints) {\n this._inputHintElement.value = ''\n }\n\n this.hide()\n\n if (this._config.clearSearchOnSelect) {\n this.search('')\n }\n\n this._inputElement.focus()\n this._updateSelectionCleaner()\n }\n\n _deselectOption(value) {\n this._selected = this._selected.filter(option => option.value !== String(value))\n\n const option = SelectorEngine.findOne(`[data-value=\"${value}\"]`, this._optionsElement)\n if (option) {\n option.classList.remove(CLASS_NAME_SELECTED)\n option.setAttribute('aria-selected', false)\n }\n\n EventHandler.trigger(this._element, EVENT_CHANGED, {\n value: this._selected\n })\n }\n\n _updateSelectionCleaner() {\n if (!this._config.cleaner || this._selectionCleanerElement === null) {\n return\n }\n\n if (this._selected.length > 0) {\n this._selectionCleanerElement.style.removeProperty('display')\n return\n }\n\n this._selectionCleanerElement.style.display = 'none'\n }\n\n _updateOptionsList(options = this._options) {\n for (const option of options) {\n if (Array.isArray(option.options)) {\n this._updateOptionsList(option.options)\n continue\n }\n\n if (option.selected) {\n this._selectOption(option)\n }\n }\n }\n\n _filterOptionsList() {\n const options = SelectorEngine.find(SELECTOR_OPTION, this._menu)\n let visibleOptions = 0\n\n for (const option of options) {\n // eslint-disable-next-line unicorn/prefer-includes\n if (option.textContent.toLowerCase().indexOf(this._search) === -1) {\n option.style.display = 'none'\n } else {\n if (this._config.highlightOptionsOnSearch) {\n option.innerHTML = this._highlightOption(option.textContent)\n }\n\n option.style.removeProperty('display')\n visibleOptions++\n }\n\n const optgroup = option.closest(SELECTOR_OPTGROUP)\n if (optgroup) {\n // eslint-disable-next-line unicorn/prefer-array-some\n if (SelectorEngine.children(optgroup, SELECTOR_OPTION).filter(element => this._isVisible(element)).length > 0) {\n optgroup.style.removeProperty('display')\n } else {\n optgroup.style.display = 'none'\n }\n }\n }\n\n if (visibleOptions > 0) {\n if (SelectorEngine.findOne(SELECTOR_OPTIONS_EMPTY, this._menu)) {\n SelectorEngine.findOne(SELECTOR_OPTIONS_EMPTY, this._menu).remove()\n }\n\n return\n }\n\n if (visibleOptions === 0) {\n if (this._config.searchNoResultsLabel) {\n const placeholder = document.createElement('div')\n placeholder.classList.add(CLASS_NAME_OPTIONS_EMPTY)\n placeholder.innerHTML = this._config.searchNoResultsLabel\n\n if (!SelectorEngine.findOne(SELECTOR_OPTIONS_EMPTY, this._menu)) {\n SelectorEngine.findOne(SELECTOR_OPTIONS, this._menu).append(placeholder)\n }\n\n return\n }\n\n this.hide()\n }\n }\n\n _selectMenuItem({ key, target }) {\n const items = SelectorEngine.find(SELECTOR_VISIBLE_ITEMS, this._menu).filter(element => isVisible(element))\n\n if (!items.length) {\n return\n }\n\n // if target isn't included in items (e.g. when expanding the dropdown)\n // allow cycling to get the last item in case key equals ARROW_UP_KEY\n getNextActiveElement(items, target, key === ARROW_DOWN_KEY, !items.includes(target)).focus()\n }\n\n _configAfterMerge(config) {\n if (config.container === true) {\n config.container = document.body\n }\n\n if (typeof config.container === 'object' || typeof config.container === 'string') {\n config.container = getElement(config.container)\n }\n\n if (typeof config.options === 'string') {\n config.options = config.options.split(/,\\s*/).map(String)\n }\n\n if (typeof config.search === 'string') {\n config.search = config.search.split(/,\\s*/).map(String)\n }\n\n return config\n }\n\n // Static\n\n static AutoCompleteInterface(element, config) {\n const data = AutoComplete.getOrCreateInstance(element, config)\n\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n\n data[config]()\n }\n }\n\n static jQueryInterface(config) {\n return this.each(function () {\n AutoComplete.AutoCompleteInterface(this, config)\n })\n }\n\n static clearMenus(event) {\n if (event && (event.button === RIGHT_MOUSE_BUTTON ||\n (event.type === 'keyup' && event.key !== TAB_KEY))) {\n return\n }\n\n const selects = SelectorEngine.find(SELECTOR_AUTO_COMPLETE)\n\n for (let i = 0, len = selects.length; i < len; i++) {\n const context = Data.get(selects[i], DATA_KEY)\n const relatedTarget = {\n relatedTarget: selects[i]\n }\n\n if (event && event.type === 'click') {\n relatedTarget.clickEvent = event\n }\n\n if (!context) {\n continue\n }\n\n if (!context._element.classList.contains(CLASS_NAME_SHOW)) {\n continue\n }\n\n if (context._element.contains(event.target)) {\n continue\n }\n\n context.hide()\n context.search('')\n if (context._config.allowOnlyDefinedOptions && context._selected.length === 0) {\n context._inputElement.value = ''\n }\n\n EventHandler.trigger(context._element, EVENT_HIDDEN)\n }\n }\n}\n\n/**\n * Data API implementation\n */\n\nEventHandler.on(window, EVENT_LOAD_DATA_API, () => {\n for (const ac of SelectorEngine.find(SELECTOR_AUTO_COMPLETE)) {\n AutoComplete.AutoCompleteInterface(ac)\n }\n})\nEventHandler.on(document, EVENT_CLICK_DATA_API, AutoComplete.clearMenus)\nEventHandler.on(document, EVENT_KEYUP_DATA_API, AutoComplete.clearMenus)\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(AutoComplete)\n\nexport default AutoComplete\n"],"names":["NAME","DATA_KEY","EVENT_KEY","DATA_API_KEY","ARROW_UP_KEY","ARROW_DOWN_KEY","BACKSPACE_KEY","DELETE_KEY","ENTER_KEY","ESCAPE_KEY","TAB_KEY","RIGHT_MOUSE_BUTTON","SELECTOR_OPTGROUP","SELECTOR_OPTION","SELECTOR_OPTIONS","SELECTOR_OPTIONS_EMPTY","SELECTOR_AUTO_COMPLETE","SELECTOR_VISIBLE_ITEMS","EVENT_CHANGED","EVENT_CLICK","EVENT_HIDE","EVENT_HIDDEN","EVENT_INPUT","EVENT_KEYDOWN","EVENT_KEYUP","EVENT_SHOW","EVENT_SHOWN","EVENT_CLICK_DATA_API","EVENT_KEYUP_DATA_API","EVENT_LOAD_DATA_API","CLASS_NAME_AUTO_COMPLETE","CLASS_NAME_AUTO_COMPLETE_DROPDOWN","CLASS_NAME_CLEANER","CLASS_NAME_DISABLED","CLASS_NAME_INPUT_GROUP","CLASS_NAME_LABEL","CLASS_NAME_OPTGROUP","CLASS_NAME_OPTGROUP_LABEL","CLASS_NAME_OPTION","CLASS_NAME_OPTIONS","CLASS_NAME_OPTIONS_EMPTY","CLASS_NAME_SELECTED","CLASS_NAME_SHOW","Default","allowOnlyDefinedOptions","ariaCleanerLabel","ariaIndicatorLabel","cleaner","clearSearchOnSelect","container","disabled","highlightOptionsOnSearch","indicator","invalid","name","options","optionsMaxHeight","placeholder","required","search","searchNoResultsLabel","showHints","valid","value","DefaultType","AutoComplete","BaseComponent","constructor","element","config","_indicatorElement","_inputElement","_inputHintElement","_togglerElement","_optionsElement","_menu","_selected","_options","_getOptionsFromConfig","_popper","_search","_createAutoComplete","_addEventListeners","Data","set","_element","toggle","_isShown","hide","show","_config","_flattenOptions","filter","option","label","toLowerCase","includes","length","EventHandler","trigger","classList","add","setAttribute","style","minWidth","offsetWidth","_createPopper","destroy","remove","dispose","clear","deselectAll","_filterOptionsList","_isExternalSearch","update","_configAfterMerge","innerHTML","_createOptions","Array","isArray","_deselectOption","_updateSelectionCleaner","flat","opt","push","_getClassNames","split","_highlightOption","regex","RegExp","replace","string","_isGlobalSearch","_isVisible","window","getComputedStyle","display","contains","on","event","key","focus","preventDefault","_selectMenuItem","stopPropagation","target","startsWith","slice","selectionStart","_selectOption","_onOptionsClick","_selectionCleanerElement","_option$value","isSelected","selected","String","className","_createSelection","_createButtons","_createOptionsContainer","_updateOptionsList","_this$_config$placeho","togglerEl","document","createElement","tabIndex","inputHintEl","getUID","toString","autocomplete","readOnly","append","inputEl","role","buttons","type","Popper","TypeError","popperConfig","modifiers","boundary","offset","placement","isRTL","createPopper","dropdownDiv","optionsDiv","maxHeight","overflow","parentElement","optgroup","optgrouplabel","textContent","optionDiv","dataset","foundOption","_findOptionByValue","found","selectedOption","SelectorEngine","findOne","removeProperty","find","visibleOptions","indexOf","closest","children","items","isVisible","getNextActiveElement","body","getElement","map","AutoCompleteInterface","data","getOrCreateInstance","jQueryInterface","each","clearMenus","button","selects","i","len","context","get","relatedTarget","ac","defineJQueryPlugin"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAAA;EACA;EACA;EACA;EACA;EACA;;;EAgBA;EACA;EACA;EACA;EACA;;EAEA,MAAMA,IAAI,GAAG,eAAe;EAC5B,MAAMC,QAAQ,GAAG,sBAAsB;EACvC,MAAMC,SAAS,GAAG,CAAA,CAAA,EAAID,QAAQ,CAAA,CAAE;EAChC,MAAME,YAAY,GAAG,WAAW;EAEhC,MAAMC,YAAY,GAAG,SAAS;EAC9B,MAAMC,cAAc,GAAG,WAAW;EAClC,MAAMC,aAAa,GAAG,WAAW;EACjC,MAAMC,UAAU,GAAG,QAAQ;EAC3B,MAAMC,SAAS,GAAG,OAAO;EACzB,MAAMC,UAAU,GAAG,QAAQ;EAC3B,MAAMC,OAAO,GAAG,KAAK;EACrB,MAAMC,kBAAkB,GAAG,CAAC,CAAA;;EAE5B,MAAMC,iBAAiB,GAAG,yBAAyB;EACnD,MAAMC,eAAe,GAAG,uBAAuB;EAC/C,MAAMC,gBAAgB,GAAG,wBAAwB;EACjD,MAAMC,sBAAsB,GAAG,8BAA8B;EAC7D,MAAMC,sBAAsB,GAAG,gBAAgB;EAC/C,MAAMC,sBAAsB,GAAG,4EAA4E;EAE3G,MAAMC,aAAa,GAAG,CAAA,OAAA,EAAUhB,SAAS,CAAA,CAAE;EAC3C,MAAMiB,WAAW,GAAG,CAAA,KAAA,EAAQjB,SAAS,CAAA,CAAE;EACvC,MAAMkB,UAAU,GAAG,CAAA,IAAA,EAAOlB,SAAS,CAAA,CAAE;EACrC,MAAMmB,YAAY,GAAG,CAAA,MAAA,EAASnB,SAAS,CAAA,CAAE;EACzC,MAAMoB,WAAW,GAAG,CAAA,KAAA,EAAQpB,SAAS,CAAA,CAAE;EACvC,MAAMqB,aAAa,GAAG,CAAA,OAAA,EAAUrB,SAAS,CAAA,CAAE;EAC3C,MAAMsB,WAAW,GAAG,CAAA,KAAA,EAAQtB,SAAS,CAAA,CAAE;EACvC,MAAMuB,UAAU,GAAG,CAAA,IAAA,EAAOvB,SAAS,CAAA,CAAE;EACrC,MAAMwB,WAAW,GAAG,CAAA,KAAA,EAAQxB,SAAS,CAAA,CAAE;EACvC,MAAMyB,oBAAoB,GAAG,CAAA,KAAA,EAAQzB,SAAS,CAAA,EAAGC,YAAY,CAAA,CAAE;EAC/D,MAAMyB,oBAAoB,GAAG,CAAA,KAAA,EAAQ1B,SAAS,CAAA,EAAGC,YAAY,CAAA,CAAE;EAC/D,MAAM0B,mBAAmB,GAAG,CAAA,IAAA,EAAO3B,SAAS,CAAA,EAAGC,YAAY,CAAA,CAAE;EAE7D,MAAM2B,wBAAwB,GAAG,eAAe;EAChD,MAAMC,iCAAiC,GAAG,wBAAwB;EAClE,MAAMC,kBAAkB,GAAG,uBAAuB;EAClD,MAAMC,mBAAmB,GAAG,UAAU;EACtC,MAAMC,sBAAsB,GAAG,2BAA2B;EAC1D,MAAMC,gBAAgB,GAAG,OAAO;EAChC,MAAMC,mBAAmB,GAAG,wBAAwB;EACpD,MAAMC,yBAAyB,GAAG,8BAA8B;EAChE,MAAMC,iBAAiB,GAAG,sBAAsB;EAChD,MAAMC,kBAAkB,GAAG,uBAAuB;EAClD,MAAMC,wBAAwB,GAAG,6BAA6B;EAC9D,MAAMC,mBAAmB,GAAG,UAAU;EACtC,MAAMC,eAAe,GAAG,MAAM;EAE9B,MAAMC,OAAO,GAAG;EACdC,EAAAA,uBAAuB,EAAE,KAAK;EAC9BC,EAAAA,gBAAgB,EAAE,sBAAsB;EACxCC,EAAAA,kBAAkB,EAAE,iBAAiB;EACrCC,EAAAA,OAAO,EAAE,KAAK;EACdC,EAAAA,mBAAmB,EAAE,IAAI;EACzBC,EAAAA,SAAS,EAAE,KAAK;EAChBC,EAAAA,QAAQ,EAAE,KAAK;EACfC,EAAAA,wBAAwB,EAAE,KAAK;EAC/BC,EAAAA,SAAS,EAAE,IAAI;EACfC,EAAAA,OAAO,EAAE,KAAK;EACdC,EAAAA,IAAI,EAAE,IAAI;EACVC,EAAAA,OAAO,EAAE,KAAK;EACdC,EAAAA,gBAAgB,EAAE,MAAM;EACxBC,EAAAA,WAAW,EAAE,IAAI;EACjBC,EAAAA,QAAQ,EAAE,KAAK;EACfC,EAAAA,MAAM,EAAE,IAAI;EACZC,EAAAA,oBAAoB,EAAE,kBAAkB;EACxCC,EAAAA,SAAS,EAAE,KAAK;EAChBC,EAAAA,KAAK,EAAE,KAAK;EACZC,EAAAA,KAAK,EAAE;EACT,CAAC;EAED,MAAMC,WAAW,GAAG;EAClBpB,EAAAA,uBAAuB,EAAE,SAAS;EAClCC,EAAAA,gBAAgB,EAAE,QAAQ;EAC1BC,EAAAA,kBAAkB,EAAE,QAAQ;EAC5BC,EAAAA,OAAO,EAAE,SAAS;EAClBC,EAAAA,mBAAmB,EAAE,SAAS;EAC9BC,EAAAA,SAAS,EAAE,0BAA0B;EACrCC,EAAAA,QAAQ,EAAE,SAAS;EACnBC,EAAAA,wBAAwB,EAAE,SAAS;EACnCC,EAAAA,SAAS,EAAE,SAAS;EACpBC,EAAAA,OAAO,EAAE,SAAS;EAClBC,EAAAA,IAAI,EAAE,eAAe;EACrBC,EAAAA,OAAO,EAAE,cAAc;EACvBC,EAAAA,gBAAgB,EAAE,iBAAiB;EACnCC,EAAAA,WAAW,EAAE,eAAe;EAC5BC,EAAAA,QAAQ,EAAE,SAAS;EACnBC,EAAAA,MAAM,EAAE,qBAAqB;EAC7BC,EAAAA,oBAAoB,EAAG,gBAAiB;EACxCC,EAAAA,SAAS,EAAE,SAAS;EACpBC,EAAAA,KAAK,EAAE,SAAS;EAChBC,EAAAA,KAAK,EAAE;EACT,CAAC;;EAED;EACA;EACA;EACA;EACA;;EAEA,MAAME,YAAY,SAASC,aAAa,CAAC;EACvCC,EAAAA,WAAWA,CAACC,OAAO,EAAEC,MAAM,EAAE;EAC3B,IAAA,KAAK,CAACD,OAAO,EAAEC,MAAM,CAAC;MAEtB,IAAI,CAACC,iBAAiB,GAAG,IAAI;MAC7B,IAAI,CAACC,aAAa,GAAG,IAAI;MACzB,IAAI,CAACC,iBAAiB,GAAG,IAAI;MAC7B,IAAI,CAACC,eAAe,GAAG,IAAI;MAC3B,IAAI,CAACC,eAAe,GAAG,IAAI;MAE3B,IAAI,CAACC,KAAK,GAAG,IAAI;MACjB,IAAI,CAACC,SAAS,GAAG,EAAE;EACnB,IAAA,IAAI,CAACC,QAAQ,GAAG,IAAI,CAACC,qBAAqB,EAAE;MAC5C,IAAI,CAACC,OAAO,GAAG,IAAI;MACnB,IAAI,CAACC,OAAO,GAAG,EAAE;MAEjB,IAAI,CAACC,mBAAmB,EAAE;MAC1B,IAAI,CAACC,kBAAkB,EAAE;MACzBC,IAAI,CAACC,GAAG,CAAC,IAAI,CAACC,QAAQ,EAAEpF,QAAQ,EAAE,IAAI,CAAC;EACzC,EAAA;;EAEA;;IAEA,WAAW0C,OAAOA,GAAG;EACnB,IAAA,OAAOA,OAAO;EAChB,EAAA;IAEA,WAAWqB,WAAWA,GAAG;EACvB,IAAA,OAAOA,WAAW;EACpB,EAAA;IAEA,WAAWhE,IAAIA,GAAG;EAChB,IAAA,OAAOA,IAAI;EACb,EAAA;;EAEA;;EAEAsF,EAAAA,MAAMA,GAAG;EACP,IAAA,OAAO,IAAI,CAACC,QAAQ,EAAE,GAAG,IAAI,CAACC,IAAI,EAAE,GAAG,IAAI,CAACC,IAAI,EAAE;EACpD,EAAA;EAEAA,EAAAA,IAAIA,GAAG;MACL,IAAI,IAAI,CAACC,OAAO,CAACxC,QAAQ,IAAI,IAAI,CAACqC,QAAQ,EAAE,EAAE;EAC5C,MAAA;EACF,IAAA;EAEA,IAAA,IACE,CAAC,IAAI,CAACG,OAAO,CAAC9B,oBAAoB,IAClC,IAAI,CAAC+B,eAAe,EAAE,CAACC,MAAM,CAACC,MAAM,IAAIA,MAAM,CAACC,KAAK,CAACC,WAAW,EAAE,CAACC,QAAQ,CAAC,IAAI,CAAChB,OAAO,CAACe,WAAW,EAAE,CAAC,CAAC,CAACE,MAAM,KAAK,CAAC,EAAE;EACvH,MAAA;EACF,IAAA;MAEAC,YAAY,CAACC,OAAO,CAAC,IAAI,CAACd,QAAQ,EAAE5D,UAAU,CAAC;MAC/C,IAAI,CAAC4D,QAAQ,CAACe,SAAS,CAACC,GAAG,CAAC3D,eAAe,CAAC;MAC5C,IAAI,CAAC2C,QAAQ,CAACiB,YAAY,CAAC,eAAe,EAAE,IAAI,CAAC;EAEjD,IAAA,IAAI,IAAI,CAACZ,OAAO,CAACzC,SAAS,EAAE;EAC1B,MAAA,IAAI,CAAC0B,KAAK,CAAC4B,KAAK,CAACC,QAAQ,GAAG,CAAA,EAAG,IAAI,CAACnB,QAAQ,CAACoB,WAAW,CAAA,EAAA,CAAI;QAC5D,IAAI,CAAC9B,KAAK,CAACyB,SAAS,CAACC,GAAG,CAAC3D,eAAe,CAAC;EAC3C,IAAA;MAEAwD,YAAY,CAACC,OAAO,CAAC,IAAI,CAACd,QAAQ,EAAE3D,WAAW,CAAC;MAEhD,IAAI,CAACgF,aAAa,EAAE;EACtB,EAAA;EAEAlB,EAAAA,IAAIA,GAAG;MACLU,YAAY,CAACC,OAAO,CAAC,IAAI,CAACd,QAAQ,EAAEjE,UAAU,CAAC;MAE/C,IAAI,IAAI,CAAC2D,OAAO,EAAE;EAChB,MAAA,IAAI,CAACA,OAAO,CAAC4B,OAAO,EAAE;EACxB,IAAA;;EAEA;EACA;EACA;EACA;;MAEA,IAAI,CAACtB,QAAQ,CAACe,SAAS,CAACQ,MAAM,CAAClE,eAAe,CAAC;MAC/C,IAAI,CAAC2C,QAAQ,CAACiB,YAAY,CAAC,eAAe,EAAE,OAAO,CAAC;EAEpD,IAAA,IAAI,IAAI,CAACZ,OAAO,CAACzC,SAAS,EAAE;QAC1B,IAAI,CAAC0B,KAAK,CAACyB,SAAS,CAACQ,MAAM,CAAClE,eAAe,CAAC;EAC9C,IAAA;MAEAwD,YAAY,CAACC,OAAO,CAAC,IAAI,CAACd,QAAQ,EAAEhE,YAAY,CAAC;EACnD,EAAA;EAEAwF,EAAAA,OAAOA,GAAG;MACR,IAAI,IAAI,CAAC9B,OAAO,EAAE;EAChB,MAAA,IAAI,CAACA,OAAO,CAAC4B,OAAO,EAAE;EACxB,IAAA;MAEA,KAAK,CAACE,OAAO,EAAE;EACjB,EAAA;EAEAC,EAAAA,KAAKA,GAAG;MACN,IAAI,CAACC,WAAW,EAAE;EAClB,IAAA,IAAI,CAACpD,MAAM,CAAC,EAAE,CAAC;MACf,IAAI,CAACqD,kBAAkB,EAAE;EACzB,IAAA,IAAI,CAACzC,aAAa,CAACR,KAAK,GAAG,EAAE;EAC/B,EAAA;IAEAJ,MAAMA,CAACmC,KAAK,EAAE;EACZ,IAAA,IAAI,CAACd,OAAO,GAAGc,KAAK,CAACG,MAAM,GAAG,CAAC,GAAGH,KAAK,CAACC,WAAW,EAAE,GAAG,EAAE;EAC1D,IAAA,IAAI,CAAC,IAAI,CAACkB,iBAAiB,EAAE,EAAE;QAC7B,IAAI,CAACD,kBAAkB,EAAE;EAC3B,IAAA;MAEAd,YAAY,CAACC,OAAO,CAAC,IAAI,CAACd,QAAQ,EAAE/D,WAAW,EAAE;EAC/CyC,MAAAA,KAAK,EAAE+B;EACT,KAAC,CAAC;EACJ,EAAA;IAEAoB,MAAMA,CAAC7C,MAAM,EAAE;MACb,IAAIA,MAAM,CAACN,KAAK,EAAE;QAChB,IAAI,CAACgD,WAAW,EAAE;EACpB,IAAA;MAEA,IAAI,CAACrB,OAAO,GAAG;QAAE,GAAG,IAAI,CAACA,OAAO;EAAE,MAAA,GAAG,IAAI,CAACyB,iBAAiB,CAAC9C,MAAM;OAAG;EACrE,IAAA,IAAI,CAACQ,QAAQ,GAAG,IAAI,CAACC,qBAAqB,EAAE;EAC5C,IAAA,IAAI,CAACJ,eAAe,CAAC0C,SAAS,GAAG,EAAE;MACnC,IAAI,CAACC,cAAc,CAAC,IAAI,CAAC3C,eAAe,EAAE,IAAI,CAACG,QAAQ,CAAC;EAC1D,EAAA;EAEAkC,EAAAA,WAAWA,CAACxD,OAAO,GAAG,IAAI,CAACqB,SAAS,EAAE;EACpC,IAAA,KAAK,MAAMiB,MAAM,IAAItC,OAAO,EAAE;QAC5B,IAAIsC,MAAM,CAAC3C,QAAQ,EAAE;EACnB,QAAA;EACF,MAAA;QAEA,IAAIoE,KAAK,CAACC,OAAO,CAAC1B,MAAM,CAACtC,OAAO,CAAC,EAAE;EACjC,QAAA,IAAI,CAACwD,WAAW,CAAClB,MAAM,CAACtC,OAAO,CAAC;EAChC,QAAA;EACF,MAAA;EAEA,MAAA,IAAI,CAACiE,eAAe,CAAC3B,MAAM,CAAC9B,KAAK,CAAC;QAClC,IAAI,CAAC0D,uBAAuB,EAAE;EAChC,IAAA;EACF,EAAA;;EAEA;;IAEA9B,eAAeA,CAACpC,OAAO,GAAG,IAAI,CAACsB,QAAQ,EAAE6C,IAAI,GAAG,EAAE,EAAE;EAClD,IAAA,KAAK,MAAMC,GAAG,IAAIpE,OAAO,EAAE;QACzB,IAAIoE,GAAG,IAAIL,KAAK,CAACC,OAAO,CAACI,GAAG,CAACpE,OAAO,CAAC,EAAE;UACrC,IAAI,CAACoC,eAAe,CAACgC,GAAG,CAACpE,OAAO,EAAEmE,IAAI,CAAC;EACvC,QAAA;EACF,MAAA;EAEAA,MAAAA,IAAI,CAACE,IAAI,CAACD,GAAG,CAAC;EAChB,IAAA;EAEA,IAAA,OAAOD,IAAI;EACb,EAAA;EAEAG,EAAAA,cAAcA,GAAG;MACf,OAAO,IAAI,CAACxC,QAAQ,CAACe,SAAS,CAACrC,KAAK,CAAC+D,KAAK,CAAC,GAAG,CAAC;EACjD,EAAA;IAEAC,gBAAgBA,CAACjC,KAAK,EAAE;MACtB,MAAMkC,KAAK,GAAG,IAAIC,MAAM,CAAC,IAAI,CAACjD,OAAO,EAAE,IAAI,CAAC;MAC5C,OAAOc,KAAK,CAACoC,OAAO,CAACF,KAAK,EAAEG,MAAM,IAAI,CAAA,QAAA,EAAWA,MAAM,CAAA,SAAA,CAAW,CAAC;EACrE,EAAA;EAEAlB,EAAAA,iBAAiBA,GAAG;MAClB,OAAOK,KAAK,CAACC,OAAO,CAAC,IAAI,CAAC7B,OAAO,CAAC/B,MAAM,CAAC,IAAI,IAAI,CAAC+B,OAAO,CAAC/B,MAAM,CAACqC,QAAQ,CAAC,UAAU,CAAC;EACvF,EAAA;EAEAoC,EAAAA,eAAeA,GAAG;MAChB,OAAOd,KAAK,CAACC,OAAO,CAAC,IAAI,CAAC7B,OAAO,CAAC/B,MAAM,CAAC,IAAI,IAAI,CAAC+B,OAAO,CAAC/B,MAAM,CAACqC,QAAQ,CAAC,QAAQ,CAAC;EACrF,EAAA;IAEAqC,UAAUA,CAACjE,OAAO,EAAE;EAClB,IAAA,MAAMmC,KAAK,GAAG+B,MAAM,CAACC,gBAAgB,CAACnE,OAAO,CAAC;EAC9C,IAAA,OAAQmC,KAAK,CAACiC,OAAO,KAAK,MAAM;EAClC,EAAA;EAEAjD,EAAAA,QAAQA,GAAG;MACT,OAAO,IAAI,CAACF,QAAQ,CAACe,SAAS,CAACqC,QAAQ,CAAC/F,eAAe,CAAC;EAC1D,EAAA;;EAEA;;EAEAwC,EAAAA,kBAAkBA,GAAG;MACnBgB,YAAY,CAACwC,EAAE,CAAC,IAAI,CAACrD,QAAQ,EAAElE,WAAW,EAAE,MAAM;EAChD,MAAA,IAAI,CAAC,IAAI,CAACuE,OAAO,CAACxC,QAAQ,EAAE;UAC1B,IAAI,CAACuC,IAAI,EAAE;EACb,MAAA;EACF,IAAA,CAAC,CAAC;MAEFS,YAAY,CAACwC,EAAE,CAAC,IAAI,CAACrD,QAAQ,EAAE9D,aAAa,EAAEoH,KAAK,IAAI;EACrD,MAAA,IAAIA,KAAK,CAACC,GAAG,KAAKnI,UAAU,EAAE;UAC5B,IAAI,CAAC+E,IAAI,EAAE;EACX,QAAA,IAAI,IAAI,CAACE,OAAO,CAAC9C,uBAAuB,IAAI,IAAI,CAACgC,SAAS,CAACqB,MAAM,KAAK,CAAC,EAAE;EACvE,UAAA,IAAI,CAACtC,MAAM,CAAC,EAAE,CAAC;EACf,UAAA,IAAI,CAACY,aAAa,CAACR,KAAK,GAAG,EAAE;EAC/B,QAAA;EAEA,QAAA;EACF,MAAA;QAEA,IAAI,IAAI,CAACqE,eAAe,EAAE,KAAKO,KAAK,CAACC,GAAG,CAAC3C,MAAM,KAAK,CAAC,IAAI0C,KAAK,CAACC,GAAG,KAAKtI,aAAa,IAAIqI,KAAK,CAACC,GAAG,KAAKrI,UAAU,CAAC,EAAE;EACjH,QAAA,IAAI,CAACgE,aAAa,CAACsE,KAAK,EAAE;EAC5B,MAAA;EACF,IAAA,CAAC,CAAC;MAEF3C,YAAY,CAACwC,EAAE,CAAC,IAAI,CAAC/D,KAAK,EAAEpD,aAAa,EAAEoH,KAAK,IAAI;QAClD,IAAI,IAAI,CAACP,eAAe,EAAE,KAAKO,KAAK,CAACC,GAAG,CAAC3C,MAAM,KAAK,CAAC,IAAI0C,KAAK,CAACC,GAAG,KAAKtI,aAAa,IAAIqI,KAAK,CAACC,GAAG,KAAKrI,UAAU,CAAC,EAAE;EACjH,QAAA,IAAI,CAACgE,aAAa,CAACsE,KAAK,EAAE;EAC5B,MAAA;EACF,IAAA,CAAC,CAAC;MAEF3C,YAAY,CAACwC,EAAE,CAAC,IAAI,CAACjE,eAAe,EAAElD,aAAa,EAAEoH,KAAK,IAAI;EAC5D,MAAA,IAAI,CAAC,IAAI,CAACpD,QAAQ,EAAE,KAAKoD,KAAK,CAACC,GAAG,KAAKpI,SAAS,IAAImI,KAAK,CAACC,GAAG,KAAKvI,cAAc,CAAC,EAAE;UACjFsI,KAAK,CAACG,cAAc,EAAE;UACtB,IAAI,CAACrD,IAAI,EAAE;EACX,QAAA;EACF,MAAA;QAEA,IAAI,IAAI,CAACF,QAAQ,EAAE,IAAIoD,KAAK,CAACC,GAAG,KAAKvI,cAAc,EAAE;UACnDsI,KAAK,CAACG,cAAc,EAAE;EACtB,QAAA,IAAI,CAACC,eAAe,CAACJ,KAAK,CAAC;EAC7B,MAAA;EACF,IAAA,CAAC,CAAC;MAEFzC,YAAY,CAACwC,EAAE,CAAC,IAAI,CAACpE,iBAAiB,EAAEnD,WAAW,EAAEwH,KAAK,IAAI;QAC5DA,KAAK,CAACG,cAAc,EAAE;QACtBH,KAAK,CAACK,eAAe,EAAE;QACvB,IAAI,CAAC1D,MAAM,EAAE;EACf,IAAA,CAAC,CAAC;MAEFY,YAAY,CAACwC,EAAE,CAAC,IAAI,CAACnE,aAAa,EAAE/C,WAAW,EAAEmH,KAAK,IAAI;EACxD,MAAA,IAAIA,KAAK,CAACC,GAAG,CAAC3C,MAAM,KAAK,CAAC,IAAI0C,KAAK,CAACC,GAAG,KAAKtI,aAAa,IAAIqI,KAAK,CAACC,GAAG,KAAKrI,UAAU,EAAE;UACrF,MAAM;EAAEwD,UAAAA;WAAO,GAAG4E,KAAK,CAACM,MAAM;UAC9B,IAAI,CAAClC,WAAW,EAAE;EAClB,QAAA,IAAI,CAACpD,MAAM,CAACI,KAAK,CAAC;EAClB,QAAA,IAAI,IAAI,CAAC2B,OAAO,CAAC7B,SAAS,EAAE;EAC1B,UAAA,MAAMN,OAAO,GAAGQ,KAAK,GACnB,IAAI,CAAC4B,eAAe,EAAE,CAACC,MAAM,CAACC,MAAM,IAAIA,MAAM,CAACC,KAAK,CAACC,WAAW,EAAE,CAACmD,UAAU,CAACnF,KAAK,CAACgC,WAAW,EAAE,CAAC,CAAC,GACnG,EAAE;EACJ,UAAA,IAAI,CAACvB,iBAAiB,CAACT,KAAK,GAAGR,OAAO,CAAC0C,MAAM,GAAG,CAAC,GAAG,CAAA,EAAGlC,KAAK,CAAA,EAAGR,OAAO,CAAC,CAAC,CAAC,CAACuC,KAAK,CAACqD,KAAK,CAACpF,KAAK,CAACkC,MAAM,CAAC,CAAA,CAAE,GAAG,EAAE;EAC5G,QAAA;EACF,MAAA;EACF,IAAA,CAAC,CAAC;MAEFC,YAAY,CAACwC,EAAE,CAAC,IAAI,CAACnE,aAAa,EAAEhD,aAAa,EAAEoH,KAAK,IAAI;EAC1D,MAAA,IAAI,CAAC,IAAI,CAACpD,QAAQ,EAAE,IAAIoD,KAAK,CAACC,GAAG,KAAKlI,OAAO,EAAE;UAC7C,IAAI,CAAC+E,IAAI,EAAE;EACb,MAAA;EAEA,MAAA,IAAIkD,KAAK,CAACC,GAAG,KAAKvI,cAAc,IAAI,IAAI,CAACkE,aAAa,CAACR,KAAK,CAACkC,MAAM,KAAK,IAAI,CAAC1B,aAAa,CAAC6E,cAAc,EAAE;EACzG,QAAA,IAAI,CAACL,eAAe,CAACJ,KAAK,CAAC;EAC3B,QAAA;EACF,MAAA;QAEA,IAAIA,KAAK,CAACC,GAAG,KAAKlI,OAAO,IAAI,IAAI,CAACgF,OAAO,CAAC7B,SAAS,IAAI,IAAI,CAACU,aAAa,CAACR,KAAK,CAACkC,MAAM,GAAG,CAAC,EAAE;EAC1F,QAAA,IAAI,IAAI,CAACzB,iBAAiB,CAACT,KAAK,EAAE;YAChC4E,KAAK,CAACG,cAAc,EAAE;YACtBH,KAAK,CAACK,eAAe,EAAE;EACzB,QAAA;EAEA,QAAA,MAAMzF,OAAO,GAAG,IAAI,CAACoC,eAAe,EAAE,CAACC,MAAM,CAACC,MAAM,IAAIA,MAAM,CAACC,KAAK,CAACC,WAAW,EAAE,CAACmD,UAAU,CAAC,IAAI,CAAC3E,aAAa,CAACR,KAAK,CAACgC,WAAW,EAAE,CAAC,CAAC;EAEtI,QAAA,IAAIxC,OAAO,CAAC0C,MAAM,GAAG,CAAC,EAAE;EACtB,UAAA,IAAI,CAACoD,aAAa,CAAC9F,OAAO,CAAC,CAAC,CAAC,CAAC;EAChC,QAAA;EACF,MAAA;EAEA,MAAA,IAAIoF,KAAK,CAACC,GAAG,KAAKpI,SAAS,EAAE;UAC3BmI,KAAK,CAACG,cAAc,EAAE;UACtBH,KAAK,CAACK,eAAe,EAAE;UAEvB,IAAI,IAAI,CAACzE,aAAa,CAACR,KAAK,CAACkC,MAAM,KAAK,CAAC,EAAE;EACzC,UAAA;EACF,QAAA;EAEA,QAAA,MAAM1C,OAAO,GAAG,IAAI,CAACoC,eAAe,EAAE,CAACC,MAAM,CAACC,MAAM,IAAIA,MAAM,CAACC,KAAK,CAACC,WAAW,EAAE,KAAK,IAAI,CAACxB,aAAa,CAACR,KAAK,CAACgC,WAAW,EAAE,CAAC;EAE9H,QAAA,IAAIxC,OAAO,CAAC0C,MAAM,GAAG,CAAC,EAAE;EACtB,UAAA,IAAI,CAACoD,aAAa,CAAC9F,OAAO,CAAC,CAAC,CAAC,CAAC;EAChC,QAAA;EAEA,QAAA,IAAIA,OAAO,CAAC0C,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAACP,OAAO,CAAC9C,uBAAuB,EAAE;YACjEsD,YAAY,CAACC,OAAO,CAAC,IAAI,CAACd,QAAQ,EAAEnE,aAAa,EAAE;EACjD6C,YAAAA,KAAK,EAAE,IAAI,CAACQ,aAAa,CAACR;EAC5B,WAAC,CAAC;YAEF,IAAI,CAACyB,IAAI,EAAE;EAEX,UAAA,IAAI,IAAI,CAACE,OAAO,CAAC1C,mBAAmB,EAAE;EACpC,YAAA,IAAI,CAACW,MAAM,CAAC,EAAE,CAAC;EACjB,UAAA;EACF,QAAA;EACF,MAAA;EACF,IAAA,CAAC,CAAC;MAEFuC,YAAY,CAACwC,EAAE,CAAC,IAAI,CAAChE,eAAe,EAAEvD,WAAW,EAAEwH,KAAK,IAAI;QAC1DA,KAAK,CAACG,cAAc,EAAE;QACtBH,KAAK,CAACK,eAAe,EAAE;EACvB,MAAA,IAAI,CAACM,eAAe,CAACX,KAAK,CAACM,MAAM,CAAC;EACpC,IAAA,CAAC,CAAC;MAEF/C,YAAY,CAACwC,EAAE,CAAC,IAAI,CAACa,wBAAwB,EAAEpI,WAAW,EAAEwH,KAAK,IAAI;EACnE,MAAA,IAAI,CAAC,IAAI,CAACjD,OAAO,CAACxC,QAAQ,EAAE;UAC1ByF,KAAK,CAACG,cAAc,EAAE;UACtBH,KAAK,CAACK,eAAe,EAAE;UACvB,IAAI,CAAClC,KAAK,EAAE;EACd,MAAA;EACF,IAAA,CAAC,CAAC;MAEFZ,YAAY,CAACwC,EAAE,CAAC,IAAI,CAAChE,eAAe,EAAEnD,aAAa,EAAEoH,KAAK,IAAI;EAC5D,MAAA,IAAIA,KAAK,CAACC,GAAG,KAAKpI,SAAS,EAAE;EAC3B,QAAA,IAAI,CAAC8I,eAAe,CAACX,KAAK,CAACM,MAAM,CAAC;EACpC,MAAA;EAEA,MAAA,IAAI,CAAC7I,YAAY,EAAEC,cAAc,CAAC,CAAC2F,QAAQ,CAAC2C,KAAK,CAACC,GAAG,CAAC,EAAE;UACtDD,KAAK,CAACG,cAAc,EAAE;EACtB,QAAA,IAAI,CAACC,eAAe,CAACJ,KAAK,CAAC;EAC7B,MAAA;EACF,IAAA,CAAC,CAAC;EACJ,EAAA;IAEA7D,qBAAqBA,CAACvB,OAAO,GAAG,IAAI,CAACmC,OAAO,CAACnC,OAAO,EAAE;MACpD,IAAI,CAACA,OAAO,IAAI,CAAC+D,KAAK,CAACC,OAAO,CAAChE,OAAO,CAAC,EAAE;EACvC,MAAA,OAAO,EAAE;EACX,IAAA;MAEA,MAAMsB,QAAQ,GAAG,EAAE;EACnB,IAAA,KAAK,MAAMgB,MAAM,IAAItC,OAAO,EAAE;EAAA,MAAA,IAAAiG,aAAA;EAC5B,MAAA,IAAI3D,MAAM,CAACtC,OAAO,IAAI+D,KAAK,CAACC,OAAO,CAAC1B,MAAM,CAACtC,OAAO,CAAC,EAAE;UACnDsB,QAAQ,CAAC+C,IAAI,CAAC;YACZ9B,KAAK,EAAED,MAAM,CAACC,KAAK;EACnBvC,UAAAA,OAAO,EAAE,IAAI,CAACuB,qBAAqB,CAACe,MAAM,CAACtC,OAAO;EACpD,SAAC,CAAC;EACF,QAAA;EACF,MAAA;QAEA,MAAMuC,KAAK,GAAG,OAAOD,MAAM,KAAK,QAAQ,GAAGA,MAAM,GAAGA,MAAM,CAACC,KAAK;EAChE,MAAA,MAAM/B,KAAK,GAAA,CAAAyF,aAAA,GAAG3D,MAAM,CAAC9B,KAAK,KAAA,IAAA,GAAAyF,aAAA,GAAK,OAAO3D,MAAM,KAAK,QAAQ,GAAGA,MAAM,GAAGA,MAAM,CAACC,KAAM;EAClF,MAAA,MAAM2D,UAAU,GAAG5D,MAAM,CAAC6D,QAAQ,IAAK,IAAI,CAAChE,OAAO,CAAC3B,KAAK,IAAI,IAAI,CAAC2B,OAAO,CAAC3B,KAAK,KAAKA,KAAM;QAE1Fc,QAAQ,CAAC+C,IAAI,CAAC;UACZ9B,KAAK;UACL/B,KAAK;EACL,QAAA,IAAG0F,UAAU,IAAI;EAAEC,UAAAA,QAAQ,EAAE;WAAM,CAAA;UACnC,IAAG7D,MAAM,CAAC3C,QAAQ,IAAI;EAAEA,UAAAA,QAAQ,EAAE;WAAM;EAC1C,OAAC,CAAC;EAEF,MAAA,IAAIuG,UAAU,EAAE;EACd,QAAA,IAAI,CAAC7E,SAAS,CAACgD,IAAI,CAAC;YAClB9B,KAAK,EAAED,MAAM,CAACC,KAAK;EACnB/B,UAAAA,KAAK,EAAE4F,MAAM,CAAC9D,MAAM,CAACC,KAAK;EAC5B,SAAC,CAAC;EACJ,MAAA;EACF,IAAA;EAEA,IAAA,OAAOjB,QAAQ;EACjB,EAAA;EAEAI,EAAAA,mBAAmBA,GAAG;MACpB,IAAI,CAACI,QAAQ,CAACe,SAAS,CAACC,GAAG,CAACvE,wBAAwB,CAAC;EACrD,IAAA,IAAI,CAACuD,QAAQ,CAACe,SAAS,CAACd,MAAM,CAAC,YAAY,EAAE,IAAI,CAACI,OAAO,CAACrC,OAAO,CAAC;EAClE,IAAA,IAAI,CAACgC,QAAQ,CAACe,SAAS,CAACd,MAAM,CAAC,UAAU,EAAE,IAAI,CAACI,OAAO,CAAC5B,KAAK,CAAC;MAC9D,IAAI,CAACuB,QAAQ,CAACiB,YAAY,CAAC,eAAe,EAAE,OAAO,CAAC;EAEpD,IAAA,IAAI,IAAI,CAACZ,OAAO,CAACxC,QAAQ,EAAE;QACzB,IAAI,CAACmC,QAAQ,CAACe,SAAS,CAACC,GAAG,CAACpE,mBAAmB,CAAC;EAClD,IAAA;MAEA,KAAK,MAAM2H,SAAS,IAAI,IAAI,CAAC/B,cAAc,EAAE,EAAE;QAC7C,IAAI,CAACxC,QAAQ,CAACe,SAAS,CAACC,GAAG,CAACuD,SAAS,CAAC;EACxC,IAAA;MAEA,IAAI,CAACC,gBAAgB,EAAE;MACvB,IAAI,CAACC,cAAc,EAAE;MACrB,IAAI,CAACC,uBAAuB,EAAE;MAC9B,IAAI,CAACC,kBAAkB,EAAE;EAC3B,EAAA;EAEAH,EAAAA,gBAAgBA,GAAG;EAAA,IAAA,IAAAI,qBAAA;EACjB,IAAA,MAAMC,SAAS,GAAGC,QAAQ,CAACC,aAAa,CAAC,KAAK,CAAC;EAC/CF,IAAAA,SAAS,CAAC9D,SAAS,CAACC,GAAG,CAACnE,sBAAsB,CAAC;MAC/C,IAAI,CAACuC,eAAe,GAAGyF,SAAS;EAEhC,IAAA,IAAI,CAAC,IAAI,CAACxE,OAAO,CAAC/B,MAAM,IAAI,CAAC,IAAI,CAAC+B,OAAO,CAACxC,QAAQ,EAAE;EAClDgH,MAAAA,SAAS,CAACG,QAAQ,GAAG,EAAE;EACzB,IAAA;EAEA,IAAA,IAAI,CAAC,IAAI,CAAC3E,OAAO,CAACxC,QAAQ,IAAI,IAAI,CAACwC,OAAO,CAAC7B,SAAS,EAAE;EACpD,MAAA,MAAMyG,WAAW,GAAGH,QAAQ,CAACC,aAAa,CAAC,OAAO,CAAC;QACnDE,WAAW,CAAClE,SAAS,CAACC,GAAG,CAAC,cAAc,EAAE,yBAAyB,EAAE,8BAA8B,CAAC;QACpGiE,WAAW,CAAChE,YAAY,CAAC,MAAM,EAAG,IAAI,CAACZ,OAAO,CAACpC,IAAI,IAAIiH,eAAM,CAAC,CAAA,EAAG,IAAI,CAACpG,WAAW,CAACnE,IAAI,CAAA,KAAA,CAAO,CAAC,CAACwK,QAAQ,EAAG,CAAC;QAC3GF,WAAW,CAACG,YAAY,GAAG,KAAK;QAChCH,WAAW,CAACI,QAAQ,GAAG,IAAI;EAC3BJ,MAAAA,WAAW,CAACD,QAAQ,GAAG,EAAE;EACzBC,MAAAA,WAAW,CAAChE,YAAY,CAAC,aAAa,EAAE,IAAI,CAAC;EAE7C4D,MAAAA,SAAS,CAACS,MAAM,CAACL,WAAW,CAAC;QAC7B,IAAI,CAAC9F,iBAAiB,GAAG8F,WAAW;EACtC,IAAA;EAEA,IAAA,MAAMM,OAAO,GAAGT,QAAQ,CAACC,aAAa,CAAC,OAAO,CAAC;MAC/CQ,OAAO,CAACxE,SAAS,CAACC,GAAG,CAAC,cAAc,EAAE,yBAAyB,CAAC;MAChEuE,OAAO,CAACtE,YAAY,CAAC,MAAM,EAAG,IAAI,CAACZ,OAAO,CAACpC,IAAI,IAAIiH,eAAM,CAAC,CAAA,EAAG,IAAI,CAACpG,WAAW,CAACnE,IAAI,CAAA,CAAE,CAAC,CAACwK,QAAQ,EAAG,CAAC;MAClGI,OAAO,CAACH,YAAY,GAAG,KAAK;EAC5BG,IAAAA,OAAO,CAACnH,WAAW,GAAA,CAAAwG,qBAAA,GAAG,IAAI,CAACvE,OAAO,CAACjC,WAAW,KAAA,IAAA,GAAAwG,qBAAA,GAAI,EAAE;MACpDW,OAAO,CAACC,IAAI,GAAG,UAAU;EACzBD,IAAAA,OAAO,CAACtE,YAAY,CAAC,mBAAmB,EAAE,MAAM,CAAC;EACjDsE,IAAAA,OAAO,CAACtE,YAAY,CAAC,eAAe,EAAE,SAAS,CAAC;EAEhD,IAAA,IAAI,IAAI,CAACZ,OAAO,CAACxC,QAAQ,EAAE;EACzB0H,MAAAA,OAAO,CAACtE,YAAY,CAAC,UAAU,EAAE,IAAI,CAAC;EACtCsE,MAAAA,OAAO,CAACP,QAAQ,GAAG,EAAE;EACvB,IAAA;EAEA,IAAA,IAAI,IAAI,CAAC3E,OAAO,CAAChC,QAAQ,EAAE;EACzBkH,MAAAA,OAAO,CAACtE,YAAY,CAAC,UAAU,EAAE,IAAI,CAAC;EACxC,IAAA;EAEA4D,IAAAA,SAAS,CAACS,MAAM,CAACC,OAAO,CAAC;MACzB,IAAI,CAACrG,aAAa,GAAGqG,OAAO;EAE5B,IAAA,IAAI,CAACvF,QAAQ,CAACsF,MAAM,CAACT,SAAS,CAAC;EACjC,EAAA;EAEAJ,EAAAA,cAAcA,GAAG;EACf,IAAA,IAAI,CAAC,IAAI,CAACpE,OAAO,CAAC3C,OAAO,IAAI,CAAC,IAAI,CAAC2C,OAAO,CAACtC,SAAS,EAAE;EACpD,MAAA;EACF,IAAA;EAEA,IAAA,MAAM0H,OAAO,GAAGX,QAAQ,CAACC,aAAa,CAAC,KAAK,CAAC;EAC7CU,IAAAA,OAAO,CAAC1E,SAAS,CAACC,GAAG,CAAC,uBAAuB,CAAC;EAE9C,IAAA,IAAI,CAAC,IAAI,CAACX,OAAO,CAACxC,QAAQ,IAAI,IAAI,CAACwC,OAAO,CAAC3C,OAAO,EAAE;EAClD,MAAA,MAAMA,OAAO,GAAGoH,QAAQ,CAACC,aAAa,CAAC,QAAQ,CAAC;QAChDrH,OAAO,CAACgI,IAAI,GAAG,QAAQ;EACvBhI,MAAAA,OAAO,CAACqD,SAAS,CAACC,GAAG,CAACrE,kBAAkB,CAAC;EACzCe,MAAAA,OAAO,CAACwD,KAAK,CAACiC,OAAO,GAAG,MAAM;QAC9BzF,OAAO,CAACuD,YAAY,CAAC,YAAY,EAAE,IAAI,CAACZ,OAAO,CAAC7C,gBAAgB,CAAC;EAEjEiI,MAAAA,OAAO,CAACH,MAAM,CAAC5H,OAAO,CAAC;QACvB,IAAI,CAACwG,wBAAwB,GAAGxG,OAAO;EACzC,IAAA;EAEA,IAAA,IAAI,IAAI,CAAC2C,OAAO,CAACtC,SAAS,EAAE;EAC1B,MAAA,MAAMA,SAAS,GAAG+G,QAAQ,CAACC,aAAa,CAAC,QAAQ,CAAC;QAClDhH,SAAS,CAAC2H,IAAI,GAAG,QAAQ;EACzB3H,MAAAA,SAAS,CAACgD,SAAS,CAACC,GAAG,CAAC,yBAAyB,CAAC;QAClDjD,SAAS,CAACkD,YAAY,CAAC,YAAY,EAAE,IAAI,CAACZ,OAAO,CAAC5C,kBAAkB,CAAC;EAErE,MAAA,IAAI,IAAI,CAAC4C,OAAO,CAACxC,QAAQ,EAAE;EACzBE,QAAAA,SAAS,CAACiH,QAAQ,GAAG,EAAE;EACzB,MAAA;EAEAS,MAAAA,OAAO,CAACH,MAAM,CAACvH,SAAS,CAAC;QACzB,IAAI,CAACkB,iBAAiB,GAAGlB,SAAS;QAClC,IAAI,CAACkB,iBAAiB,GAAGlB,SAAS;EACpC,IAAA;EAEA,IAAA,IAAI,CAACqB,eAAe,CAACkG,MAAM,CAACG,OAAO,CAAC;MACpC,IAAI,CAACrD,uBAAuB,EAAE;EAChC,EAAA;EAEAf,EAAAA,aAAaA,GAAG;EACd,IAAA,IAAI,OAAOsE,iBAAM,KAAK,WAAW,EAAE;EACjC,MAAA,MAAM,IAAIC,SAAS,CAAC,0EAA0E,CAAC;EACjG,IAAA;EAEA,IAAA,MAAMC,YAAY,GAAG;EACnBC,MAAAA,SAAS,EAAE,CAAC;EACV7H,QAAAA,IAAI,EAAE,iBAAiB;EACvBC,QAAAA,OAAO,EAAE;EACP6H,UAAAA,QAAQ,EAAE;EACZ;EACF,OAAC,EACD;EACE9H,QAAAA,IAAI,EAAE,QAAQ;EACdC,QAAAA,OAAO,EAAE;EACP8H,UAAAA,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC;EACf;EACF,OAAC,CAAC;EACFC,MAAAA,SAAS,EAAEC,cAAK,EAAE,GAAG,YAAY,GAAG;OACrC;EAED,IAAA,IAAI,CAACxG,OAAO,GAAGiG,iBAAM,CAACQ,YAAY,CAAC,IAAI,CAAC/G,eAAe,EAAE,IAAI,CAACE,KAAK,EAAEuG,YAAY,CAAC;EACpF,EAAA;EAEAnB,EAAAA,uBAAuBA,GAAG;EACxB,IAAA,MAAM0B,WAAW,GAAGtB,QAAQ,CAACC,aAAa,CAAC,KAAK,CAAC;EACjDqB,IAAAA,WAAW,CAACrF,SAAS,CAACC,GAAG,CAACtE,iCAAiC,CAAC;EAE5D,IAAA,MAAM2J,UAAU,GAAGvB,QAAQ,CAACC,aAAa,CAAC,KAAK,CAAC;EAChDsB,IAAAA,UAAU,CAACtF,SAAS,CAACC,GAAG,CAAC9D,kBAAkB,CAAC;EAC5CmJ,IAAAA,UAAU,CAACpF,YAAY,CAAC,MAAM,EAAE,SAAS,CAAC;EAE1C,IAAA,IAAI,IAAI,CAACZ,OAAO,CAAClC,gBAAgB,KAAK,MAAM,EAAE;QAC5CkI,UAAU,CAACnF,KAAK,CAACoF,SAAS,GAAG,CAAA,EAAG,IAAI,CAACjG,OAAO,CAAClC,gBAAgB,CAAA,EAAA,CAAI;EACjEkI,MAAAA,UAAU,CAACnF,KAAK,CAACqF,QAAQ,GAAG,MAAM;EACpC,IAAA;EAEAH,IAAAA,WAAW,CAACd,MAAM,CAACe,UAAU,CAAC;MAE9B,MAAM;EAAEzI,MAAAA;OAAW,GAAG,IAAI,CAACyC,OAAO;EAClC,IAAA,IAAIzC,SAAS,EAAE;EACbA,MAAAA,SAAS,CAAC0H,MAAM,CAACc,WAAW,CAAC;EAC/B,IAAA,CAAC,MAAM;EACL,MAAA,IAAI,CAACpG,QAAQ,CAACsF,MAAM,CAACc,WAAW,CAAC;EACnC,IAAA;MAEA,IAAI,CAACpE,cAAc,CAACqE,UAAU,EAAE,IAAI,CAAC7G,QAAQ,CAAC;MAC9C,IAAI,CAACH,eAAe,GAAGgH,UAAU;MACjC,IAAI,CAAC/G,KAAK,GAAG8G,WAAW;EAC1B,EAAA;EAEApE,EAAAA,cAAcA,CAACwE,aAAa,EAAEtI,OAAO,EAAE;EACrC,IAAA,KAAK,MAAMsC,MAAM,IAAItC,OAAO,EAAE;QAC5B,IAAI+D,KAAK,CAACC,OAAO,CAAC1B,MAAM,CAACtC,OAAO,CAAC,EAAE;EACjC,QAAA,MAAMuI,QAAQ,GAAG3B,QAAQ,CAACC,aAAa,CAAC,KAAK,CAAC;EAC9C0B,QAAAA,QAAQ,CAAC1F,SAAS,CAACC,GAAG,CAACjE,mBAAmB,CAAC;EAC3C0J,QAAAA,QAAQ,CAACxF,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC;EAEtC,QAAA,MAAMyF,aAAa,GAAG5B,QAAQ,CAACC,aAAa,CAAC,KAAK,CAAC;EACnD2B,QAAAA,aAAa,CAACC,WAAW,GAAGnG,MAAM,CAACC,KAAK;EACxCiG,QAAAA,aAAa,CAAC3F,SAAS,CAACC,GAAG,CAAChE,yBAAyB,CAAC;EACtDyJ,QAAAA,QAAQ,CAACnB,MAAM,CAACoB,aAAa,CAAC;UAE9B,IAAI,CAAC1E,cAAc,CAACyE,QAAQ,EAAEjG,MAAM,CAACtC,OAAO,CAAC;EAC7CsI,QAAAA,aAAa,CAAClB,MAAM,CAACmB,QAAQ,CAAC;EAE9B,QAAA;EACF,MAAA;EAEA,MAAA,MAAMG,SAAS,GAAG9B,QAAQ,CAACC,aAAa,CAAC,KAAK,CAAC;EAC/C6B,MAAAA,SAAS,CAAC7F,SAAS,CAACC,GAAG,CAAC/D,iBAAiB,CAAC;QAE1C,IAAIuD,MAAM,CAAC3C,QAAQ,EAAE;EACnB+I,QAAAA,SAAS,CAAC7F,SAAS,CAACC,GAAG,CAACpE,mBAAmB,CAAC;EAC5CgK,QAAAA,SAAS,CAAC3F,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC;EACjD,MAAA;EAEA2F,MAAAA,SAAS,CAACC,OAAO,CAACnI,KAAK,GAAG8B,MAAM,CAAC9B,KAAK;QACtCkI,SAAS,CAAC5B,QAAQ,GAAG,CAAC;EACtB,MAAA,IAAI,IAAI,CAACpD,iBAAiB,EAAE,IAAI,IAAI,CAACvB,OAAO,CAACvC,wBAAwB,IAAI,IAAI,CAAC6B,OAAO,EAAE;UACrFiH,SAAS,CAAC7E,SAAS,GAAG,IAAI,CAACW,gBAAgB,CAAClC,MAAM,CAACC,KAAK,CAAC;EAC3D,MAAA,CAAC,MAAM;EACLmG,QAAAA,SAAS,CAACD,WAAW,GAAGnG,MAAM,CAACC,KAAK;EACtC,MAAA;EAEA+F,MAAAA,aAAa,CAAClB,MAAM,CAACsB,SAAS,CAAC;EACjC,IAAA;EACF,EAAA;IAEA3C,eAAeA,CAAClF,OAAO,EAAE;EACvB,IAAA,IAAI,CAACA,OAAO,CAACgC,SAAS,CAACqC,QAAQ,CAACnG,iBAAiB,CAAC,IAAI8B,OAAO,CAACgC,SAAS,CAACqC,QAAQ,CAACtG,gBAAgB,CAAC,EAAE;EAClG,MAAA;EACF,IAAA;MAEA,MAAM4B,KAAK,GAAG4F,MAAM,CAACvF,OAAO,CAAC8H,OAAO,CAACnI,KAAK,CAAC;EAC3C,IAAA,MAAMoI,WAAW,GAAG,IAAI,CAACC,kBAAkB,CAACrI,KAAK,CAAC;EAElD,IAAA,IAAIoI,WAAW,EAAE;EACf,MAAA,IAAI,CAAC9C,aAAa,CAAC8C,WAAW,CAAC;EACjC,IAAA;EACF,EAAA;IAEAC,kBAAkBA,CAACrI,KAAK,EAAER,OAAO,GAAG,IAAI,CAACsB,QAAQ,EAAE;EACjD,IAAA,KAAK,MAAMgB,MAAM,IAAItC,OAAO,EAAE;EAC5B,MAAA,IAAIsC,MAAM,CAAC9B,KAAK,KAAKA,KAAK,EAAE;EAC1B,QAAA,OAAO8B,MAAM;EACf,MAAA;EAEA,MAAA,IAAIA,MAAM,CAACtC,OAAO,IAAI+D,KAAK,CAACC,OAAO,CAAC1B,MAAM,CAACtC,OAAO,CAAC,EAAE;UACnD,MAAM8I,KAAK,GAAG,IAAI,CAACD,kBAAkB,CAACrI,KAAK,EAAE8B,MAAM,CAACtC,OAAO,CAAC;EAC5D,QAAA,IAAI8I,KAAK,EAAE;EACT,UAAA,OAAOA,KAAK;EACd,QAAA;EACF,MAAA;EACF,IAAA;EAEA,IAAA,OAAO,IAAI;EACb,EAAA;IAEAhD,aAAaA,CAACxD,MAAM,EAAE;MACpB,IAAI,CAACkB,WAAW,EAAE;MAElB,IAAI,IAAI,CAACnC,SAAS,CAACgB,MAAM,CAAC0G,cAAc,IAAIA,cAAc,CAACvI,KAAK,KAAK8B,MAAM,CAAC9B,KAAK,CAAC,CAACkC,MAAM,KAAK,CAAC,EAAE;EAC/F,MAAA,IAAI,CAACrB,SAAS,CAACgD,IAAI,CAAC/B,MAAM,CAAC;EAC7B,IAAA;EAEA,IAAA,MAAMsG,WAAW,GAAGI,cAAc,CAACC,OAAO,CAAC,CAAA,aAAA,EAAgB3G,MAAM,CAAC9B,KAAK,CAAA,EAAA,CAAI,EAAE,IAAI,CAACW,eAAe,CAAC;EAClG,IAAA,IAAIyH,WAAW,EAAE;EACfA,MAAAA,WAAW,CAAC/F,SAAS,CAACC,GAAG,CAAC5D,mBAAmB,CAAC;EAC9C0J,MAAAA,WAAW,CAAC7F,YAAY,CAAC,eAAe,EAAE,IAAI,CAAC;EACjD,IAAA;MAEAJ,YAAY,CAACC,OAAO,CAAC,IAAI,CAACd,QAAQ,EAAEnE,aAAa,EAAE;EACjD6C,MAAAA,KAAK,EAAE8B;EACT,KAAC,CAAC;EAEF,IAAA,IAAI,CAACtB,aAAa,CAACR,KAAK,GAAG8B,MAAM,CAACC,KAAK;EAEvC,IAAA,IAAI,IAAI,CAACJ,OAAO,CAAC7B,SAAS,EAAE;EAC1B,MAAA,IAAI,CAACW,iBAAiB,CAACT,KAAK,GAAG,EAAE;EACnC,IAAA;MAEA,IAAI,CAACyB,IAAI,EAAE;EAEX,IAAA,IAAI,IAAI,CAACE,OAAO,CAAC1C,mBAAmB,EAAE;EACpC,MAAA,IAAI,CAACW,MAAM,CAAC,EAAE,CAAC;EACjB,IAAA;EAEA,IAAA,IAAI,CAACY,aAAa,CAACsE,KAAK,EAAE;MAC1B,IAAI,CAACpB,uBAAuB,EAAE;EAChC,EAAA;IAEAD,eAAeA,CAACzD,KAAK,EAAE;EACrB,IAAA,IAAI,CAACa,SAAS,GAAG,IAAI,CAACA,SAAS,CAACgB,MAAM,CAACC,MAAM,IAAIA,MAAM,CAAC9B,KAAK,KAAK4F,MAAM,CAAC5F,KAAK,CAAC,CAAC;EAEhF,IAAA,MAAM8B,MAAM,GAAG0G,cAAc,CAACC,OAAO,CAAC,CAAA,aAAA,EAAgBzI,KAAK,CAAA,EAAA,CAAI,EAAE,IAAI,CAACW,eAAe,CAAC;EACtF,IAAA,IAAImB,MAAM,EAAE;EACVA,MAAAA,MAAM,CAACO,SAAS,CAACQ,MAAM,CAACnE,mBAAmB,CAAC;EAC5CoD,MAAAA,MAAM,CAACS,YAAY,CAAC,eAAe,EAAE,KAAK,CAAC;EAC7C,IAAA;MAEAJ,YAAY,CAACC,OAAO,CAAC,IAAI,CAACd,QAAQ,EAAEnE,aAAa,EAAE;QACjD6C,KAAK,EAAE,IAAI,CAACa;EACd,KAAC,CAAC;EACJ,EAAA;EAEA6C,EAAAA,uBAAuBA,GAAG;EACxB,IAAA,IAAI,CAAC,IAAI,CAAC/B,OAAO,CAAC3C,OAAO,IAAI,IAAI,CAACwG,wBAAwB,KAAK,IAAI,EAAE;EACnE,MAAA;EACF,IAAA;EAEA,IAAA,IAAI,IAAI,CAAC3E,SAAS,CAACqB,MAAM,GAAG,CAAC,EAAE;QAC7B,IAAI,CAACsD,wBAAwB,CAAChD,KAAK,CAACkG,cAAc,CAAC,SAAS,CAAC;EAC7D,MAAA;EACF,IAAA;EAEA,IAAA,IAAI,CAAClD,wBAAwB,CAAChD,KAAK,CAACiC,OAAO,GAAG,MAAM;EACtD,EAAA;EAEAwB,EAAAA,kBAAkBA,CAACzG,OAAO,GAAG,IAAI,CAACsB,QAAQ,EAAE;EAC1C,IAAA,KAAK,MAAMgB,MAAM,IAAItC,OAAO,EAAE;QAC5B,IAAI+D,KAAK,CAACC,OAAO,CAAC1B,MAAM,CAACtC,OAAO,CAAC,EAAE;EACjC,QAAA,IAAI,CAACyG,kBAAkB,CAACnE,MAAM,CAACtC,OAAO,CAAC;EACvC,QAAA;EACF,MAAA;QAEA,IAAIsC,MAAM,CAAC6D,QAAQ,EAAE;EACnB,QAAA,IAAI,CAACL,aAAa,CAACxD,MAAM,CAAC;EAC5B,MAAA;EACF,IAAA;EACF,EAAA;EAEAmB,EAAAA,kBAAkBA,GAAG;MACnB,MAAMzD,OAAO,GAAGgJ,cAAc,CAACG,IAAI,CAAC7L,eAAe,EAAE,IAAI,CAAC8D,KAAK,CAAC;MAChE,IAAIgI,cAAc,GAAG,CAAC;EAEtB,IAAA,KAAK,MAAM9G,MAAM,IAAItC,OAAO,EAAE;EAC5B;EACA,MAAA,IAAIsC,MAAM,CAACmG,WAAW,CAACjG,WAAW,EAAE,CAAC6G,OAAO,CAAC,IAAI,CAAC5H,OAAO,CAAC,KAAK,EAAE,EAAE;EACjEa,QAAAA,MAAM,CAACU,KAAK,CAACiC,OAAO,GAAG,MAAM;EAC/B,MAAA,CAAC,MAAM;EACL,QAAA,IAAI,IAAI,CAAC9C,OAAO,CAACvC,wBAAwB,EAAE;YACzC0C,MAAM,CAACuB,SAAS,GAAG,IAAI,CAACW,gBAAgB,CAAClC,MAAM,CAACmG,WAAW,CAAC;EAC9D,QAAA;EAEAnG,QAAAA,MAAM,CAACU,KAAK,CAACkG,cAAc,CAAC,SAAS,CAAC;EACtCE,QAAAA,cAAc,EAAE;EAClB,MAAA;EAEA,MAAA,MAAMb,QAAQ,GAAGjG,MAAM,CAACgH,OAAO,CAACjM,iBAAiB,CAAC;EAClD,MAAA,IAAIkL,QAAQ,EAAE;EACZ;UACA,IAAIS,cAAc,CAACO,QAAQ,CAAChB,QAAQ,EAAEjL,eAAe,CAAC,CAAC+E,MAAM,CAACxB,OAAO,IAAI,IAAI,CAACiE,UAAU,CAACjE,OAAO,CAAC,CAAC,CAAC6B,MAAM,GAAG,CAAC,EAAE;EAC7G6F,UAAAA,QAAQ,CAACvF,KAAK,CAACkG,cAAc,CAAC,SAAS,CAAC;EAC1C,QAAA,CAAC,MAAM;EACLX,UAAAA,QAAQ,CAACvF,KAAK,CAACiC,OAAO,GAAG,MAAM;EACjC,QAAA;EACF,MAAA;EACF,IAAA;MAEA,IAAImE,cAAc,GAAG,CAAC,EAAE;QACtB,IAAIJ,cAAc,CAACC,OAAO,CAACzL,sBAAsB,EAAE,IAAI,CAAC4D,KAAK,CAAC,EAAE;EAC9D4H,QAAAA,cAAc,CAACC,OAAO,CAACzL,sBAAsB,EAAE,IAAI,CAAC4D,KAAK,CAAC,CAACiC,MAAM,EAAE;EACrE,MAAA;EAEA,MAAA;EACF,IAAA;MAEA,IAAI+F,cAAc,KAAK,CAAC,EAAE;EACxB,MAAA,IAAI,IAAI,CAACjH,OAAO,CAAC9B,oBAAoB,EAAE;EACrC,QAAA,MAAMH,WAAW,GAAG0G,QAAQ,CAACC,aAAa,CAAC,KAAK,CAAC;EACjD3G,QAAAA,WAAW,CAAC2C,SAAS,CAACC,GAAG,CAAC7D,wBAAwB,CAAC;EACnDiB,QAAAA,WAAW,CAAC2D,SAAS,GAAG,IAAI,CAAC1B,OAAO,CAAC9B,oBAAoB;UAEzD,IAAI,CAAC2I,cAAc,CAACC,OAAO,CAACzL,sBAAsB,EAAE,IAAI,CAAC4D,KAAK,CAAC,EAAE;EAC/D4H,UAAAA,cAAc,CAACC,OAAO,CAAC1L,gBAAgB,EAAE,IAAI,CAAC6D,KAAK,CAAC,CAACgG,MAAM,CAAClH,WAAW,CAAC;EAC1E,QAAA;EAEA,QAAA;EACF,MAAA;QAEA,IAAI,CAAC+B,IAAI,EAAE;EACb,IAAA;EACF,EAAA;EAEAuD,EAAAA,eAAeA,CAAC;MAAEH,GAAG;EAAEK,IAAAA;EAAO,GAAC,EAAE;MAC/B,MAAM8D,KAAK,GAAGR,cAAc,CAACG,IAAI,CAACzL,sBAAsB,EAAE,IAAI,CAAC0D,KAAK,CAAC,CAACiB,MAAM,CAACxB,OAAO,IAAI4I,kBAAS,CAAC5I,OAAO,CAAC,CAAC;EAE3G,IAAA,IAAI,CAAC2I,KAAK,CAAC9G,MAAM,EAAE;EACjB,MAAA;EACF,IAAA;;EAEA;EACA;MACAgH,6BAAoB,CAACF,KAAK,EAAE9D,MAAM,EAAEL,GAAG,KAAKvI,cAAc,EAAE,CAAC0M,KAAK,CAAC/G,QAAQ,CAACiD,MAAM,CAAC,CAAC,CAACJ,KAAK,EAAE;EAC9F,EAAA;IAEA1B,iBAAiBA,CAAC9C,MAAM,EAAE;EACxB,IAAA,IAAIA,MAAM,CAACpB,SAAS,KAAK,IAAI,EAAE;EAC7BoB,MAAAA,MAAM,CAACpB,SAAS,GAAGkH,QAAQ,CAAC+C,IAAI;EAClC,IAAA;EAEA,IAAA,IAAI,OAAO7I,MAAM,CAACpB,SAAS,KAAK,QAAQ,IAAI,OAAOoB,MAAM,CAACpB,SAAS,KAAK,QAAQ,EAAE;QAChFoB,MAAM,CAACpB,SAAS,GAAGkK,mBAAU,CAAC9I,MAAM,CAACpB,SAAS,CAAC;EACjD,IAAA;EAEA,IAAA,IAAI,OAAOoB,MAAM,CAACd,OAAO,KAAK,QAAQ,EAAE;EACtCc,MAAAA,MAAM,CAACd,OAAO,GAAGc,MAAM,CAACd,OAAO,CAACuE,KAAK,CAAC,MAAM,CAAC,CAACsF,GAAG,CAACzD,MAAM,CAAC;EAC3D,IAAA;EAEA,IAAA,IAAI,OAAOtF,MAAM,CAACV,MAAM,KAAK,QAAQ,EAAE;EACrCU,MAAAA,MAAM,CAACV,MAAM,GAAGU,MAAM,CAACV,MAAM,CAACmE,KAAK,CAAC,MAAM,CAAC,CAACsF,GAAG,CAACzD,MAAM,CAAC;EACzD,IAAA;EAEA,IAAA,OAAOtF,MAAM;EACf,EAAA;;EAEA;;EAEA,EAAA,OAAOgJ,qBAAqBA,CAACjJ,OAAO,EAAEC,MAAM,EAAE;MAC5C,MAAMiJ,IAAI,GAAGrJ,YAAY,CAACsJ,mBAAmB,CAACnJ,OAAO,EAAEC,MAAM,CAAC;EAE9D,IAAA,IAAI,OAAOA,MAAM,KAAK,QAAQ,EAAE;EAC9B,MAAA,IAAI,OAAOiJ,IAAI,CAACjJ,MAAM,CAAC,KAAK,WAAW,EAAE;EACvC,QAAA,MAAM,IAAI4G,SAAS,CAAC,CAAA,iBAAA,EAAoB5G,MAAM,GAAG,CAAC;EACpD,MAAA;EAEAiJ,MAAAA,IAAI,CAACjJ,MAAM,CAAC,EAAE;EAChB,IAAA;EACF,EAAA;IAEA,OAAOmJ,eAAeA,CAACnJ,MAAM,EAAE;EAC7B,IAAA,OAAO,IAAI,CAACoJ,IAAI,CAAC,YAAY;EAC3BxJ,MAAAA,YAAY,CAACoJ,qBAAqB,CAAC,IAAI,EAAEhJ,MAAM,CAAC;EAClD,IAAA,CAAC,CAAC;EACJ,EAAA;IAEA,OAAOqJ,UAAUA,CAAC/E,KAAK,EAAE;MACvB,IAAIA,KAAK,KAAKA,KAAK,CAACgF,MAAM,KAAKhN,kBAAkB,IAC9CgI,KAAK,CAACoC,IAAI,KAAK,OAAO,IAAIpC,KAAK,CAACC,GAAG,KAAKlI,OAAQ,CAAC,EAAE;EACpD,MAAA;EACF,IAAA;EAEA,IAAA,MAAMkN,OAAO,GAAGrB,cAAc,CAACG,IAAI,CAAC1L,sBAAsB,CAAC;EAE3D,IAAA,KAAK,IAAI6M,CAAC,GAAG,CAAC,EAAEC,GAAG,GAAGF,OAAO,CAAC3H,MAAM,EAAE4H,CAAC,GAAGC,GAAG,EAAED,CAAC,EAAE,EAAE;EAClD,MAAA,MAAME,OAAO,GAAG5I,IAAI,CAAC6I,GAAG,CAACJ,OAAO,CAACC,CAAC,CAAC,EAAE5N,QAAQ,CAAC;EAC9C,OAAsB;UACpBgO,aAAa,EAAEL,OAAO,CAACC,CAAC;;EAG1B,MAAA,IAAIlF,KAAK,IAAIA,KAAK,CAACoC,IAAI,KAAK,OAAO,EAAE;QAIrC,IAAI,CAACgD,OAAO,EAAE;EACZ,QAAA;EACF,MAAA;QAEA,IAAI,CAACA,OAAO,CAAC1I,QAAQ,CAACe,SAAS,CAACqC,QAAQ,CAAC/F,eAAe,CAAC,EAAE;EACzD,QAAA;EACF,MAAA;QAEA,IAAIqL,OAAO,CAAC1I,QAAQ,CAACoD,QAAQ,CAACE,KAAK,CAACM,MAAM,CAAC,EAAE;EAC3C,QAAA;EACF,MAAA;QAEA8E,OAAO,CAACvI,IAAI,EAAE;EACduI,MAAAA,OAAO,CAACpK,MAAM,CAAC,EAAE,CAAC;EAClB,MAAA,IAAIoK,OAAO,CAACrI,OAAO,CAAC9C,uBAAuB,IAAImL,OAAO,CAACnJ,SAAS,CAACqB,MAAM,KAAK,CAAC,EAAE;EAC7E8H,QAAAA,OAAO,CAACxJ,aAAa,CAACR,KAAK,GAAG,EAAE;EAClC,MAAA;QAEAmC,YAAY,CAACC,OAAO,CAAC4H,OAAO,CAAC1I,QAAQ,EAAEhE,YAAY,CAAC;EACtD,IAAA;EACF,EAAA;EACF;;EAEA;EACA;EACA;;EAEA6E,YAAY,CAACwC,EAAE,CAACJ,MAAM,EAAEzG,mBAAmB,EAAE,MAAM;IACjD,KAAK,MAAMqM,EAAE,IAAI3B,cAAc,CAACG,IAAI,CAAC1L,sBAAsB,CAAC,EAAE;EAC5DiD,IAAAA,YAAY,CAACoJ,qBAAqB,CAACa,EAAE,CAAC;EACxC,EAAA;EACF,CAAC,CAAC;EACFhI,YAAY,CAACwC,EAAE,CAACyB,QAAQ,EAAExI,oBAAoB,EAAEsC,YAAY,CAACyJ,UAAU,CAAC;EACxExH,YAAY,CAACwC,EAAE,CAACyB,QAAQ,EAAEvI,oBAAoB,EAAEqC,YAAY,CAACyJ,UAAU,CAAC;;EAExE;EACA;EACA;;AAEAS,6BAAkB,CAAClK,YAAY,CAAC;;;;;;;;"} \ No newline at end of file diff --git a/js/dist/autocomplete.js b/js/dist/autocomplete.js new file mode 100644 index 000000000..9d6c035ab --- /dev/null +++ b/js/dist/autocomplete.js @@ -0,0 +1,867 @@ +/*! + * CoreUI autocomplete.js v5.15.0 (https://coreui.io) + * Copyright 2025 The CoreUI Team (https://github.com/orgs/coreui/people) + * Licensed under MIT (https://github.com/coreui/coreui/blob/main/LICENSE) + */ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('@popperjs/core'), require('./base-component.js'), require('./dom/data.js'), require('./dom/event-handler.js'), require('./dom/selector-engine.js'), require('./util/sanitizer.js'), require('./util/index.js')) : + typeof define === 'function' && define.amd ? define(['@popperjs/core', './base-component', './dom/data', './dom/event-handler', './dom/selector-engine', './util/sanitizer', './util/index'], factory) : + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Autocomplete = factory(global["@popperjs/core"], global.BaseComponent, global.Data, global.EventHandler, global.SelectorEngine, global.Sanitizer, global.Index)); +})(this, (function (Popper, BaseComponent, Data, EventHandler, SelectorEngine, sanitizer_js, index_js) { 'use strict'; + + function _interopNamespaceDefault(e) { + const n = Object.create(null, { [Symbol.toStringTag]: { value: 'Module' } }); + if (e) { + for (const k in e) { + if (k !== 'default') { + const d = Object.getOwnPropertyDescriptor(e, k); + Object.defineProperty(n, k, d.get ? d : { + enumerable: true, + get: () => e[k] + }); + } + } + } + n.default = e; + return Object.freeze(n); + } + + const Popper__namespace = /*#__PURE__*/_interopNamespaceDefault(Popper); + + /** + * -------------------------------------------------------------------------- + * CoreUI PRO autocomplete.js + * License (https://coreui.io/pro/license/) + * -------------------------------------------------------------------------- + */ + + + /** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + + const NAME = 'autocomplete'; + const DATA_KEY = 'coreui.autocomplete'; + const EVENT_KEY = `.${DATA_KEY}`; + const DATA_API_KEY = '.data-api'; + const ARROW_UP_KEY = 'ArrowUp'; + const ARROW_DOWN_KEY = 'ArrowDown'; + const BACKSPACE_KEY = 'Backspace'; + const DELETE_KEY = 'Delete'; + const ENTER_KEY = 'Enter'; + const ESCAPE_KEY = 'Escape'; + const TAB_KEY = 'Tab'; + const RIGHT_MOUSE_BUTTON = 2; // MouseEvent.button value for the secondary button, usually the right button + + const EVENT_BLUR = `blur${EVENT_KEY}`; + const EVENT_CHANGED = `changed${EVENT_KEY}`; + const EVENT_CLICK = `click${EVENT_KEY}`; + const EVENT_HIDE = `hide${EVENT_KEY}`; + const EVENT_HIDDEN = `hidden${EVENT_KEY}`; + const EVENT_INPUT = `input${EVENT_KEY}`; + const EVENT_KEYDOWN = `keydown${EVENT_KEY}`; + const EVENT_KEYUP = `keyup${EVENT_KEY}`; + const EVENT_SHOW = `show${EVENT_KEY}`; + const EVENT_SHOWN = `shown${EVENT_KEY}`; + const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`; + const EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY}${DATA_API_KEY}`; + const EVENT_LOAD_DATA_API = `load${EVENT_KEY}${DATA_API_KEY}`; + const CLASS_NAME_AUTOCOMPLETE = 'autocomplete'; + const CLASS_NAME_BUTTONS = 'autocomplete-buttons'; + const CLASS_NAME_CLEANER = 'autocomplete-cleaner'; + const CLASS_NAME_DISABLED = 'disabled'; + const CLASS_NAME_DROPDOWN = 'autocomplete-dropdown'; + const CLASS_NAME_INDICATOR = 'autocomplete-indicator'; + const CLASS_NAME_INPUT = 'autocomplete-input'; + const CLASS_NAME_INPUT_HINT = 'autocomplete-input-hint'; + const CLASS_NAME_INPUT_GROUP = 'autocomplete-input-group'; + const CLASS_NAME_LABEL = 'label'; + const CLASS_NAME_OPTGROUP = 'autocomplete-optgroup'; + const CLASS_NAME_OPTGROUP_LABEL = 'autocomplete-optgroup-label'; + const CLASS_NAME_OPTION = 'autocomplete-option'; + const CLASS_NAME_OPTIONS = 'autocomplete-options'; + const CLASS_NAME_OPTIONS_EMPTY = 'autocomplete-options-empty'; + const CLASS_NAME_SELECTED = 'selected'; + const CLASS_NAME_SHOW = 'show'; + const SELECTOR_DATA_TOGGLE = '[data-coreui-toggle="autocomplete"]:not(.disabled)'; + const SELECTOR_DATA_TOGGLE_SHOWN = `.autocomplete:not(.disabled).${CLASS_NAME_SHOW}`; + const SELECTOR_INDICATOR = '.autocomplete-indicator'; + const SELECTOR_OPTGROUP = '.autocomplete-optgroup'; + const SELECTOR_OPTION = '.autocomplete-option'; + const SELECTOR_OPTIONS = '.autocomplete-options'; + const SELECTOR_OPTIONS_EMPTY = '.autocomplete-options-empty'; + const SELECTOR_VISIBLE_ITEMS = '.autocomplete-options .autocomplete-option:not(.disabled):not(:disabled)'; + const Default = { + allowList: sanitizer_js.DefaultAllowlist, + allowOnlyDefinedOptions: false, + ariaCleanerLabel: 'Clear selection', + ariaIndicatorLabel: 'Toggle visibility of options menu', + cleaner: false, + clearSearchOnSelect: true, + container: false, + disabled: false, + highlightOptionsOnSearch: false, + id: null, + indicator: false, + invalid: false, + name: null, + options: false, + optionsGroupsTemplate: null, + optionsMaxHeight: 'auto', + optionsTemplate: null, + placeholder: null, + required: false, + sanitize: true, + sanitizeFn: null, + search: null, + searchNoResultsLabel: false, + showHints: false, + valid: false, + value: null + }; + const DefaultType = { + allowList: 'object', + allowOnlyDefinedOptions: 'boolean', + ariaCleanerLabel: 'string', + ariaIndicatorLabel: 'string', + cleaner: 'boolean', + clearSearchOnSelect: 'boolean', + container: '(string|element|boolean)', + disabled: 'boolean', + highlightOptionsOnSearch: 'boolean', + id: '(string|null)', + indicator: 'boolean', + invalid: 'boolean', + name: '(string|null)', + options: '(array|null)', + optionsGroupsTemplate: '(function|null)', + optionsMaxHeight: '(number|string)', + optionsTemplate: '(function|null)', + placeholder: '(string|null)', + required: 'boolean', + sanitize: 'boolean', + sanitizeFn: '(null|function)', + search: '(array|string|null)', + searchNoResultsLabel: 'boolean|string', + showHints: 'boolean', + valid: 'boolean', + value: '(number|string|null)' + }; + + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + + class Autocomplete extends BaseComponent { + constructor(element, config) { + var _this$_config$id; + super(element, config); + this._uniqueId = (_this$_config$id = this._config.id) != null ? _this$_config$id : index_js.getUID(`${this.constructor.NAME}`); + this._indicatorElement = null; + this._inputElement = null; + this._inputHintElement = null; + this._togglerElement = null; + this._optionsElement = null; + this._menu = null; + this._selected = []; + this._options = this._getOptionsFromConfig(); + this._popper = null; + this._search = ''; + this._createAutocomplete(); + this._addEventListeners(); + Data.set(this._element, DATA_KEY, this); + } + + // Getters + + static get Default() { + return Default; + } + static get DefaultType() { + return DefaultType; + } + static get NAME() { + return NAME; + } + + // Public + + toggle() { + return this._isShown() ? this.hide() : this.show(); + } + show() { + if (this._config.disabled || this._isShown()) { + return; + } + if (!this._config.searchNoResultsLabel && this._flattenOptions().filter(option => option.label.toLowerCase().includes(this._search.toLowerCase())).length === 0) { + return; + } + EventHandler.trigger(this._element, EVENT_SHOW); + this._element.classList.add(CLASS_NAME_SHOW); + this._inputElement.setAttribute('aria-expanded', true); + if (this._config.container) { + this._menu.style.minWidth = `${this._element.offsetWidth}px`; + this._menu.classList.add(CLASS_NAME_SHOW); + } + EventHandler.trigger(this._element, EVENT_SHOWN); + this._createPopper(); + } + hide() { + EventHandler.trigger(this._element, EVENT_HIDE); + if (this._popper) { + this._popper.destroy(); + } + this._element.classList.remove(CLASS_NAME_SHOW); + this._inputElement.setAttribute('aria-expanded', 'false'); + if (this._config.container) { + this._menu.classList.remove(CLASS_NAME_SHOW); + } + if (this._inputHintElement) { + this._inputHintElement.value = ''; + } + EventHandler.trigger(this._element, EVENT_HIDDEN); + } + dispose() { + if (this._popper) { + this._popper.destroy(); + } + super.dispose(); + } + clear() { + this.deselectAll(); + this.search(''); + this._filterOptionsList(); + this._inputElement.value = ''; + } + search(label) { + this._search = label.length > 0 ? label.toLowerCase() : ''; + if (!this._isExternalSearch()) { + this._filterOptionsList(); + } + EventHandler.trigger(this._element, EVENT_INPUT, { + value: label + }); + } + update(config) { + if (config.value) { + this.deselectAll(); + } + this._config = { + ...this._config, + ...this._configAfterMerge(config) + }; + this._options = this._getOptionsFromConfig(); + this._optionsElement.innerHTML = ''; + this._createOptions(this._optionsElement, this._options); + } + deselectAll(options = this._selected) { + for (const option of options) { + if (option.disabled) { + continue; + } + if (Array.isArray(option.options)) { + this.deselectAll(option.options); + continue; + } + this._deselectOption(option.value); + this._updateCleaner(); + } + } + + // Helpers + + _flattenOptions(options = this._options, flat = []) { + for (const opt of options) { + if (opt && Array.isArray(opt.options)) { + this._flattenOptions(opt.options, flat); + continue; + } + flat.push(opt); + } + return flat; + } + _getClassNames() { + return this._element.classList.value.split(' '); + } + _highlightOption(label) { + const regex = new RegExp(this._search, 'gi'); + return label.replace(regex, string => `${string}`); + } + _isExternalSearch() { + return Array.isArray(this._config.search) && this._config.search.includes('external'); + } + _isGlobalSearch() { + return Array.isArray(this._config.search) && this._config.search.includes('global'); + } + _isVisible(element) { + const style = window.getComputedStyle(element); + return style.display !== 'none'; + } + _isShown() { + return this._element.classList.contains(CLASS_NAME_SHOW); + } + + // Private + + _addEventListeners() { + EventHandler.on(this._element, EVENT_CLICK, event => { + if (!this._config.disabled && !event.target.closest(SELECTOR_INDICATOR)) { + this.show(); + } + }); + EventHandler.on(this._element, EVENT_KEYDOWN, event => { + if (event.key === ESCAPE_KEY) { + this.hide(); + if (this._config.allowOnlyDefinedOptions && this._selected.length === 0) { + this.search(''); + this._inputElement.value = ''; + } + return; + } + if (this._isGlobalSearch() && (event.key.length === 1 || event.key === BACKSPACE_KEY || event.key === DELETE_KEY)) { + this._inputElement.focus(); + } + }); + EventHandler.on(this._menu, EVENT_KEYDOWN, event => { + if (this._isGlobalSearch() && (event.key.length === 1 || event.key === BACKSPACE_KEY || event.key === DELETE_KEY)) { + this._inputElement.focus(); + } + }); + EventHandler.on(this._togglerElement, EVENT_KEYDOWN, event => { + if (!this._isShown() && (event.key === ENTER_KEY || event.key === ARROW_DOWN_KEY)) { + event.preventDefault(); + this.show(); + return; + } + if (this._isShown() && event.key === ARROW_DOWN_KEY) { + event.preventDefault(); + this._selectMenuItem(event); + } + }); + EventHandler.on(this._indicatorElement, EVENT_CLICK, event => { + event.preventDefault(); + // event.stopPropagation() + this.toggle(); + }); + EventHandler.on(this._inputElement, EVENT_BLUR, () => { + const options = this._flattenOptions().filter(option => option.label.toLowerCase().startsWith(this._inputElement.value.toLowerCase())); + if (this._config.allowOnlyDefinedOptions && this._selected.length === 0 && options.length === 0) { + this.clear(); + } + }); + EventHandler.on(this._inputElement, EVENT_KEYDOWN, event => { + if (!this._isShown() && event.key !== TAB_KEY) { + this.show(); + } + if (event.key === ARROW_DOWN_KEY && this._inputElement.value.length === this._inputElement.selectionStart) { + this._selectMenuItem(event); + return; + } + if (event.key === TAB_KEY && this._config.showHints && this._inputElement.value.length > 0) { + if (this._inputHintElement.value) { + event.preventDefault(); + event.stopPropagation(); + } + const options = this._flattenOptions().filter(option => option.label.toLowerCase().startsWith(this._inputElement.value.toLowerCase())); + if (options.length > 0) { + this._selectOption(options[0]); + } + } + if (event.key === ENTER_KEY) { + event.preventDefault(); + event.stopPropagation(); + if (this._inputElement.value.length === 0) { + return; + } + const options = this._flattenOptions().filter(option => option.label.toLowerCase() === this._inputElement.value.toLowerCase()); + if (options.length > 0) { + this._selectOption(options[0]); + } + if (options.length === 0 && !this._config.allowOnlyDefinedOptions) { + EventHandler.trigger(this._element, EVENT_CHANGED, { + value: this._inputElement.value + }); + this.hide(); + if (this._config.clearSearchOnSelect) { + this.search(''); + } + } + } + }); + EventHandler.on(this._inputElement, EVENT_KEYUP, event => { + if (event.key.length === 1 || event.key === BACKSPACE_KEY || event.key === DELETE_KEY) { + const { + value + } = event.target; + this.deselectAll(); + this.search(value); + if (this._config.showHints) { + const options = value ? this._flattenOptions().filter(option => option.label.toLowerCase().startsWith(value.toLowerCase())) : []; + this._inputHintElement.value = options.length > 0 ? `${value}${options[0].label.slice(value.length)}` : ''; + } + } + }); + EventHandler.on(this._optionsElement, EVENT_CLICK, event => { + event.preventDefault(); + event.stopPropagation(); + this._onOptionsClick(event.target); + }); + EventHandler.on(this._cleanerElement, EVENT_CLICK, event => { + if (!this._config.disabled) { + event.preventDefault(); + event.stopPropagation(); + this.clear(); + } + }); + EventHandler.on(this._optionsElement, EVENT_KEYDOWN, event => { + if (event.key === ENTER_KEY) { + this._onOptionsClick(event.target); + } + if ([ARROW_UP_KEY, ARROW_DOWN_KEY].includes(event.key)) { + event.preventDefault(); + this._selectMenuItem(event); + } + }); + } + _getOptionsFromConfig(options = this._config.options) { + if (!options || !Array.isArray(options)) { + return []; + } + const _options = []; + for (const option of options) { + var _option$value; + if (option.options && Array.isArray(option.options)) { + const customGroupProperties = { + ...option + }; + delete customGroupProperties.label; + delete customGroupProperties.options; + _options.push({ + ...customGroupProperties, + label: option.label, + options: this._getOptionsFromConfig(option.options) + }); + continue; + } + const label = typeof option === 'string' ? option : option.label; + const value = (_option$value = option.value) != null ? _option$value : typeof option === 'string' ? option : option.label; + const isSelected = option.selected || this._config.value && this._config.value === value; + const customProperties = typeof option === 'object' ? { + ...option + } : {}; + delete customProperties.label; + delete customProperties.value; + delete customProperties.selected; + delete customProperties.disabled; + _options.push({ + ...customProperties, + label, + value, + ...(isSelected && { + selected: true + }), + ...(option.disabled && { + disabled: true + }) + }); + if (isSelected) { + this._selected.push({ + label: option.label, + value: String(option.label) + }); + } + } + return _options; + } + _createAutocomplete() { + this._element.classList.add(CLASS_NAME_AUTOCOMPLETE); + this._element.classList.toggle('is-invalid', this._config.invalid); + this._element.classList.toggle('is-valid', this._config.valid); + if (this._config.disabled) { + this._element.classList.add(CLASS_NAME_DISABLED); + } + for (const className of this._getClassNames()) { + this._element.classList.add(className); + } + this._createInputGroup(); + this._createButtons(); + this._createOptionsContainer(); + this._updateOptionsList(); + } + _createInputGroup() { + var _this$_config$placeho; + const togglerEl = document.createElement('div'); + togglerEl.classList.add(CLASS_NAME_INPUT_GROUP); + this._togglerElement = togglerEl; + if (!this._config.search && !this._config.disabled) { + togglerEl.tabIndex = -1; + } + if (!this._config.disabled && this._config.showHints) { + const inputHintEl = document.createElement('input'); + inputHintEl.classList.add(CLASS_NAME_INPUT, CLASS_NAME_INPUT_HINT); + inputHintEl.setAttribute('name', (this._config.name || `${this._uniqueId}-hint`).toString()); + inputHintEl.autocomplete = 'off'; + inputHintEl.readOnly = true; + inputHintEl.tabIndex = -1; + inputHintEl.setAttribute('aria-hidden', true); + togglerEl.append(inputHintEl); + this._inputHintElement = inputHintEl; + } + const inputEl = document.createElement('input'); + inputEl.classList.add(CLASS_NAME_INPUT); + inputEl.id = this._uniqueId; + inputEl.setAttribute('name', (this._config.name || this._uniqueId).toString()); + inputEl.autocomplete = 'off'; + inputEl.placeholder = (_this$_config$placeho = this._config.placeholder) != null ? _this$_config$placeho : ''; + inputEl.role = 'combobox'; + inputEl.setAttribute('aria-autocomplete', 'list'); + inputEl.setAttribute('aria-expanded', 'false'); + inputEl.setAttribute('aria-haspopup', 'listbox'); + if (this._config.disabled) { + inputEl.setAttribute('disabled', true); + inputEl.tabIndex = -1; + } + if (this._config.required) { + inputEl.setAttribute('required', true); + } + togglerEl.append(inputEl); + this._inputElement = inputEl; + this._element.append(togglerEl); + } + _createButtons() { + if (!this._config.cleaner && !this._config.indicator) { + return; + } + const buttons = document.createElement('div'); + buttons.classList.add(CLASS_NAME_BUTTONS); + if (!this._config.disabled && this._config.cleaner) { + const cleaner = document.createElement('button'); + cleaner.type = 'button'; + cleaner.classList.add(CLASS_NAME_CLEANER); + cleaner.style.display = 'none'; + cleaner.setAttribute('aria-label', this._config.ariaCleanerLabel); + buttons.append(cleaner); + this._cleanerElement = cleaner; + } + if (this._config.indicator) { + const indicator = document.createElement('button'); + indicator.type = 'button'; + indicator.classList.add(CLASS_NAME_INDICATOR); + indicator.setAttribute('aria-label', this._config.ariaIndicatorLabel); + if (this._config.disabled) { + indicator.tabIndex = -1; + } + buttons.append(indicator); + this._indicatorElement = indicator; + this._indicatorElement = indicator; + } + this._togglerElement.append(buttons); + this._updateCleaner(); + } + _createPopper() { + if (typeof Popper__namespace === 'undefined') { + throw new TypeError('CoreUI\'s Auto Complete component require Popper (https://popper.js.org)'); + } + const popperConfig = { + modifiers: [{ + name: 'preventOverflow', + options: { + boundary: 'clippingParents' + } + }, { + name: 'offset', + options: { + offset: [0, 2] + } + }], + placement: index_js.isRTL() ? 'bottom-end' : 'bottom-start' + }; + this._popper = Popper__namespace.createPopper(this._togglerElement, this._menu, popperConfig); + } + _createOptionsContainer() { + const dropdownDiv = document.createElement('div'); + dropdownDiv.classList.add(CLASS_NAME_DROPDOWN); + dropdownDiv.role = 'listbox'; + dropdownDiv.setAttribute('aria-labelledby', this._uniqueId); + const optionsDiv = document.createElement('div'); + optionsDiv.classList.add(CLASS_NAME_OPTIONS); + if (this._config.optionsMaxHeight !== 'auto') { + optionsDiv.style.maxHeight = `${this._config.optionsMaxHeight}px`; + optionsDiv.style.overflow = 'auto'; + } + dropdownDiv.append(optionsDiv); + const { + container + } = this._config; + if (container) { + container.append(dropdownDiv); + } else { + this._element.append(dropdownDiv); + } + this._createOptions(optionsDiv, this._options); + this._optionsElement = optionsDiv; + this._menu = dropdownDiv; + } + _createOptions(parentElement, options) { + for (const option of options) { + if (Array.isArray(option.options)) { + const optgroup = document.createElement('div'); + optgroup.classList.add(CLASS_NAME_OPTGROUP); + optgroup.setAttribute('role', 'group'); + const optgrouplabel = document.createElement('div'); + if (this._config.optionsGroupsTemplate && typeof this._config.optionsGroupsTemplate === 'function') { + optgrouplabel.innerHTML = this._config.sanitize ? sanitizer_js.sanitizeHtml(this._config.optionsGroupsTemplate(option), this._config.allowList, this._config.sanitizeFn) : this._config.optionsGroupsTemplate(option); + } else { + optgrouplabel.textContent = option.label; + } + optgrouplabel.classList.add(CLASS_NAME_OPTGROUP_LABEL); + optgroup.append(optgrouplabel); + this._createOptions(optgroup, option.options); + parentElement.append(optgroup); + continue; + } + const optionDiv = document.createElement('div'); + optionDiv.classList.add(CLASS_NAME_OPTION); + if (option.disabled) { + optionDiv.classList.add(CLASS_NAME_DISABLED); + optionDiv.setAttribute('aria-disabled', 'true'); + } + optionDiv.dataset.value = option.value; + optionDiv.tabIndex = 0; + if (this._isExternalSearch() && this._config.highlightOptionsOnSearch && this._search) { + optionDiv.innerHTML = this._highlightOption(option.label); + } else if (this._config.optionsTemplate && typeof this._config.optionsTemplate === 'function') { + optionDiv.innerHTML = this._config.sanitize ? sanitizer_js.sanitizeHtml(this._config.optionsTemplate(option), this._config.allowList, this._config.sanitizeFn) : this._config.optionsTemplate(option); + } else { + optionDiv.textContent = option.label; + } + parentElement.append(optionDiv); + } + } + _onOptionsClick(element) { + if (element.classList.contains(CLASS_NAME_LABEL)) { + return; + } + if (!element.classList.contains(CLASS_NAME_OPTION)) { + element = element.closest(SELECTOR_OPTION); + if (!element) { + return; + } + } + const value = String(element.dataset.value); + const foundOption = this._findOptionByValue(value); + if (foundOption) { + this._selectOption(foundOption); + } + } + _findOptionByValue(value, options = this._options) { + for (const option of options) { + if (option.value === value) { + return option; + } + if (option.options && Array.isArray(option.options)) { + const found = this._findOptionByValue(value, option.options); + if (found) { + return found; + } + } + } + return null; + } + _selectOption(option) { + this.deselectAll(); + if (this._selected.filter(selectedOption => selectedOption.value === option.value).length === 0) { + this._selected.push(option); + } + const foundOption = SelectorEngine.findOne(`[data-value="${option.value}"]`, this._optionsElement); + if (foundOption) { + foundOption.classList.add(CLASS_NAME_SELECTED); + foundOption.setAttribute('aria-selected', true); + } + EventHandler.trigger(this._element, EVENT_CHANGED, { + value: option + }); + this._inputElement.value = option.label; + if (this._config.showHints) { + this._inputHintElement.value = ''; + } + this.hide(); + if (this._config.clearSearchOnSelect) { + this.search(''); + } + this._inputElement.focus(); + this._updateCleaner(); + } + _deselectOption(value) { + this._selected = this._selected.filter(option => option.value !== String(value)); + const option = SelectorEngine.findOne(`[data-value="${value}"]`, this._optionsElement); + if (option) { + option.classList.remove(CLASS_NAME_SELECTED); + option.setAttribute('aria-selected', false); + } + EventHandler.trigger(this._element, EVENT_CHANGED, { + value: this._selected + }); + } + _updateCleaner() { + if (!this._config.cleaner || this._cleanerElement === null) { + return; + } + if (this._selected.length > 0) { + this._cleanerElement.style.removeProperty('display'); + return; + } + this._cleanerElement.style.display = 'none'; + } + _updateOptionsList(options = this._options) { + for (const option of options) { + if (Array.isArray(option.options)) { + this._updateOptionsList(option.options); + continue; + } + if (option.selected) { + this._selectOption(option); + } + } + } + _filterOptionsList() { + const options = SelectorEngine.find(SELECTOR_OPTION, this._menu); + let visibleOptions = 0; + for (const option of options) { + // eslint-disable-next-line unicorn/prefer-includes + if (option.textContent.toLowerCase().indexOf(this._search) === -1) { + option.style.display = 'none'; + } else { + if (this._config.highlightOptionsOnSearch && !this._config.optionsTemplate) { + option.innerHTML = this._highlightOption(option.textContent); + } + option.style.removeProperty('display'); + visibleOptions++; + } + const optgroup = option.closest(SELECTOR_OPTGROUP); + if (optgroup) { + // eslint-disable-next-line unicorn/prefer-array-some + if (SelectorEngine.children(optgroup, SELECTOR_OPTION).filter(element => this._isVisible(element)).length > 0) { + optgroup.style.removeProperty('display'); + } else { + optgroup.style.display = 'none'; + } + } + } + if (visibleOptions > 0) { + if (SelectorEngine.findOne(SELECTOR_OPTIONS_EMPTY, this._menu)) { + SelectorEngine.findOne(SELECTOR_OPTIONS_EMPTY, this._menu).remove(); + } + return; + } + if (visibleOptions === 0) { + if (this._config.searchNoResultsLabel) { + const placeholder = document.createElement('div'); + placeholder.classList.add(CLASS_NAME_OPTIONS_EMPTY); + placeholder.innerHTML = this._config.searchNoResultsLabel; + if (!SelectorEngine.findOne(SELECTOR_OPTIONS_EMPTY, this._menu)) { + SelectorEngine.findOne(SELECTOR_OPTIONS, this._menu).append(placeholder); + } + return; + } + this.hide(); + } + } + _selectMenuItem({ + key, + target + }) { + const items = SelectorEngine.find(SELECTOR_VISIBLE_ITEMS, this._menu).filter(element => index_js.isVisible(element)); + if (!items.length) { + return; + } + + // if target isn't included in items (e.g. when expanding the dropdown) + // allow cycling to get the last item in case key equals ARROW_UP_KEY + index_js.getNextActiveElement(items, target, key === ARROW_DOWN_KEY, !items.includes(target)).focus(); + } + _configAfterMerge(config) { + if (config.container === true) { + config.container = document.body; + } + if (typeof config.container === 'object' || typeof config.container === 'string') { + config.container = index_js.getElement(config.container); + } + if (typeof config.options === 'string') { + config.options = config.options.split(/,\s*/).map(String); + } + if (typeof config.search === 'string') { + config.search = config.search.split(/,\s*/).map(String); + } + return config; + } + + // Static + + static autocompleteInterface(element, config) { + const data = Autocomplete.getOrCreateInstance(element, config); + if (typeof config === 'string') { + if (typeof data[config] === 'undefined') { + throw new TypeError(`No method named "${config}"`); + } + data[config](); + } + } + static jQueryInterface(config) { + return this.each(function () { + Autocomplete.autocompleteInterface(this, config); + }); + } + static clearMenus(event) { + if (event.button === RIGHT_MOUSE_BUTTON || event.type === 'keyup' && event.key !== TAB_KEY) { + return; + } + const openToggles = SelectorEngine.find(SELECTOR_DATA_TOGGLE_SHOWN); + for (const toggle of openToggles) { + const context = Autocomplete.getInstance(toggle); + if (!context) { + continue; + } + const composedPath = event.composedPath(); + if (composedPath.includes(context._element)) { + continue; + } + ({ + relatedTarget: context._element + }); + if (event.type === 'click') ; + context.hide(); + context.search(''); + if (context._config.allowOnlyDefinedOptions && context._selected.length === 0) { + context._inputElement.value = ''; + } + } + } + } + + /** + * Data API implementation + */ + + EventHandler.on(window, EVENT_LOAD_DATA_API, () => { + for (const autocomplete of SelectorEngine.find(SELECTOR_DATA_TOGGLE)) { + Autocomplete.autocompleteInterface(autocomplete); + } + }); + EventHandler.on(document, EVENT_CLICK_DATA_API, Autocomplete.clearMenus); + EventHandler.on(document, EVENT_KEYUP_DATA_API, Autocomplete.clearMenus); + + /** + * jQuery + */ + + index_js.defineJQueryPlugin(Autocomplete); + + return Autocomplete; + +})); +//# sourceMappingURL=autocomplete.js.map diff --git a/js/dist/autocomplete.js.map b/js/dist/autocomplete.js.map new file mode 100644 index 000000000..c27c566ae --- /dev/null +++ b/js/dist/autocomplete.js.map @@ -0,0 +1 @@ +{"version":3,"file":"autocomplete.js","sources":["../src/autocomplete.js"],"sourcesContent":["/**\n * --------------------------------------------------------------------------\n * CoreUI PRO autocomplete.js\n * License (https://coreui.io/pro/license/)\n * --------------------------------------------------------------------------\n */\n\nimport * as Popper from '@popperjs/core'\nimport BaseComponent from './base-component.js'\nimport Data from './dom/data.js'\nimport EventHandler from './dom/event-handler.js'\nimport SelectorEngine from './dom/selector-engine.js'\nimport { DefaultAllowlist, sanitizeHtml } from './util/sanitizer.js'\nimport {\n defineJQueryPlugin,\n getNextActiveElement,\n getElement,\n getUID,\n isVisible,\n isRTL\n} from './util/index.js'\n\n/**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\nconst NAME = 'autocomplete'\nconst DATA_KEY = 'coreui.autocomplete'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst DATA_API_KEY = '.data-api'\n\nconst ARROW_UP_KEY = 'ArrowUp'\nconst ARROW_DOWN_KEY = 'ArrowDown'\nconst BACKSPACE_KEY = 'Backspace'\nconst DELETE_KEY = 'Delete'\nconst ENTER_KEY = 'Enter'\nconst ESCAPE_KEY = 'Escape'\nconst TAB_KEY = 'Tab'\nconst RIGHT_MOUSE_BUTTON = 2 // MouseEvent.button value for the secondary button, usually the right button\n\nconst EVENT_BLUR = `blur${EVENT_KEY}`\nconst EVENT_CHANGED = `changed${EVENT_KEY}`\nconst EVENT_CLICK = `click${EVENT_KEY}`\nconst EVENT_HIDE = `hide${EVENT_KEY}`\nconst EVENT_HIDDEN = `hidden${EVENT_KEY}`\nconst EVENT_INPUT = `input${EVENT_KEY}`\nconst EVENT_KEYDOWN = `keydown${EVENT_KEY}`\nconst EVENT_KEYUP = `keyup${EVENT_KEY}`\nconst EVENT_SHOW = `show${EVENT_KEY}`\nconst EVENT_SHOWN = `shown${EVENT_KEY}`\nconst EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`\nconst EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY}${DATA_API_KEY}`\nconst EVENT_LOAD_DATA_API = `load${EVENT_KEY}${DATA_API_KEY}`\n\nconst CLASS_NAME_AUTOCOMPLETE = 'autocomplete'\nconst CLASS_NAME_BUTTONS = 'autocomplete-buttons'\nconst CLASS_NAME_CLEANER = 'autocomplete-cleaner'\nconst CLASS_NAME_DISABLED = 'disabled'\nconst CLASS_NAME_DROPDOWN = 'autocomplete-dropdown'\nconst CLASS_NAME_INDICATOR = 'autocomplete-indicator'\nconst CLASS_NAME_INPUT = 'autocomplete-input'\nconst CLASS_NAME_INPUT_HINT = 'autocomplete-input-hint'\nconst CLASS_NAME_INPUT_GROUP = 'autocomplete-input-group'\nconst CLASS_NAME_LABEL = 'label'\nconst CLASS_NAME_OPTGROUP = 'autocomplete-optgroup'\nconst CLASS_NAME_OPTGROUP_LABEL = 'autocomplete-optgroup-label'\nconst CLASS_NAME_OPTION = 'autocomplete-option'\nconst CLASS_NAME_OPTIONS = 'autocomplete-options'\nconst CLASS_NAME_OPTIONS_EMPTY = 'autocomplete-options-empty'\nconst CLASS_NAME_SELECTED = 'selected'\nconst CLASS_NAME_SHOW = 'show'\n\nconst SELECTOR_DATA_TOGGLE = '[data-coreui-toggle=\"autocomplete\"]:not(.disabled)'\nconst SELECTOR_DATA_TOGGLE_SHOWN = `.autocomplete:not(.disabled).${CLASS_NAME_SHOW}`\nconst SELECTOR_INDICATOR = '.autocomplete-indicator'\nconst SELECTOR_OPTGROUP = '.autocomplete-optgroup'\nconst SELECTOR_OPTION = '.autocomplete-option'\nconst SELECTOR_OPTIONS = '.autocomplete-options'\nconst SELECTOR_OPTIONS_EMPTY = '.autocomplete-options-empty'\nconst SELECTOR_VISIBLE_ITEMS = '.autocomplete-options .autocomplete-option:not(.disabled):not(:disabled)'\n\nconst Default = {\n allowList: DefaultAllowlist,\n allowOnlyDefinedOptions: false,\n ariaCleanerLabel: 'Clear selection',\n ariaIndicatorLabel: 'Toggle visibility of options menu',\n cleaner: false,\n clearSearchOnSelect: true,\n container: false,\n disabled: false,\n highlightOptionsOnSearch: false,\n id: null,\n indicator: false,\n invalid: false,\n name: null,\n options: false,\n optionsGroupsTemplate: null,\n optionsMaxHeight: 'auto',\n optionsTemplate: null,\n placeholder: null,\n required: false,\n sanitize: true,\n sanitizeFn: null,\n search: null,\n searchNoResultsLabel: false,\n showHints: false,\n valid: false,\n value: null\n}\n\nconst DefaultType = {\n allowList: 'object',\n allowOnlyDefinedOptions: 'boolean',\n ariaCleanerLabel: 'string',\n ariaIndicatorLabel: 'string',\n cleaner: 'boolean',\n clearSearchOnSelect: 'boolean',\n container: '(string|element|boolean)',\n disabled: 'boolean',\n highlightOptionsOnSearch: 'boolean',\n id: '(string|null)',\n indicator: 'boolean',\n invalid: 'boolean',\n name: '(string|null)',\n options: '(array|null)',\n optionsGroupsTemplate: '(function|null)',\n optionsMaxHeight: '(number|string)',\n optionsTemplate: '(function|null)',\n placeholder: '(string|null)',\n required: 'boolean',\n sanitize: 'boolean',\n sanitizeFn: '(null|function)',\n search: '(array|string|null)',\n searchNoResultsLabel: ('boolean|string'),\n showHints: 'boolean',\n valid: 'boolean',\n value: '(number|string|null)'\n}\n\n/**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\nclass Autocomplete extends BaseComponent {\n constructor(element, config) {\n super(element, config)\n\n this._uniqueId = this._config.id ?? getUID(`${this.constructor.NAME}`)\n this._indicatorElement = null\n this._inputElement = null\n this._inputHintElement = null\n this._togglerElement = null\n this._optionsElement = null\n\n this._menu = null\n this._selected = []\n this._options = this._getOptionsFromConfig()\n this._popper = null\n this._search = ''\n\n this._createAutocomplete()\n this._addEventListeners()\n\n Data.set(this._element, DATA_KEY, this)\n }\n\n // Getters\n\n static get Default() {\n return Default\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n static get NAME() {\n return NAME\n }\n\n // Public\n\n toggle() {\n return this._isShown() ? this.hide() : this.show()\n }\n\n show() {\n if (this._config.disabled || this._isShown()) {\n return\n }\n\n if (\n !this._config.searchNoResultsLabel &&\n this._flattenOptions().filter(option => option.label.toLowerCase().includes(this._search.toLowerCase())).length === 0) {\n return\n }\n\n EventHandler.trigger(this._element, EVENT_SHOW)\n this._element.classList.add(CLASS_NAME_SHOW)\n this._inputElement.setAttribute('aria-expanded', true)\n\n if (this._config.container) {\n this._menu.style.minWidth = `${this._element.offsetWidth}px`\n this._menu.classList.add(CLASS_NAME_SHOW)\n }\n\n EventHandler.trigger(this._element, EVENT_SHOWN)\n\n this._createPopper()\n }\n\n hide() {\n EventHandler.trigger(this._element, EVENT_HIDE)\n\n if (this._popper) {\n this._popper.destroy()\n }\n\n this._element.classList.remove(CLASS_NAME_SHOW)\n this._inputElement.setAttribute('aria-expanded', 'false')\n\n if (this._config.container) {\n this._menu.classList.remove(CLASS_NAME_SHOW)\n }\n\n if (this._inputHintElement) {\n this._inputHintElement.value = ''\n }\n\n EventHandler.trigger(this._element, EVENT_HIDDEN)\n }\n\n dispose() {\n if (this._popper) {\n this._popper.destroy()\n }\n\n super.dispose()\n }\n\n clear() {\n this.deselectAll()\n this.search('')\n this._filterOptionsList()\n this._inputElement.value = ''\n }\n\n search(label) {\n this._search = label.length > 0 ? label.toLowerCase() : ''\n if (!this._isExternalSearch()) {\n this._filterOptionsList()\n }\n\n EventHandler.trigger(this._element, EVENT_INPUT, {\n value: label\n })\n }\n\n update(config) {\n if (config.value) {\n this.deselectAll()\n }\n\n this._config = { ...this._config, ...this._configAfterMerge(config) }\n this._options = this._getOptionsFromConfig()\n this._optionsElement.innerHTML = ''\n this._createOptions(this._optionsElement, this._options)\n }\n\n deselectAll(options = this._selected) {\n for (const option of options) {\n if (option.disabled) {\n continue\n }\n\n if (Array.isArray(option.options)) {\n this.deselectAll(option.options)\n continue\n }\n\n this._deselectOption(option.value)\n this._updateCleaner()\n }\n }\n\n // Helpers\n\n _flattenOptions(options = this._options, flat = []) {\n for (const opt of options) {\n if (opt && Array.isArray(opt.options)) {\n this._flattenOptions(opt.options, flat)\n continue\n }\n\n flat.push(opt)\n }\n\n return flat\n }\n\n _getClassNames() {\n return this._element.classList.value.split(' ')\n }\n\n _highlightOption(label) {\n const regex = new RegExp(this._search, 'gi')\n return label.replace(regex, string => `${string}`)\n }\n\n _isExternalSearch() {\n return Array.isArray(this._config.search) && this._config.search.includes('external')\n }\n\n _isGlobalSearch() {\n return Array.isArray(this._config.search) && this._config.search.includes('global')\n }\n\n _isVisible(element) {\n const style = window.getComputedStyle(element)\n return (style.display !== 'none')\n }\n\n _isShown() {\n return this._element.classList.contains(CLASS_NAME_SHOW)\n }\n\n // Private\n\n _addEventListeners() {\n EventHandler.on(this._element, EVENT_CLICK, event => {\n if (!this._config.disabled && !event.target.closest(SELECTOR_INDICATOR)) {\n this.show()\n }\n })\n\n EventHandler.on(this._element, EVENT_KEYDOWN, event => {\n if (event.key === ESCAPE_KEY) {\n this.hide()\n if (this._config.allowOnlyDefinedOptions && this._selected.length === 0) {\n this.search('')\n this._inputElement.value = ''\n }\n\n return\n }\n\n if (this._isGlobalSearch() && (event.key.length === 1 || event.key === BACKSPACE_KEY || event.key === DELETE_KEY)) {\n this._inputElement.focus()\n }\n })\n\n EventHandler.on(this._menu, EVENT_KEYDOWN, event => {\n if (this._isGlobalSearch() && (event.key.length === 1 || event.key === BACKSPACE_KEY || event.key === DELETE_KEY)) {\n this._inputElement.focus()\n }\n })\n\n EventHandler.on(this._togglerElement, EVENT_KEYDOWN, event => {\n if (!this._isShown() && (event.key === ENTER_KEY || event.key === ARROW_DOWN_KEY)) {\n event.preventDefault()\n this.show()\n return\n }\n\n if (this._isShown() && event.key === ARROW_DOWN_KEY) {\n event.preventDefault()\n this._selectMenuItem(event)\n }\n })\n\n EventHandler.on(this._indicatorElement, EVENT_CLICK, event => {\n event.preventDefault()\n // event.stopPropagation()\n this.toggle()\n })\n\n EventHandler.on(this._inputElement, EVENT_BLUR, () => {\n const options = this._flattenOptions().filter(option => option.label.toLowerCase().startsWith(this._inputElement.value.toLowerCase()))\n if (this._config.allowOnlyDefinedOptions && this._selected.length === 0 && options.length === 0) {\n this.clear()\n }\n })\n\n EventHandler.on(this._inputElement, EVENT_KEYDOWN, event => {\n if (!this._isShown() && event.key !== TAB_KEY) {\n this.show()\n }\n\n if (event.key === ARROW_DOWN_KEY && this._inputElement.value.length === this._inputElement.selectionStart) {\n this._selectMenuItem(event)\n return\n }\n\n if (event.key === TAB_KEY && this._config.showHints && this._inputElement.value.length > 0) {\n if (this._inputHintElement.value) {\n event.preventDefault()\n event.stopPropagation()\n }\n\n const options = this._flattenOptions().filter(option => option.label.toLowerCase().startsWith(this._inputElement.value.toLowerCase()))\n\n if (options.length > 0) {\n this._selectOption(options[0])\n }\n }\n\n if (event.key === ENTER_KEY) {\n event.preventDefault()\n event.stopPropagation()\n\n if (this._inputElement.value.length === 0) {\n return\n }\n\n const options = this._flattenOptions().filter(option => option.label.toLowerCase() === this._inputElement.value.toLowerCase())\n\n if (options.length > 0) {\n this._selectOption(options[0])\n }\n\n if (options.length === 0 && !this._config.allowOnlyDefinedOptions) {\n EventHandler.trigger(this._element, EVENT_CHANGED, {\n value: this._inputElement.value\n })\n\n this.hide()\n\n if (this._config.clearSearchOnSelect) {\n this.search('')\n }\n }\n }\n })\n\n EventHandler.on(this._inputElement, EVENT_KEYUP, event => {\n if (event.key.length === 1 || event.key === BACKSPACE_KEY || event.key === DELETE_KEY) {\n const { value } = event.target\n this.deselectAll()\n this.search(value)\n if (this._config.showHints) {\n const options = value ?\n this._flattenOptions().filter(option => option.label.toLowerCase().startsWith(value.toLowerCase())) :\n []\n this._inputHintElement.value = options.length > 0 ? `${value}${options[0].label.slice(value.length)}` : ''\n }\n }\n })\n\n EventHandler.on(this._optionsElement, EVENT_CLICK, event => {\n event.preventDefault()\n event.stopPropagation()\n this._onOptionsClick(event.target)\n })\n\n EventHandler.on(this._cleanerElement, EVENT_CLICK, event => {\n if (!this._config.disabled) {\n event.preventDefault()\n event.stopPropagation()\n this.clear()\n }\n })\n\n EventHandler.on(this._optionsElement, EVENT_KEYDOWN, event => {\n if (event.key === ENTER_KEY) {\n this._onOptionsClick(event.target)\n }\n\n if ([ARROW_UP_KEY, ARROW_DOWN_KEY].includes(event.key)) {\n event.preventDefault()\n this._selectMenuItem(event)\n }\n })\n }\n\n _getOptionsFromConfig(options = this._config.options) {\n if (!options || !Array.isArray(options)) {\n return []\n }\n\n const _options = []\n for (const option of options) {\n if (option.options && Array.isArray(option.options)) {\n const customGroupProperties = { ...option }\n\n delete customGroupProperties.label\n delete customGroupProperties.options\n\n _options.push({\n ...customGroupProperties,\n label: option.label,\n options: this._getOptionsFromConfig(option.options)\n })\n\n continue\n }\n\n const label = typeof option === 'string' ? option : option.label\n const value = option.value ?? (typeof option === 'string' ? option : option.label)\n const isSelected = option.selected || (this._config.value && this._config.value === value)\n\n const customProperties = typeof option === 'object' ? { ...option } : {}\n\n delete customProperties.label\n delete customProperties.value\n delete customProperties.selected\n delete customProperties.disabled\n\n _options.push({\n ...customProperties,\n label,\n value,\n ...isSelected && { selected: true },\n ...option.disabled && { disabled: true }\n })\n\n if (isSelected) {\n this._selected.push({\n label: option.label,\n value: String(option.label)\n })\n }\n }\n\n return _options\n }\n\n _createAutocomplete() {\n this._element.classList.add(CLASS_NAME_AUTOCOMPLETE)\n this._element.classList.toggle('is-invalid', this._config.invalid)\n this._element.classList.toggle('is-valid', this._config.valid)\n\n if (this._config.disabled) {\n this._element.classList.add(CLASS_NAME_DISABLED)\n }\n\n for (const className of this._getClassNames()) {\n this._element.classList.add(className)\n }\n\n this._createInputGroup()\n this._createButtons()\n this._createOptionsContainer()\n this._updateOptionsList()\n }\n\n _createInputGroup() {\n const togglerEl = document.createElement('div')\n togglerEl.classList.add(CLASS_NAME_INPUT_GROUP)\n this._togglerElement = togglerEl\n\n if (!this._config.search && !this._config.disabled) {\n togglerEl.tabIndex = -1\n }\n\n if (!this._config.disabled && this._config.showHints) {\n const inputHintEl = document.createElement('input')\n inputHintEl.classList.add(CLASS_NAME_INPUT, CLASS_NAME_INPUT_HINT)\n inputHintEl.setAttribute('name', (this._config.name || `${this._uniqueId}-hint`).toString())\n inputHintEl.autocomplete = 'off'\n inputHintEl.readOnly = true\n inputHintEl.tabIndex = -1\n inputHintEl.setAttribute('aria-hidden', true)\n\n togglerEl.append(inputHintEl)\n this._inputHintElement = inputHintEl\n }\n\n const inputEl = document.createElement('input')\n inputEl.classList.add(CLASS_NAME_INPUT)\n inputEl.id = this._uniqueId\n inputEl.setAttribute('name', (this._config.name || this._uniqueId).toString())\n inputEl.autocomplete = 'off'\n inputEl.placeholder = this._config.placeholder ?? ''\n inputEl.role = 'combobox'\n inputEl.setAttribute('aria-autocomplete', 'list')\n inputEl.setAttribute('aria-expanded', 'false')\n inputEl.setAttribute('aria-haspopup', 'listbox')\n\n if (this._config.disabled) {\n inputEl.setAttribute('disabled', true)\n inputEl.tabIndex = -1\n }\n\n if (this._config.required) {\n inputEl.setAttribute('required', true)\n }\n\n togglerEl.append(inputEl)\n this._inputElement = inputEl\n\n this._element.append(togglerEl)\n }\n\n _createButtons() {\n if (!this._config.cleaner && !this._config.indicator) {\n return\n }\n\n const buttons = document.createElement('div')\n buttons.classList.add(CLASS_NAME_BUTTONS)\n\n if (!this._config.disabled && this._config.cleaner) {\n const cleaner = document.createElement('button')\n cleaner.type = 'button'\n cleaner.classList.add(CLASS_NAME_CLEANER)\n cleaner.style.display = 'none'\n cleaner.setAttribute('aria-label', this._config.ariaCleanerLabel)\n\n buttons.append(cleaner)\n this._cleanerElement = cleaner\n }\n\n if (this._config.indicator) {\n const indicator = document.createElement('button')\n indicator.type = 'button'\n indicator.classList.add(CLASS_NAME_INDICATOR)\n indicator.setAttribute('aria-label', this._config.ariaIndicatorLabel)\n\n if (this._config.disabled) {\n indicator.tabIndex = -1\n }\n\n buttons.append(indicator)\n this._indicatorElement = indicator\n this._indicatorElement = indicator\n }\n\n this._togglerElement.append(buttons)\n this._updateCleaner()\n }\n\n _createPopper() {\n if (typeof Popper === 'undefined') {\n throw new TypeError('CoreUI\\'s Auto Complete component require Popper (https://popper.js.org)')\n }\n\n const popperConfig = {\n modifiers: [{\n name: 'preventOverflow',\n options: {\n boundary: 'clippingParents'\n }\n },\n {\n name: 'offset',\n options: {\n offset: [0, 2]\n }\n }],\n placement: isRTL() ? 'bottom-end' : 'bottom-start'\n }\n\n this._popper = Popper.createPopper(this._togglerElement, this._menu, popperConfig)\n }\n\n _createOptionsContainer() {\n const dropdownDiv = document.createElement('div')\n dropdownDiv.classList.add(CLASS_NAME_DROPDOWN)\n dropdownDiv.role = 'listbox'\n dropdownDiv.setAttribute('aria-labelledby', this._uniqueId)\n\n const optionsDiv = document.createElement('div')\n optionsDiv.classList.add(CLASS_NAME_OPTIONS)\n\n if (this._config.optionsMaxHeight !== 'auto') {\n optionsDiv.style.maxHeight = `${this._config.optionsMaxHeight}px`\n optionsDiv.style.overflow = 'auto'\n }\n\n dropdownDiv.append(optionsDiv)\n\n const { container } = this._config\n if (container) {\n container.append(dropdownDiv)\n } else {\n this._element.append(dropdownDiv)\n }\n\n this._createOptions(optionsDiv, this._options)\n this._optionsElement = optionsDiv\n this._menu = dropdownDiv\n }\n\n _createOptions(parentElement, options) {\n for (const option of options) {\n if (Array.isArray(option.options)) {\n const optgroup = document.createElement('div')\n optgroup.classList.add(CLASS_NAME_OPTGROUP)\n optgroup.setAttribute('role', 'group')\n\n const optgrouplabel = document.createElement('div')\n if (this._config.optionsGroupsTemplate && typeof this._config.optionsGroupsTemplate === 'function') {\n optgrouplabel.innerHTML = this._config.sanitize ?\n sanitizeHtml(this._config.optionsGroupsTemplate(option), this._config.allowList, this._config.sanitizeFn) :\n this._config.optionsGroupsTemplate(option)\n } else {\n optgrouplabel.textContent = option.label\n }\n\n optgrouplabel.classList.add(CLASS_NAME_OPTGROUP_LABEL)\n optgroup.append(optgrouplabel)\n\n this._createOptions(optgroup, option.options)\n parentElement.append(optgroup)\n\n continue\n }\n\n const optionDiv = document.createElement('div')\n optionDiv.classList.add(CLASS_NAME_OPTION)\n\n if (option.disabled) {\n optionDiv.classList.add(CLASS_NAME_DISABLED)\n optionDiv.setAttribute('aria-disabled', 'true')\n }\n\n optionDiv.dataset.value = option.value\n optionDiv.tabIndex = 0\n if (this._isExternalSearch() && this._config.highlightOptionsOnSearch && this._search) {\n optionDiv.innerHTML = this._highlightOption(option.label)\n } else if (this._config.optionsTemplate && typeof this._config.optionsTemplate === 'function') {\n optionDiv.innerHTML = this._config.sanitize ?\n sanitizeHtml(this._config.optionsTemplate(option), this._config.allowList, this._config.sanitizeFn) :\n this._config.optionsTemplate(option)\n } else {\n optionDiv.textContent = option.label\n }\n\n parentElement.append(optionDiv)\n }\n }\n\n _onOptionsClick(element) {\n if (element.classList.contains(CLASS_NAME_LABEL)) {\n return\n }\n\n if (!element.classList.contains(CLASS_NAME_OPTION)) {\n element = element.closest(SELECTOR_OPTION)\n\n if (!element) {\n return\n }\n }\n\n const value = String(element.dataset.value)\n const foundOption = this._findOptionByValue(value)\n\n if (foundOption) {\n this._selectOption(foundOption)\n }\n }\n\n _findOptionByValue(value, options = this._options) {\n for (const option of options) {\n if (option.value === value) {\n return option\n }\n\n if (option.options && Array.isArray(option.options)) {\n const found = this._findOptionByValue(value, option.options)\n if (found) {\n return found\n }\n }\n }\n\n return null\n }\n\n _selectOption(option) {\n this.deselectAll()\n\n if (this._selected.filter(selectedOption => selectedOption.value === option.value).length === 0) {\n this._selected.push(option)\n }\n\n const foundOption = SelectorEngine.findOne(`[data-value=\"${option.value}\"]`, this._optionsElement)\n if (foundOption) {\n foundOption.classList.add(CLASS_NAME_SELECTED)\n foundOption.setAttribute('aria-selected', true)\n }\n\n EventHandler.trigger(this._element, EVENT_CHANGED, {\n value: option\n })\n\n this._inputElement.value = option.label\n\n if (this._config.showHints) {\n this._inputHintElement.value = ''\n }\n\n this.hide()\n\n if (this._config.clearSearchOnSelect) {\n this.search('')\n }\n\n this._inputElement.focus()\n this._updateCleaner()\n }\n\n _deselectOption(value) {\n this._selected = this._selected.filter(option => option.value !== String(value))\n\n const option = SelectorEngine.findOne(`[data-value=\"${value}\"]`, this._optionsElement)\n if (option) {\n option.classList.remove(CLASS_NAME_SELECTED)\n option.setAttribute('aria-selected', false)\n }\n\n EventHandler.trigger(this._element, EVENT_CHANGED, {\n value: this._selected\n })\n }\n\n _updateCleaner() {\n if (!this._config.cleaner || this._cleanerElement === null) {\n return\n }\n\n if (this._selected.length > 0) {\n this._cleanerElement.style.removeProperty('display')\n return\n }\n\n this._cleanerElement.style.display = 'none'\n }\n\n _updateOptionsList(options = this._options) {\n for (const option of options) {\n if (Array.isArray(option.options)) {\n this._updateOptionsList(option.options)\n continue\n }\n\n if (option.selected) {\n this._selectOption(option)\n }\n }\n }\n\n _filterOptionsList() {\n const options = SelectorEngine.find(SELECTOR_OPTION, this._menu)\n let visibleOptions = 0\n\n for (const option of options) {\n // eslint-disable-next-line unicorn/prefer-includes\n if (option.textContent.toLowerCase().indexOf(this._search) === -1) {\n option.style.display = 'none'\n } else {\n if (this._config.highlightOptionsOnSearch && !this._config.optionsTemplate) {\n option.innerHTML = this._highlightOption(option.textContent)\n }\n\n option.style.removeProperty('display')\n visibleOptions++\n }\n\n const optgroup = option.closest(SELECTOR_OPTGROUP)\n if (optgroup) {\n // eslint-disable-next-line unicorn/prefer-array-some\n if (SelectorEngine.children(optgroup, SELECTOR_OPTION).filter(element => this._isVisible(element)).length > 0) {\n optgroup.style.removeProperty('display')\n } else {\n optgroup.style.display = 'none'\n }\n }\n }\n\n if (visibleOptions > 0) {\n if (SelectorEngine.findOne(SELECTOR_OPTIONS_EMPTY, this._menu)) {\n SelectorEngine.findOne(SELECTOR_OPTIONS_EMPTY, this._menu).remove()\n }\n\n return\n }\n\n if (visibleOptions === 0) {\n if (this._config.searchNoResultsLabel) {\n const placeholder = document.createElement('div')\n placeholder.classList.add(CLASS_NAME_OPTIONS_EMPTY)\n placeholder.innerHTML = this._config.searchNoResultsLabel\n\n if (!SelectorEngine.findOne(SELECTOR_OPTIONS_EMPTY, this._menu)) {\n SelectorEngine.findOne(SELECTOR_OPTIONS, this._menu).append(placeholder)\n }\n\n return\n }\n\n this.hide()\n }\n }\n\n _selectMenuItem({ key, target }) {\n const items = SelectorEngine.find(SELECTOR_VISIBLE_ITEMS, this._menu).filter(element => isVisible(element))\n\n if (!items.length) {\n return\n }\n\n // if target isn't included in items (e.g. when expanding the dropdown)\n // allow cycling to get the last item in case key equals ARROW_UP_KEY\n getNextActiveElement(items, target, key === ARROW_DOWN_KEY, !items.includes(target)).focus()\n }\n\n _configAfterMerge(config) {\n if (config.container === true) {\n config.container = document.body\n }\n\n if (typeof config.container === 'object' || typeof config.container === 'string') {\n config.container = getElement(config.container)\n }\n\n if (typeof config.options === 'string') {\n config.options = config.options.split(/,\\s*/).map(String)\n }\n\n if (typeof config.search === 'string') {\n config.search = config.search.split(/,\\s*/).map(String)\n }\n\n return config\n }\n\n // Static\n\n static autocompleteInterface(element, config) {\n const data = Autocomplete.getOrCreateInstance(element, config)\n\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n\n data[config]()\n }\n }\n\n static jQueryInterface(config) {\n return this.each(function () {\n Autocomplete.autocompleteInterface(this, config)\n })\n }\n\n static clearMenus(event) {\n if (event.button === RIGHT_MOUSE_BUTTON || (event.type === 'keyup' && event.key !== TAB_KEY)) {\n return\n }\n\n const openToggles = SelectorEngine.find(SELECTOR_DATA_TOGGLE_SHOWN)\n\n for (const toggle of openToggles) {\n const context = Autocomplete.getInstance(toggle)\n\n if (!context) {\n continue\n }\n\n const composedPath = event.composedPath()\n\n if (\n composedPath.includes(context._element)\n ) {\n continue\n }\n\n const relatedTarget = { relatedTarget: context._element }\n\n if (event.type === 'click') {\n relatedTarget.clickEvent = event\n }\n\n context.hide()\n context.search('')\n if (context._config.allowOnlyDefinedOptions && context._selected.length === 0) {\n context._inputElement.value = ''\n }\n }\n }\n}\n\n/**\n * Data API implementation\n */\n\nEventHandler.on(window, EVENT_LOAD_DATA_API, () => {\n for (const autocomplete of SelectorEngine.find(SELECTOR_DATA_TOGGLE)) {\n Autocomplete.autocompleteInterface(autocomplete)\n }\n})\nEventHandler.on(document, EVENT_CLICK_DATA_API, Autocomplete.clearMenus)\nEventHandler.on(document, EVENT_KEYUP_DATA_API, Autocomplete.clearMenus)\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Autocomplete)\n\nexport default Autocomplete\n"],"names":["NAME","DATA_KEY","EVENT_KEY","DATA_API_KEY","ARROW_UP_KEY","ARROW_DOWN_KEY","BACKSPACE_KEY","DELETE_KEY","ENTER_KEY","ESCAPE_KEY","TAB_KEY","RIGHT_MOUSE_BUTTON","EVENT_BLUR","EVENT_CHANGED","EVENT_CLICK","EVENT_HIDE","EVENT_HIDDEN","EVENT_INPUT","EVENT_KEYDOWN","EVENT_KEYUP","EVENT_SHOW","EVENT_SHOWN","EVENT_CLICK_DATA_API","EVENT_KEYUP_DATA_API","EVENT_LOAD_DATA_API","CLASS_NAME_AUTOCOMPLETE","CLASS_NAME_BUTTONS","CLASS_NAME_CLEANER","CLASS_NAME_DISABLED","CLASS_NAME_DROPDOWN","CLASS_NAME_INDICATOR","CLASS_NAME_INPUT","CLASS_NAME_INPUT_HINT","CLASS_NAME_INPUT_GROUP","CLASS_NAME_LABEL","CLASS_NAME_OPTGROUP","CLASS_NAME_OPTGROUP_LABEL","CLASS_NAME_OPTION","CLASS_NAME_OPTIONS","CLASS_NAME_OPTIONS_EMPTY","CLASS_NAME_SELECTED","CLASS_NAME_SHOW","SELECTOR_DATA_TOGGLE","SELECTOR_DATA_TOGGLE_SHOWN","SELECTOR_INDICATOR","SELECTOR_OPTGROUP","SELECTOR_OPTION","SELECTOR_OPTIONS","SELECTOR_OPTIONS_EMPTY","SELECTOR_VISIBLE_ITEMS","Default","allowList","DefaultAllowlist","allowOnlyDefinedOptions","ariaCleanerLabel","ariaIndicatorLabel","cleaner","clearSearchOnSelect","container","disabled","highlightOptionsOnSearch","id","indicator","invalid","name","options","optionsGroupsTemplate","optionsMaxHeight","optionsTemplate","placeholder","required","sanitize","sanitizeFn","search","searchNoResultsLabel","showHints","valid","value","DefaultType","Autocomplete","BaseComponent","constructor","element","config","_this$_config$id","_uniqueId","_config","getUID","_indicatorElement","_inputElement","_inputHintElement","_togglerElement","_optionsElement","_menu","_selected","_options","_getOptionsFromConfig","_popper","_search","_createAutocomplete","_addEventListeners","Data","set","_element","toggle","_isShown","hide","show","_flattenOptions","filter","option","label","toLowerCase","includes","length","EventHandler","trigger","classList","add","setAttribute","style","minWidth","offsetWidth","_createPopper","destroy","remove","dispose","clear","deselectAll","_filterOptionsList","_isExternalSearch","update","_configAfterMerge","innerHTML","_createOptions","Array","isArray","_deselectOption","_updateCleaner","flat","opt","push","_getClassNames","split","_highlightOption","regex","RegExp","replace","string","_isGlobalSearch","_isVisible","window","getComputedStyle","display","contains","on","event","target","closest","key","focus","preventDefault","_selectMenuItem","startsWith","selectionStart","stopPropagation","_selectOption","slice","_onOptionsClick","_cleanerElement","_option$value","customGroupProperties","isSelected","selected","customProperties","String","className","_createInputGroup","_createButtons","_createOptionsContainer","_updateOptionsList","_this$_config$placeho","togglerEl","document","createElement","tabIndex","inputHintEl","toString","autocomplete","readOnly","append","inputEl","role","buttons","type","Popper","TypeError","popperConfig","modifiers","boundary","offset","placement","isRTL","createPopper","dropdownDiv","optionsDiv","maxHeight","overflow","parentElement","optgroup","optgrouplabel","sanitizeHtml","textContent","optionDiv","dataset","foundOption","_findOptionByValue","found","selectedOption","SelectorEngine","findOne","removeProperty","find","visibleOptions","indexOf","children","items","isVisible","getNextActiveElement","body","getElement","map","autocompleteInterface","data","getOrCreateInstance","jQueryInterface","each","clearMenus","button","openToggles","context","getInstance","composedPath","relatedTarget","defineJQueryPlugin"],"mappings":"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"} \ No newline at end of file diff --git a/js/src/autocomplete.js b/js/src/autocomplete.js index 8f44a77a0..2064f966f 100644 --- a/js/src/autocomplete.js +++ b/js/src/autocomplete.js @@ -374,7 +374,6 @@ class Autocomplete extends BaseComponent { EventHandler.on(this._indicatorElement, EVENT_CLICK, event => { event.preventDefault() - // event.stopPropagation() this.toggle() }) From 292d5ee8d8fcf76c4ed8e4cb568b0daae008d922 Mon Sep 17 00:00:00 2001 From: mrholek Date: Sun, 27 Jul 2025 14:17:36 +0200 Subject: [PATCH 5/5] chore: clean-up --- js/dist/auto-complete copy.js | 884 ------------------------------ js/dist/auto-complete copy.js.map | 1 - 2 files changed, 885 deletions(-) delete mode 100644 js/dist/auto-complete copy.js delete mode 100644 js/dist/auto-complete copy.js.map diff --git a/js/dist/auto-complete copy.js b/js/dist/auto-complete copy.js deleted file mode 100644 index 3d5427213..000000000 --- a/js/dist/auto-complete copy.js +++ /dev/null @@ -1,884 +0,0 @@ -/*! - * CoreUI auto-complete copy.js v5.15.0 (https://coreui.io) - * Copyright 2025 The CoreUI Team (https://github.com/orgs/coreui/people) - * Licensed under MIT (https://github.com/coreui/coreui/blob/main/LICENSE) - */ -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('@popperjs/core'), require('./base-component.js'), require('./dom/data.js'), require('./dom/event-handler.js'), require('./dom/selector-engine.js'), require('./util/index.js')) : - typeof define === 'function' && define.amd ? define(['@popperjs/core', './base-component', './dom/data', './dom/event-handler', './dom/selector-engine', './util/index'], factory) : - (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global["AutoComplete copy"] = factory(global["@popperjs/core"], global.BaseComponent, global.Data, global.EventHandler, global.SelectorEngine, global.Index)); -})(this, (function (Popper, BaseComponent, Data, EventHandler, SelectorEngine, index_js) { 'use strict'; - - function _interopNamespaceDefault(e) { - const n = Object.create(null, { [Symbol.toStringTag]: { value: 'Module' } }); - if (e) { - for (const k in e) { - if (k !== 'default') { - const d = Object.getOwnPropertyDescriptor(e, k); - Object.defineProperty(n, k, d.get ? d : { - enumerable: true, - get: () => e[k] - }); - } - } - } - n.default = e; - return Object.freeze(n); - } - - const Popper__namespace = /*#__PURE__*/_interopNamespaceDefault(Popper); - - /** - * -------------------------------------------------------------------------- - * CoreUI PRO auto-complete.js - * License (https://coreui.io/pro/license/) - * -------------------------------------------------------------------------- - */ - - - /** - * ------------------------------------------------------------------------ - * Constants - * ------------------------------------------------------------------------ - */ - - const NAME = 'auto-complete'; - const DATA_KEY = 'coreui.auto-complete'; - const EVENT_KEY = `.${DATA_KEY}`; - const DATA_API_KEY = '.data-api'; - - // Keys - const ARROW_UP_KEY = 'ArrowUp'; - const ARROW_DOWN_KEY = 'ArrowDown'; - // const ARROW_LEFT_KEY = 'ArrowLeft' - const ARROW_RIGHT_KEY = 'ArrowRight'; - const BACKSPACE_KEY = 'Backspace'; - const DELETE_KEY = 'Delete'; - const ENTER_KEY = 'Enter'; - const ESCAPE_KEY = 'Escape'; - const TAB_KEY = 'Tab'; - const RIGHT_MOUSE_BUTTON = 2; - - // Selectors - const SELECTOR_AC = '.auto-complete'; - // const SELECTOR_AC_INPUT_GROUP = '.auto-complete-input-group' - // const SELECTOR_AC_SELECTION = '.auto-complete-selection' - // const SELECTOR_AC_HINT = '.auto-complete-selection-hint' - // const SELECTOR_AC_CLEANER = '.auto-complete-cleaner' - // const SELECTOR_AC_INDICATOR = '.auto-complete-indicator' - // const SELECTOR_AC_DROPDOWN = '.auto-complete-dropdown' - const SELECTOR_AC_OPTIONS = '.auto-complete-options'; - const SELECTOR_AC_OPTION = '.auto-complete-option'; - const SELECTOR_AC_OPTIONS_EMPTY = '.auto-complete-options-empty'; - const SELECTOR_AC_VISIBLE_ITEMS = '.auto-complete-options .auto-complete-option:not(.disabled):not(:disabled)'; - - // Events - const EVENT_CHANGED = `changed${EVENT_KEY}`; // { value: Option | null } - const EVENT_INPUT = `input${EVENT_KEY}`; // when user types search text - const EVENT_SEARCH = `search${EVENT_KEY}`; // after internal filter applied - const EVENT_SHOW = `show${EVENT_KEY}`; - const EVENT_SHOWN = `shown${EVENT_KEY}`; - const EVENT_HIDE = `hide${EVENT_KEY}`; - const EVENT_HIDDEN = `hidden${EVENT_KEY}`; - const EVENT_CLICK = `click${EVENT_KEY}`; - const EVENT_KEYDOWN = `keydown${EVENT_KEY}`; - // const EVENT_KEYUP = `keyup${EVENT_KEY}` - const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`; - const EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY}${DATA_API_KEY}`; - const EVENT_LOAD_DATA_API = `load${EVENT_KEY}${DATA_API_KEY}`; - - // Class names - const CLASS_NAME_AC = 'auto-complete'; - const CLASS_NAME_INPUT_GROUP = 'auto-complete-input-group'; - const CLASS_NAME_HINT = 'auto-complete-selection-hint'; - const CLASS_NAME_SELECTION = 'auto-complete-selection'; - const CLASS_NAME_DROPDOWN = 'auto-complete-dropdown'; - const CLASS_NAME_OPTIONS = 'auto-complete-options'; - const CLASS_NAME_OPTION = 'auto-complete-option'; - const CLASS_NAME_OPTIONS_EMPTY = 'auto-complete-options-empty'; - const CLASS_NAME_DISABLED = 'disabled'; - const CLASS_NAME_SHOW = 'show'; - const CLASS_NAME_CLEANER = 'auto-complete-cleaner'; - const CLASS_NAME_INDICATOR = 'auto-complete-indicator'; - const CLASS_NAME_IS_INVALID = 'is-invalid'; - const CLASS_NAME_IS_VALID = 'is-valid'; - - // Default config mirrors CAutoComplete props where meaningful. - const Default = { - allowCreateOptions: false, - allowOnlyDefinedOptions: false, - cleaner: true, - clearSearchOnSelect: true, - container: false, - // false | element | selector | true (-> body) - disabled: false, - globalSearch: true, - hightlightOptionsOnSearch: true, - id: null, - invalid: false, - loading: false, - name: null, - options: [], - // array of Option | OptionsGroup | string - optionsMaxHeight: 'auto', - optionsTemplate: null, - // fn(option) => HTML - optionsGroupsTemplate: null, - // fn(group) => HTML - placeholder: '', - readOnly: false, - required: false, - resetSelectionOnOptionsChange: false, - search: true, - // true | 'external' - searchNoResultsLabel: 'No results found', - showHints: true, - size: null, - // 'sm' | 'lg' - valid: false, - value: null, - // initial string value - // virtualScroller: false, // not implemented in vanilla; reserved - visible: false, - visibleItems: 10 - }; - - // Type hints (string descriptors for BaseComponent._typeCheckConfig if used) - const DefaultType = { - allowCreateOptions: 'boolean', - allowOnlyDefinedOptions: 'boolean', - cleaner: 'boolean', - clearSearchOnSelect: 'boolean', - container: '(string|element|boolean)', - disabled: 'boolean', - globalSearch: 'boolean', - hightlightOptionsOnSearch: 'boolean', - id: '(string|null)', - invalid: 'boolean', - loading: 'boolean', - name: '(string|null)', - options: 'array', - optionsMaxHeight: '(number|string)', - optionsTemplate: '(function|null)', - optionsGroupsTemplate: '(function|null)', - placeholder: 'string', - readOnly: 'boolean', - required: 'boolean', - resetSelectionOnOptionsChange: 'boolean', - search: '(boolean|string)', - searchNoResultsLabel: '(boolean|string)', - showHints: 'boolean', - size: '(string|null)', - valid: 'boolean', - value: '(string|null)', - // virtualScroller: 'boolean', - visible: 'boolean', - visibleItems: 'number' - }; - - // ------------------------------------------------------------------------ - // Helpers for options dataset - // ------------------------------------------------------------------------ - - function normalizeOption(raw) { - var _ref, _raw$label; - // Accept string shorthand: 'foo' => { value: 'foo', label: 'foo' } - if (typeof raw === 'string') { - return { - value: raw, - label: raw - }; - } - - // Group test - if (raw && Array.isArray(raw.options)) { - return { - label: raw.label, - options: raw.options.map(normalizeOption) - }; - } - - // Single option - const value = String(raw.value); - return { - value, - label: (_ref = (_raw$label = raw.label) != null ? _raw$label : raw.text) != null ? _ref : value, - disabled: Boolean(raw.disabled), - selected: Boolean(raw.selected) - }; - } - function flattenOptions(options, flat = []) { - for (const opt of options) { - if (opt && Array.isArray(opt.options)) { - flattenOptions(opt.options, flat); - continue; - } - flat.push(opt); - } - return flat; - } - function getOptionLabel(opt) { - var _ref2, _opt$label; - return typeof opt === 'string' ? opt : (_ref2 = (_opt$label = opt.label) != null ? _opt$label : opt.text) != null ? _ref2 : String(opt.value); - } - function isOptionDisabled(opt) { - return Boolean(opt && typeof opt === 'object' && opt.disabled); - } - - /** - * ------------------------------------------------------------------------ - * Class Definition - * ------------------------------------------------------------------------ - */ - - class AutoComplete extends BaseComponent { - constructor(element, config) { - super(element); - this._config = this._getConfig(config); - this._indicatorElement = null; - this._cleanerElement = null; - this._dropdownElement = null; - this._optionsElement = null; - this._hintInputElement = null; - this._inputElement = null; - this._togglerElement = null; - this._popper = null; - this._options = this._getOptionsFromConfig(this._config.options); - this._userOptions = []; - this._selected = []; - this._search = ''; - this._visible = this._config.visible; - this._hint = null; - this._createAutoComplete(); - this._addEventListeners(); - Data.set(this._element, DATA_KEY, this); - - // Initial value resolution (string or preselected flag) - this._initInitialValue(); - } - - // Getters ----------------------------------------------------------------- - static get NAME() { - return NAME; - } - static get Default() { - return Default; - } - static get DefaultType() { - return DefaultType; - } - - // Public API --------------------------------------------------------------- - toggle() { - return this._isShown() ? this.hide() : this.show(); - } - show() { - var _this$_inputElement; - if (this._config.disabled || this._isShown()) { - return; - } - if (this._filteredOptions().length === 0 && this._config.searchNoResultsLabel === false) { - return; - } - EventHandler.trigger(this._element, EVENT_SHOW); - this._clone.classList.add(CLASS_NAME_SHOW); - this._clone.setAttribute('aria-expanded', true); - if (this._config.container) { - this._dropdownElement.style.minWidth = `${this._clone.offsetWidth}px`; - this._dropdownElement.classList.add(CLASS_NAME_SHOW); - } - EventHandler.trigger(this._element, EVENT_SHOWN); - this._createPopper(); - (_this$_inputElement = this._inputElement) == null || _this$_inputElement.focus(); - } - hide() { - EventHandler.trigger(this._element, EVENT_HIDE); - if (this._popper) { - this._popper.destroy(); - } - this._clone.classList.remove(CLASS_NAME_SHOW); - this._clone.setAttribute('aria-expanded', 'false'); - if (this._config.container) { - this._dropdownElement.classList.remove(CLASS_NAME_SHOW); - } - EventHandler.trigger(this._element, EVENT_HIDDEN); - } - dispose() { - if (this._popper) { - this._popper.destroy(); - } - super.dispose(); - } - update(config) { - const reset = config && config.value !== undefined; - this._config = { - ...this._config, - ...this._configAfterMerge(config) - }; - this._options = this._getOptionsFromConfig(this._config.options); - if (reset || this._config.resetSelectionOnOptionsChange) { - this._selected = []; - } - this._clone.remove(); - this._element.innerHTML = ''; - this._createAutoComplete(); - this._addEventListeners(); - } - getValue() { - return this._selected.length ? this._selected[0] : null; - } - - // Private ------------------------------------------------------------------ - - _addEventListeners() { - // toggle show when clicking group wrapper - EventHandler.on(this._clone, EVENT_CLICK, () => { - if (!this._config.disabled) { - this.show(); - } - }); - - // keyboard from wrapper (globalSearch behaviour) - EventHandler.on(this._clone, EVENT_KEYDOWN, event => { - if (event.key === ESCAPE_KEY) { - this.hide(); - return; - } - if (this._config.globalSearch && (event.key.length === 1 || event.key === BACKSPACE_KEY || event.key === DELETE_KEY)) { - var _this$_inputElement2; - (_this$_inputElement2 = this._inputElement) == null || _this$_inputElement2.focus(); - } - }); - - // indicator button explicit toggle - EventHandler.on(this._indicatorElement, EVENT_CLICK, event => { - event.preventDefault(); - event.stopPropagation(); - this.toggle(); - }); - - // cleaner button - if (this._cleanerElement) { - EventHandler.on(this._cleanerElement, EVENT_CLICK, event => { - event.preventDefault(); - event.stopPropagation(); - this._clearSelection(); - }); - } - - // input typing - EventHandler.on(this._inputElement, EVENT_INPUT, event => { - const { - value - } = event.target; - this._onInputChange(value); - }); - EventHandler.on(this._inputElement, EVENT_KEYDOWN, event => this._onInputKeyDown(event)); - - // options click delegate - EventHandler.on(this._optionsElement, EVENT_CLICK, event => { - event.preventDefault(); - event.stopPropagation(); - this._onOptionsClick(event.target); - }); - - // options keyboard - EventHandler.on(this._optionsElement, EVENT_KEYDOWN, event => { - if (event.key === ENTER_KEY) { - this._onOptionsClick(event.target); - } - if ([ARROW_UP_KEY, ARROW_DOWN_KEY].includes(event.key)) { - event.preventDefault(); - this._selectMenuItem(event); - } - }); - } - _onInputChange(text) { - this._search = text; - EventHandler.trigger(this._element, EVENT_INPUT, { - value: text - }); - this._filterOptionsList(); - this._updateHint(); - EventHandler.trigger(this._element, EVENT_SEARCH); - } - _onInputKeyDown(event) { - if (event.key === ESCAPE_KEY) { - this._getOrCreateOption(); - this.hide(); - return; - } - if (event.key === ARROW_DOWN_KEY) { - event.preventDefault(); - this.show(); - const first = SelectorEngine.findOne(SELECTOR_AC_OPTION, this._optionsElement); - if (first) { - first.focus(); - } - return; - } - if (this._config.showHints && this._hint && (event.key === ARROW_RIGHT_KEY || event.key === TAB_KEY)) { - event.preventDefault(); - this._selectOption(this._hint); - return; - } - if (event.key === ENTER_KEY) { - this._getOrCreateOption(); - return; - } - if (event.key === BACKSPACE_KEY || event.key === DELETE_KEY) { - this._clearSelection(); - } - } - _onOptionsClick(element) { - if (!element.classList.contains(CLASS_NAME_OPTION)) { - return; - } - const { - value - } = element.dataset; - const opt = this._findOptionByValue(value); - if (opt && isOptionDisabled(opt)) { - return; - } - this._selectOption(opt || { - value, - label: value - }); - if (this._config.clearSearchOnSelect) { - this._onInputChange(''); - this._inputElement.value = ''; - this._inputElement.focus(); - } - this.hide(); - } - _selectMenuItem({ - key, - target - }) { - const items = SelectorEngine.find(SELECTOR_AC_VISIBLE_ITEMS, this._dropdownElement).filter(el => index_js.isVisible(el)); - if (!items.length) { - return; - } - index_js.getNextActiveElement(items, target, key === ARROW_DOWN_KEY, !items.includes(target)).focus(); - } - _getOptionsFromConfig(options = []) { - return options.map(normalizeOption); - } - _filteredOptions() { - const all = [...this._options, ...this._userOptions]; - if (!this._search) { - return all; - } - const s = this._search.toLowerCase(); - return all.filter(opt => { - if (opt.options) { - // group: include groups where any child matches - return opt.options.some(o => getOptionLabel(o).toLowerCase().includes(s)); - } - return getOptionLabel(opt).toLowerCase().includes(s); - }); - } - _filteredFlatOptions() { - return flattenOptions(this._filteredOptions()); - } - _updateHint() { - if (!this._config.showHints || !this._hintInputElement) { - return; - } - const s = this._search; - if (!s) { - this._hint = null; - this._hintInputElement.value = ''; - return; - } - const flat = this._filteredFlatOptions(); - const found = flat.find(opt => getOptionLabel(opt).toLowerCase().startsWith(s.toLowerCase())); - this._hint = found || null; - this._hintInputElement.value = found ? `${s}${getOptionLabel(found).slice(s.length)}` : ''; - } - _getOrCreateOption() { - const s = this._search.trim(); - if (s === '') { - return; - } - const flat = this._filteredFlatOptions(); - const found = flat.find(opt => getOptionLabel(opt).toLowerCase() === s.toLowerCase()); - if (found && isOptionDisabled(found)) { - return; - } - if (!found && this._config.allowOnlyDefinedOptions) { - return; - } - if (found) { - this._selectOption(found); - return; - } - if (this._config.allowCreateOptions) { - const userOpt = { - value: s, - label: s - }; - this._userOptions.push(userOpt); - this._selectOption(userOpt); - return; - } - this._selectOption({ - value: s, - label: s - }); - } - _selectOption(opt) { - if (opt && opt.disabled) { - return; - } - this._selected = opt ? [opt] : []; - if (this._inputElement) { - this._inputElement.value = opt ? getOptionLabel(opt) : ''; - } - this._updateCleanerVisibility(); - EventHandler.trigger(this._element, EVENT_CHANGED, { - value: this.getValue() - }); - } - _clearSelection() { - this._selectOption(null); - } - _findOptionByValue(value, options = [...this._options, ...this._userOptions]) { - for (const opt of options) { - if (opt && Array.isArray(opt.options)) { - const found = this._findOptionByValue(value, opt.options); - if (found) { - return found; - } - continue; - } - if (String(opt.value) === String(value)) { - return opt; - } - } - return null; - } - _filterOptionsList() { - const s = this._search.toLowerCase(); - const options = SelectorEngine.find(SELECTOR_AC_OPTION, this._dropdownElement); - let visibleOptions = 0; - for (const option of options) { - const match = option.textContent.toLowerCase().includes(s); - if (match) { - option.style.removeProperty('display'); - visibleOptions++; - } else { - option.style.display = 'none'; - } - } - if (visibleOptions > 0) { - const empty = SelectorEngine.findOne(SELECTOR_AC_OPTIONS_EMPTY, this._dropdownElement); - if (empty) { - empty.remove(); - } - return; - } - if (visibleOptions === 0) { - const placeholder = document.createElement('div'); - placeholder.classList.add(CLASS_NAME_OPTIONS_EMPTY); - placeholder.innerHTML = this._config.searchNoResultsLabel; - const container = SelectorEngine.findOne(SELECTOR_AC_OPTIONS, this._dropdownElement); - if (container && !SelectorEngine.findOne(SELECTOR_AC_OPTIONS_EMPTY, container)) { - container.append(placeholder); - } - } - } - _createAutoComplete() { - // root clone - const acEl = document.createElement('div'); - acEl.classList.add(CLASS_NAME_AC); - acEl.classList.toggle(CLASS_NAME_IS_INVALID, this._config.invalid); - acEl.classList.toggle(CLASS_NAME_IS_VALID, this._config.valid); - acEl.setAttribute('aria-expanded', 'false'); - if (this._config.disabled) { - acEl.classList.add(CLASS_NAME_DISABLED); - } - if (this._config.size) { - acEl.classList.add(`${CLASS_NAME_AC}-${this._config.size}`); - } - - // copy any extra classes from source element - for (const className of this._element.classList) { - acEl.classList.add(className); - } - this._clone = acEl; - this._element.parentNode.insertBefore(acEl, this._element.nextSibling); - - // input group - const inputGroupEl = document.createElement('div'); - inputGroupEl.classList.add(CLASS_NAME_INPUT_GROUP); - this._togglerElement = inputGroupEl; - acEl.append(inputGroupEl); - - // hint input (readonly overlay) if enabled - if (this._config.showHints) { - const hintEl = document.createElement('input'); - hintEl.classList.add('form-control', CLASS_NAME_SELECTION, CLASS_NAME_HINT); - hintEl.autocomplete = 'off'; - hintEl.readOnly = true; - hintEl.tabIndex = -1; - inputGroupEl.append(hintEl); - this._hintInputElement = hintEl; - } - - // main text input - const inputEl = document.createElement('input'); - inputEl.type = 'text'; - inputEl.classList.add('form-control', CLASS_NAME_SELECTION); - if (this._config.disabled) { - inputEl.disabled = true; - } - if (this._config.id) { - inputEl.id = this._config.id; - } - if (this._config.name) { - inputEl.name = this._config.name; - } - if (this._config.placeholder) { - inputEl.placeholder = this._config.placeholder; - } - inputEl.autocomplete = 'off'; - inputEl.required = Boolean(this._config.required); - inputEl.readOnly = Boolean(this._config.readOnly); - inputEl.setAttribute('aria-autocomplete', 'list'); - inputEl.setAttribute('role', 'combobox'); - inputGroupEl.append(inputEl); - this._inputElement = inputEl; - - // buttons - const buttonsEl = document.createElement('div'); - buttonsEl.classList.add('auto-complete-buttons'); - inputGroupEl.append(buttonsEl); - if (!this._config.disabled && !this._config.readOnly && this._config.cleaner) { - const cleanerEl = document.createElement('button'); - cleanerEl.type = 'button'; - cleanerEl.classList.add(CLASS_NAME_CLEANER); - buttonsEl.append(cleanerEl); - this._cleanerElement = cleanerEl; - } - const indicatorEl = document.createElement('button'); - indicatorEl.type = 'button'; - indicatorEl.classList.add(CLASS_NAME_INDICATOR); - if (this._config.disabled) { - indicatorEl.tabIndex = -1; - } - buttonsEl.append(indicatorEl); - this._indicatorElement = indicatorEl; - - // dropdown container - const dropdownEl = document.createElement('div'); - dropdownEl.classList.add(CLASS_NAME_DROPDOWN); - dropdownEl.setAttribute('role', 'menu'); - if (this._config.container) ; else { - acEl.append(dropdownEl); - } - this._dropdownElement = dropdownEl; - - // options container - const optionsEl = document.createElement('div'); - optionsEl.classList.add(CLASS_NAME_OPTIONS); - if (this._config.optionsMaxHeight !== 'auto') { - optionsEl.style.maxHeight = `${this._config.optionsMaxHeight}px`; - optionsEl.style.overflow = 'auto'; - } - dropdownEl.append(optionsEl); - this._optionsElement = optionsEl; - - // create options markup - this._createOptions(optionsEl, this._options); - - // hide source element (if etc.)\n this._hideNativeElement()\n\n // ensure container\n const { container } = this._config\n if (container) {\n const _container = container === true ? document.body : getElement(container)\n _container.append(dropdownEl)\n }\n\n // reflect initial show state if configured\n if (this._visible) {\n this.show()\n }\n\n this._updateCleanerVisibility()\n }\n\n _createOptions(parent, options) {\n for (const opt of options) {\n if (Array.isArray(opt.options)) {\n const labelEl = document.createElement('div')\n labelEl.classList.add('auto-complete-optgroup-label')\n labelEl.innerHTML = opt.label\n parent.append(labelEl)\n this._createOptions(parent, opt.options)\n continue\n }\n\n const optEl = document.createElement('div')\n optEl.classList.add(CLASS_NAME_OPTION)\n if (opt.disabled) {\n optEl.classList.add(CLASS_NAME_DISABLED)\n }\n\n optEl.dataset.value = String(opt.value)\n optEl.tabIndex = 0\n optEl.innerHTML = this._renderOptionContent(opt)\n parent.append(optEl)\n }\n }\n\n _renderOptionContent(opt) {\n if (this._config.optionsTemplate) {\n try {\n return this._config.optionsTemplate(opt)\n } catch {/* ignore */}\n }\n\n if (this._config.hightlightOptionsOnSearch && this._search) {\n const label = getOptionLabel(opt)\n const idx = label.toLowerCase().indexOf(this._search.toLowerCase())\n if (idx !== -1) {\n const before = label.slice(0, idx)\n const match = label.slice(idx, idx + this._search.length)\n const after = label.slice(idx + this._search.length)\n return `${before}${match}${after}`\n }\n\n return label\n }\n\n return getOptionLabel(opt)\n }\n\n _hideNativeElement() {\n this._element.tabIndex = -1\n this._element.style.display = 'none'\n }\n\n _initInitialValue() {\n const cfgVal = this._config.value\n if (cfgVal && typeof cfgVal === 'string') {\n const found = this._findOptionByValue(cfgVal) || { value: cfgVal, label: cfgVal }\n this._selectOption(found)\n return\n }\n\n // look for preselected in options\n const flat = flattenOptions(this._options)\n const pre = flat.find(o => o.selected)\n if (pre) {\n this._selectOption(pre)\n }\n }\n\n _updateCleanerVisibility() {\n if (!this._cleanerElement) {\n return\n }\n\n if (this._selected.length > 0) {\n this._cleanerElement.style.removeProperty('display')\n return\n }\n\n this._cleanerElement.style.display = 'none'\n }\n\n _createPopper() {\n if (typeof Popper === 'undefined') {\n throw new TypeError('CoreUI\\'s auto complete require Popper (https://popper.js.org)')\n }\n\n const popperConfig = {\n modifiers: [{\n name: 'preventOverflow',\n options: { boundary: 'clippingParents' }\n }, {\n name: 'offset',\n options: { offset: [0, 2] }\n }],\n placement: isRTL() ? 'bottom-end' : 'bottom-start'\n }\n this._popper = Popper.createPopper(this._togglerElement, this._dropdownElement, popperConfig)\n }\n\n _isShown() {\n return this._clone.classList.contains(CLASS_NAME_SHOW)\n }\n\n _configAfterMerge(config = {}) {\n if (config.container === true) {\n config.container = document.body\n }\n\n if (typeof config.container === 'object' || typeof config.container === 'string') {\n config.container = getElement(config.container)\n }\n\n if (typeof config.options === 'string') {\n config.options = config.options.split(/,\\s*/).map(String)\n }\n\n return config\n }\n}\n\n// ------------------------------------------------------------------------\n// Data API implementation ----------------------------------------------------\n// ------------------------------------------------------------------------\n\nEventHandler.on(window, EVENT_LOAD_DATA_API, () => {\n for (const ac of SelectorEngine.find(SELECTOR_AC)) {\n if (ac.tabIndex !== -1) {\n AutoComplete.autoCompleteInterface(ac)\n }\n }\n})\nEventHandler.on(document, EVENT_CLICK_DATA_API, clearMenus)\nEventHandler.on(document, EVENT_KEYUP_DATA_API, clearMenus)\n\nfunction clearMenus(event) {\n if (event && (event.button === RIGHT_MOUSE_BUTTON || (event.type === 'keyup' && event.key !== TAB_KEY))) {\n return\n }\n\n const acs = SelectorEngine.find(SELECTOR_AC)\n for (const el of acs) {\n const context = Data.get(el, DATA_KEY)\n const relatedTarget = { relatedTarget: el }\n if (event && event.type === 'click') {\n relatedTarget.clickEvent = event\n }\n\n if (!context) {\n continue\n }\n\n if (!context._clone.classList.contains(CLASS_NAME_SHOW)) {\n continue\n }\n\n if (context._clone.contains(event.target)) {\n continue\n }\n\n context.hide()\n EventHandler.trigger(context._element, EVENT_HIDDEN, relatedTarget)\n }\n}\n\n// Static interface + jQuery bridge ------------------------------------------\n\nAutoComplete.autoCompleteInterface = function (element, config) {\n const data = AutoComplete.getOrCreateInstance(element, config)\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n\n data[config]()\n }\n}\n\nAutoComplete.jQueryInterface = function (config) {\n return this.each(function () {\n AutoComplete.autoCompleteInterface(this, config)\n })\n}\n\ndefineJQueryPlugin(AutoComplete)\n\nexport default AutoComplete\n"],"names":["NAME","DATA_KEY","EVENT_KEY","DATA_API_KEY","ARROW_UP_KEY","ARROW_DOWN_KEY","ARROW_RIGHT_KEY","BACKSPACE_KEY","DELETE_KEY","ENTER_KEY","ESCAPE_KEY","TAB_KEY","RIGHT_MOUSE_BUTTON","SELECTOR_AC","SELECTOR_AC_OPTIONS","SELECTOR_AC_OPTION","SELECTOR_AC_OPTIONS_EMPTY","SELECTOR_AC_VISIBLE_ITEMS","EVENT_CHANGED","EVENT_INPUT","EVENT_SEARCH","EVENT_SHOW","EVENT_SHOWN","EVENT_HIDE","EVENT_HIDDEN","EVENT_CLICK","EVENT_KEYDOWN","EVENT_CLICK_DATA_API","EVENT_KEYUP_DATA_API","EVENT_LOAD_DATA_API","CLASS_NAME_AC","CLASS_NAME_INPUT_GROUP","CLASS_NAME_HINT","CLASS_NAME_SELECTION","CLASS_NAME_DROPDOWN","CLASS_NAME_OPTIONS","CLASS_NAME_OPTION","CLASS_NAME_OPTIONS_EMPTY","CLASS_NAME_DISABLED","CLASS_NAME_SHOW","CLASS_NAME_CLEANER","CLASS_NAME_INDICATOR","CLASS_NAME_IS_INVALID","CLASS_NAME_IS_VALID","Default","allowCreateOptions","allowOnlyDefinedOptions","cleaner","clearSearchOnSelect","container","disabled","globalSearch","hightlightOptionsOnSearch","id","invalid","loading","name","options","optionsMaxHeight","optionsTemplate","optionsGroupsTemplate","placeholder","readOnly","required","resetSelectionOnOptionsChange","search","searchNoResultsLabel","showHints","size","valid","value","visible","visibleItems","DefaultType","normalizeOption","raw","_ref","_raw$label","label","Array","isArray","map","String","text","Boolean","selected","flattenOptions","flat","opt","push","getOptionLabel","_ref2","_opt$label","isOptionDisabled","AutoComplete","BaseComponent","constructor","element","config","_config","_getConfig","_indicatorElement","_cleanerElement","_dropdownElement","_optionsElement","_hintInputElement","_inputElement","_togglerElement","_popper","_options","_getOptionsFromConfig","_userOptions","_selected","_search","_visible","_hint","_createAutoComplete","_addEventListeners","Data","set","_element","_initInitialValue","toggle","_isShown","hide","show","_this$_inputElement","_filteredOptions","length","EventHandler","trigger","_clone","classList","add","setAttribute","style","minWidth","offsetWidth","_createPopper","focus","destroy","remove","dispose","update","reset","undefined","_configAfterMerge","innerHTML","getValue","on","event","key","_this$_inputElement2","preventDefault","stopPropagation","_clearSelection","target","_onInputChange","_onInputKeyDown","_onOptionsClick","includes","_selectMenuItem","_filterOptionsList","_updateHint","_getOrCreateOption","first","SelectorEngine","findOne","_selectOption","contains","dataset","_findOptionByValue","items","find","filter","el","isVisible","getNextActiveElement","all","s","toLowerCase","some","o","_filteredFlatOptions","found","startsWith","slice","trim","userOpt","_updateCleanerVisibility","visibleOptions","option","match","textContent","removeProperty","display","empty","document","createElement","append","acEl","className","parentNode","insertBefore","nextSibling","inputGroupEl","hintEl","autocomplete","tabIndex","inputEl","type","buttonsEl","cleanerEl","indicatorEl","dropdownEl","optionsEl","maxHeight","overflow","_createOptions","_hideNativeElement","_container","body","getElement","parent","labelEl","optEl","_renderOptionContent","_unused","idx","indexOf","before","after","cfgVal","pre","Popper","TypeError","popperConfig","modifiers","boundary","offset","placement","isRTL","createPopper","split","window","ac","autoCompleteInterface","clearMenus","button","acs","context","get","relatedTarget","clickEvent","data","getOrCreateInstance","jQueryInterface","each","defineJQueryPlugin"],"mappings":"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"} \ No newline at end of file