Архитектура библиотеки опирается на несколько ключевых абстракций, которые определяют поведение компонента, структуру данных и взаимодействие с DOM. Основные типы формируют контракт между пользовательским кодом, внутренним состоянием и внешними источниками данных.
Option представляет единицу выбора в выпадающем списке.
Это фундаментальная структура, из которой строится весь набор доступных
значений.
Типовая форма:
interface Option {
value: string | number
text: string
disabled?: boolean
$order?: number
[key: string]: any
}
Ключевые особенности:
value — уникальный идентификатор опции, используемый
для хранения выбранного состоянияtext — отображаемая строкаdisabled — флаг недоступности выбораВ контексте асинхронной загрузки данные часто нормализуются к этой структуре перед попаданием в компонент.
Item — это выбранная сущность, отражающая текущее
состояние выбора. Внутренне Item тесно связан с Option, но представляет
уже активное состояние.
type Item = string
или в расширенных реализациях:
type Item = string | number
Особенности:
value из OptionВнутреннее представление всегда стремится к примитивному типу для упрощения сериализации и сравнения.
Группировка опций реализуется через OptGroup, который
описывает логическую категорию элементов.
interface OptGroup {
label: string
value?: string
disabled?: boolean
optgroup: true
[key: string]: any
}
Структурные свойства:
label — заголовок группыoptgroup — маркер типаОпции внутри группы не изменяют свою природу — они остаются
Option, но связываются с группой через
optgroup или вложенную структуру данных.
Конфигурация компонента определяется через большой интерфейс
Settings, который управляет логикой поведения, рендерингом
и источниками данных.
interface Settings {
valueField: string
labelField: string
searchField: string | string[]
options: Option[]
items: Item[]
placeholder?: string
maxItems?: number
create?: boolean | ((input: string) => boolean)
persist?: boolean
loadThrottle?: number
preload?: boolean | "focus"
[key: string]: any
}
Ключевые аспекты:
valueField и labelField
позволяет работать с произвольными структурами данныхsearchField определяет поля для фильтрацииcreate включает режим создания новых элементовmaxItems ограничивает множественный выборloadThrottle регулирует частоту асинхронных
запросовРасширяемость настроек является критической частью архитектуры, позволяя внедрять плагины и пользовательские расширения без изменения ядра.
Экземпляр компонента представляет собой объект с состоянием, методами управления и API для внешнего взаимодействия.
interface TomSelectInstance {
settings: Settings
options: Record<string, Option>
items: Item[]
addOption(data: Option): void
addItem(value: string | number, silent?: boolean): void
removeItem(value: string | number): void
clear(): void
clearOptions(): void
focus(): void
blur(): void
destroy(): void
refreshOptions(triggerDropdown?: boolean): void
}
Поведенческие особенности:
addItem синхронизирует состояние UI и внутренний массив
itemsremoveItem влияет как на DOM, так и на модель
данныхclear сбрасывает текущее состояние без удаления
конфигурацииdestroy полностью освобождает ресурсы и возвращает
исходный DOMВнутренняя реализация обычно включает дополнительные приватные методы, не входящие в публичный контракт.
Система событий строится вокруг стандартного паттерна publish/subscribe.
Основные события:
interface TomSelectEvents {
"item_add": (value: Item) => void
"item_remove": (value: Item) => void
"option_add": (option: Option) => void
"dropdown_open": () => void
"dropdown_close": () => void
"change": (value: Item[]) => void
"type": (query: string) => void
}
Особенности:
change агрегирует состояние itemstype используется для отслеживания ввода и триггера
поискаsilent режим методов
APIКомпонент взаимодействует с DOM через набор строго определённых ссылок на элементы.
interface TomSelectControl {
input: HTMLInputElement
dropdown: HTMLElement
control: HTMLElement
dropdown_content: HTMLElement
wrapper: HTMLElement
}
Назначение:
input — точка ввода текстаdropdown — контейнер спискаcontrol — основная область взаимодействияdropdown_content — динамически обновляемая часть
спискаwrapper — корневой контейнер компонентаЭти ссылки используются для оптимизированных операций обновления без полной перерисовки.
Поисковый механизм опирается на функцию фильтрации, тип которой определяется как:
type ScoreFunction = (search: string, option: Option) => number
или более сложная форма:
type FilterFunction = (item: Option, query: string) => boolean
Использование:
ScoreFunction применяется для ранжирования
результатовFilterFunction используется для бинарного
включения/исключенияФильтрация может быть переопределена через настройки, что позволяет реализовать кастомные алгоритмы поиска (например, fuzzy search или поиск по токенам).
Для работы с удалёнными источниками данных используется контракт загрузчика:
type LoadCallback = (query: string, callback: (options: Option[]) => void) => void
и альтернативная Promise-форма:
type LoadFunction = (query: string) => Promise<Option[]>
Поведение:
LoadCallback используется для legacy APILoadFunction предпочтителен для современных
реализацийOption[]Механизм создания новых значений определяется функцией:
type CreateFilter = (input: string) => boolean
и генератором:
type CreateFunction = (input: string) => Option
Особенности:
itemsДля обеспечения работы UI используются дополнительные типы:
interface ActiveItem {
value: Item
$el: HTMLElement
}
interface HighlightState {
index: number
lastQuery: string
}
Назначение:
ActiveItem связывает данные и DOM-узелHighlightState управляет состоянием навигации по
спискуЭти структуры не входят в публичное API, но определяют поведение навигации и визуального выделения.
Плагины расширяют функциональность через единый контракт:
interface TomSelectPlugin {
initialize?: (instance: TomSelectInstance) => void
destroy?: () => void
}
Принципы:
initialize получает доступ к экземпляру компонентаdestroy используется для очистки подписок и
состоянияsettings, DOM и
событияСистема плагинов проектируется как слабосвязанная, позволяя накладывать расширения без изменения ядра.
Вся система типов формирует замкнутый цикл данных:
Option определяет исходный наборItem фиксирует выбранное состояниеSettings управляет поведениемTomSelectInstance связывает всё в единый APIЭта структура обеспечивает предсказуемость состояния и стабильность взаимодействия между слоями компонента без необходимости прямого управления DOM извне.