/**
* TyMultiselect Web Component
* PORTED FROM: clj/ty/components/multiselect.cljs
*
* A multiselect dropdown component using ty-tag for selections with:
* - Tag-only options (only ty-tag elements supported)
* - Multiple selection with visual tags
* - Desktop mode with smart positioning
* - Mobile mode with full-screen modal
* - Search and filtering capabilities
* - Keyboard navigation
* - Form association for native form submission with multiple values
* - Scroll locking when dropdown is open
* - Outside click to close
*
* @example
* ```html
*
*
* JavaScript
* TypeScript
* Python
*
*
*
*
* JavaScript
* TypeScript
* Python
*
*
*
*
*
*
*

*
John Doe
*
*
*
* ```
*/
import type { Flavor, Size } from '../types/common.js';
import { TyComponent } from '../base/ty-component.js';
import type { PropertyChange } from '../utils/property-manager.js';
/**
* Tag data structure
*/
interface TagData {
value: string;
text: string;
element: HTMLElement;
}
/**
* Component state structure
*/
interface MultiselectState {
open: boolean;
search: string;
highlightedIndex: number;
filteredTags: TagData[];
selectedValues: string[];
mode: 'desktop' | 'mobile';
expandedSection: 'selected' | 'available';
}
/**
* Ty Multiselect Component
*/
export declare class TyMultiselect extends TyComponent {
protected static properties: {
value: {
type: "string";
visual: boolean;
formValue: boolean;
emitChange: boolean;
default: string;
coerce: (v: any) => string;
};
name: {
type: "string";
default: string;
};
placeholder: {
type: "string";
visual: boolean;
default: string;
};
label: {
type: "string";
visual: boolean;
default: string;
};
disabled: {
type: "boolean";
visual: boolean;
default: boolean;
};
readonly: {
type: "boolean";
visual: boolean;
default: boolean;
};
required: {
type: "boolean";
visual: boolean;
default: boolean;
};
searchable: {
type: "boolean";
visual: boolean;
default: boolean;
aliases: {
'not-searchable': boolean;
};
};
size: {
type: "string";
visual: boolean;
default: string;
validate: (v: any) => boolean;
coerce: (v: any) => any;
};
flavor: {
type: "string";
visual: boolean;
default: string;
validate: (v: any) => boolean;
coerce: (v: any) => any;
};
delay: {
type: "number";
default: number;
validate: (v: any) => boolean;
coerce: (v: any) => number;
};
'selected-label': {
type: "string";
visual: boolean;
default: string;
};
'available-label': {
type: "string";
visual: boolean;
default: string;
};
'no-selection-message': {
type: "string";
visual: boolean;
default: string;
};
'no-options-message': {
type: "string";
visual: boolean;
default: string;
};
};
private _value;
private _name;
private _placeholder;
private _label;
private _disabled;
private _readonly;
private _required;
private _searchable;
private _size;
private _flavor;
private _selectedLabel;
private _availableLabel;
private _noSelectionMessage;
private _noOptionsMessage;
private _state;
set expandedSection(value: 'selected' | 'available');
get expandedSection(): 'selected' | 'available';
private _stubClickHandler;
private _outsideClickHandler;
private _tagClickHandler;
private _tagDismissHandler;
private _searchInputHandler;
private _blockSearchClick;
private _keyboardHandler;
private _delay;
private _searchDebounceTimer;
private _optionsScrollbar;
constructor();
/**
* Called when component is connected to DOM
* TyComponent handles property capture automatically
*/
protected onConnect(): void;
/**
* Called when component is disconnected from DOM
* Clean up event listeners and timers
*/
protected onDisconnect(): void;
/**
* Called when properties change
* Handle state synchronization BEFORE render
*/
protected onPropertiesChanged(changes: PropertyChange[]): void;
/**
* Get the form value for this component
* Returns FormData with multiple entries (HTMX standard)
*/
protected getFormValue(): FormDataEntryValue | FormData | null;
/**
* Parse multiselect value (comma-separated string to array)
*/
private parseValue;
/**
* Initialize component state from attributes
* Reads from both property and attribute (like ClojureScript version)
*/
private initializeState;
/**
* Get all ty-tag elements from the component (ALL slots)
*/
private getTagElements;
/**
* Extract value and text from a ty-tag element
*/
private getTagData;
/**
* Select a tag - set selected state, move to selected slot, make dismissible
*/
private selectTag;
/**
* Deselect a tag - remove selected state, remove from selected slot, remove dismissible
*/
private deselectTag;
/**
* Get array of currently selected values from tags (ALWAYS reads from DOM)
*/
private getSelectedValues;
/**
* Check if all available tags are selected
*/
private allTagsSelected;
/**
* Sync tag selection states with desired values
*/
private syncSelectedTags;
/**
* Central update function - synchronizes everything
* Uses TyComponent's property system for proper lifecycle
*/
private updateComponentValue;
/**
* Calculate and set dropdown position with smart direction detection
*/
private calculatePosition;
private _setupOptionsScrollbar;
private _destroyOptionsScrollbar;
/**
* Open dropdown dialog (desktop mode)
* Using