{"_id":"@avis-ai/tryout","_rev":"7-c4e2b440150e4bcf12125698f53f6073","name":"@avis-ai/tryout","dist-tags":{"latest":"1.0.6"},"versions":{"1.0.0":{"name":"@avis-ai/tryout","version":"1.0.0","keywords":["avis-ai","virtual-try-on","try-on","fashion","react","ecommerce"],"license":"ISC","_id":"@avis-ai/tryout@1.0.0","maintainers":[{"name":"adminavis","email":"admin@avi-s.in"}],"homepage":"https://github.com/avisadmin/avis-ai#readme","bugs":{"url":"https://github.com/avisadmin/avis-ai/issues"},"dist":{"shasum":"386c23cb160c1919e34bd32f95762f1c7831fb87","tarball":"https://registry.npmjs.org/@avis-ai/tryout/-/tryout-1.0.0.tgz","fileCount":18,"integrity":"sha512-1N63/nTkcM4dXPGojsppEuCRuJg9qVQyRpTOL91Rk6N1ZyfTTi+6Wq0a2Ib8zPOZhNtKM+2QTZgZbrmvPt6L3A==","signatures":[{"sig":"MEYCIQDHOj/RVIuUgzTUmLX7fbKJPeJ3bGJbjyEKCkh1L6IPMAIhAOzyimwHrg2CRJAfw3v7VNnmyOTSJXggGYRNC0KVOnWE","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":79950},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"54e6675d789aa115e83f6dbdb321d0a977fd4147","scripts":{"build":"tsc -p tsconfig.json","build:watch":"tsc -p tsconfig.json --watch","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"adminavis","email":"admin@avi-s.in"},"repository":{"url":"git+https://github.com/avisadmin/avis-ai.git","type":"git","directory":"packages/tryout"},"_npmVersion":"10.9.3","description":"React components and hooks for Avis AI virtual try-on (reference images, generate, optional local persistence).","directories":{},"_nodeVersion":"22.18.0","dependencies":{"@avis-ai/sdk-js":"^0.0.8"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"react":"^18.3.1","react-dom":"^18.3.1","typescript":"^5.9.3","@types/react":"^18","@types/react-dom":"^18"},"peerDependencies":{"react":">=18.0.0","react-dom":">=18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/tryout_1.0.0_1777194982542_0.9409781144568383","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@avis-ai/tryout","version":"1.0.1","keywords":["avis-ai","virtual-try-on","try-on","fashion","react","ecommerce"],"license":"ISC","_id":"@avis-ai/tryout@1.0.1","maintainers":[{"name":"adminavis","email":"admin@avi-s.in"}],"homepage":"https://github.com/avisadmin/avis-ai#readme","bugs":{"url":"https://github.com/avisadmin/avis-ai/issues"},"dist":{"shasum":"300fa6e3ff3f6e3f892fcffd2a7943f046028a8a","tarball":"https://registry.npmjs.org/@avis-ai/tryout/-/tryout-1.0.1.tgz","fileCount":18,"integrity":"sha512-0AfFE3uol13K8f4apGQfWOwa9yJN2HREmV0VeRG3dgKT05g6HS5HshX4fcCl2PUXbFGxcPJSKDnIURznlBEfaQ==","signatures":[{"sig":"MEUCIQCXjKd2O6Zqxkmowmxg3rkjoTg/JNyX+ytmxWH5EeWCnwIgQLAdqEZbyUI5v8PWyoN7h83KMXBBKezxLv9+LSOYRFc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":87296},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"464203380d1c92703aa63285b2563f9f979c1613","scripts":{"build":"tsc -p tsconfig.json","build:watch":"tsc -p tsconfig.json --watch","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"adminavis","email":"admin@avi-s.in"},"repository":{"url":"git+https://github.com/avisadmin/avis-ai.git","type":"git","directory":"packages/tryout"},"_npmVersion":"10.9.3","description":"React components and hooks for Avis AI virtual try-on (reference images, generate, optional local persistence).","directories":{},"_nodeVersion":"22.18.0","dependencies":{"@avis-ai/sdk-js":"0.0.8"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"react":"^18.3.1","react-dom":"^18.3.1","typescript":"^5.9.3","@types/react":"^18","@types/react-dom":"^18"},"peerDependencies":{"react":">=18.0.0","react-dom":">=18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/tryout_1.0.1_1777284038068_0.5612510168185079","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@avis-ai/tryout","version":"1.0.2","keywords":["avis-ai","virtual-try-on","try-on","fashion","react","ecommerce"],"license":"ISC","_id":"@avis-ai/tryout@1.0.2","maintainers":[{"name":"adminavis","email":"admin@avi-s.in"}],"homepage":"https://github.com/avisadmin/avis-ai#readme","bugs":{"url":"https://github.com/avisadmin/avis-ai/issues"},"dist":{"shasum":"b2bd212a5725e67f0c18c28d416d25aa27f6cb15","tarball":"https://registry.npmjs.org/@avis-ai/tryout/-/tryout-1.0.2.tgz","fileCount":18,"integrity":"sha512-CteCnxLQCJ8asnB7oqeZUlLRLtiezI3hmdDICmB4PLrirc8+8YpTttJvGgo+aC83biyfmkQzKOAEKOUtB+TpvA==","signatures":[{"sig":"MEQCIFRqotRWhNssaQLqJlHC8SYfmmRXrK15/A4keNQQ3Cp2AiAx77Yy5fG9YhKSl6eCCWcKMgJaqV3hKSKRUReasfYL/A==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":88487},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"6195c617cd4ad71eeee9d78631d2f6efef71c6c2","scripts":{"build":"tsc -p tsconfig.json","build:watch":"tsc -p tsconfig.json --watch","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"adminavis","email":"admin@avi-s.in"},"repository":{"url":"git+https://github.com/avisadmin/avis-ai.git","type":"git","directory":"packages/tryout"},"_npmVersion":"10.9.3","description":"React components and hooks for Avis AI virtual try-on (reference images, generate, optional local persistence).","directories":{},"_nodeVersion":"22.18.0","dependencies":{"@avis-ai/sdk-js":"0.0.8"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"react":"^18.3.1","react-dom":"^18.3.1","typescript":"^5.9.3","@types/react":"^18","@types/react-dom":"^18"},"peerDependencies":{"react":">=18.0.0","react-dom":">=18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/tryout_1.0.2_1777286520386_0.6749346870144193","host":"s3://npm-registry-packages-npm-production"}},"1.0.3":{"name":"@avis-ai/tryout","version":"1.0.3","keywords":["avis-ai","virtual-try-on","try-on","fashion","react","ecommerce"],"license":"ISC","_id":"@avis-ai/tryout@1.0.3","maintainers":[{"name":"adminavis","email":"admin@avi-s.in"}],"homepage":"https://github.com/avisadmin/avis-ai#readme","bugs":{"url":"https://github.com/avisadmin/avis-ai/issues"},"dist":{"shasum":"a6c3884e6ae6bd68100381f7576439c965521f93","tarball":"https://registry.npmjs.org/@avis-ai/tryout/-/tryout-1.0.3.tgz","fileCount":18,"integrity":"sha512-wZzL5tstS09ZlRhgFSM9vwkg13nOyjCDj2FYm/5xzhtjRdSa2CnSgylle8HPjHQSeRtXtVMnter9fJKFSvmBRQ==","signatures":[{"sig":"MEYCIQCDLyldmN76RZeLkpHVKKJLz0gAAibND6AN+v8dJunjggIhAICfZTxW/KMNg5ny3fxo2QZJ9u8bweEOrSS0csQnUG8w","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":94838},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"3726bea2eb82c2e8a76e46617618e85241324487","scripts":{"build":"tsc -p tsconfig.json","build:watch":"tsc -p tsconfig.json --watch","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"adminavis","email":"admin@avi-s.in"},"repository":{"url":"git+https://github.com/avisadmin/avis-ai.git","type":"git","directory":"packages/tryout"},"_npmVersion":"10.9.3","description":"React components and hooks for Avis AI virtual try-on (reference images, generate, optional local persistence).","directories":{},"_nodeVersion":"22.18.0","dependencies":{"@avis-ai/sdk-js":"0.0.8"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"react":"^18.3.1","react-dom":"^18.3.1","typescript":"^5.9.3","@types/react":"^18","@types/react-dom":"^18"},"peerDependencies":{"react":">=18.0.0","react-dom":">=18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/tryout_1.0.3_1777365187932_0.4335109946029647","host":"s3://npm-registry-packages-npm-production"}},"1.0.4":{"name":"@avis-ai/tryout","version":"1.0.4","keywords":["avis-ai","virtual-try-on","try-on","fashion","react","ecommerce"],"license":"ISC","_id":"@avis-ai/tryout@1.0.4","maintainers":[{"name":"adminavis","email":"admin@avi-s.in"}],"homepage":"https://github.com/avisadmin/avis-ai#readme","bugs":{"url":"https://github.com/avisadmin/avis-ai/issues"},"dist":{"shasum":"4b96d8b01aa4c269f42b2d68bb34966d27fc4ea2","tarball":"https://registry.npmjs.org/@avis-ai/tryout/-/tryout-1.0.4.tgz","fileCount":18,"integrity":"sha512-0vDOCHIGIJYTMiV42DIw/qasQ7ZcAnPlv6mTjRlttyoxo0dUIMyhlYqRg6YuvrzyR1TiJttQUAVI2UmVsYkuhw==","signatures":[{"sig":"MEUCIQDYajKUwf9kqVtxOktm6oaf23hxM5TcUplj1n594D4SXwIgQR+NVZ+TzcpXRAKW6XuHBvqLoFF+A8eaaVIdcfygCTo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":93608},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"b7a17bb09a293bf2c16f3fd93f9087a5ebba6390","scripts":{"build":"tsc -p tsconfig.json","build:watch":"tsc -p tsconfig.json --watch","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"adminavis","email":"admin@avi-s.in"},"repository":{"url":"git+https://github.com/avisadmin/avis-ai.git","type":"git","directory":"packages/tryout"},"_npmVersion":"10.9.3","description":"React components and hooks for Avis AI virtual try-on (reference images, generate, optional local persistence).","directories":{},"_nodeVersion":"22.18.0","dependencies":{"@avis-ai/sdk-js":"0.0.8"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"react":"^18.3.1","react-dom":"^18.3.1","typescript":"^5.9.3","@types/react":"^18","@types/react-dom":"^18"},"peerDependencies":{"react":">=18.0.0","react-dom":">=18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/tryout_1.0.4_1777446764666_0.2797005919280777","host":"s3://npm-registry-packages-npm-production"}},"1.0.5":{"name":"@avis-ai/tryout","version":"1.0.5","keywords":["avis-ai","virtual-try-on","try-on","fashion","react","ecommerce"],"license":"ISC","_id":"@avis-ai/tryout@1.0.5","maintainers":[{"name":"adminavis","email":"admin@avi-s.in"}],"homepage":"https://github.com/avisadmin/avis-ai#readme","bugs":{"url":"https://github.com/avisadmin/avis-ai/issues"},"dist":{"shasum":"9fa5dd63652f708a10c96b98c0d3f6355075e150","tarball":"https://registry.npmjs.org/@avis-ai/tryout/-/tryout-1.0.5.tgz","fileCount":18,"integrity":"sha512-Odm10jgoBSy/Iht6wuCiBA7kbWKT0DVAodk0gSHvOfpLfVpeo+wtGRi++gpTZm8md9RoSyjfNsgu6pOhez5ROw==","signatures":[{"sig":"MEUCIQDumwGQQQ9Qca+a0U1i5WTXASDux9NZp1KNqAlcJVoyOgIgVBl3Rz+HoZpJm+qBl3wnvM8XfHjLiokMOrl6+1g8Y2M=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":96566},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"dcd40a472e7a6cf4f253b2eb2f1bd826fa8d45cc","scripts":{"build":"tsc -p tsconfig.json","build:watch":"tsc -p tsconfig.json --watch","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"adminavis","email":"admin@avi-s.in"},"repository":{"url":"git+https://github.com/avisadmin/avis-ai.git","type":"git","directory":"packages/tryout"},"_npmVersion":"10.9.3","description":"React components and hooks for Avis AI virtual try-on (reference images, generate, optional local persistence).","directories":{},"_nodeVersion":"22.18.0","dependencies":{"@avis-ai/sdk-js":"0.0.8"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"react":"^18.3.1","react-dom":"^18.3.1","typescript":"^5.9.3","@types/react":"^18","@types/react-dom":"^18"},"peerDependencies":{"react":">=18.0.0","react-dom":">=18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/tryout_1.0.5_1777578858327_0.6033860090269041","host":"s3://npm-registry-packages-npm-production"}},"1.0.6":{"name":"@avis-ai/tryout","version":"1.0.6","description":"React components and hooks for Avis AI virtual try-on (reference images, generate, optional local persistence).","license":"ISC","repository":{"type":"git","url":"git+https://github.com/avisadmin/avis-ai.git","directory":"packages/tryout"},"keywords":["avis-ai","virtual-try-on","try-on","fashion","react","ecommerce"],"type":"module","main":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"import":"./dist/index.js","types":"./dist/index.d.ts"}},"publishConfig":{"access":"public"},"peerDependencies":{"react":">=18.0.0","react-dom":">=18.0.0"},"dependencies":{"@avis-ai/sdk-js":"0.0.8"},"devDependencies":{"@types/react":"^18","@types/react-dom":"^18","react":"^18.3.1","react-dom":"^18.3.1","typescript":"^5.9.3"},"scripts":{"build":"tsc -p tsconfig.json","build:watch":"tsc -p tsconfig.json --watch","prepublishOnly":"pnpm run build"},"_id":"@avis-ai/tryout@1.0.6","gitHead":"fac16c0193190912edf9ec3bdb390c230367501c","bugs":{"url":"https://github.com/avisadmin/avis-ai/issues"},"homepage":"https://github.com/avisadmin/avis-ai#readme","_nodeVersion":"22.18.0","_npmVersion":"10.9.3","dist":{"integrity":"sha512-3t8B4BybkP2KZty6YmeoBiNyyVWdf9jFCO9xMacCT6nIEx3EWfBOfprbYEoFdR8elUVv6C97pROntDyX4pn7+Q==","shasum":"4337993bd3f19b4c6daf216a0175a4b37d8cf491","tarball":"https://registry.npmjs.org/@avis-ai/tryout/-/tryout-1.0.6.tgz","fileCount":18,"unpackedSize":96566,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIEf63GoaYuv8S6Oobg0iw8kPNxPIXVeQuyR4s+EfoG3JAiBFmkqnSPI2Y7nIroEuDITS5WU9bDND3SVJUH6CfNzIFA=="}]},"_npmUser":{"name":"adminavis","email":"admin@avi-s.in"},"directories":{},"maintainers":[{"name":"adminavis","email":"admin@avi-s.in"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/tryout_1.0.6_1777583310673_0.4284199191680167"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-26T09:16:22.400Z","modified":"2026-04-30T21:08:30.970Z","1.0.0":"2026-04-26T09:16:22.687Z","1.0.1":"2026-04-27T10:00:38.215Z","1.0.2":"2026-04-27T10:42:00.533Z","1.0.3":"2026-04-28T08:33:08.121Z","1.0.4":"2026-04-29T07:12:44.830Z","1.0.5":"2026-04-30T19:54:18.492Z","1.0.6":"2026-04-30T21:08:30.817Z"},"bugs":{"url":"https://github.com/avisadmin/avis-ai/issues"},"license":"ISC","homepage":"https://github.com/avisadmin/avis-ai#readme","keywords":["avis-ai","virtual-try-on","try-on","fashion","react","ecommerce"],"repository":{"type":"git","url":"git+https://github.com/avisadmin/avis-ai.git","directory":"packages/tryout"},"description":"React components and hooks for Avis AI virtual try-on (reference images, generate, optional local persistence).","maintainers":[{"name":"adminavis","email":"admin@avi-s.in"}],"readme":"# Avis Tryout (`@avis-ai/tryout`)\r\n\r\nReact components and hooks for **virtual try-on**: upload or import garment and face **reference images**, optional body measurements, and **generate** a composed look using the same **project API key** and billing model as [AvisChat](https://www.npmjs.com/package/@avis-ai/avischat). Reference images are stored on the **API host (S3)**; only **public `https` URLs** are sent to the image model (no huge base64 payloads).\r\n\r\n**Headless option:** use **`AvisTryoutClient`** from this package (same REST calls as the UI). It builds on **[`@avis-ai/sdk-js`](https://www.npmjs.com/package/@avis-ai/sdk-js)** for `Authorization: Bearer` requests and error parsing.\r\n\r\n## Contents\r\n\r\n- [Getting your API key](#getting-your-api-key)\r\n- [Allowed domains (browser)](#allowed-domains-browser)\r\n- [Installation](#installation)\r\n- [Quick start (embedded UI)](#quick-start-embedded-ui)\r\n- [Headless: client + hook](#headless-client--hook)\r\n- [REST API overview](#rest-api-overview)\r\n- [Images: upload, import, generate](#images-upload-import-generate)\r\n- [Partner integrations (URLs vs upload)](#partner-integrations-urls-vs-upload)\r\n- [Body measurements](#body-measurements)\r\n- [`<AvisTryout />` props](#avistryout-props)\r\n- [`useAvisTryout` hook](#usetryout-hook)\r\n- [Result preview & zoom (optional)](#result-preview--zoom-optional)\r\n- [Session & local history](#session--local-history)\r\n- [React Native / mobile](#react-native--mobile)\r\n- [Embedding without React (script widget)](#embedding-without-react-script-widget)\r\n- [Proxy / production](#proxy--production)\r\n- [TypeScript types](#typescript-types)\r\n- [Styling](#styling)\r\n- [Errors](#errors)\r\n- [Next.js notes](#nextjs-notes)\r\n\r\n---\r\n\r\n## Getting your API key\r\n\r\nSame project key as chat — create a project in the dashboard and use its API key on every tryout request.\r\n\r\n1. Log in to the **[Dashboard](https://dashboard-ai.avi-s.in)**  \r\n2. **Create a project** (or open an existing one)  \r\n3. **Copy the API key** — shown once; store it securely  \r\n\r\nUse the key as **`apiKey`** on `<AvisTryout />` / **`AvisTryoutClient`**, or keep it on your server and proxy tryout routes (see [Proxy / production](#proxy--production)).\r\n\r\n---\r\n\r\n## Allowed domains (browser)\r\n\r\nIf the project has **allowed domains** configured in the dashboard, browser calls must send a valid **`Origin`** header that matches one of those domains. Otherwise the API responds with **`403`** (`DOMAIN_NOT_ALLOWED`). Server-to-server calls (no `Origin`) are not restricted by that list.\r\n\r\n---\r\n\r\n## Installation\r\n\r\n**Peer dependencies:** React **18+** and **React DOM 18+** (React DOM is required for optional full-screen zoom, which uses `createPortal`).\r\n\r\n```bash\r\nnpm install @avis-ai/tryout @avis-ai/sdk-js\r\npnpm add @avis-ai/tryout @avis-ai/sdk-js\r\nyarn add @avis-ai/tryout @avis-ai/sdk-js\r\n```\r\n\r\n---\r\n\r\n## Quick start (embedded UI)\r\n\r\n```tsx\r\n\"use client\";\r\n\r\nimport { AvisTryout } from \"@avis-ai/tryout\";\r\n\r\nexport function MyTryout() {\r\n  return (\r\n    <AvisTryout\r\n      apiKey={process.env.NEXT_PUBLIC_AVIS_API_KEY!}\r\n    />\r\n  );\r\n}\r\n```\r\n\r\nYou get gender chips, optional face/top/bottom/accessory image URL + file upload, measurements panel, generate button, **Reset all**, and recent results with **Edit & generate** / **Regenerate** actions. **`baseUrl`** defaults to **`https://api-ai.avi-s.in`** if omitted.\r\n\r\n---\r\n\r\n## Headless: client + hook\r\n\r\n### `AvisTryoutClient`\r\n\r\n```tsx\r\nimport { AvisTryoutClient } from \"@avis-ai/tryout\";\r\n\r\nconst client = new AvisTryoutClient({\r\n  apiKey: process.env.AVIS_API_KEY!,\r\n});\r\n\r\nconst { url } = await client.uploadTryoutImage(file);\r\nconst out = await client.generate({\r\n  sessionId: \"my-session\",\r\n  person: { faceImageUrl: url, gender: \"female\" },\r\n  outfit: {\r\n    top: { imageUrl: topUrl, color: \"navy\" },\r\n    bottom: { imageUrl: bottomUrl }\r\n  }\r\n});\r\nconsole.log(out.imageUrl);\r\n```\r\n\r\n### `useAvisTryout`\r\n\r\nSame defaults as `<AvisTryout />`, plus **local profile + history**. On the web, persistence defaults to **`localStorage`** plus **IndexedDB** for mirrored result blobs when available. Pass **`persistence`** to use **AsyncStorage** (or in-memory) on React Native — see [React Native / mobile](#react-native--mobile).\r\n\r\n```tsx\r\nimport { useAvisTryout } from \"@avis-ai/tryout\";\r\n\r\nfunction CustomTryout() {\r\n  const { profile, setProfile, history, isLoading, error, generateTryout, resetTryout } = useAvisTryout({\r\n    apiKey: \"your-api-key\"\r\n  });\r\n\r\n  return (\r\n    <div>\r\n      <button type=\"button\" disabled={isLoading} onClick={() => generateTryout()}>\r\n        Generate\r\n      </button>\r\n      <button type=\"button\" onClick={() => void resetTryout()}>\r\n        Reset\r\n      </button>\r\n      {error && <p>{error.message}</p>}\r\n      {history.map((h) => (\r\n        <img key={h.id} src={h.displayUrl ?? h.imageUrl} alt=\"\" width={200} />\r\n      ))}\r\n    </div>\r\n  );\r\n}\r\n```\r\n\r\n---\r\n\r\n## REST API overview\r\n\r\nAll routes use **`Authorization: Bearer <project_api_key>`** and **`Content-Type: application/json`** except **`POST /v1/tryout/upload`** (multipart form field **`file`**).\r\n\r\n| Method | Path | Purpose |\r\n|--------|------|--------|\r\n| `POST` | `/v1/tryout/upload` | Multipart image → stored file → returns `{ url }` (public `https`). |\r\n| `POST` | `/v1/tryout/import-image` | JSON `{ \"url\" }` → server fetches image (rules apply) → returns `{ url }`. |\r\n| `POST` | `/v1/tryout/generate` | JSON tryout payload → returns `{ imageUrl, sessionId, ... }`. |\r\n| `POST` | `/v1/tryout/mirror-result-image` | JSON `{ \"imageUrl\" }` → returns raw image bytes (allowlisted hosts); used to persist results locally without CORS issues. |\r\n\r\n**Default API origin:** `https://api-ai.avi-s.in` (strip trailing slash when overriding).\r\n\r\n---\r\n\r\n## Images: upload, import, generate\r\n\r\n1. **Upload** (`uploadTryoutImage`) or **import** (`importTryoutImageFromUrl`) each reference image so you receive a **stable `https` URL** on your storage (e.g. S3).  \r\n2. Put those URLs in **`person.faceImageUrl`**, **`outfit.top.imageUrl`**, **`outfit.bottom.imageUrl`**, **`outfit.accessories[].imageUrl`** as needed.  \r\n3. Call **`generate`** with that JSON. **`data:` URLs are rejected** — always host first.\r\n\r\n---\r\n\r\n## Partner integrations (URLs vs upload)\r\n\r\n- **Multipart upload** — best when you already have file bytes (browser or your backend).  \r\n- **Import by URL** — best when partners expose **direct CDN image URLs** (`image/jpeg`, etc.). Product **HTML pages** are a poor source; the server may try to resolve `og:image` / `twitter:image` for HTML responses, but **direct asset URLs** are what you want in production.\r\n\r\n---\r\n\r\n## Body measurements\r\n\r\nOptional **`person.bodyMeasurements`** uses **US-style retail units**:\r\n\r\n| Field | Unit |\r\n|-------|------|\r\n| `heightInches` | inches |\r\n| `weightLbs` | pounds |\r\n| `chestInches`, `waistInches`, `hipInches`, `shoulderInches`, `inseamInches` | inches |\r\n\r\nOmit any field you do not need.\r\n\r\n---\r\n\r\n## `<AvisTryout />` props\r\n\r\n**Required:** **`apiKey`**. All other props are optional.\r\n\r\n| Prop | Type | Default | Description |\r\n|------|------|---------|-------------|\r\n| `apiKey` | `string` | — | Project API key (`Bearer`). |\r\n| `baseUrl` | `string` | `https://api-ai.avi-s.in` | API origin (no trailing slash). Optional if you use the hosted API. |\r\n| `sessionId` | `string` | auto in hook | Passed through to `generate`; hook persists session id in `localStorage`. |\r\n| `quality` | `\"low\" \\| \"medium\" \\| \"high\"` | provider/default behavior | Optional integration-level override for generation quality (no built-in UI selector). When set, each generate call uses this quality. |\r\n| `theme` | `\"light\" \\| \"dark\"` | `\"dark\"` | |\r\n| `title` / `subtitle` | `string` | defaults | Header copy. |\r\n| `className` / `style` | — | — | Outer container. |\r\n| `styles` | `AvisTryoutStyleOverrides` | — | Inline style overrides per region (see source types). |\r\n| `maxAccessories` | `number` | `10` | Cap for accessory rows. |\r\n| `showImagePreviews` | `boolean` | `true` | Toggle inline previews for selected images. |\r\n| `zoomableGeneratedImages` | `boolean` | `false` | When `true`, tap result for full-screen zoom (wheel + drag). **Off** for API-only / custom layouts. |\r\n| `persistence` | `TryoutPersistence` | web default | Pluggable storage for profile/history/session (e.g. `createAsyncStorageTryoutPersistence` on native). |\r\n| `uploadLoader` | `ReactNode \\| (section) => ReactNode` | AVIS branded loader | Custom loader for active upload section. Only the in-progress section is disabled; other sections stay interactive. |\r\n| `labels` | `object` | — | `generateButton`, `resetButton`, `regenerateButton`, `editButton`, `recentTitle`, `addAccessory`, `removeAccessory`, `noHistory`, `tapToZoomHint`. |\r\n\r\n---\r\n\r\n### Custom upload loader\r\n\r\n`uploadLoader` controls what is shown while a section upload/import is in progress.\r\n\r\nBehavior:\r\n\r\n- Loader appears only for the **active section** that is uploading.\r\n- Only that section's upload controls are disabled; other sections remain usable.\r\n- If `uploadLoader` is omitted, AvisTryout uses the default AVIS-branded animated loader.\r\n\r\nYou can pass either:\r\n\r\n- **`ReactNode`**: one shared loader UI for every section.\r\n- **`(section: string) => ReactNode`**: dynamic loader based on section id.\r\n\r\nSection ids passed to the function:\r\n\r\n- `face`\r\n- `top`\r\n- `bottom`\r\n- `acc-<index>` (for accessories, e.g. `acc-0`, `acc-1`)\r\n\r\nExample (single shared loader):\r\n\r\n```tsx\r\n<AvisTryout\r\n  apiKey={API_KEY}\r\n  uploadLoader={<span style={{ fontSize: 12 }}>Uploading to AVIS…</span>}\r\n/>\r\n```\r\n\r\nExample (custom per section):\r\n\r\n```tsx\r\n<AvisTryout\r\n  apiKey={API_KEY}\r\n  uploadLoader={(section) => (\r\n    <span style={{ fontSize: 12 }}>\r\n      {section.startsWith(\"acc-\") ? \"Uploading accessory…\" : `Uploading ${section}…`}\r\n    </span>\r\n  )}\r\n/>\r\n```\r\n\r\n---\r\n\r\n## `useAvisTryout` hook\r\n\r\n**Options:** `apiKey`, `baseUrl?`, `sessionId?`, `quality?` (same as component/client), plus:\r\n\r\n- **`persistence?`** — see **`TryoutPersistence`** and **`createAsyncStorageTryoutPersistence`** in the package exports.\r\n- **`persistHistoryBySession?`** (`boolean`, default `true`) — stores/loads recent history under a session-scoped key so refresh keeps the same session's recents.\r\n\r\n### Quality behavior\r\n\r\n- If you pass **`quality`**, the hook/component applies it on every `generate` request.\r\n- Supported values: **`low`**, **`medium`**, **`high`**.\r\n- In Replicate mode, server maps quality to resolution before upstream call:\r\n  - `low -> 1K`\r\n  - `medium -> 2K`\r\n  - `high -> 4K`\r\n\r\n**Returns:**\r\n\r\n| Field | Type | Description |\r\n|-------|------|-------------|\r\n| `profile` | `TryoutGenerateInput` | Form state; synced to `localStorage`. |\r\n| `setProfile` | `(patch) => void` | Merge patch into profile and persist. |\r\n| `history` | `TryoutHistoryItem[]` | Recent generations; `displayUrl` may be a `blob:` from IndexedDB. |\r\n| `isLoading` | `boolean` | `true` while generate (+ mirror) runs. |\r\n| `error` | `Error \\| null` | Last error. |\r\n| `generateTryout` | `(input?) => Promise<TryoutGenerateOutput>` | Merges `profile`, calls API, updates history, mirrors result for offline-friendly thumbnails. |\r\n| `resetTryout` | `() => Promise<void>` | Clears profile, history, mirrored local blobs, and persisted tryout `sessionId` for a fresh start. |\r\n\r\nUse the embedded component's history actions to speed iteration:\r\n\r\n- **`Edit & generate`**: loads a previous item's input back into the form so users can tweak and regenerate.\r\n- **`Regenerate`**: reruns generation with that item's exact previous input.\r\n\r\n---\r\n\r\n## Result preview & zoom (optional)\r\n\r\nSet **`zoomableGeneratedImages`** to enable an e-commerce style **tap → full-screen** preview: **scroll to zoom**, **drag when zoomed**, **double-click to reset**, **Esc** / backdrop / **Close** to dismiss. Partners who only consume **`generate`** JSON can leave this **`false`**.\r\n\r\n---\r\n\r\n## Session & local history\r\n\r\n- **`sessionId`** in the generate payload groups usage on the server; the hook generates and persists one under the key **`avis-tryout-session-id`** (in the active persistence adapter) unless you pass **`sessionId`**.  \r\n- **History** is JSON under **`avis-tryout-history`** and (by default) also under **`avis-tryout-history:<sessionId>`**. Session-scoped history is what enables recent items to survive refresh for the same session in the demo.  \r\n- On the web, mirrored result thumbnails use **IndexedDB** when **`persistence.canMirror`** is true; otherwise history items use the remote **`imageUrl`** only (URLs may expire).  \r\n- Old saved profiles with **cm/kg** measurements are **migrated to inches/lb** on load when possible.\r\n- **`resetTryout()`** clears profile/history/session keys and mirrored local images for complete reset flows.\r\n\r\n---\r\n\r\n## React Native / mobile\r\n\r\n- **`<AvisTryout />`** is built for **React DOM** (`react-dom`, file inputs, `createPortal`). Use it inside a **WebView** if you want the stock UI on mobile, or build your own screen with the primitives below.  \r\n- **`AvisTryoutClient`** is **`fetch`-only** — safe to use in **React Native** and native shells for upload, import, generate, and mirror.  \r\n- **`useAvisTryout`** works in RN when you pass **`persistence`**: use **`createAsyncStorageTryoutPersistence(AsyncStorage)`** from **`@react-native-async-storage/async-storage`** (you add that dependency in your app; this package does not depend on it). Mirroring to a local blob cache stays **off** on that adapter (`canMirror: false`), so **`history[].displayUrl`** is usually undefined and you should render **`imageUrl`** (or download/cache images yourself if you need offline thumbnails).\r\n\r\n```tsx\r\nimport AsyncStorage from \"@react-native-async-storage/async-storage\";\r\nimport {\r\n  useAvisTryout,\r\n  createAsyncStorageTryoutPersistence\r\n} from \"@avis-ai/tryout\";\r\n\r\nconst persistence = createAsyncStorageTryoutPersistence(AsyncStorage);\r\n\r\nfunction TryoutScreen() {\r\n  const { profile, setProfile, history, isLoading, error, generateTryout } = useAvisTryout({\r\n    apiKey: YOUR_KEY,\r\n    persistence\r\n  });\r\n  // … your RN UI; images: <Image source={{ uri: h.displayUrl ?? h.imageUrl }} />\r\n}\r\n```\r\n\r\nFor tests or SSR with no storage, use **`createMemoryTryoutPersistence()`**.\r\n\r\n---\r\n\r\n## Embedding without React (script widget)\r\n\r\nIf your site is not React-based, load the hosted tryout iframe widget script from your API origin.\r\n\r\n```html\r\n<script\r\n  src=\"https://api-ai.avi-s.in/tryout-widget.js\"\r\n  data-api-key=\"sk_live_xxx\"\r\n  data-embed-url=\"https://demo-ai.avi-s.in/tryout-embed\"\r\n  data-floating=\"true\"\r\n  data-width=\"420px\"\r\n  data-height=\"760px\"\r\n></script>\r\n```\r\n\r\nSupported attributes:\r\n\r\n- `data-api-key` (required): project API key used by the embedded tryout UI.\r\n- `data-embed-url` (optional): hosted embed page URL. Defaults to `http://localhost:3002/tryout-embed` for local development.\r\n- `data-floating` (optional, default `true`): floating launcher mode (`true`) vs always-visible panel (`false`).\r\n- `data-width`, `data-height`, `data-bottom`, `data-right`, `data-border-radius`, `data-z-index` (optional): iframe layout tuning.\r\n- `data-launcher-size`, `data-launcher-label`, `data-launcher-emoji` (optional): floating launcher appearance.\r\n\r\nFor production, host your own public embed page (or use your demo host), then point `data-embed-url` to that URL.\r\n\r\n---\r\n\r\n## Proxy / production\r\n\r\nFor production, avoid exposing a **live** project secret in the browser if your policy forbids it. Proxy **`/v1/tryout/*`** from your origin and attach the key on the server, or issue short-lived tokens your BFF exchanges for upstream calls.\r\n\r\n```tsx\r\n<AvisTryout\r\n  apiKey={process.env.NEXT_PUBLIC_AVIS_API_KEY!}\r\n  baseUrl={process.env.NEXT_PUBLIC_AVIS_BASE_URL}\r\n/>\r\n```\r\n\r\n`NEXT_PUBLIC_*` keys are visible to clients — use only for **dev/staging** or **public** keys you accept rotating.\r\n\r\n---\r\n\r\n## TypeScript types\r\n\r\nRe-exported from **`@avis-ai/tryout`**:\r\n\r\n```ts\r\nimport type {\r\n  AvisTryoutProps,\r\n  AvisTryoutStyleOverrides,\r\n  TryoutPersistence,\r\n  TryoutGenerateInput,\r\n  TryoutGenerateOutput,\r\n  TryoutClientOptions,\r\n  TryoutHistoryItem,\r\n  TryoutPerson,\r\n  TryoutOutfit,\r\n  TryoutRender,\r\n  BodyMeasurements,\r\n  GarmentInput,\r\n  AccessoryInput,\r\n  UseAvisTryoutOptions,\r\n  UseAvisTryoutReturn\r\n} from \"@avis-ai/tryout\";\r\n```\r\n\r\n---\r\n\r\n## Styling\r\n\r\n`<AvisTryout />` uses **inline styles** by default. Pass **`styles`** (`AvisTryoutStyleOverrides`) to merge **React `CSSProperties`** over regions such as `container`, `form`, `buttonPrimary`, `historyCard`, `imagePreview`, etc. (see `AvisTryout.tsx`).\r\n\r\n---\r\n\r\n## Errors\r\n\r\n- Failed uploads/imports/generate throw from **`AvisTryoutClient`** using **`parseErrorResponse`** from **`@avis-ai/sdk-js`**.  \r\n- `<AvisTryout />` shows the last **`error.message`** under the form.  \r\n- **`401` / `403`** — bad key, or origin not in **allowed domains**.\r\n\r\n---\r\n\r\n## Next.js notes\r\n\r\n- Add **`\"use client\"`** to any file that imports **`AvisTryout`** or **`useAvisTryout`**.  \r\n- Do not read **`localStorage`** for **`sessionId`** on the server render; follow the same hydration pattern as [AvisChat README](https://www.npmjs.com/package/@avis-ai/avischat) **Session persistence** (initialize ids in `useEffect` after mount).\r\n\r\n---\r\n\r\n## Related packages\r\n\r\n| Package | Role |\r\n|---------|------|\r\n| [`@avis-ai/avischat`](https://www.npmjs.com/package/@avis-ai/avischat) | Chat UI + `useAvisChat` |\r\n| [`@avis-ai/sdk-js`](https://www.npmjs.com/package/@avis-ai/sdk-js) | `Avis` client, `parseErrorResponse`, chat APIs |\r\n","readmeFilename":"README.md"}