{"_id":"@alsocoder/apna-select","_rev":"6-69872d69cacaec05845afb722e19f66a","name":"@alsocoder/apna-select","dist-tags":{"latest":"0.2.3"},"versions":{"0.1.0":{"name":"@alsocoder/apna-select","version":"0.1.0","keywords":["react","react-component","select","dropdown","combobox","multi-select","multiselect","searchable-select","async-select","remote-select","form","form-control","ui-component","vanilla-css","css-variables","radix-ui","accessible","a11y","keyboard-navigation","typescript","apna-select","alsocoder"],"author":{"url":"https://alsocoder.com","name":"Also Coder"},"license":"MIT","_id":"@alsocoder/apna-select@0.1.0","maintainers":[{"name":"alsocoder-org","email":"alsocoder@gmail.com"}],"homepage":"https://github.com/alsocoders/apna-select#readme","bugs":{"url":"https://github.com/alsocoders/apna-select/issues"},"dist":{"shasum":"158502da500086f8bce31f09655d7f333cc4bd72","tarball":"https://registry.npmjs.org/@alsocoder/apna-select/-/apna-select-0.1.0.tgz","fileCount":9,"integrity":"sha512-IrEtV+G+I3WPGyKNkrXY3NtjhnjOtoVXqvmMZ2a7tTpDF5WX7Ddh6t2avuRBD4C0h5aqbAYdpxcdLc587E95NA==","signatures":[{"sig":"MEUCIQDcVu/LksavZUgisp2rhAF4EUDWU6hY2V8p9Dv65a/A8QIgGIofb6O9NlEJymIgAGglN9o0cISUABxgkaREJoo0v1c=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":188402},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./styles.css":"./dist/styles.css"},"scripts":{"dev":"tsup --watch","build":"tsup","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"_npmUser":{"name":"alsocoder-org","email":"alsocoder@gmail.com"},"repository":{"url":"git+https://github.com/alsocoders/apna-select.git","type":"git"},"_npmVersion":"12.0.1","description":"A flexible React select component with single/multi select, search, async API loading, and vanilla CSS customization.","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.16.0","browserslist":["Chrome >= 90","Firefox >= 90","Safari >= 14","Edge >= 90","iOS >= 14","Samsung >= 15","not dead"],"dependencies":{"clsx":"^2.1.1","@radix-ui/react-popover":"^1.1.14","@radix-ui/react-checkbox":"^1.3.2"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.0","react":"^19.1.0","react-dom":"^19.1.0","typescript":"^5.9.2","@types/react":"^19.1.8","@types/react-dom":"^19.1.6"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/apna-select_0.1.0_1785398834464_0.4024829076745253","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@alsocoder/apna-select","version":"0.1.1","keywords":["react","react-component","select","dropdown","combobox","multi-select","multiselect","searchable-select","async-select","remote-select","form","form-control","ui-component","vanilla-css","css-variables","radix-ui","accessible","a11y","keyboard-navigation","typescript","apna-select","alsocoder"],"author":{"url":"https://alsocoder.com","name":"Also Coder"},"license":"MIT","_id":"@alsocoder/apna-select@0.1.1","maintainers":[{"name":"alsocoder-org","email":"alsocoder@gmail.com"}],"homepage":"https://github.com/alsocoders/apna-select#readme","bugs":{"url":"https://github.com/alsocoders/apna-select/issues"},"dist":{"shasum":"84f1eb097527aa9ddfb36b4a7735c7bacbcab2f7","tarball":"https://registry.npmjs.org/@alsocoder/apna-select/-/apna-select-0.1.1.tgz","fileCount":9,"integrity":"sha512-wvTn10ryFBvyNHKIo0lKUwgYdcolYb9CKUnD8ZdM4x+fzIwFTTO7/gEffNlQnFPKxiiLnVs67NeDGoHxIz7cpA==","signatures":[{"sig":"MEUCIQDk6MDFr8yfeF3Ysc+xpv3kaaCicxOC12wDL8c29VyuNQIgeXLOC9Qc14Lxd2IGfl/zHncTtwnomHoR8it/2lodp0Q=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":187634},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./styles.css":"./dist/styles.css"},"scripts":{"dev":"tsup --watch","build":"tsup","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"_npmUser":{"name":"alsocoder-org","email":"alsocoder@gmail.com"},"repository":{"url":"git+https://github.com/alsocoders/apna-select.git","type":"git"},"_npmVersion":"12.0.1","description":"A flexible React select component with single/multi select, search, async API loading, and vanilla CSS customization.","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.16.0","browserslist":["Chrome >= 90","Firefox >= 90","Safari >= 14","Edge >= 90","iOS >= 14","Samsung >= 15","not dead"],"dependencies":{"clsx":"^2.1.1","@radix-ui/react-popover":"^1.1.14","@radix-ui/react-checkbox":"^1.3.2"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.0","react":"^19.1.0","react-dom":"^19.1.0","typescript":"^5.9.2","@types/react":"^19.1.8","@types/react-dom":"^19.1.6"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/apna-select_0.1.1_1785400136966_0.3967403159678786","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@alsocoder/apna-select","version":"0.2.0","keywords":["react","react-component","select","dropdown","combobox","multi-select","multiselect","searchable-select","async-select","remote-select","form","form-control","ui-component","css-variables","radix-ui","accessible","a11y","keyboard-navigation","typescript","apna-select","alsocoder"],"author":{"url":"https://alsocoder.com","name":"Also Coder"},"license":"MIT","_id":"@alsocoder/apna-select@0.2.0","maintainers":[{"name":"alsocoder-org","email":"alsocoder@gmail.com"}],"homepage":"https://github.com/alsocoders/apna-select#readme","bugs":{"url":"https://github.com/alsocoders/apna-select/issues"},"dist":{"shasum":"b3fd5104789ac4bf231e083cb0d9a3b06d486133","tarball":"https://registry.npmjs.org/@alsocoder/apna-select/-/apna-select-0.2.0.tgz","fileCount":9,"integrity":"sha512-mCaBDo1CrCuZJ3E6iNMmL1CLydb1JqpVay2ceKhq7V9HPRQ/sM1uu1uo2lcAZN3xV7VYOMcQyYwVEFETMa6Zaw==","signatures":[{"sig":"MEQCIGabeN9xHNiLzYwAXgd6VUsug5nEc3S+72gLOrpkr/AxAiAY93c5PDBoFMGNaehHnCnSazzdQc44RMVTnSfilw60FA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":250016},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./styles.css":"./dist/styles.css"},"scripts":{"dev":"tsup --watch","build":"tsup","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"_npmUser":{"name":"alsocoder-org","email":"alsocoder@gmail.com"},"repository":{"url":"git+https://github.com/alsocoders/apna-select.git","type":"git"},"_npmVersion":"12.0.1","description":"A flexible React select component with single/multi select, search, async API loading, and CSS customization.","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.16.0","browserslist":["Chrome >= 90","Firefox >= 90","Safari >= 14","Edge >= 90","iOS >= 14","Samsung >= 15","not dead"],"dependencies":{"clsx":"^2.1.1","@radix-ui/react-popover":"^1.1.14","@radix-ui/react-checkbox":"^1.3.2"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.0","react":"^19.1.0","react-dom":"^19.1.0","typescript":"^5.9.2","@types/react":"^19.1.8","@types/react-dom":"^19.1.6"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/apna-select_0.2.0_1785405729323_0.11687478267523654","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@alsocoder/apna-select","version":"0.2.1","keywords":["react","react-component","select","dropdown","combobox","multi-select","multiselect","searchable-select","async-select","remote-select","form","form-control","ui-component","css-variables","radix-ui","accessible","a11y","keyboard-navigation","typescript","apna-select","alsocoder"],"author":{"url":"https://alsocoder.com","name":"Also Coder"},"license":"MIT","_id":"@alsocoder/apna-select@0.2.1","maintainers":[{"name":"alsocoder-org","email":"alsocoder@gmail.com"}],"homepage":"https://github.com/alsocoders/apna-select#readme","bugs":{"url":"https://github.com/alsocoders/apna-select/issues"},"dist":{"shasum":"06640fb945968c7146d7e6d9d230926f2c30c4c5","tarball":"https://registry.npmjs.org/@alsocoder/apna-select/-/apna-select-0.2.1.tgz","fileCount":9,"integrity":"sha512-6NcK09NZtTzzs1oB9CkELtfzKg1nxefLnCcRTz/xN7L2jM3xyHcNf8bZzX6zIWfocm98QeQ8KN+pMtqLekImTg==","signatures":[{"sig":"MEUCIFQtdkoNi7quooiorUWvI67Az5pV0uD0jNiYKPc6DjT0AiEAo9ejt/ELJyky0uY6mw4E2+SQyE3/JOufbw8MhLjx4xM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":250156},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./styles.css":"./dist/styles.css"},"scripts":{"dev":"tsup --watch","build":"tsup","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"_npmUser":{"name":"alsocoder-org","email":"alsocoder@gmail.com"},"repository":{"url":"git+https://github.com/alsocoders/apna-select.git","type":"git"},"_npmVersion":"12.0.1","description":"A flexible React select component with single/multi select, search, async API loading, and CSS customization.","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.16.0","browserslist":["Chrome >= 90","Firefox >= 90","Safari >= 14","Edge >= 90","iOS >= 14","Samsung >= 15","not dead"],"dependencies":{"clsx":"^2.1.1","@radix-ui/react-popover":"^1.1.14","@radix-ui/react-checkbox":"^1.3.2"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.0","react":"^19.1.0","react-dom":"^19.1.0","typescript":"^5.9.2","@types/react":"^19.1.8","@types/react-dom":"^19.1.6"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/apna-select_0.2.1_1785587447370_0.32559447648730955","host":"s3://npm-registry-packages-npm-production"}},"0.2.2":{"name":"@alsocoder/apna-select","version":"0.2.2","keywords":["react","react-component","select","dropdown","combobox","multi-select","multiselect","searchable-select","async-select","remote-select","form","form-control","ui-component","css-variables","radix-ui","accessible","a11y","keyboard-navigation","typescript","apna-select","alsocoder"],"author":{"url":"https://alsocoder.com","name":"Also Coder"},"license":"MIT","_id":"@alsocoder/apna-select@0.2.2","maintainers":[{"name":"alsocoder-org","email":"alsocoder@gmail.com"}],"homepage":"https://github.com/alsocoders/apna-select#readme","bugs":{"url":"https://github.com/alsocoders/apna-select/issues"},"dist":{"shasum":"ac6ede8a3b6e6a84efcc0e796d06d8889c971614","tarball":"https://registry.npmjs.org/@alsocoder/apna-select/-/apna-select-0.2.2.tgz","fileCount":9,"integrity":"sha512-K0REazxC6bfxLqtGrVMBaYRFZVJ4buUPCAKijaSa/KLP6xfzz2DzL6OSRZ3fZOwQ6O3yGpez9IQkoJNo1S58IA==","signatures":[{"sig":"MEYCIQC1LSMMgQI3u9shr6b51MCAv/Q1S9vY+LTGB7vq7upWTgIhAORNo8sbiMu2PL4UhDtF3aqjxHca8O3If5Z1N8kT+QTB","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":251218},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./styles.css":"./dist/styles.css"},"scripts":{"dev":"tsup --watch","build":"tsup","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"_npmUser":{"name":"alsocoder-org","email":"alsocoder@gmail.com"},"repository":{"url":"git+https://github.com/alsocoders/apna-select.git","type":"git"},"_npmVersion":"12.0.1","description":"A flexible React select component with single/multi select, search, async API loading, and CSS customization.","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.16.0","browserslist":["Chrome >= 90","Firefox >= 90","Safari >= 14","Edge >= 90","iOS >= 14","Samsung >= 15","not dead"],"dependencies":{"clsx":"^2.1.1","@radix-ui/react-popover":"^1.1.14","@radix-ui/react-checkbox":"^1.3.2","@radix-ui/react-dismissable-layer":"^1.1.11"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.0","react":"^19.1.0","react-dom":"^19.1.0","typescript":"^5.9.2","@types/react":"^19.1.8","@types/react-dom":"^19.1.6"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/apna-select_0.2.2_1785592243111_0.28748372066632544","host":"s3://npm-registry-packages-npm-production"}},"0.2.3":{"name":"@alsocoder/apna-select","version":"0.2.3","description":"A flexible React select component with single/multi select, search, async API loading, and CSS customization.","license":"MIT","author":{"name":"Also Coder","url":"https://alsocoder.com"},"type":"module","main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./styles.css":"./dist/styles.css"},"sideEffects":["*.css"],"scripts":{"build":"tsup","dev":"tsup --watch","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"keywords":["react","react-component","select","dropdown","combobox","multi-select","multiselect","searchable-select","async-select","remote-select","form","form-control","ui-component","css-variables","radix-ui","accessible","a11y","keyboard-navigation","typescript","apna-select","alsocoder"],"browserslist":["Chrome >= 90","Firefox >= 90","Safari >= 14","Edge >= 90","iOS >= 14","Samsung >= 15","not dead"],"repository":{"type":"git","url":"git+https://github.com/alsocoders/apna-select.git"},"bugs":{"url":"https://github.com/alsocoders/apna-select/issues"},"homepage":"https://github.com/alsocoders/apna-select#readme","peerDependencies":{"react":">=18","react-dom":">=18"},"dependencies":{"@radix-ui/react-checkbox":"^1.3.2","@radix-ui/react-dismissable-layer":"^1.1.11","@radix-ui/react-popover":"^1.1.14","clsx":"^2.1.1"},"devDependencies":{"@types/react":"^19.1.8","@types/react-dom":"^19.1.6","react":"^19.1.0","react-dom":"^19.1.0","tsup":"^8.5.0","typescript":"^5.9.2"},"_id":"@alsocoder/apna-select@0.2.3","_nodeVersion":"24.16.0","_npmVersion":"12.0.1","dist":{"integrity":"sha512-jzbow98ATjljikar4iMmmHUW3zFGZjEOSQIA9jeRIf4GmshHvajeOvQgh89LCiWn0HXg9SePSY7QHt+MZKuTsQ==","shasum":"f40fdbac7aacf6af21cd305056c2bdc6f84372d3","tarball":"https://registry.npmjs.org/@alsocoder/apna-select/-/apna-select-0.2.3.tgz","fileCount":10,"unpackedSize":259999,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCCgAnqtf2PC4G08JNV7PnsyVrBvEKjtlPZgBzBY6h0ZAIgWo+ioc4UoU/BXOi2Sb4jWXsV5OT4Df4KC1dm7qbA70M="}]},"_npmUser":{"name":"alsocoder-org","email":"alsocoder@gmail.com"},"directories":{},"maintainers":[{"name":"alsocoder-org","email":"alsocoder@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/apna-select_0.2.3_1785770557057_0.4646073585508148"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-30T08:07:14.261Z","modified":"2026-08-03T15:22:37.365Z","0.1.0":"2026-07-30T08:07:14.610Z","0.1.1":"2026-07-30T08:28:57.111Z","0.2.0":"2026-07-30T10:02:09.450Z","0.2.1":"2026-08-01T12:30:47.519Z","0.2.2":"2026-08-01T13:50:43.275Z","0.2.3":"2026-08-03T15:22:37.215Z"},"bugs":{"url":"https://github.com/alsocoders/apna-select/issues"},"author":{"name":"Also Coder","url":"https://alsocoder.com"},"license":"MIT","homepage":"https://github.com/alsocoders/apna-select#readme","keywords":["react","react-component","select","dropdown","combobox","multi-select","multiselect","searchable-select","async-select","remote-select","form","form-control","ui-component","css-variables","radix-ui","accessible","a11y","keyboard-navigation","typescript","apna-select","alsocoder"],"repository":{"type":"git","url":"git+https://github.com/alsocoders/apna-select.git"},"description":"A flexible React select component with single/multi select, search, async API loading, and CSS customization.","maintainers":[{"name":"alsocoder-org","email":"alsocoder@gmail.com"}],"readme":"# @alsocoder/apna-select\r\n\r\nA flexible React select component with single/multi select, search, and async API loading.\r\n\r\n## Features\r\n\r\n- Single and multi select\r\n- Client-side and server-side search\r\n- Controlled and uncontrolled modes\r\n- Async data loading via `url` or `loadOptions`\r\n- Native form support with hidden inputs (`name` prop)\r\n- Fully customizable via `className`, `classNames`, and CSS variables\r\n- Built on Radix UI Popover + Checkbox\r\n- Keyboard navigation (Arrow keys, Enter, Escape, Home, End)\r\n- Cross-browser compatible (Chrome, Firefox, Safari, Edge, iOS)\r\n\r\n## Installation\r\n\r\n```bash\r\nnpm install @alsocoder/apna-select\r\n```\r\n\r\nPeer dependencies:\r\n\r\n```bash\r\nnpm install react react-dom\r\n```\r\n\r\n## Setup\r\n\r\nImport the stylesheet once in your app entry:\r\n\r\n```tsx\r\nimport { ApnaSelect } from \"@alsocoder/apna-select\"\r\nimport \"@alsocoder/apna-select/styles.css\"\r\n```\r\n\r\n## Basic Usage\r\n\r\n### Static single select\r\n\r\n```tsx\r\nimport { ApnaSelect } from \"@alsocoder/apna-select\"\r\nimport \"@alsocoder/apna-select/styles.css\"\r\n\r\nconst options = [\r\n  { value: \"active\", label: \"Active\" },\r\n  { value: \"inactive\", label: \"Inactive\" },\r\n]\r\n\r\nexport function StatusSelect() {\r\n  const [status, setStatus] = useState(\"\")\r\n\r\n  return (\r\n    <ApnaSelect\r\n      options={options}\r\n      value={status}\r\n      onValueChange={setStatus}\r\n      placeholder=\"Select status\"\r\n    />\r\n  )\r\n}\r\n```\r\n\r\n### Multi select\r\n\r\n```tsx\r\n<ApnaSelect\r\n  multiple\r\n  options={options}\r\n  value={selected}\r\n  onValueChange={setSelected}\r\n  placeholder=\"Select skills\"\r\n/>\r\n```\r\n\r\n## Theming with CSS Variables\r\n\r\nOverride colors globally without touching component code:\r\n\r\n```css\r\n:root {\r\n  --apna-select-trigger-border: #3b82f6;\r\n  --apna-select-trigger-bg: #eff6ff;\r\n  --apna-select-option-hover: #dbeafe;\r\n  --apna-select-primary: #2563eb;\r\n}\r\n```\r\n\r\n### Available CSS variables\r\n\r\n| Variable | Default fallback | Description |\r\n|----------|------------------|-------------|\r\n| `--apna-select-trigger-bg` | `--input` | Trigger background |\r\n| `--apna-select-trigger-border` | `--border` | Trigger border |\r\n| `--apna-select-trigger-text` | `--foreground` | Selected text color |\r\n| `--apna-select-trigger-placeholder` | `--muted-foreground` | Placeholder color |\r\n| `--apna-select-content-bg` | `--popover` | Dropdown background |\r\n| `--apna-select-content-text` | `--popover-foreground` | Dropdown text |\r\n| `--apna-select-content-border` | `--border` | Dropdown border |\r\n| `--apna-select-option-hover` | `--muted` | Option hover background |\r\n| `--apna-select-option-selected` | `--muted` | Selected option background |\r\n| `--apna-select-option-highlighted` | primary tint | Keyboard/mouse highlight |\r\n| `--apna-select-muted` | `--muted-foreground` | Muted text/icons |\r\n| `--apna-select-ring` | `--ring` | Focus ring color |\r\n| `--apna-select-primary` | `--primary` | Checkbox/check color |\r\n| `--apna-select-destructive` | `--destructive` | Error text color |\r\n| `--apna-select-radius` | `0.5rem` | Border radius |\r\n| `--apna-select-font-size` | `0.875rem` | Font size |\r\n\r\n## Customization\r\n\r\n### Level 1: Shortcut props\r\n\r\n```tsx\r\n<ApnaSelect\r\n  options={options}\r\n  className=\"my-trigger\"\r\n  contentClassName=\"my-dropdown\"\r\n/>\r\n```\r\n\r\n### Level 2: Granular classNames\r\n\r\n```tsx\r\n<ApnaSelect\r\n  options={options}\r\n  classNames={{\r\n    trigger: \"rounded-xl\",\r\n    option: \"font-bold\",\r\n  }}\r\n/>\r\n```\r\n\r\n### Level 3: CSS variables (see above)\r\n\r\n### Available classNames slots\r\n\r\n| Slot | Default class | Description |\r\n|------|---------------|-------------|\r\n| `field` | `apna-select-field` | Trigger wrapper |\r\n| `trigger` | `apna-select-trigger` | Main trigger |\r\n| `triggerLabel` | `apna-select-trigger-label` | Selected label text |\r\n| `triggerBadges` | `apna-select-badges` | Badge container (multi) |\r\n| `badge` | `apna-select-badge` | Single badge |\r\n| `badgeLabel` | `apna-select-badge-label` | Badge text |\r\n| `badgeRemove` | `apna-select-badge-remove` | Badge remove button |\r\n| `clear` | `apna-select-clear` | Clear button |\r\n| `chevron` | `apna-select-chevron` | Chevron icon |\r\n| `content` | `apna-select-content` | Popover panel |\r\n| `groupLabel` | `apna-select-group-label` | Option group heading |\r\n| `searchContainer` | `apna-select-search` | Search bar wrapper |\r\n| `searchInput` | `apna-select-search-input` | Search input |\r\n| `searchIcon` | `apna-select-search-icon` | Search icon |\r\n| `list` | `apna-select-list` | Options scroll container |\r\n| `option` | `apna-select-option` | Each option button |\r\n| `optionSelected` | `apna-select-option--selected` | Selected option state |\r\n| `optionHighlighted` | `apna-select-option--highlighted` | Keyboard/mouse highlight |\r\n| `optionLabel` | `apna-select-option-label` | Option label text |\r\n| `optionCheck` | `apna-select-option-check` | Check icon (single select) |\r\n| `empty` | `apna-select-empty` | Empty state message |\r\n| `checkbox` | `apna-select-checkbox` | Multi-select checkbox |\r\n| `loading` | `apna-select-loading` | Loading state |\r\n| `error` | `apna-select-error` | Error state |\r\n| `retryButton` | `apna-select-retry` | Retry button |\r\n| `spinner` | `apna-select-spinner` | Loading spinner |\r\n\r\n### Option groups\r\n\r\nAdd a `group` field on options:\r\n\r\n```tsx\r\nconst options = [\r\n  { value: \"in\", label: \"India\", group: \"Asia\" },\r\n  { value: \"jp\", label: \"Japan\", group: \"Asia\" },\r\n  { value: \"us\", label: \"United States\", group: \"Americas\" },\r\n]\r\n\r\n<ApnaSelect options={options} placeholder=\"Select country\" />\r\n```\r\n\r\n### Clearable + badge multi-select\r\n\r\n```tsx\r\n<ApnaSelect clearable options={options} value={value} onValueChange={setValue} />\r\n\r\n<ApnaSelect\r\n  multiple\r\n  multipleDisplay=\"badges\"\r\n  clearable\r\n  options={options}\r\n  value={selected}\r\n  onValueChange={setSelected}\r\n/>\r\n```\r\n\r\nWhen theming with CSS variables, apply the same theme class to `classNames.content` as well — the dropdown renders in a portal.\r\n\r\n## Async Usage\r\n\r\n### Fetch once (load on open)\r\n\r\n```tsx\r\n<ApnaSelect\r\n  url=\"/api/cities\"\r\n  mapResponse={(data) =>\r\n    data.map((city) => ({ value: city.id, label: city.name }))\r\n  }\r\n  placeholder=\"Select city\"\r\n/>\r\n```\r\n\r\n### Server-side search\r\n\r\n```tsx\r\n<ApnaSelect\r\n  url=\"/api/users\"\r\n  searchMode=\"server\"\r\n  searchParam=\"q\"\r\n  debounceMs={300}\r\n  minSearchLength={2}\r\n  mapResponse={(data) => data.users}\r\n  placeholder=\"Search users\"\r\n/>\r\n```\r\n\r\n### Custom fetcher (axios, auth, etc.)\r\n\r\n```tsx\r\n<ApnaSelect\r\n  searchMode=\"server\"\r\n  debounceMs={400}\r\n  loadOptions={async (search, { signal }) => {\r\n    const res = await fetch(`/api/products?q=${search}`, { signal })\r\n    const data = await res.json()\r\n    return data.items.map((item) => ({\r\n      value: item.slug,\r\n      label: item.title,\r\n    }))\r\n  }}\r\n/>\r\n```\r\n\r\n### Standalone hook\r\n\r\n```tsx\r\nimport { ApnaSelect, useApnaSelectOptions } from \"@alsocoder/apna-select\"\r\n\r\nconst { options, loading, error, retry } = useApnaSelectOptions({\r\n  url: \"/api/states\",\r\n  mapResponse: (data) => data.states,\r\n})\r\n\r\nreturn (\r\n  <ApnaSelect\r\n    options={options}\r\n    loading={loading}\r\n    error={error}\r\n    onRetry={retry}\r\n  />\r\n)\r\n```\r\n\r\n## Props\r\n\r\n### Core\r\n\r\n| Prop | Type | Default | Description |\r\n|------|------|---------|-------------|\r\n| `options` | `ApnaSelectOption[]` | — | Static options (required in static mode) |\r\n| `multiple` | `boolean` | `false` | Enable multi select |\r\n| `value` | `string \\| string[]` | — | Controlled value |\r\n| `defaultValue` | `string \\| string[]` | — | Uncontrolled default |\r\n| `onValueChange` | `function` | — | Change handler |\r\n| `placeholder` | `string` | `\"Select option\"` | Placeholder text |\r\n| `searchPlaceholder` | `string` | `\"Search...\"` | Search input placeholder |\r\n| `emptyText` | `string` | `\"No results found.\"` | Empty state text |\r\n| `minSearchText` | `string` | auto | Prompt before server search |\r\n| `clearable` | `boolean` | `false` | Show clear button when selected |\r\n| `clearLabel` | `string` | `\"Clear selection\"` | Clear button aria-label |\r\n| `multipleDisplay` | `\"text\" \\| \"badges\"` | `\"text\"` | Multi-select display mode |\r\n| `resolveLabel` | `function` | — | Resolve label for controlled values |\r\n| `searchThreshold` | `number` | `8` | Min options before search shows |\r\n| `disabled` | `boolean` | `false` | Disable the select |\r\n| `name` | `string` | — | Hidden input name for forms |\r\n| `id` | `string` | — | HTML id attribute |\r\n| `className` | `string` | — | Trigger class shortcut |\r\n| `contentClassName` | `string` | — | Content class shortcut |\r\n| `classNames` | `object` | — | Granular class overrides |\r\n| `filterFn` | `function` | label match | Client-side filter function |\r\n| `icons` | `object` | inline SVGs | Custom chevron/search/check icons |\r\n\r\n### Async\r\n\r\n| Prop | Type | Default | Description |\r\n|------|------|---------|-------------|\r\n| `url` | `string` | — | API endpoint |\r\n| `method` | `\"GET\" \\| \"POST\"` | `\"GET\"` | HTTP method |\r\n| `headers` | `object` | — | Request headers |\r\n| `body` | `object` | — | POST request body |\r\n| `searchMode` | `\"client\" \\| \"server\"` | `\"client\"` | Search behavior |\r\n| `searchParam` | `string` | `\"search\"` | Query param for server search |\r\n| `debounceMs` | `number` | `300` | Debounce for server search |\r\n| `minSearchLength` | `number` | `0` | Min chars before API call |\r\n| `mapResponse` | `function` | auto-detect | Transform API response |\r\n| `loadOptions` | `function` | — | Custom async loader |\r\n| `fetchOnMount` | `boolean` | `true` | Fetch when dropdown opens |\r\n| `cacheKey` | `string` | url-based | Cache key |\r\n| `loading` | `boolean` | auto | Manual loading state |\r\n| `error` | `string \\| Error` | auto | Manual error state |\r\n| `onRetry` | `function` | auto | Retry handler |\r\n| `loadingText` | `string` | `\"Loading...\"` | Loading message |\r\n| `errorText` | `string` | — | Custom error message |\r\n\r\n## Native Form Integration\r\n\r\n```tsx\r\n<form onSubmit={handleSubmit}>\r\n  <ApnaSelect\r\n    name=\"service\"\r\n    options={options}\r\n    value={service}\r\n    onValueChange={setService}\r\n  />\r\n  <button type=\"submit\">Submit</button>\r\n</form>\r\n```\r\n\r\n## react-hook-form Example\r\n\r\n```tsx\r\nimport { Controller, useForm } from \"react-hook-form\"\r\nimport { ApnaSelect } from \"@alsocoder/apna-select\"\r\n\r\nfunction MyForm() {\r\n  const { control, handleSubmit } = useForm()\r\n\r\n  return (\r\n    <form onSubmit={handleSubmit(console.log)}>\r\n      <Controller\r\n        name=\"status\"\r\n        control={control}\r\n        render={({ field }) => (\r\n          <ApnaSelect\r\n            options={options}\r\n            value={field.value}\r\n            onValueChange={field.onChange}\r\n          />\r\n        )}\r\n      />\r\n    </form>\r\n  )\r\n}\r\n```\r\n\r\n## Keyboard Navigation\r\n\r\n| Key | Action |\r\n|-----|--------|\r\n| `ArrowDown` / `ArrowUp` | Move highlight / open dropdown |\r\n| `Enter` / `Space` | Select highlighted option / open dropdown |\r\n| `Home` / `End` | Jump to first / last option |\r\n| `Escape` | Close dropdown |\r\n| `Tab` | Close dropdown and move focus |\r\n\r\nWorks on trigger button and search input. Mouse hover syncs with keyboard highlight.\r\n\r\n## Browser Compatibility\r\n\r\nTested and supported on modern browsers:\r\n\r\n| Browser | Minimum Version |\r\n|---------|-----------------|\r\n| Chrome | 90+ |\r\n| Firefox | 90+ |\r\n| Safari | 14+ |\r\n| Edge | 90+ |\r\n| iOS Safari | 14+ |\r\n| Samsung Internet | 15+ |\r\n\r\nCSS includes fallbacks for older engines:\r\n- Solid color fallbacks before `color-mix()`\r\n- `-webkit-` prefixes for flexbox and animations\r\n- `prefers-reduced-motion` support (disables animations)\r\n- `-webkit-overflow-scrolling: touch` for iOS scroll\r\n\r\nRequires **React 18+**. Internet Explorer is not supported.\r\n\r\n## Exports\r\n\r\n```tsx\r\nimport {\r\n  ApnaSelect,\r\n  useApnaSelectOptions,\r\n  defaultClassNames,\r\n  defaultMapResponse,\r\n  clearOptionsCache,\r\n} from \"@alsocoder/apna-select\"\r\n```\r\n\r\n## Changelog\r\n\r\n### v0.2.3\r\n\r\n- `onBlur` prop for react-hook-form integration\r\n- `fieldError` / `fieldErrorText` for field-level validation (separate from async fetch errors)\r\n- `label`, `required`, trigger error border, and `aria-invalid`\r\n\r\n### v0.2.2\r\n\r\n- `DismissableLayerBranch` on portaled popover — works inside Radix Dialog / ApnaModal\r\n- `pointer-events: auto` on popover for Dialog body scroll-lock compatibility\r\n- `@radix-ui/react-dismissable-layer` added as explicit dependency\r\n\r\n### v0.2.1\r\n\r\n- Popover z-index uses `--apna-overlay-nested-z-popover` for ApnaModal compatibility\r\n\r\n### v0.2.0\r\n\r\n- `clearable` prop with clear button\r\n- `multipleDisplay=\"badges\"` for chip-style multi-select\r\n- Option groups via `group` field on options\r\n- `resolveLabel` for controlled server-search values\r\n- `minSearchText` for async server search prompt state\r\n- Selected label cache for async server search\r\n- Keyboard, scroll, and async UX fixes\r\n\r\n### v0.1.0\r\n\r\n- Initial release\r\n- Single/multi select with search\r\n- Async API loading (`url`, `loadOptions`, `useApnaSelectOptions`)\r\n- CSS variables for theming\r\n- Customizable via `className`, `classNames`, and CSS variables\r\n- Keyboard navigation and accessibility improvements\r\n- Cross-browser CSS with fallbacks and reduced-motion support\r\n\r\n## Development\r\n\r\n```bash\r\nnpm install\r\nnpm run build\r\ncd playground && npm install && npm run dev\r\n```\r\n\r\n## Roadmap\r\n\r\n- Cascading/dependent selects (composition pattern)\r\n\r\n## License\r\n\r\nMIT\r\n","readmeFilename":"README.md"}