{"_id":"@cappasoft/openrouter-model-selector","_rev":"4-6fc37b479ef05c515710fcb6ff336dcd","name":"@cappasoft/openrouter-model-selector","dist-tags":{"latest":"1.3.0"},"versions":{"1.0.0":{"name":"@cappasoft/openrouter-model-selector","version":"1.0.0","keywords":["openrouter","llm","models","react","ui","component"],"license":"MIT","_id":"@cappasoft/openrouter-model-selector@1.0.0","maintainers":[{"name":"ecappa","email":"ecappannelli@gmail.com"}],"homepage":"https://github.com/ecappa/openrouter-model-selector#readme","bugs":{"url":"https://github.com/ecappa/openrouter-model-selector/issues"},"dist":{"shasum":"c98f6edbee6ae354113c1b82f8334a13b1fbbcf6","tarball":"https://registry.npmjs.org/@cappasoft/openrouter-model-selector/-/openrouter-model-selector-1.0.0.tgz","fileCount":6,"integrity":"sha512-CHYT+L3cneh8eJhjzTONqJ5malITCzhfkxi3lbVjqvcTkvXxQ19KM7JWL/wVNBD81vxy0yvMe28y3eq4hBNxhQ==","signatures":[{"sig":"MEYCIQDiZMXwdd2r6akdU/MQCXJ0OnEzfZZLFzsfiTtob7ndIwIhAMnJiTZFbhJIX3VCv5NOI8nLhUz2k7UytgZ/ehMobaJC","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":137019},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./styles.css":"./dist/styles.css"},"gitHead":"a9340c5407b5e7cb4a9f0633fb9410366f90641f","scripts":{"dev":"tsup --watch","build":"tsup && npm run build:css","build:css":"tailwindcss -i ./src/styles.css -o ./dist/styles.css --minify"},"_npmUser":{"name":"ecappa","email":"ecappannelli@gmail.com"},"repository":{"url":"git+https://github.com/ecappa/openrouter-model-selector.git","type":"git","directory":"packages/openrouter-model-selector"},"_npmVersion":"11.7.0","description":"React UI component for selecting OpenRouter models","directories":{},"_nodeVersion":"24.12.0","dependencies":{"clsx":"^2.1.1","lucide-react":"^0.462.0","tailwind-merge":"^2.6.0","@radix-ui/react-slot":"^1.2.3","@radix-ui/react-dialog":"^1.1.14","@radix-ui/react-select":"^2.2.5","class-variance-authority":"^0.7.1","@cappasoft/openrouter-models":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","typescript":"^5.8.3","tailwindcss":"^3.4.17","@types/react":"^18.3.23","@types/react-dom":"^18.3.7"},"peerDependencies":{"react":"^18.0.0","react-dom":"^18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/openrouter-model-selector_1.0.0_1767668324158_0.32754396019859544","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@cappasoft/openrouter-model-selector","version":"1.1.0","keywords":["openrouter","llm","models","react","ui","component"],"license":"MIT","_id":"@cappasoft/openrouter-model-selector@1.1.0","maintainers":[{"name":"ecappa","email":"ecappannelli@gmail.com"}],"homepage":"https://github.com/ecappa/openrouter-model-selector#readme","bugs":{"url":"https://github.com/ecappa/openrouter-model-selector/issues"},"dist":{"shasum":"dd439cae330ca7a6abe18820543cbb8a9dfb5e2d","tarball":"https://registry.npmjs.org/@cappasoft/openrouter-model-selector/-/openrouter-model-selector-1.1.0.tgz","fileCount":6,"integrity":"sha512-At2BA6MfjAGybpFF/7ArN2W4VeXuS2rEFCNTIfWDFU3qtldTMd8jgwoNBNqyToUzhNnltCG/xHpj591Ddm+NLQ==","signatures":[{"sig":"MEYCIQCC+wj5LVXWkqIplCrF5vovNHdR0JSftMfWpXHj7/wj0QIhAJdOEg+GxYB4r4s8trINLFjRKBzKVGdt8tX0w8//RY4m","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":143704},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./styles.css":"./dist/styles.css"},"gitHead":"fa896d52f6ee5aeb82934871f5ff8088697776bc","scripts":{"dev":"tsup --watch","build":"tsup && npm run build:css","build:css":"tailwindcss -i ./src/styles.css -o ./dist/styles.css --minify"},"_npmUser":{"name":"ecappa","email":"ecappannelli@gmail.com"},"repository":{"url":"git+https://github.com/ecappa/openrouter-model-selector.git","type":"git","directory":"packages/openrouter-model-selector"},"_npmVersion":"10.8.2","description":"React UI component for selecting OpenRouter models","directories":{},"_nodeVersion":"20.19.6","dependencies":{"clsx":"^2.1.1","lucide-react":"^0.462.0","tailwind-merge":"^2.6.0","@radix-ui/react-slot":"^1.2.3","@radix-ui/react-dialog":"^1.1.14","@radix-ui/react-select":"^2.2.5","class-variance-authority":"^0.7.1","@cappasoft/openrouter-models":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","typescript":"^5.8.3","tailwindcss":"^3.4.17","@types/react":"^18.3.23","@types/react-dom":"^18.3.7"},"peerDependencies":{"react":"^18.0.0","react-dom":"^18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/openrouter-model-selector_1.1.0_1767672765619_0.359512869452864","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@cappasoft/openrouter-model-selector","version":"1.2.0","keywords":["openrouter","llm","models","react","ui","component"],"license":"MIT","_id":"@cappasoft/openrouter-model-selector@1.2.0","maintainers":[{"name":"ecappa","email":"ecappannelli@gmail.com"}],"homepage":"https://github.com/ecappa/openrouter-model-selector#readme","bugs":{"url":"https://github.com/ecappa/openrouter-model-selector/issues"},"dist":{"shasum":"d01152719d38245d3ccd3f948bca3449799fd932","tarball":"https://registry.npmjs.org/@cappasoft/openrouter-model-selector/-/openrouter-model-selector-1.2.0.tgz","fileCount":6,"integrity":"sha512-LhIqKwh530SnG/tUhMV8vKVPebWjrmShv7XCWkcbnHSA99I+ImePpzBSYq9HvajXLSbQyGKzgKeZfWYLQi8yjQ==","signatures":[{"sig":"MEUCIQD2gFoSUnQrpefHNq1ZDMhMduzg6gMcT8hLBIjABpaA8QIgNn54RWvycM09ytEWxonUOAz7wBm0Mfxq3BrDNhzzDko=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":143134},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./styles.css":"./dist/styles.css"},"gitHead":"d71d3d23e21e0191a1073f14ff0bf8b73ff341d9","scripts":{"dev":"tsup --watch","build":"tsup && npm run build:css","build:css":"tailwindcss -i ./src/styles.css -o ./dist/styles.css --minify"},"_npmUser":{"name":"ecappa","email":"ecappannelli@gmail.com"},"repository":{"url":"git+https://github.com/ecappa/openrouter-model-selector.git","type":"git","directory":"packages/openrouter-model-selector"},"_npmVersion":"11.7.0","description":"React UI component for selecting OpenRouter models","directories":{},"_nodeVersion":"24.12.0","dependencies":{"clsx":"^2.1.1","lucide-react":"^0.462.0","tailwind-merge":"^2.6.0","@radix-ui/react-slot":"^1.2.3","@radix-ui/react-dialog":"^1.1.14","@radix-ui/react-select":"^2.2.5","class-variance-authority":"^0.7.1","@cappasoft/openrouter-models":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","typescript":"^5.8.3","tailwindcss":"^3.4.17","@types/react":"^18.3.23","@types/react-dom":"^18.3.7"},"peerDependencies":{"react":"^18.0.0","react-dom":"^18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/openrouter-model-selector_1.2.0_1767816645132_0.2599131433480568","host":"s3://npm-registry-packages-npm-production"}},"1.3.0":{"name":"@cappasoft/openrouter-model-selector","version":"1.3.0","description":"React UI component for selecting OpenRouter models","type":"module","main":"./dist/index.js","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./styles.css":"./dist/styles.css"},"scripts":{"build":"tsup && npm run build:css","build:css":"tailwindcss -i ./src/styles.css -o ./dist/styles.css --minify","dev":"tsup --watch"},"keywords":["openrouter","llm","models","react","ui","component"],"repository":{"type":"git","url":"git+https://github.com/ecappa/openrouter-model-selector.git","directory":"packages/openrouter-model-selector"},"license":"MIT","peerDependencies":{"react":"^18.0.0","react-dom":"^18.0.0"},"dependencies":{"@cappasoft/openrouter-models":"^1.0.0","@radix-ui/react-dialog":"^1.1.14","@radix-ui/react-select":"^2.2.5","@radix-ui/react-slot":"^1.2.3","class-variance-authority":"^0.7.1","clsx":"^2.1.1","lucide-react":"^0.462.0","tailwind-merge":"^2.6.0"},"devDependencies":{"@types/react":"^18.3.23","@types/react-dom":"^18.3.7","tailwindcss":"^3.4.17","tsup":"^8.3.5","typescript":"^5.8.3"},"gitHead":"4774d4cfb9c22edc0636a88458b643351279112d","_id":"@cappasoft/openrouter-model-selector@1.3.0","bugs":{"url":"https://github.com/ecappa/openrouter-model-selector/issues"},"homepage":"https://github.com/ecappa/openrouter-model-selector#readme","_nodeVersion":"24.12.0","_npmVersion":"11.7.0","dist":{"integrity":"sha512-sxTd19FZe+S5poR+Nu3u3S7xRto1Sm7aiWNHIJaSbPPQ7Fw/cmzzfrv8SIFJM4zrIf2zymNCFKs8wOp7db5RhA==","shasum":"854eb162e85206426d8f6bb42af107edfa3460bd","tarball":"https://registry.npmjs.org/@cappasoft/openrouter-model-selector/-/openrouter-model-selector-1.3.0.tgz","fileCount":6,"unpackedSize":148171,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIHvzDsxAQ0+Y7KRJLzFo/cxdtXcY6PW8g4PRxyBlH69lAiBC/OOH/zOvRGYToE/K1rkMTSp1eHrZ7b0EwBk5LqY1yQ=="}]},"_npmUser":{"name":"ecappa","email":"ecappannelli@gmail.com"},"directories":{},"maintainers":[{"name":"ecappa","email":"ecappannelli@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/openrouter-model-selector_1.3.0_1767840753346_0.3761258795468345"},"_hasShrinkwrap":false}},"time":{"created":"2026-01-06T02:58:44.056Z","modified":"2026-01-08T02:52:33.717Z","1.0.0":"2026-01-06T02:58:44.300Z","1.1.0":"2026-01-06T04:12:45.765Z","1.2.0":"2026-01-07T20:10:45.289Z","1.3.0":"2026-01-08T02:52:33.496Z"},"bugs":{"url":"https://github.com/ecappa/openrouter-model-selector/issues"},"license":"MIT","homepage":"https://github.com/ecappa/openrouter-model-selector#readme","keywords":["openrouter","llm","models","react","ui","component"],"repository":{"type":"git","url":"git+https://github.com/ecappa/openrouter-model-selector.git","directory":"packages/openrouter-model-selector"},"description":"React UI component for selecting OpenRouter models","maintainers":[{"name":"ecappa","email":"ecappannelli@gmail.com"}],"readme":"# 🤖 @cappasoft/openrouter-model-selector\n\n[![npm version](https://img.shields.io/npm/v/@cappasoft/openrouter-model-selector.svg?style=flat-square)](https://www.npmjs.com/package/@cappasoft/openrouter-model-selector)\n\nA beautiful React component for selecting AI models from [OpenRouter](https://openrouter.ai).\n\n## Installation\n\n```bash\nnpm install @cappasoft/openrouter-model-selector\n```\n\n## Usage\n\n```tsx\nimport { useState } from 'react'\nimport { ModelSelector } from '@cappasoft/openrouter-model-selector'\nimport '@cappasoft/openrouter-model-selector/styles.css'\n\nexport function App() {\n  const [model, setModel] = useState('openai/gpt-4o')\n\n  return (\n    <ModelSelector\n      value={model}\n      onValueChange={setModel}\n      apiKey=\"sk-or-v1-...\"\n    />\n  )\n}\n```\n\n## Props\n\n| Prop | Type | Description |\n|------|------|-------------|\n| `value` | `string` | Currently selected model ID |\n| `onValueChange` | `(modelId: string) => void` | Callback when model changes |\n| `apiKey` | `string` | Your OpenRouter API key |\n| `disabled?` | `boolean` | Disable the selector |\n| `contrast?` | `\"default\" \\| \"high-contrast\"` | Increase contrast for secondary text (prices, metadata, headers) |\n| `endpoint?` | `string` | Custom OpenRouter endpoint (optional) |\n| `locale?` | `\"en\" \\| \"fr\"` | UI language (labels + formatting) |\n| `labels?` | `Partial<Labels>` | Override i18n labels |\n| `className?` | `string` | Wrapper class name |\n| `showSearch?` | `boolean` | Show search input (default: true) |\n| `showPricing?` | `boolean` | Show pricing (default: true) |\n| `showFilters?` | `boolean` | Show provider/capability filters (default: true) |\n| `variant?` | `\"default\" \\| \"compact\"` | Layout variant |\n| `showAllInModal?` | `boolean` | Put the full library in a modal |\n| `infoToggle?` | `boolean` | Adds an “info” button to show the selected model details |\n\n## Customization (contrast)\n\nIf your app theme makes secondary text too light, prefer using `contrast=\"high-contrast\"`:\n\n```tsx\n<ModelSelector\n  value={model}\n  onValueChange={setModel}\n  apiKey=\"sk-or-v1-...\"\n  contrast=\"high-contrast\"\n/>\n```\n\nYou can also override the exposed CSS variables (scoped to `.orm-root`):\n\n```css\n.orm-root {\n  --orm-text-secondary: hsl(var(--foreground) / 0.85);\n}\n```\n\n## CSS Isolation\n\nThis component uses **CSS isolation** to prevent style leaks into your application. All Tailwind classes are scoped to `.orm-root`, ensuring that:\n\n- ✅ The component's styles don't affect your app (shadcn, etc.)\n- ✅ Your app's global styles don't affect the component\n- ✅ Portals (Select dropdowns, Dialogs) are properly scoped\n\n### How it works\n\n1. **Root wrapper**: The component automatically wraps itself with `.orm-root`\n2. **Tailwind scoping**: All generated Tailwind utilities are prefixed with `.orm-root` (e.g., `.orm-root .flex`, `.orm-root .text-sm`)\n3. **Portal wrapping**: Select and Dialog portals are wrapped with `.orm-root` to maintain isolation\n\n### Double wrapping\n\nIn some cases (e.g., `showAllInModal`), you may see `.orm-root` appear multiple times in the DOM:\n\n```html\n<div class=\"orm-root\">          <!-- Main wrapper -->\n  <div class=\"orm-root\">        <!-- Portal wrapper -->\n    <SelectContent>...</SelectContent>\n  </div>\n</div>\n```\n\nThis is **intentional and safe**. The redundant wrappers ensure robust isolation even when portals are rendered outside the React tree.\n\n### Z-index conflicts\n\nIf you experience z-index conflicts with your app (e.g., navbar, modals), you can add CSS isolation:\n\n```css\n.orm-root {\n  isolation: isolate;\n}\n```\n\nThis creates a new stacking context and prevents z-index conflicts.\n\n### Overriding styles\n\nYour `className` prop is applied to the **content** (not the root wrapper), so it has priority over internal styles:\n\n```tsx\n<ModelSelector className=\"text-lg\" /> {/* Overrides internal text-sm */}\n```\n\n## Use cases (Playground)\n\n### 1) API key from env (Vite)\n\n```bash\nexport VITE_OPENROUTER_API_KEY=\"sk-or-v1-...\"\n```\n\n### 2) “Draft + Apply” pattern (recommended)\n\n```tsx\nimport { useState } from 'react'\nimport { ModelSelector } from '@cappasoft/openrouter-model-selector'\nimport '@cappasoft/openrouter-model-selector/styles.css'\n\nexport function App() {\n  const initialKey = (import.meta as any).env?.VITE_OPENROUTER_API_KEY ?? ''\n  const [apiKeyDraft, setApiKeyDraft] = useState(initialKey)\n  const [apiKey, setApiKey] = useState(initialKey)\n  const [model, setModel] = useState('openai/gpt-4o')\n\n  return (\n    <>\n      <input value={apiKeyDraft} onChange={(e) => setApiKeyDraft(e.target.value)} placeholder=\"sk-or-v1-...\" />\n      <button onClick={() => setApiKey(apiKeyDraft.trim())}>Apply</button>\n      <button onClick={() => { setApiKeyDraft(''); setApiKey('') }}>Clear</button>\n\n      <ModelSelector value={model} onValueChange={setModel} apiKey={apiKey} />\n    </>\n  )\n}\n```\n\n### 3) Locale switch (en/fr)\n\n```tsx\n<ModelSelector value={model} onValueChange={setModel} apiKey={apiKey} locale=\"fr\" />\n```\n\n### 4) Full library in a modal\n\n```tsx\n<ModelSelector value={model} onValueChange={setModel} apiKey={apiKey} showAllInModal />\n```\n\n### 5) Toggle model details (info panel)\n\n```tsx\n<ModelSelector value={model} onValueChange={setModel} apiKey={apiKey} showAllInModal infoToggle />\n```\n\n### 6) High contrast\n\n```tsx\n<ModelSelector value={model} onValueChange={setModel} apiKey={apiKey} contrast=\"high-contrast\" />\n```\n\n## Features\n\n- 🎨 Beautiful UI with dark mode support\n- 🔍 Smart search by name, provider, or capability\n- 📂 Models grouped by provider\n- ⭐ Curated recommended models\n- 🪶 Lightweight and tree-shakeable\n\n## License\n\nMIT","readmeFilename":"README.md"}