forge-select
v0.7.4
Published
A modern, lightweight, highly customizable replacement for Select2.
Maintainers
Readme
Forge Select
«A modern, lightweight, highly customizable replacement for Select2.»
Forge Select is a next-generation JavaScript select component built for modern web applications. It provides a clean API, powerful customization options, excellent performance, and accessibility while remaining framework-agnostic.
Why Forge Select?
Select2 has served the community well for many years, but modern web development has evolved.
Forge Select is designed to provide:
- 🚀 High performance
- 🎨 Fully customizable UI
- 📱 Responsive and mobile-friendly
- ♿ Accessibility (ARIA) support
- 🔍 Fast searching
- 🌳 Nested option groups
- 🏷️ Single & multiple selection
- 🧩 Plugin architecture
- 🌐 AJAX & remote data loading
- 🌙 Dark mode support
- 🌍 Internationalization (i18n)
- 📦 Zero dependency
Documentation
Browse the documentation website at https://forgeselect.konexforge.com/docs/, or read the sources in docs/:
- API Reference — constructor, options, methods, events
- Examples — copy-pasteable snippets for every feature and framework
- Playground — live demo
- Migration from Select2 — option/event/method mapping and a migration checklist
- Benchmarks — reproducible bundle, initialization, search, and scrolling baseline
- Plugin Development Guide — write and register your own plugins
Features
- Single Select
- Multiple Select
- Searchable Dropdown
- Async Data Source (AJAX with debounce, optional infinite-scroll pagination)
- Rich Item Rendering (avatar + label + description, XSS-safe built-in fields)
- Virtual Scrolling (automatic for large lists, with per-option render caching)
- Custom Templates
- Tags Mode (create options from free text)
- Keyboard Navigation
- Disabled Options
- Option Groups
- Tree Select (nested options with expand/collapse and cascading multi-select)
- Drag & Drop Tag Ordering (reorder a multi-select's selected tags by mouse/touch/pen, or Alt+Left/Alt+Right on keyboard)
- Clear Selection
- Placeholder
- Custom Themes (CSS variables, dark mode included)
- Event System
- Plugin Architecture
- Internationalization (en/vi built in, custom string tables)
- TypeScript Support (written in strict TypeScript, ships
.d.ts)
Installation
npm install forge-select
# or
yarn add forge-select
# or
pnpm add forge-selectQuick Start
<select id="country">
<option value="vn">Vietnam</option>
<option value="jp">Japan</option>
<option value="us">United States</option>
</select>import ForgeSelect from "forge-select";
import "forge-select/styles.css";
new ForgeSelect("#country");Configuration
const select = new ForgeSelect("#country", {
placeholder: "Select a country",
searchable: true,
multiple: false,
clearable: true,
allowCreate: false,
theme: "default",
});See the API Reference for all options, including data, ajax, templateResult, templateSelection, virtualScroll, language, and plugins.
Events
select.on("change", (value) => console.log(value));
select.on("open", () => {});
select.on("close", () => {});
select.on("search", (query) => console.log("searching:", query));
select.on("clear", () => {});
select.on("error", (error) => console.error(error));Unsubscribe with select.off(event, handler).
Use select.setValue(value, { emitChange: false }) to synchronize external controlled state without emitting change.
Examples
new ForgeSelect("#users", {
ajax: {
url: (query) => `/api/users?q=${encodeURIComponent(query)}`,
debounce: 300,
transform: (response) => response.items.map((u) => ({ value: u.id, label: u.name })),
},
});More copy-pasteable snippets (multi-select, tags, custom templates, virtual scrolling, React/Vue/Svelte) are in docs/examples.md.
Playground
Write and run Forge Select code in the browser at https://forgeselect.konexforge.com/playground/ — with presets for every major feature. A curated feature showcase also lives at https://forgeselect.konexforge.com/demo/. See docs/playground.md for details and local setup.
API Reference
| Option | Type | Default | Description |
| --------------------- | ---------------------------------- | ----------- | --------------------------------------------------- |
| placeholder | string | "" | Text shown when nothing is selected |
| searchable | boolean | true | Show a search input in the dropdown |
| multiple | boolean | false | Allow selecting more than one option |
| clearable | boolean | false | Show a button to clear the current selection |
| allowCreate | boolean | false | Let the user create a new option from free text |
| sortable | boolean | false | Multi-select: let the user reorder selected tags |
| closeOnSelect | boolean | false | Multi-select: close the dropdown after each pick |
| maxSelections | number | undefined | Multi-select: caps the number of selected values |
| theme | string | "default" | Named theme applied to the control |
| required | boolean | false | Native form validation on a <select> mount |
| data | Array<Option \| OptionGroup> | undefined | Static options, used instead of <option> children |
| ajax | AjaxConfig | undefined | Remote data source config |
| filterOption | (option, query) => boolean | undefined | Custom match predicate for search filtering |
| minSearchLength | number | 0 | Minimum query length before filtering/ajax runs |
| minResultsForSearch | number | 0 | Hide local search below an option-count threshold |
| isOptionDisabled | (option) => boolean | undefined | Dynamically disable an option per render |
| virtualScroll | boolean | (auto) | Virtualize the list once it exceeds ~100 rows |
| itemHeight | number \| "auto" | 36 | Fixed or measured variable-height virtual rows |
| language | string \| Record<string, string> | "en" | Locale code or a custom string table for i18n |
| plugins | Array<ForgeSelectPlugin> | [] | Plugins to register on this instance |
| openOnFocus | boolean | false | Open the dropdown on keyboard focus |
| dropdownParent | HTMLElement \| string | undefined | Portal container for overflow-constrained layouts |
Full constructor signature, all options, instance methods, and events are documented in docs/api-reference.md.
Theming
Styling is driven entirely by CSS custom properties, and a dark theme ships out of the box:
new ForgeSelect("#country", { theme: "dark" });.forge-select {
--fs-border-focus: #e11d48;
--fs-radius: 4px;
}Framework Support
Forge Select is vanilla TypeScript/JavaScript, so it can be mounted inside any framework today. Official wrapper packages exist for a couple of them:
- Vanilla JavaScript
- React — via
forge-select-react(ForgeSelectReactcomponent, controlledvalue/onChange) - Vue — via
forge-select-vue(ForgeSelectVuecomponent,v-modelsupport) - Angular — mount manually (see
docs/examples.md) - Svelte — mount manually (see
docs/examples.md) - Next.js
- Nuxt
- Astro
Browser Support
- Chrome
- Edge
- Firefox
- Safari
- Mobile Browsers
Migration from Select2
Forge Select is designed as a drop-in-concept replacement for Select2: no jQuery dependency, native accessibility, and a smaller API surface. A full option/event/method mapping table and a step-by-step migration checklist are available in docs/migration-from-select2.md.
Benchmarks
Run npm run bench for a reproducible JSON baseline covering bundle size, initialization, 10,000-option search latency, and virtual-scroll performance. The methodology and result fields are documented in docs/benchmarks.md.
Roadmap
- [x] Tree Select
- [x] Virtualized List
- [x] Async Pagination
- [x] Drag & Drop Ordering
- [x] Theme Builder
- [x] CSS Variables
- [x] React Component
- [x] Vue Component
Plugin Development Guide
Forge Select uses a small plugin architecture (onInit, onOpen, onClose, onDestroy lifecycle hooks) so behavior can be extended without forking the core. See docs/plugin-development.md for the plugin interface and a complete example plugin.
Development
npm install # install dev dependencies
npm test # run the vitest + jsdom test suite
npm run typecheck # strict TypeScript check
npm run build # build ESM + CJS + type declarations into dist/Source lives in src/, styles in styles/forge-select.css, and tests in tests/.
Contributing
Contributions are welcome! See CONTRIBUTING.md for the development setup, project layout, and PR guidelines. Release history lives in CHANGELOG.md, and security reports should follow SECURITY.md. This project follows a Code of Conduct; by participating you agree to abide by its terms.
License
Built with ❤️ by KonexForge.
