@n-ramos/comboselect
v1.0.7
Published
A modern, flexible select/autocomplete component with tags support
Maintainers
Readme
ComboSelect Documentation
Version: 1.0.0
License: MIT
📚 Table of Contents
- Introduction
- Installation
- Quick Start
- Configuration Options
- Data Sources
- API Integration
- Events & Callbacks
- Customization
- Public Methods
- Examples
- TypeScript Support
- Browser Support
Introduction
ComboSelect is a modern, flexible autocomplete component with tag support, built with TypeScript and styled with Tailwind CSS v4.
Key Features
- ✅ Single & Multiple Selection
- ✅ Local & Remote Data
- ✅ Tag System with Counter
- ✅ Keyboard Navigation
- ✅ Duplicate Prevention
- ✅ Customizable Rendering
- ✅ TypeScript Support
- ✅ Zero Dependencies
Installation
NPM
npm install comboselectYarn
yarn add comboselectImport
import { ComboSelect } from 'comboselect';
import 'comboselect/style.css';Quick Start
Basic Example
const cities = [
{ id: 1, name: 'Paris' },
{ id: 2, name: 'London' }
];
new ComboSelect('#city-select', {
dataSource: cities,
labelSuggestion: 'name',
valueSuggestion: 'id',
placeholder: 'Select a city...'
});Multiple Selection
new ComboSelect('#cities', {
dataSource: cities,
multiple: true,
maxItems: 5,
incrementValueSize: 3
});Configuration Options
Main Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| dataSource | Array \| Function | - | Local data |
| autocompleteUrl | string | - | API endpoint |
| labelSuggestion | string | 'label' | Label key |
| valueSuggestion | string \| null | null | Value key |
| multiple | boolean | false | Multiple selection |
| maxItems | number | - | Max items |
| incrementValueSize | number | - | Visible tags before +N |
| placeholder | string | 'Sélectionner...' | Placeholder |
| minChars | number | 1 | Min chars |
| debounceDelay | number | 300 | Debounce (ms) |
| closeOnSelect | boolean | true | Close on select |
Data Sources
Local Array
new ComboSelect('#input', {
dataSource: [
{ id: 1, name: 'Option 1' },
{ id: 2, name: 'Option 2' }
]
});Async Function
new ComboSelect('#input', {
dataSource: async () => {
const res = await fetch('/api/data');
return await res.json();
}
});Nested Properties
new ComboSelect('#input', {
dataSource: data,
labelSuggestion: 'user.profile.name'
});API Integration
Basic API
new ComboSelect('#input', {
autocompleteUrl: 'https://api.example.com/search'
});With resultsKey
// Response: { items: [...] }
new ComboSelect('#input', {
autocompleteUrl: 'https://api.example.com/search',
resultsKey: 'items'
});
// Response: { data: { users: [...] } }
new ComboSelect('#input', {
autocompleteUrl: 'https://api.example.com/search',
resultsKey: 'data.users'
});Custom Transform
new ComboSelect('#input', {
autocompleteUrl: 'https://api.example.com/search',
transformResponse: (response) => {
return response.payload.items.map(item => ({
id: item.identifier,
label: item.displayName
}));
}
});POST Request
new ComboSelect('#input', {
autocompleteUrl: 'https://api.example.com/search',
httpMethod: 'POST',
httpHeaders: {
'Authorization': 'Bearer TOKEN'
}
});Events & Callbacks
new ComboSelect('#input', {
onSelect: (item) => {
console.log('Selected:', item);
},
onRemove: (item) => {
console.log('Removed:', item);
},
onChange: (items) => {
console.log('All items:', items);
},
onLoad: (data) => {
console.log('Data loaded:', data);
},
onError: (error) => {
console.error('Error:', error);
}
});Available Callbacks
onSelect(item)- When item is selectedonRemove(item)- When item is removedonChange(items)- When selection changesonLoad(data)- When data loadsonSearch(query)- When user typesonOpen()- When dropdown opensonClose()- When dropdown closesonError(error)- When error occurs
Customization
Custom Suggestions
new ComboSelect('#input', {
renderSuggestion: (user) => \`
\${user.name}
\${user.email}
\`
});Custom Tags
new ComboSelect('#input', {
renderTag: (item) => {
return \`\${item.original.flag} \${item.label}\`;
}
});Custom CSS
new ComboSelect('#input', {
cssUrl: '/path/to/custom-theme.css'
});Public Methods
const combo = new ComboSelect('#input', options);
// Get values
const values = combo.getValue(); // Returns: SelectedItem[]
// Set values
combo.setValue([
{ label: 'Paris', value: 1, original: {...} }
]);
// Clear all
combo.clear();
// Add item
combo.addItem({ label: 'Item', value: 1, original: {} });
// Remove item
combo.removeItem({ label: 'Item', value: 1, original: {} });
// Open/Close
combo.open();
combo.close();
// Enable/Disable
combo.enable();
combo.disable();
// Clear cache
combo.clearCache();
// Destroy
combo.destroy();Examples
Example 1: Cities with Population
new ComboSelect('#cities', {
dataSource: cities,
labelSuggestion: 'name',
multiple: true,
renderSuggestion: (city) => \`
\${city.name}
\${city.population.toLocaleString()} inhabitants
\`
});Example 2: Countries with Flags
new ComboSelect('#countries', {
dataSource: countries,
labelSuggestion: 'name',
renderSuggestion: (country) => \`
\${country.flag} \${country.name}
\`,
renderTag: (item) => \`
\${item.original.flag} \${item.label}
\`
});Example 3: GitHub Repositories
new ComboSelect('#repos', {
autocompleteUrl: 'https://api.github.com/search/repositories',
resultsKey: 'items',
searchParam: 'q',
labelSuggestion: 'full_name',
multiple: true,
incrementValueSize: 3,
renderSuggestion: (repo) => \`
\${repo.full_name}
⭐ \${repo.stargazers_count}
\`
});Example 4: Form Integration
const form = document.getElementById('myForm');
const combo = new ComboSelect('#cities', {
dataSource: cities,
multiple: true,
onChange: (items) => {
console.log('Selected:', items);
}
});
form.addEventListener('submit', async (e) => {
e.preventDefault();
const values = combo.getValue();
const response = await fetch('/api/submit', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ cities: values })
});
const result = await response.json();
console.log('Result:', result);
});TypeScript Support
Type Definitions
import { ComboSelect, ComboSelectConfig, SelectedItem } from 'comboselect';
const config: ComboSelectConfig = {
dataSource: cities,
multiple: true,
maxItems: 5
};
const combo = new ComboSelect('#input', config);
const values: SelectedItem[] = combo.getValue();SelectedItem Interface
interface SelectedItem {
label: string;
value: any;
original: any;
}Browser Support
- ✅ Chrome (last 2 versions)
- ✅ Firefox (last 2 versions)
- ✅ Safari (last 2 versions)
- ✅ Edge (last 2 versions)
Minimum Requirements:
- ES2020 support
- Fetch API
- Promise support
Troubleshooting
Dropdown not showing
- Check that
minCharsrequirement is met - Verify
dataSourceorautocompleteUrlis properly configured - Check browser console for errors
Styles not applied
- Ensure CSS is imported:
import 'comboselect/style.css' - Check for CSS conflicts with your framework
API calls not working
- Verify
autocompleteUrlis correct - Check CORS configuration on your server
- Use
onErrorcallback to debug
TypeScript errors
- Ensure
@typesare installed - Check
tsconfig.jsonconfiguration - Import types:
import type { ComboSelectConfig } from 'comboselect'
License
MIT License - see LICENSE file for details
Contributing
Contributions are welcome! Please open an issue or submit a pull request.
Support
- 📧 Email: [email protected]
- 🐛 Issues: https://github.com/yourusername/comboselect/issues
- 📖 Docs: https://comboselect.dev
