{"id":30232374,"url":"https://github.com/seadonggyun4/seo-select","last_synced_at":"2025-08-14T23:57:54.973Z","repository":{"id":306737566,"uuid":"1027065839","full_name":"seadonggyun4/seo-select","owner":"seadonggyun4","description":"A lightweight and extensible select component built with Lit","archived":false,"fork":false,"pushed_at":"2025-08-11T02:52:21.000Z","size":2938,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-08-11T03:01:47.629Z","etag":null,"topics":["lit","react","scss","select","ts","web-components"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/seo-select","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/seadonggyun4.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-07-27T08:32:20.000Z","updated_at":"2025-08-11T02:52:22.000Z","dependencies_parsed_at":"2025-07-27T10:29:07.750Z","dependency_job_id":"2d8a17d0-fac5-4bf8-bddd-e8a292876f73","html_url":"https://github.com/seadonggyun4/seo-select","commit_stats":null,"previous_names":["seadonggyun4/seo-select"],"tags_count":50,"template":false,"template_full_name":null,"purl":"pkg:github/seadonggyun4/seo-select","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seadonggyun4%2Fseo-select","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seadonggyun4%2Fseo-select/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seadonggyun4%2Fseo-select/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seadonggyun4%2Fseo-select/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/seadonggyun4","download_url":"https://codeload.github.com/seadonggyun4/seo-select/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seadonggyun4%2Fseo-select/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270500676,"owners_count":24595163,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-14T02:00:10.309Z","response_time":75,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["lit","react","scss","select","ts","web-components"],"created_at":"2025-08-14T23:57:18.718Z","updated_at":"2025-08-14T23:57:54.958Z","avatar_url":"https://github.com/seadonggyun4.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# seo-select\n![npm](https://img.shields.io/npm/dt/seo-select?style=flat\u0026label=NPM%20Downloads)\n![GitHub Repo stars](https://img.shields.io/github/stars/seadonggyun4/seo-select?style=flat\u0026label=GitHub%20Stars)\n\n\u003cimg width=\"300\" height=\"300\" alt=\"logo\" src=\"https://github.com/user-attachments/assets/e567ea31-d046-45b3-80d1-9a1e32c7e002\" /\u003e\n\nA lightweight and extensible select component built with Lit, designed to work seamlessly across frameworks. Supports search, virtual scrolling, multiple selection, i18n, and flexible theming.\n\n\u003e 🌟 Support with a `GitHub star` — your encouragement means the world to me!\n\n- **[GitHub](https://github.com/seadonggyun4/seo-select)**\n- **[NPM: seo-select](https://www.npmjs.com/package/seo-select)**\n- **[NPM: seo-select-react](https://www.npmjs.com/package/seo-select-react)**\n- **[DemoSite](https://seo-select.netlify.app/)**\n\n## Features\n\n- 🎨 **Multiple Themes**: Basic, float themes with dark mode support\n- 🌍 **Internationalization**: Built-in support for multiple languages (EN, KO, JA, ZH)\n- 🔍 **Search Functionality**: Advanced multilingual search with fuzzy matching\n- ♿ **Accessibility**: Full keyboard navigation and screen reader support\n- 🚀 **Virtual Scrolling**: High performance with large datasets\n- 📏 **Auto Width**: Automatic width calculation based on content\n- 🎯 **Multiple Selection**: Tag-based multi-select with individual remove buttons\n- 💡 **Lightweight Web Component**: Built with native Web Components for minimal size and seamless integration across any framework.\n- ⚡ **Modern Event System**: Standard addEventListener with type-safe helpers\n\n## Installation\n\n### For Modern Bundlers (Recommended)\n\n```bash\nnpm install seo-select\n```\n\n```javascript\n// Import basic select component\nimport 'seo-select';\n\n// Import search-enabled select component\nimport 'seo-select/components/seo-select-search';\n\n// Import Style\nimport 'seo-select/styles'\n\n// Import Types\nimport 'seo-select/types';\n```\n\n### For Direct Browser Usage\n\n```html\n\u003c!-- Import both JavaScript and CSS files --\u003e\n\u003clink rel=\"stylesheet\" href=\"./min/index.css\"\u003e\n\u003cscript type=\"module\" src=\"./min/index.js\"\u003e\u003c/script\u003e\n```\n\n**Alternative**: Download pre-built files from [GitHub Releases](https://github.com/seadonggyun4/seo-select/releases)\n\n## Components Overview\n\n### `seo-select` - Basic Select Component\n\nStandard dropdown functionality with virtual scrolling, multiple selection, themes, and form integration.\n\n### `seo-select-search` - Search-Enhanced Select Component\n\nExtended component with real-time multilingual search including Korean initial consonant search (ㅎㄱㅇ → 한국어), Japanese romaji search (nihongo → 日本語), and Chinese pinyin search (beijing → 北京).\n\n## Basic Usage Examples\n\n### Simple Select\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n\u003chead\u003e\n  \u003cscript type=\"module\"\u003e\n    import 'seo-select';\n  \u003c/script\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n  \u003cseo-select name=\"country\" required\u003e\n    \u003coption value=\"us\"\u003eUnited States\u003c/option\u003e\n    \u003coption value=\"kr\"\u003eSouth Korea\u003c/option\u003e\n    \u003coption value=\"jp\"\u003eJapan\u003c/option\u003e\n  \u003c/seo-select\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\n### Search-enabled Select\n\n```html\n\u003cscript type=\"module\"\u003e\n  import 'seo-select/components/seo-select-search';\n\u003c/script\u003e\n\n\u003cseo-select-search \n  name=\"city\" \n  theme=\"float\" \n  language=\"en\"\n  show-reset\u003e\n  \u003coption value=\"seoul\"\u003eSeoul\u003c/option\u003e\n  \u003coption value=\"tokyo\"\u003eTokyo\u003c/option\u003e\n  \u003coption value=\"beijing\"\u003eBeijing\u003c/option\u003e\n\u003c/seo-select-search\u003e\n```\n\n### Multiple Selection\n\n```html\n\u003cseo-select-search \n  multiple \n  name=\"skills\" \n  theme=\"float\"\n  show-reset\u003e\n  \u003coption value=\"js\"\u003eJavaScript\u003c/option\u003e\n  \u003coption value=\"ts\"\u003eTypeScript\u003c/option\u003e\n  \u003coption value=\"python\"\u003ePython\u003c/option\u003e\n\u003c/seo-select-search\u003e\n```\n\n\n## Event System\n\n### Standard addEventListener (Recommended)\n\n```typescript\n// Works in any framework — listen to custom events emitted by the component.\n// All event payloads are provided in `event.detail`.\n\nsearchSelect.addEventListener('onSelect', (event: CustomEvent\u003c{ label: string; value: string }\u003e) =\u003e {\n  console.log('Selected:', event.detail.label, event.detail.value);\n});\n\nsearchSelect.addEventListener('onDeselect', (event: CustomEvent\u003c{ label: string; value: string }\u003e) =\u003e {\n  console.log('Deselected:', event.detail.label, event.detail.value);\n});\n\nsearchSelect.addEventListener(\n  'onReset',\n  ( event: CustomEvent\u003c{ value: string; label: string } | { values: string[]; labels: string[] } \u003e) =\u003e {\n    if ('values' in event.detail) {\n      console.log('Reset multiple:', event.detail.values, event.detail.labels);\n    } else {\n      console.log('Reset single:', event.detail.value, event.detail.label);\n    }\n  }\n);\n\nsearchSelect.addEventListener('onChange', () =\u003e {\n  console.log('Value changed');\n});\n\nsearchSelect.addEventListener('onOpen', (event: CustomEvent\u003c{ selectInstance?: any }\u003e) =\u003e {\n  console.log('Dropdown opened', event.detail);\n});\n\n// Search-specific events (seo-select-search only)\nsearchSelect.addEventListener(\n  'onSearchChange',\n  ( event: CustomEvent\u003c{ searchText: string } | { searchText: string; previousSearchText: string } \u003e ) =\u003e {\n    console.log('Search text changed:', event.detail.searchText);\n  }\n);\n\nsearchSelect.addEventListener(\n  'onSearchFilter',\n  (\n    event: CustomEvent\u003c{\n      filteredOptions: VirtualSelectOption[];\n      searchText: string;\n      hasResults: boolean;\n    }\u003e\n  ) =\u003e {\n    console.log(\n      `Search filtered: ${event.detail.filteredOptions.length} results for \"${event.detail.searchText}\"`\n    );\n  }\n);\n```\n\n### Type-Safe Helper Methods (Built-in)\n\n```typescript\n// These helper methods wrap `addEventListener` for better DX (Developer Experience).\n// They provide typed callbacks and cleaner syntax.\n\nsearchSelect.onSelect(({ label, value }) =\u003e {\n  console.log('Selected:', label, value);\n});\n\nsearchSelect.onDeselect(({ label, value }) =\u003e {\n  console.log('Deselected:', label, value);\n});\n\nsearchSelect.onReset((detail) =\u003e {\n  console.log('Reset event:', detail);\n});\n\nsearchSelect.onChange(() =\u003e {\n  console.log('Value changed');\n});\n\nsearchSelect.onOpen(() =\u003e {\n  console.log('Dropdown opened');\n});\n\n// Search-specific helpers\nsearchSelect.onSearchChange((searchText) =\u003e {\n  console.log('Search text changed:', searchText);\n});\n\nsearchSelect.onSearchFilter((filteredOptions) =\u003e {\n  console.log('Filtered results count:', filteredOptions.length);\n});\n\n```\n\n### JavaScript/TypeScript Usage\n\n```typescript\nimport 'seo-select/components/seo-select-search';\n\n// Create the element programmatically\nconst select = document.createElement('seo-select-search');\nselect.optionItems = [\n  { value: 'option1', label: 'Option 1' },\n  { value: 'option2', label: 'Option 2' }\n];\nselect.multiple = true;\nselect.theme = 'float';\nselect.language = 'ko';\n\n// Append to the DOM\ndocument.body.appendChild(select);\n\n// Handle events using addEventListener\nselect.addEventListener('onSelect', (event: CustomEvent\u003c{ label: string; value: string }\u003e) =\u003e {\n  console.log('Selected:', event.detail.label, event.detail.value);\n});\n\n// Or use the built-in helper methods\nselect.onSelect(({ label, value }) =\u003e {\n  console.log('Selected:', label, value);\n});\n```\n\n## Events Reference\n\n### Common Events (Both Components)\n\n| Event Name | Properties | Description |\n|------------|------------|-------------|\n| `onSelect` | `{ label, value }` | User selects an option |\n| `onDeselect` | `{ label, value }` | User removes selected option (multiple mode) |\n| `onChange` | - | Form value changes |\n| `onReset` | `{ value, label }` or `{ values, labels }` | Component resets to default |\n| `onOpen` | - | Dropdown opens |\n\n### Search Component Additional Events (SeoSelectSearch Only)\n\n| Event Name | Properties | Description |\n|------------|------------|-------------|\n| `onSearchChange` | `searchText: string` | Search text changes in real-time |\n| `onSearchFilter` | `filteredOptions: VirtualSelectOption[]` | Search results are filtered |\n\n## Component Properties\n\n### Common Properties\n\n| Property | Type | Default | Description |\n|----------|------|---------|-------------|\n| `name` | `string` | - | Form field name |\n| `required` | `boolean` | `false` | Whether the field is required |\n| `multiple` | `boolean` | `false` | Enable multiple selection |\n| `theme` | `'basic' \\| 'float'` | `'float'` | Visual theme |\n| `dark` | `boolean` | `false` | Enable dark mode |\n| `language` | `'en' \\| 'ko' \\| 'ja' \\| 'zh'` | `'en'` | Interface language |\n| `showReset` | `boolean` | `true` | Show reset button |\n| `width` | `string` | `null` | Custom width (auto-calculated if not set) |\n\n### SeoSelectSearch Additional Properties\n\n| Property | Type | Default | Description |\n|----------|------|---------|-------------|\n| `searchTexts` | `Partial\u003cSearchLocalizedTexts\u003e` | `{}` | Custom search-related texts |\n\n\n## Methods\n\n### SeoSelect (Basic Component)\n\nThe basic `seo-select` component provides fundamental option management and value control methods:\n\n#### Value Management\n```typescript\n// Get/Set single value\nconst currentValue = select.value;\nselect.value = 'option1';\n\n// Get/Set multiple values (when multiple=true)\nconst selectedValues = select.selectedValues; // ['opt1', 'opt2']\nselect.selectedValues = ['opt1', 'opt3'];\n\n// Reset to default value\nselect.resetToDefaultValue();\n```\n\n#### Dynamic Option Management\n```typescript\n// Add multiple options at once (replaces existing options)\nselect.addOptions([\n  { value: 'opt1', label: 'Option 1' },\n  { value: 'opt2', label: 'Option 2' }\n], preserveSelection); // preserveSelection: boolean (default: false)\n\n// Add a single option\nselect.addOption({ value: 'new', label: 'New Option' }, index); // index: optional position\n\n// Remove a specific option by value\nselect.clearOption('option-value-to-remove');\n\n// Remove all options\nselect.clearAllOptions();\n\n// Batch update operations (highly optimized for performance)\nselect.batchUpdateOptions([\n  { action: 'add', option: { value: 'new1', label: 'New 1' } },\n  { action: 'remove', value: 'old-option' },\n  { action: 'update', value: 'existing', option: { value: 'existing', label: 'Updated Label' } }\n]);\n```\n\n#### Customization Methods\n```typescript\n// Change language dynamically\nselect.setLanguage('ko'); // 'en' | 'ko' | 'ja' | 'zh'\n\n// Set custom localized texts\nselect.setTexts({ \n  placeholder: 'Custom placeholder...',\n  required: 'This field is required',\n  resetToDefault: 'Reset selection'\n});\n\n// Enable/disable auto-width calculation\nselect.setAutoWidth(true);\n\n// Clear internal caches (useful for memory optimization)\nselect.clearCaches();\n```\n\n#### Event Management (Type-Safe Helpers)\n```typescript\n// Basic events (always available)\nselect.onSelect((event) =\u003e {\n  console.log('Selected:', event.label, event.value);\n});\n\nselect.onDeselect((event) =\u003e {\n  console.log('Deselected:', event.label, event.value);\n});\n\nselect.onReset((event) =\u003e {\n  if (select.multiple) {\n    console.log('Reset multiple:', event.values, event.labels);\n  } else {\n    console.log('Reset single:', event.value, event.label);\n  }\n});\n\nselect.onChange(() =\u003e {\n  console.log('Form value changed');\n});\n\nselect.onOpen(() =\u003e {\n  console.log('Dropdown opened');\n});\n```\n\n#### Utility Methods\n```typescript\n// Get current option count\nconst optionCount = select.options.length;\n\n// Get selected index (single mode only)\nconst selectedIndex = select.selectedIndex;\n\n// Get default value\nconst defaultValue = select.defaultValue;\n\n// Check if component has options\nconst hasOptions = !select.hasNoOptions();\n```\n\n### SeoSelectSearch (Search-Enhanced Component)\n\nThe `seo-select-search` component extends the basic component with advanced search functionality:\n\n#### Search-Specific Methods\n```typescript\n// ► Practical example: Auto-focus search when dropdown opens\nsearchSelect.onOpen(() =\u003e {\n  // Set initial search text to help users\n  searchSelect.searchText = 'Seoul';\n  \n  // Or clear previous search and let user type fresh\n  searchSelect.clearSearchText();\n});\n\n// ► Advanced example: Set search based on previous selection\nlet lastSelected = '';\nsearchSelect.onSelect((event) =\u003e {\n  lastSelected = event.value;\n});\n\nsearchSelect.onOpen(() =\u003e {\n  if (lastSelected.startsWith('kr')) {\n    searchSelect.searchText = 'Korean';\n  }\n});\n```\n\n#### Advanced Option Management\n```typescript\n// Update options while preserving search state\nsearchSelect.updateOptionsWithSearch([\n  { value: 'opt1', label: 'Searchable Option 1' },\n  { value: 'opt2', label: 'Searchable Option 2' }\n], preserveSearch); // preserveSearch: boolean (default: true)\n\n// Load options dynamically based on search\nawait searchSelect.loadOptionsForSearch('search term', async (searchText) =\u003e {\n  // Custom async function to load options\n  const response = await fetch(`/api/search?q=${searchText}`);\n  return await response.json();\n});\n```\n\n#### Search Event Handling\n```typescript\n// Listen to search text changes\nsearchSelect.onSearchChange((searchText) =\u003e {\n  console.log('User typed:', searchText);\n  // Trigger API calls, analytics, etc.\n});\n\n// Listen to search filter events\nsearchSelect.onSearchFilter((filteredOptions) =\u003e {\n  console.log(`Found ${filteredOptions.length} results`);\n  // Update UI indicators, show result counts, etc.\n});\n```\n\n#### Custom Search Texts\n```typescript\n// Set search-specific localized texts\nsearchSelect.setSearchTexts({\n  searchPlaceholder: 'Type to search...',\n  noMatchText: 'No results found'\n});\n```\n\n#### Inherited Methods\nThe `seo-select-search` component inherits all methods from the basic `seo-select` component, so you can use all the value management, option management, and customization methods mentioned above.\n\n#### Performance Considerations\n```typescript\n// For large datasets, use batch operations\nsearchSelect.batchUpdateOptions(largeUpdateArray);\n\n// Clear caches when dealing with frequent option updates\nsearchSelect.clearCaches();\n\n// Use preserveSelection for better UX when updating options\nsearchSelect.addOptions(newOptions, true); // Preserves current selection\n```\n\n## TypeScript Support\n\n### Type Definitions\n\nFor TypeScript projects, import the type definitions to enable full type safety and IntelliSense support for custom events and component APIs:\n\n```typescript\n// Import type definitions (add this once in your project)\nimport 'seo-select/types';\n\n// Import components\nimport 'seo-select';\nimport 'seo-select/components/seo-select-search';\n```\n\n**That's it!** With just `import 'seo-select/types';`, you get:\n\n- ✅ **Full type safety** for all event listeners (`addEventListener`)\n- ✅ **IntelliSense support** for event properties (`event.label`, `event.value`)\n- ✅ **Global type extensions** for `HTMLElementEventMap`\n- ✅ **Zero configuration** - works immediately\n\n### Basic Usage with Type Safety\n\n```typescript\nimport 'seo-select/types';\nimport 'seo-select';\n\nconst select = document.createElement('seo-select');\n\n// All event listeners are now fully type-safe\nselect.addEventListener('onSelect', (event) =\u003e {\n  // TypeScript knows event.label and event.value exist\n  console.log('Selected:', event.label, event.value);\n});\n\nselect.addEventListener('onReset', (event) =\u003e {\n  // TypeScript automatically infers the correct event type\n  if (event.values) {\n    console.log('Multiple reset:', event.values, event.labels);\n  } else {\n    console.log('Single reset:', event.value, event.label);\n  }\n});\n```\n\n### Advanced Usage with Specific Types\n\nWhen you need specific types for your application logic, import them explicitly:\n\n```typescript\nimport 'seo-select/types';\nimport type { \n  VirtualSelectOption,\n  SeoSelectElement,\n  SeoSelectSearchElement,\n  SupportedLanguage,\n  BatchUpdateOption\n} from 'seo-select/types';\n\n// Type-safe option creation\nconst options: VirtualSelectOption[] = [\n  { value: 'us', label: 'United States' },\n  { value: 'kr', label: 'South Korea' }\n];\n\n// Type-safe element creation\nconst selectElement = document.createElement('seo-select') as SeoSelectElement;\nselectElement.optionItems = options;\nselectElement.language = 'ko' as SupportedLanguage;\n\n// Type-safe batch operations\nconst updates: BatchUpdateOption[] = [\n  { action: 'add', option: { value: 'jp', label: 'Japan' } },\n  { action: 'remove', value: 'us' }\n];\nselectElement.batchUpdateOptions(updates);\n```\n\n### Available Types\n\n| Category | Types |\n|----------|-------|\n| **Component Elements** | `SeoSelectElement`, `SeoSelectSearchElement` |\n| **Options \u0026 Data** | `VirtualSelectOption`, `OptionItem`, `BatchUpdateOption` |\n| **Configuration** | `SupportedLanguage`, `SelectTheme`, `LocalizedTexts`, `SearchLocalizedTexts` |\n| **Component Props** | `SeoSelectProps`, `SeoSelectSearchProps` |\n| **Events** | `ResetEventData`, `SeoSelectEventType`, `SeoSelectEvents` |\n\n### Event Constants\n\n```typescript\nimport { SeoSelectEvents } from 'seo-select/types';\n\n// Use event constants for consistency\nselect.addEventListener(SeoSelectEvents.SELECT, (event) =\u003e {\n  console.log('Selected:', event.label);\n});\n\nselect.addEventListener(SeoSelectEvents.SEARCH_CHANGE, (event) =\u003e {\n  console.log('Search text:', event.detail);\n});\n```\n\n\n## Styling and Customization\n\n### Quick Styling Example\n\n```css\nseo-select {\n  --select-border-color: #ccc;\n  --select-focus-color: #007bff;\n  --select-background: white;\n  --select-text-color: #333;\n}\n\n/* Dark mode */\nseo-select[dark] {\n  --select-background: #374151;\n  --select-text-color: #f3f4f6;\n  --select-border-color: #6b7280;\n}\n```\n\n### Complete CSS Variables Reference\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e📏 Basic Layout \u0026 Sizing Variables\u003c/strong\u003e\u003c/summary\u003e\n\n| Variable | Default Value | Description |\n|----------|---------------|-------------|\n| `--select-padding` | `0.5rem 0.8rem` | Internal padding of select box |\n| `--select-min-height` | `35px` | Minimum height of select component |\n| `--select-min-width` | `150px` | Minimum width of select component |\n| `--select-border-width` | `1px` | Border thickness |\n| `--select-transition-duration` | `0.3s` | Animation transition duration |\n| `--select-transition-easing` | `ease` | Animation easing function |\n| `--select-font-size` | `12px` | Font size of select text |\n| `--select-font-color` | `#1f1b25` | Font color of select text |\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e🎨 Theme Styles\u003c/strong\u003e\u003c/summary\u003e\n\n**Basic Theme:**\n| Variable | Default Value | Description |\n|----------|---------------|-------------|\n| `--select-basic-border-radius` | `0` | Border radius for basic theme |\n| `--select-basic-box-shadow` | `none` | Box shadow for basic theme |\n| `--select-basic-margin-bottom` | `0` | Bottom margin for basic theme |\n\n**Float Theme:**\n| Variable | Default Value | Description |\n|----------|---------------|-------------|\n| `--select-float-border-radius` | `5px` | Border radius for float theme |\n| `--select-float-box-shadow` | `0 2px 4px rgba(0, 0, 0, 0.1)` | Box shadow for float theme |\n| `--select-float-margin-bottom` | `0` | Bottom margin for float theme |\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e🏷️ Multiple Selection \u0026 Tags Variables\u003c/strong\u003e\u003c/summary\u003e\n\n| Variable | Default Value | Description |\n|----------|---------------|-------------|\n| `--select-multi-padding-right` | `3rem` | Right padding for multiple selection |\n| `--select-tags-gap` | `0.25rem` | Gap between tags in multiple mode |\n| `--select-tags-padding` | `0.25rem 0` | Padding around tags container |\n| `--select-tags-min-height` | `1.5rem` | Minimum height of tags area |\n| `--tag-padding` | `0.2rem 0.3rem` | Internal padding of tags |\n| `--tag-gap` | `0.5rem` | Gap between individual tags |\n| `--tag-border-radius` | `25rem` | Border radius of tags (pill shape) |\n| `--tag-border-width` | `1px` | Border thickness of tags |\n| `--tag-remove-size` | `1rem` | Size of tag remove button |\n| `--tag-remove-border-radius` | `50%` | Border radius of remove button |\n| `--tag-remove-transition` | `all 0.2s ease` | Transition for remove button |\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e📋 Dropdown Variables\u003c/strong\u003e\u003c/summary\u003e\n\n**Basic Dropdown:**\n| Variable | Default Value | Description |\n|----------|---------------|-------------|\n| `--dropdown-box-shadow` | `0 5px 10px rgba(0, 0, 0, 0.1)` | Box shadow of dropdown |\n| `--dropdown-border-width` | `1px` | Border thickness of dropdown |\n| `--dropdown-z-index` | `1000` | Z-index stacking order |\n| `--dropdown-basic-border-radius` | `0` | Border radius for basic theme dropdown |\n\n**Float Theme Dropdown:**\n| Variable | Default Value | Description |\n|----------|---------------|-------------|\n| `--dropdown-float-border-radius` | `5px` | Border radius for float theme dropdown |\n| `--dropdown-float-box-shadow` | `0 8px 16px rgba(0, 0, 0, 0.15)` | Enhanced shadow for float theme |\n| `--dropdown-float-top` | `130%` | Dropdown position from select box |\n| `--dropdown-float-animation-duration` | `0.2s` | Animation duration for float theme |\n| `--dropdown-float-animation-easing` | `ease-out` | Animation easing for float theme |\n| `--dropdown-float-slide-distance` | `-20px` | Slide distance for animation |\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e🔍 Search Input Variables\u003c/strong\u003e\u003c/summary\u003e\n\n| Variable | Default Value | Description |\n|----------|---------------|-------------|\n| `--search-input-padding` | `0.3rem` | Internal padding of search input |\n| `--search-input-text-indent` | `1.5rem` | Text indentation for search icon space |\n| `--search-icon-left` | `0.7rem` | Left position of search icon |\n| `--search-icon-size` | `1rem` | Size of search icon |\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e⏳ Loading State Variables\u003c/strong\u003e\u003c/summary\u003e\n\n| Variable | Default Value | Description |\n|----------|---------------|-------------|\n| `--loading-container-padding` | `1rem 2rem` | Padding around loading container |\n| `--loading-dots-gap` | `0.5rem` | Gap between loading dots |\n| `--loading-dots-margin-bottom` | `1rem` | Bottom margin of dots container |\n| `--loading-dot-size` | `0.5rem` | Size of individual loading dots |\n| `--loading-animation-duration` | `1.4s` | Duration of loading animation |\n| `--loading-text-font-size` | `0.9rem` | Font size of loading text |\n| `--loading-dot-delay-1` | `-0.32s` | Animation delay for first dot |\n| `--loading-dot-delay-2` | `-0.16s` | Animation delay for second dot |\n| `--loading-dot-delay-3` | `0s` | Animation delay for third dot |\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e📭 Empty State Variables\u003c/strong\u003e\u003c/summary\u003e\n\n| Variable | Default Value | Description |\n|----------|---------------|-------------|\n| `--no-data-container-padding` | `1rem 2rem` | Padding of \"no data\" container |\n| `--no-data-text-font-size` | `0.9rem` | Font size of \"no data\" text |\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e📃 Option Items Variables\u003c/strong\u003e\u003c/summary\u003e\n\n| Variable | Default Value | Description |\n|----------|---------------|-------------|\n| `--option-padding` | `0 0.8rem` | Internal padding of option items |\n| `--option-line-height` | `300%` | Line height of option items |\n| `--option-check-mark-margin` | `0.5rem` | Margin of checkmark in options |\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e🔄 Reset Button Variables\u003c/strong\u003e\u003c/summary\u003e\n\n**Single Select Reset:**\n| Variable | Default Value | Description |\n|----------|---------------|-------------|\n| `--reset-button-right` | `3rem` | Right position of reset button |\n| `--reset-button-padding` | `0 0.5rem` | Internal padding of reset button |\n| `--reset-button-height` | `80%` | Height of reset button |\n| `--reset-button-font-size` | `0.9rem` | Font size of reset button |\n| `--reset-button-transition` | `all 0.2s ease` | Transition for reset button |\n\n**Multiple Select Reset:**\n| Variable | Default Value | Description |\n|----------|---------------|-------------|\n| `--multi-reset-button-size` | `1.5rem` | Size of multi-select reset button |\n| `--multi-reset-button-position` | `-0.6rem` | Position adjustment for multi reset |\n| `--multi-reset-button-border-radius` | `50%` | Border radius of multi reset button |\n| `--multi-reset-button-font-size` | `0.9rem` | Font size of multi reset button |\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e↗️ Dropdown Arrow Variables\u003c/strong\u003e\u003c/summary\u003e\n\n| Variable | Default Value | Description |\n|----------|---------------|-------------|\n| `--arrow-right` | `0.8rem` | Right position of dropdown arrow |\n| `--arrow-font-size` | `0.9rem` | Font size of dropdown arrow |\n| `--arrow-margin-top` | `-0.1rem` | Top margin adjustment for arrow |\n| `--arrow-transition` | `transform 0.2s ease` | Transition for arrow rotation |\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e🎨 Color Palette Variables\u003c/strong\u003e\u003c/summary\u003e\n\n**Primary Colors:**\n| Variable | Default Value | Description |\n|----------|---------------|-------------|\n| `--primary-color` | `#3253de` | Main brand color |\n| `--primary-hover` | `#003766` | Primary color on hover state |\n| `--primary-bg-color` | `#e5f1fbf2` | Primary background color |\n| `--secondary-color` | `#5f77ca` | Secondary brand color |\n| `--secondary-hover` | `#303c65f2` | Secondary color on hover state |\n| `--secondary-bg-color` | `#eff1faf2` | Secondary background color |\n\n**Semantic State Colors:**\n| Variable | Default Value | Description |\n|----------|---------------|-------------|\n| `--success-color` | `pick(green, 5)` | Success state color |\n| `--success-hover` | `pick(green, 6)` | Success color on hover |\n| `--success-bg-color` | `pick(green, 0)` | Success background color |\n| `--error-color` | `pick(red, 5)` | Error state color |\n| `--error-hover` | `pick(red, 6)` | Error color on hover |\n| `--error-bg-color` | `color.mix(#fff, pick(red, 1), 25%)` | Error background color |\n| `--warning-color` | `pick(orange, 4)` | Warning state color |\n| `--warning-hover` | `pick(orange, 5)` | Warning color on hover |\n| `--warning-bg-color` | `color.mix(#fff, pick(orange, 1), 25%)` | Warning background color |\n| `--disabled-color` | `color.adjust(pick(gray, 3), $lightness: 5%)` | Disabled element color |\n\n**Typography Colors:**\n| Variable | Default Value | Description |\n|----------|---------------|-------------|\n| `--font-color` | `color.mix(#000, pick(indigo, 10), 70%)` | Primary text color |\n| `--font-secondary-color` | `pick(gray, 5)` | Secondary text color |\n\n**UI Element Colors:**\n| Variable | Default Value | Description |\n|----------|---------------|-------------|\n| `--border-color` | `pick(gray, 3)` | Default border color |\n| `--box-head-border-color` | `color.mix(#fff, pick(gray, 2), 35%)` | Box header border color |\n\n**Extended Color Palette (Open Color System):**\nThe component uses a sophisticated color system based on Open Color with primary color mixing:\n\n| Color Name | Usage | Available Shades |\n|------------|-------|------------------|\n| `gray` | Neutral elements, borders, backgrounds | 0-10 (lightest to darkest) |\n| `red` | Error states, destructive actions | 0-10 |\n| `pink` | Accent colors, highlights | 0-10 |\n| `grape` | Decorative elements | 0-10 |\n| `violet` | Special highlights | 0-10 |\n| `indigo` | Primary variants | 0-10 |\n| `blue` | Information states, links | 0-10 |\n| `cyan` | Cool accents | 0-10 |\n| `teal` | Fresh accents | 0-10 |\n| `green` | Success states, positive actions | 0-10 |\n| `lime` | Fresh highlights | 0-10 |\n| `yellow` | Warning states, attention | 0-10 |\n| `orange` | Warning states, alerts | 0-10 |\n\n**Using the Color System:**\n```scss\n// Access colors using the pick() function\n.my-element {\n  background-color: pick(blue, 2);    // Light blue\n  border-color: pick(blue, 5);        // Medium blue\n  color: pick(blue, 8);               // Dark blue\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e🌙 Dark Mode Color Variables\u003c/strong\u003e\u003c/summary\u003e\n\n**Background Colors:**\n| Variable | Default Value | Description |\n|----------|---------------|-------------|\n| `--dark-select-bg` | `#374151` | Background color in dark mode |\n| `--dark-dropdown-bg` | `#374151` | Dropdown background in dark mode |\n| `--dark-tag-bg` | `#4b5563` | Tag background in dark mode |\n| `--dark-search-input-bg` | `#374151` | Search input background in dark mode |\n| `--dark-accent-bg` | `#1f2937` | Darker background for special elements |\n| `--dark-card-bg` | `#374151` | Card/container background |\n| `--dark-surface-bg` | `#4b5563` | Surface element background |\n\n**Border Colors:**\n| Variable | Default Value | Description |\n|----------|---------------|-------------|\n| `--dark-border-color` | `#6b7280` | Border color in dark mode |\n| `--dark-border-hover-color` | `#60a5fa` | Border color on hover in dark mode |\n| `--dark-border-focus-color` | `#60a5fa` | Border color on focus in dark mode |\n\n**Text Colors:**\n| Variable | Default Value | Description |\n|----------|---------------|-------------|\n| `--dark-text-color` | `#f3f4f6` | Primary text color in dark mode |\n| `--dark-text-secondary-color` | `#d1d5db` | Secondary text color in dark mode |\n| `--dark-placeholder-color` | `#9ca3af` | Placeholder color in dark mode |\n| `--dark-highlight-color` | `#fbbf24` | Highlight/accent color in dark mode |\n\n**Dark Mode State Colors:**\n| Variable | Default Value | Description |\n|----------|---------------|-------------|\n| `--dark-success-color` | `#10b981` | Success state color in dark mode |\n| `--dark-warning-color` | `#f59e0b` | Warning state color in dark mode |\n| `--dark-error-color` | `#ef4444` | Error state color in dark mode |\n| `--dark-info-color` | `#3b82f6` | Information state color in dark mode |\n\n**Option Colors:**\n| Variable | Default Value | Description |\n|----------|---------------|-------------|\n| `--dark-option-hover-bg` | `#4b5563` | Option background on hover |\n| `--dark-option-selected-bg` | `#3b82f6` | Selected option background |\n| `--dark-option-focused-bg` | `#4b5563` | Focused option background |\n| `--dark-option-disabled-color` | `#9ca3af` | Disabled option text color |\n\n**Tag Colors:**\n| Variable | Default Value | Description |\n|----------|---------------|-------------|\n| `--dark-tag-text-color` | `#f3f4f6` | Tag text color in dark mode |\n| `--dark-tag-border-color` | `#60a5fa` | Tag border color in dark mode |\n| `--dark-tag-remove-hover-bg` | `#ef4444` | Tag remove button hover background |\n\n**Button Colors:**\n| Variable | Default Value | Description |\n|----------|---------------|-------------|\n| `--dark-reset-button-color` | `#d1d5db` | Reset button color in dark mode |\n| `--dark-reset-button-hover-color` | `#ef4444` | Reset button hover color |\n| `--dark-multi-reset-button-bg` | `#6b7280` | Multi reset button background |\n\n**Shadow Effects:**\n| Variable | Default Value | Description |\n|----------|---------------|-------------|\n| `--dark-float-box-shadow` | `0 4px 6px rgba(0, 0, 0, 0.4), 0 2px 4px rgba(0, 0, 0, 0.2)` | Float theme shadow in dark mode |\n| `--dark-dropdown-box-shadow` | `0 10px 20px rgba(0, 0, 0, 0.5), 0 4px 8px rgba(0, 0, 0, 0.3)` | Dropdown shadow in dark mode |\n| `--dark-search-input-focus-shadow` | `0 0 0 2px rgba(96, 165, 250, 0.3), 0 4px 12px rgba(0, 0, 0, 0.3)` | Search input focus shadow |\n\n\u003c/details\u003e\n\n## License\n\nMIT License - see [LICENSE](LICENSE) file for details.\n\n## Changelog\n\n### Version 2.x\n- **Dynamic Option Management**: Advanced methods for real-time option manipulation without re-rendering the entire component.\n- **Real-time Virtual Scroll Sync**: Instant UI updates for option changes with virtual scrolling.\n- **Enhanced State Management**: Improved consistency, reliability, and reduced state desynchronization issues.\n- **Search Component Enhancements**: Better handling of multilingual search, optimized filtering performance, and improved accuracy for Korean, Japanese, and Chinese search modes.\n- **Custom Event System Update**: All events now consistently use `CustomEvent` with payloads in `event.detail`, keeping the `on…` naming convention (e.g., `onSelect`, `onDeselect`, `onSearchChange`).  \n  This ensures compatibility with React, Angular, Vue, and other framework wrappers.\n- **Optional Property Type Safety**: Fixed issues with `exactOptionalPropertyTypes` by omitting undefined properties in event payloads.\n\n\n### Version 2.1.x\n- **Built Distribution**: Now distributes pre-built files optimized for production use\n- **Improved Performance**: Ready-to-use minified JavaScript and CSS files\n- **Better Compatibility**: Works out-of-the-box across different bundlers and environments\n- **Enhanced Developer Experience**: No additional build step required for most use cases\n- **Vite Build Integration**: Built using Vite for optimal bundle size and modern JavaScript features\n- **Web Standards \u0026 Accessibility**: replace option tags with accessible divs and optimize pool size for small datasets\n\n### Version 1.x \n- **Enhanced Event System**: Standard `addEventListener` with built-in type-safe helpers\n- **Helper Methods**: `onSelect()`, `onDeselect()`, `onReset()`, `onChange()`, `onOpen()` always available\n- **Improved DX**: Better TypeScript support and developer experience\n- **Performance**: Optimized event handling and memory management\n- **Backward Compatibility**: All existing code continues to work\n\n---\n\n\u003e **Migration Note**:  \n\u003e Version 2.x maintains full API compatibility with 1.x while changing the distribution format from source TypeScript files to pre-built, optimized JavaScript and CSS files. The new dynamic option management methods provide powerful tools for building interactive applications with real-time data updates.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseadonggyun4%2Fseo-select","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fseadonggyun4%2Fseo-select","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseadonggyun4%2Fseo-select/lists"}