@smilodon/core
v1.3.3
Published
High-performance native select component with extreme-scale virtualization - React, Vue, Svelte, Vanilla JS
Maintainers
Readme
@smilodon/core
Why Smilodon?
Smilodon is a Web Component that renders 1,000,000+ items at 60 FPS with constant DOM size, sub-millisecond search, and zero framework lock-in. Built for extreme-scale data applications where legacy libraries crash or lag.
Performance Comparison
| Library | 10K Items | 100K Items | 1M Items | Memory | FPS | |---------|-----------|------------|----------|---------|-----| | Smilodon | 38ms | 81ms | 162ms | 18 MB | 60 | | React Select | 1200ms | ❌ Crash | ❌ Crash | 200+ MB | 10-25 | | Vue Select | 890ms | ❌ Crash | ❌ Crash | 180+ MB | 15-30 | | ng-select | 1100ms | ❌ Crash | ❌ Crash | 220+ MB | 12-28 |
See full benchmarks for methodology and reproducibility.
Installation
npm install @smilodon/coreQuick Start
Vanilla JavaScript / Web Components
<!DOCTYPE html>
<html>
<head>
<script type="module">
import '@smilodon/core';
</script>
</head>
<body>
<smilodon-select id="my-select"></smilodon-select>
<script type="module">
const select = document.getElementById('my-select');
// Generate 1 million items
const items = Array.from({ length: 1_000_000 }, (_, i) => ({
label: `Item ${i + 1}`,
value: i + 1
}));
select.items = items;
select.addEventListener('change', (e) => {
console.log('Selected:', e.detail);
});
</script>
</body>
</html>Framework Usage
@smilodon/core works directly in all frameworks as a Web Component - no adapters needed!
Simply import and use <smilodon-select> in React, Vue, Svelte, or any framework:
// React, Vue, Svelte - all work the same way
import '@smilodon/core';
<smilodon-select ref={selectRef} />Optional Framework Adapters (for enhanced developer experience):
- React:
npm install @smilodon/react- React hooks and components - Vue:
npm install @smilodon/vue- Vue composables and components - Svelte:
npm install @smilodon/svelte- Svelte stores and components - Vanilla:
npm install @smilodon/vanilla- Vanilla JS helpers
These adapters provide framework-native APIs (hooks, composables) for enhanced developer experience, but are not required - the core package works everywhere!
Note: Angular support has been discontinued as of December 2025.
See the main documentation for framework-specific examples.
Key Features
🚀 Extreme Performance
- Constant DOM: Only 10-15 elements rendered regardless of dataset size
- Work Stealing: Background search workers with automatic cancellation
- Sub-millisecond Search: Fenwick tree indexing for O(log n) queries
- 60 FPS Scrolling: Hardware-accelerated virtualization
🎯 Production Ready
- TypeScript First: Complete type definitions included
- Zero Dependencies: 6.6 KB gzipped runtime
- Framework Agnostic: Works with React, Vue, Svelte, or vanilla JS
- Accessibility: WCAG 2.2 AA compliant with ARIA 1.2
🔒 Enterprise Grade
- SOC2 Compliant: Audit-ready security controls
- CSP Compatible: No eval(), no inline scripts
- SBOM Included: Full dependency transparency
- 99.8% Test Coverage: Unit, integration, and E2E tests
API Reference
Properties
interface SmilodonSelectElement extends HTMLElement {
items: SelectItem[] | string[] | number[]; // Dataset (can be millions of items)
value: any; // Current selected value
placeholder?: string; // Placeholder text
searchable?: boolean; // Enable search (default: true)
disabled?: boolean; // Disable the select
multiple?: boolean; // Multiple selection mode
virtualization?: boolean; // Enable virtualization (default: true)
maxHeight?: number; // Max dropdown height in pixels
}
interface SelectItem {
label: string; // Display text
value: any; // Value (can be any type)
disabled?: boolean; // Disable this option
group?: string; // Optgroup name
}Flexible Input Formats:
- Object arrays:
[{ value: '1', label: 'Option 1' }, ...]- String arrays:
['Apple', 'Banana', 'Cherry']- automatically converted toSelectItemformat- Number arrays:
[1, 2, 3, 5, 8]- automatically converted toSelectItemformat
Examples with Different Input Types
Object Array (Traditional)
select.items = [
{ value: 'apple', label: 'Apple' },
{ value: 'banana', label: 'Banana' },
{ value: 'cherry', label: 'Cherry' }
];String Array (Auto-converted)
select.items = ['Apple', 'Banana', 'Cherry', 'Date', 'Elderberry'];
// Automatically becomes:
// [
// { value: 'Apple', label: 'Apple' },
// { value: 'Banana', label: 'Banana' },
// ...
// ]Number Array (Auto-converted)
select.items = [1, 2, 3, 5, 8, 13, 21, 34, 55, 89];
// Automatically becomes:
// [
// { value: 1, label: '1' },
// { value: 2, label: '2' },
// ...
// ]Events
// Selection changed
select.addEventListener('change', (event: CustomEvent) => {
console.log(event.detail); // { value, label }
});
// Dropdown opened
select.addEventListener('open', () => {
console.log('Dropdown opened');
});
// Dropdown closed
select.addEventListener('close', () => {
console.log('Dropdown closed');
});
// Search query changed
select.addEventListener('search', (event: CustomEvent) => {
console.log(event.detail.query);
});Methods
// Programmatically open/close
select.open();
select.close();
// Clear selection
select.clear();
// Focus the select
select.focus();
// Get filtered items (useful for debugging)
const filtered = select.getFilteredItems();Advanced Usage
Custom Styling
Smilodon uses CSS custom properties for theming:
smilodon-select {
--smilodon-border-color: #d1d5db;
--smilodon-focus-color: #3b82f6;
--smilodon-bg-color: #ffffff;
--smilodon-text-color: #1f2937;
--smilodon-hover-bg: #f3f4f6;
--smilodon-selected-bg: #dbeafe;
--smilodon-font-family: system-ui, -apple-system, sans-serif;
--smilodon-border-radius: 0.375rem;
}Server-Side Rendering (SSR)
Smilodon gracefully handles SSR environments:
// Check if running in browser
if (typeof window !== 'undefined') {
import('@smilodon/core').then(() => {
// Initialize after hydration
});
}Performance Monitoring
Enable telemetry to monitor performance:
select.enableTelemetry = true;
select.addEventListener('telemetry', (event) => {
console.log('Performance metrics:', event.detail);
// { renderTime, searchTime, scrollFPS, memoryUsage }
});Architecture
Smilodon's performance comes from three core optimizations:
- Virtual Scrolling: Only renders visible items (10-15 DOM nodes for any dataset size)
- Work Stealing Scheduler: Search operations run in background workers with automatic cancellation
- Fenwick Tree Indexing: O(log n) search queries instead of O(n) array scans
Read the full architecture guide for implementation details.
Browser Support
| Browser | Version | |---------|---------| | Chrome | 90+ | | Firefox | 88+ | | Safari | 14.1+ | | Edge | 90+ |
Requires browsers with native Web Components support (custom elements v1).
Bundle Size
- Runtime: 6.6 KB gzipped (ESM)
- Full Package: 365 KB (includes 5 formats + source maps + types)
- Tree-shakeable: Import only what you need
TypeScript
Full TypeScript definitions included. No need for @types/* packages.
import type { SmilodonSelectElement, SelectItem } from '@smilodon/core';
const items: SelectItem[] = [
{ label: 'Option 1', value: 1 },
{ label: 'Option 2', value: 2 }
];
const select = document.querySelector('smilodon-select') as SmilodonSelectElement;
select.items = items;Documentation
- Main README: Complete guide with framework examples
- Benchmarks: Transparent performance comparisons
- API Reference: Full API documentation
- Architecture: Technical deep-dive
- Migration Guide: Migrate from React Select, Vue Select, etc.
Examples
Visit the interactive playground to see Smilodon in action with:
- 1M item datasets
- Real-time search
- Framework integrations
- Custom styling
Contributing
Contributions are welcome! Please read our Contributing Guide for details.
License
MIT © Navid Rezadoost
Support
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Security: Security Policy
