multiple-select-vanilla
Version:
This lib allows you to select multiple elements with checkboxes
359 lines (262 loc) • 13.4 kB
text/typescript
import type { TrustedHTML } from 'trusted-types/lib';
import type { CollectionData, LabelFilter, OptGroupRowData, OptionRowData, TextFilter } from './interfaces.js';
import type { LocaleKey, MultipleSelectLocale } from './locale.interface.js';
export interface MultipleSelectView {
label: string;
value?: any;
selected: boolean;
data: any;
children?: Array<{
label: string;
value: any;
selected: boolean;
disabled: boolean;
data: any;
}>;
}
export interface ClickedItem<T extends 'option' | 'optgroup'> {
label: string;
selected: boolean;
type: T;
}
export interface ClickedGroup extends ClickedItem<'optgroup'> {}
export interface ClickedOption extends ClickedItem<'option'> {
value?: any;
}
export type CloseReason =
| 'blur'
| 'body.click'
| 'hover.mouseout'
| 'key.shift+tab'
| 'key.escape'
| 'key.enter'
| 'key.space'
| 'selection'
| 'toggle.close'
| 'custom';
export type CSSStyleDeclarationReadonly =
| 'length'
| 'parentRule'
| 'getPropertyPriority'
| 'getPropertyValue'
| 'item'
| 'removeProperty'
| 'setProperty';
export type CSSStyleDeclarationWritable = keyof Omit<CSSStyleDeclaration, CSSStyleDeclarationReadonly>;
export interface MultipleSelectOption extends MultipleSelectLocale {
/** defaults to 10, when using "autoAdjustDropHeight" we might want to add a bottom (or top) padding instead of taking the entire available space */
adjustedHeightPadding: number;
/** Use optional string to override "All selected" text instead of `formatAllSelected()`, the latter should be preferred */
allSelectedText?: string;
/** Auto-adjust the Drop menu height to fit with available space */
autoAdjustDropHeight?: boolean;
/** Auto-adjust the Drop position on the side with the most available space (dropup / dropdown) */
autoAdjustDropPosition?: boolean;
/** Drop menu to automatically set its width as the maximum available width of text */
autoAdjustDropWidthByTextSize?: boolean;
/** The class name of select. */
classes?: string;
/** The class prefix of select. */
classPrefix?: string;
/**
* Should we close the drop when Tab key is pressed.
* Side note: when using a multiple select with the "OK" button enabled,
* it will require 2 Tabs (1. focus on "OK", 2. close drop)
*/
closeOnTab?: boolean;
/** HTML container to use for the drop menu, e.g. 'body' */
container?: string | HTMLElement | null;
/** Use optional string to override selected count text "# of % selected" instead of `formatCountSelected()`, the latter should be preferred */
countSelectedText?: string;
/** Dark Mode will add `.ms-dark-mode` CSS class to drop and parent elements */
darkMode?: boolean;
/** provide custom data */
data?: CollectionData;
/** Add "data-test" attribute to the "ms-parent" element */
dataTest?: string;
/** Delimiter to be displayed between each option */
displayDelimiter: string;
/** Title that can be displayed in the dropdown */
displayTitle?: boolean;
/**Defaults to false, display selected values on the element */
displayValues?: boolean;
/** Define the width of the dropdown list */
dropWidth?: number;
/** Defaults to false, add `…` after selected options if minimumCountSelected is set. Overrides countSelected option. */
ellipsis?: boolean;
/** Defaults to false, whether or not Multiple Select show a search field to search through checkbox items */
filter?: boolean;
/** Defaults to false, accept a filter by typing Enter on the keyboard */
filterAcceptOnEnter?: boolean;
/**
* Option to auto enable filter when the data length is defined.
* For example when defined as 10, the filter will show automatically when data array is over 10.
*/
filterByDataLength?: number;
/** Should we filter by Group? */
filterGroup?: boolean;
/** Add a placeholder to the input search filter when `filter` is enabled. */
filterPlaceholder?: string;
/** Defaults to false, hide the option groupd checkboses */
hideOptgroupCheckboxes?: boolean;
/** Defaults to false, Infinite Scroll will automatically reset the list (scroll back to top) whenever the scroll reaches the last item (end of the list) */
infiniteScroll?: boolean;
/** Whether or not Multiple Select open the select dropdown. */
isOpen?: boolean;
/** Defaults to false, keep the select dropdown always open */
keepOpen?: boolean;
/**
* For accessibility, you can provide a Label Id to be associated to the select button element (`.ms-choice`).
* An example can be `labelId: "custom-label"` which will be assigned to `id` and `aria-labelledby` attributes of the `.ms-choice` button.
*/
labelId?: string;
/**
* A lazy callback to load your collection only after the user clicks on the select dropdown to open it,
* the callback must be a Promise that will eventually resolve the data.
* While processing, a div with `ms-loading` class and an icon will be shown until the data is fully loaded.
*/
lazyData?: () => Promise<CollectionData>;
/** Use optional string to override "Loading..." text instead of `formatLazyLoading()` when lazy loading data is processing. */
lazyLoadingText?: string;
/** Optional I18n Locale */
locale?: LocaleKey | MultipleSelectLocale;
/** Defaults to 250, define the maximum height property of the dropdown list. */
maxHeight: number;
/** Defaults to `px`, maxHeight unit type */
maxHeightUnit?: string;
/** Defaults to 150, define the minimum height property of the dropdown list. */
minHeight: number;
/** Defaults to 500, define the maximum width of the drop when using the "autoAdjustDropWidthByTextSize: true" flag. */
maxWidth?: number;
/** Define the minimum width of the drop when using the "autoAdjustDropWidthByTextSize: true" flag. */
minWidth?: number;
/** Defaults to 3, minimum count of item selected to start showing "X items where selected". */
minimumCountSelected: number;
/** Defaults to false, whether or not Multiple Select show multiple items in a row */
multiple?: boolean;
/** Defaults to 80, Multiple Select items width */
multipleWidth?: number;
/** Defaults to an empty string, provide a name to the multiple select element */
name?: string;
/** Defaults to True, arrow navigation (and mouse hover) to highlight and possibly change selected option(s) with keyboard or mouse hovering. */
navigationHighlight?: boolean;
/** Use optional string to override text when filtering "No matches found" instead of `formatNoMatchesFound()`, the latter should be preferred */
noMatchesFoundText?: string;
/** Use optional string to override "OK" button text instead of `formatOkButton()`, the latter should be preferred */
okButtonText?: string;
/** Will open the dropdown when hovering the select */
openOnHover?: boolean;
/** A placeholder value can be defined and will be displayed until you select an item. */
placeholder?: string;
/** Defaults to 'bottom', defines the position of select dropdown, can only be bottom or top */
position: 'bottom' | 'top';
/**
* Custom Filter predicate function callback to pre-filter the data collection before rendering the select dropdown.
* Note that this will be executed before `preSort` (when defined).
*/
preFilter?: (dataItem: OptionRowData | OptGroupRowData) => boolean;
/**
* Custom Sort Comparer function callback to pre-sort the data collection before rendering the select dropdown.
* Note that this will be executed after `preSort` (when defined).
*/
preSort?: (item1: OptionRowData | OptGroupRowData, item2: OptionRowData | OptGroupRowData) => number;
/** Defaults to False, should we render option labels as HTML? */
renderOptionLabelAsHtml?: boolean;
/** Whether or not Multiple Select show select all checkbox. */
selectAll?: boolean;
/** Use optional string to override "Select All" checkbox text instead of `formatSelectAll()`, the latter should be preferred */
selectAllText?: string;
/** Defaults to false, whether or not Multiple Select allows you to select only one option */
single?: boolean;
/** Alias to `single` */
singleRadio?: boolean;
/** The size of select. */
size?: number | string;
/** Show a clear button, defaults to false */
showClear?: boolean;
/** Show a clear button on the filter search input, defaults to false */
showSearchClear?: boolean;
/** Display the OK button at bottom of the list when using multiple selection to easily close the drop, defaults to false. */
showOkButton?: boolean;
/** Defaults to False, when set to True it will use the <option label=""> (from select option value) that can be used to display selected options. */
useSelectOptionLabel?: boolean;
/** Defaults to False, same as "useSelectOptionLabel" but will also render HTML */
useSelectOptionLabelToHtml?: boolean;
/**
* Defaults to True, Virtual Scroll is used to improve performance with large set of data. The concept is to only render a subset
* of the options (~200) at a time to avoid polluting the DOM, it will also consume less memory and improve overall performance of your application.
*/
virtualScroll?: boolean;
/** Defaults to undefined, customize the width property of the dropdown list, support a percentage setting. The default will make the select input field the same width as the select. */
width?: number | string;
// --
// Methods
// ------------
/** The item styler function, return style string to customize the item style such as `background: red`. The function takes a value as argument. */
cssStyler: (value: OptionRowData | OptGroupRowData) => CSSStyleDeclaration | null;
/** Customize the filter method, for example if we want to use a startsWith character */
customFilter(options: LabelFilter | TextFilter): boolean;
/** Returns HTML label attribute of a DOM element */
labelTemplate: (elm: HTMLOptionElement) => string;
/** Returns HTML text template of a DOM element as a string */
textTemplate: (elm: HTMLOptionElement) => string;
// --
// Events
// ------------
/** Fires after the multiple-select DOM element is created. */
onAfterCreate: () => void;
/** Fires just before the dropdown is about to open. */
onBeforeOpen: () => void;
/** Fires when instance destroy method is being called, when a hard destroy is enabled it will remove the DOM element and also destroy its instance. */
onDestroy: (options: { hardDestroy: boolean }) => void;
/** Fires after instance was destroyed. */
onAfterDestroy: (options: { hardDestroy: boolean }) => void;
onDestroyed: (options: { hardDestroy: boolean }) => void;
/** (internal usage only) Fires when instance is being hard destroyed. */
onHardDestroy: () => void;
/** (internal usage only) Fires after instance was being hard destroyed. */
onAfterHardDestroy: () => void;
/** Fires when the dropdown list is opened. */
onOpen: () => void;
/** Fires when the filter is cleared. */
onClear: () => void;
/** Fires just before the close event is called. You can return `false` to prevent the drop from closing. */
// biome-ignore lint/suspicious/noConfusingVoidType: could return a boolean or not return anything
onBeforeClose: (reason?: CloseReason, e?: Event) => boolean | void;
/** Fires when the dropdown list is close. */
onClose: (reason?: CloseReason) => void;
/** Fires when all the options are checked by either clicking the `Select all` checkbox, or when the `checkall` method is programatically called. */
onCheckAll: () => void;
/** Fires when all the options are unchecked by either clicking the `Select all` checkbox, or when the `uncheckall` method is programatically called. */
onUncheckAll: () => void;
/** Bind an event handler to the "focus". */
onFocus: () => void;
/** Bind an event handler to the "blur" */
onBlur: (e?: KeyboardEvent | FocusEvent) => void;
/**
* Fires when any option/group selections changes.
* This event is triggered at the same time as other events are being triggered: (`onCheckAll`, `onUncheckAll`, `onClick`, `onOptgroupClick`)
*/
onChange: (data: {
eventName: string;
item?: ClickedGroup | ClickedOption;
selection: { labels: string[]; values: Array<string | number | boolean> };
}) => void;
/** Fires when an optgroup label is clicked on. */
onOptgroupClick: (view: MultipleSelectView) => void;
/** Fires when a checkbox is clicked but before any code is executed internally. Return `false` to prevent the click (onClick) event for being processed. */
onBeforeClick: (view: MultipleSelectView) => boolean;
/** Fires when a checkbox is checked or unchecked. */
onClick: (view: MultipleSelectView) => void;
/** Fires when a checkbox filter is changed. */
onFilter: (text?: string) => void;
/** Fires when the search filter is cleared. */
onFilterClear: () => void;
/** Custom parser to remove diacritic signs (accents) from characters when filtering select list. */
diacriticParser: (text: string) => string;
/**
* Sanitizes HTML code, for example `<script>`, to prevents XSS attacks.
* A library like DOM Purify could be used to sanitize html code, for example: `sanitizer: (dirtyHtml) => DOMPurify.sanitize(dirtyHtml || '')`
*/
sanitizer?: (html: string) => string | TrustedHTML;
}