Complete TypeScript interface and type definitions for Choices.js, covering all data structures, configuration options, and utility types.
{ .api }
interface Choice {
id: number;
label: string;
value: string;
selected: boolean;
disabled: boolean;
customProperties?: Record<string, any>;
}Usage:
const choice: Choice = {
id: 1,
label: 'Option 1',
value: 'option1',
selected: false,
disabled: false,
customProperties: {
category: 'premium',
price: 29.99,
description: 'Advanced features included'
}
};{ .api }
interface Item extends Choice {
choiceId: number;
highlighted: boolean;
}Usage:
const item: Item = {
id: 123,
choiceId: 1,
label: 'Selected Option',
value: 'selected',
selected: true,
disabled: false,
highlighted: false,
customProperties: {
addedAt: Date.now()
}
};{ .api }
interface Group {
id: number;
value: string;
active: boolean;
disabled: boolean;
choices?: Choice[];
}Usage:
const group: Group = {
id: 1,
value: 'Fruits',
active: true,
disabled: false,
choices: [
{ id: 1, label: 'Apple', value: 'apple', selected: false, disabled: false },
{ id: 2, label: 'Banana', value: 'banana', selected: false, disabled: false }
]
};{ .api }
interface Options {
// Core behavior
silent: boolean;
items: (string | Item)[];
choices: (Choice | Group)[];
renderSelectedChoices: 'always' | 'auto';
maxItemCount: number;
addItems: boolean;
addItemFilter: string | RegExp | FilterFunction | null;
removeItems: boolean;
removeItemButton: boolean;
editItems: boolean;
allowHTML: boolean;
duplicateItemsAllowed: boolean;
delimiter: string;
paste: boolean;
// Search configuration
searchEnabled: boolean;
searchChoices: boolean;
searchFloor: number;
searchResultLimit: number;
searchFields: string[] | string;
// Display options
position: PositionOptionsType;
resetScrollPosition: boolean;
shouldSort: boolean;
shouldSortItems: boolean;
sorter: (a: Choice | Item, b: Choice | Item) => number;
placeholder: boolean;
placeholderValue: string | null;
searchPlaceholderValue: string | null;
prependValue: string | null;
appendValue: string | null;
renderChoiceLimit: number;
// Text content
loadingText: string;
noResultsText: string | StringFunction;
noChoicesText: string | StringFunction;
itemSelectText: string;
uniqueItemText: string | StringFunction;
customAddItemText: string | StringFunction;
addItemText: string | StringFunction;
maxItemText: string | StringFunction;
// Advanced options
valueComparer: ValueCompareFunction;
fuseOptions: object;
labelId: string;
callbackOnInit: Function | null;
callbackOnCreateTemplates: Function | null;
classNames: ClassNames;
}{ .api }
interface ClassNames {
containerOuter: string;
containerInner: string;
input: string;
inputCloned: string;
list: string;
listItems: string;
listSingle: string;
listDropdown: string;
item: string;
itemSelectable: string;
itemDisabled: string;
itemChoice: string;
placeholder: string;
group: string;
groupHeading: string;
button: string;
activeState: string;
focusState: string;
openState: string;
disabledState: string;
highlightedState: string;
selectedState: string;
flippedState: string;
loadingState: string;
notice: string;
addChoice: string;
noResults: string;
noChoices: string;
}Usage:
const customClassNames: Partial<ClassNames> = {
containerOuter: 'custom-choices',
input: 'custom-input',
item: 'custom-item',
button: 'custom-remove-btn'
};
const choices = new Choices('#select', {
classNames: {
...DEFAULT_CLASSNAMES,
...customClassNames
}
});{ .api }
type EventType =
| 'addItem'
| 'removeItem'
| 'highlightItem'
| 'unhighlightItem'
| 'choice'
| 'change'
| 'search'
| 'showDropdown'
| 'hideDropdown'
| 'highlightChoice';{ .api }
interface ChangeEventDetail {
value: string | string[];
}
interface AddItemEventDetail {
id: number;
value: string;
label: string;
customProperties?: Record<string, any>;
keyCode?: number;
}
interface RemoveItemEventDetail {
id: number;
value: string;
label: string;
customProperties?: Record<string, any>;
}
interface ChoiceEventDetail {
choice: {
id: number;
value: string;
label: string;
customProperties?: Record<string, any>;
};
}
interface SearchEventDetail {
value: string;
resultCount: number;
}
interface HighlightItemEventDetail {
id: number;
value: string;
label: string;
}
interface UnhighlightItemEventDetail {
id: number;
value: string;
label: string;
}
interface HighlightChoiceEventDetail {
choice: {
id: number;
value: string;
label: string;
};
}{ .api }
type PositionOptionsType = 'auto' | 'top' | 'bottom';{ .api }
type PassedElementType = 'text' | 'select-one' | 'select-multiple';{ .api }
type ActionType =
| 'ADD_CHOICE'
| 'FILTER_CHOICES'
| 'ACTIVATE_CHOICES'
| 'CLEAR_CHOICES'
| 'ADD_GROUP'
| 'ADD_ITEM'
| 'REMOVE_ITEM'
| 'HIGHLIGHT_ITEM'
| 'CLEAR_ALL';{ .api }
type StringFunction = (value?: string) => string;
type NoticeStringFunction = (value: string) => string;
type NoticeLimitFunction = (maxItemCount: number) => string;
type FilterFunction = (value: string) => boolean;
type ValueCompareFunction = (value1: string, value2: string) => boolean;Usage Examples:
// String function for dynamic text
const addItemText: StringFunction = (value = '') =>
`Press Enter to add "${value}"`;
// Filter function for validation
const emailFilter: FilterFunction = (value: string) =>
/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
// Value comparison function
const caseInsensitiveComparer: ValueCompareFunction = (value1, value2) =>
value1.toLowerCase() === value2.toLowerCase();{ .api }
type TemplateFunction = (...args: any[]) => HTMLElement | string;
interface Templates {
containerOuter: TemplateFunction;
containerInner: TemplateFunction;
itemList: TemplateFunction;
placeholder: TemplateFunction;
item: TemplateFunction;
choiceList: TemplateFunction;
choiceGroup: TemplateFunction;
choice: TemplateFunction;
input: TemplateFunction;
dropdown: TemplateFunction;
notice: TemplateFunction;
option: TemplateFunction;
}{ .api }
interface KeyCodeMap {
BACK_KEY: number;
DELETE_KEY: number;
ENTER_KEY: number;
A_KEY: number;
ESC_KEY: number;
UP_KEY: number;
DOWN_KEY: number;
PAGE_UP_KEY: number;
PAGE_DOWN_KEY: number;
}Usage:
import { KEY_CODES } from 'choices.js';
document.addEventListener('keydown', (event) => {
switch (event.keyCode) {
case KEY_CODES.ENTER_KEY:
// Handle Enter
break;
case KEY_CODES.ESC_KEY:
// Handle Escape
break;
}
});{ .api }
interface Notice {
response: boolean;
notice: string;
}Usage:
function validateInput(value: string): Notice {
if (value.length < 3) {
return {
response: false,
notice: 'Input must be at least 3 characters'
};
}
return {
response: true,
notice: 'Valid input'
};
}{ .api }
type StrToEl = (str: string) => Element;{ .api }
type PartialOptions = Partial<Options>;Usage:
// Only specify options you want to override
const config: PartialOptions = {
searchEnabled: true,
maxItemCount: 5,
removeItemButton: true
};{ .api }
interface ChoiceInput {
value: string;
label: string;
selected?: boolean;
disabled?: boolean;
customProperties?: Record<string, any>;
}
interface GroupInput {
label: string;
id?: number;
disabled?: boolean;
choices: ChoiceInput[];
}
type ChoicesInput = (ChoiceInput | GroupInput)[];Usage:
const choicesData: ChoicesInput = [
{
value: 'option1',
label: 'Option 1',
selected: true
},
{
label: 'Group 1',
choices: [
{ value: 'grouped1', label: 'Grouped Option 1' },
{ value: 'grouped2', label: 'Grouped Option 2' }
]
}
];{ .api }
interface Constants {
EVENTS: Record<EventType, string>;
ACTION_TYPES: Record<ActionType, string>;
KEY_CODES: KeyCodeMap;
TEXT_TYPE: 'text';
SELECT_ONE_TYPE: 'select-one';
SELECT_MULTIPLE_TYPE: 'select-multiple';
SCROLLING_SPEED: number;
}function isChoice(item: Choice | Group): item is Choice {
return 'label' in item && 'value' in item;
}
function isGroup(item: Choice | Group): item is Group {
return 'choices' in item;
}
function isItem(obj: Choice | Item): obj is Item {
return 'choiceId' in obj && 'highlighted' in obj;
}
// Usage
choices.forEach(choice => {
if (isChoice(choice)) {
console.log('Choice:', choice.label);
} else if (isGroup(choice)) {
console.log('Group:', choice.value);
}
});{ .api }
interface ProductChoice extends Choice {
customProperties: {
price: number;
category: string;
inStock: boolean;
rating?: number;
};
}
interface UserItem extends Item {
customProperties: {
userId: number;
addedAt: number;
source: 'manual' | 'import' | 'api';
};
}Usage:
const productChoices: ProductChoice[] = [
{
id: 1,
label: 'Premium Plan',
value: 'premium',
selected: false,
disabled: false,
customProperties: {
price: 29.99,
category: 'subscription',
inStock: true,
rating: 4.8
}
}
];type ChoicesEventHandler<T = any> = (event: CustomEvent<T>) => void;
// Specific event handlers
type ChangeEventHandler = ChoicesEventHandler<ChangeEventDetail>;
type AddItemEventHandler = ChoicesEventHandler<AddItemEventDetail>;
type SearchEventHandler = ChoicesEventHandler<SearchEventDetail>;
// Usage
const handleChange: ChangeEventHandler = (event) => {
const { value } = event.detail;
console.log('Selection changed to:', value);
};
const handleAddItem: AddItemEventHandler = (event) => {
const { id, value, label, customProperties } = event.detail;
console.log(`Added item: ${label} (${value})`);
};
element.addEventListener('change', handleChange);
element.addEventListener('addItem', handleAddItem);interface ChoicesConfigBuilder {
setSearchEnabled(enabled: boolean): ChoicesConfigBuilder;
setMaxItems(count: number): ChoicesConfigBuilder;
setPlaceholder(text: string): ChoicesConfigBuilder;
build(): Options;
}
class ChoicesConfig implements ChoicesConfigBuilder {
private config: Partial<Options> = {};
setSearchEnabled(enabled: boolean) {
this.config.searchEnabled = enabled;
return this;
}
setMaxItems(count: number) {
this.config.maxItemCount = count;
return this;
}
setPlaceholder(text: string) {
this.config.placeholderValue = text;
return this;
}
build(): Options {
return { ...DEFAULT_CONFIG, ...this.config };
}
}
// Usage
const config = new ChoicesConfig()
.setSearchEnabled(true)
.setMaxItems(5)
.setPlaceholder('Choose options...')
.build();This comprehensive type system ensures type safety and IntelliSense support when working with Choices.js in TypeScript projects.