{"_id":"@bunny.net/upload-solid","_rev":"2-aba3f941743abe71d4af788cac1183f1","name":"@bunny.net/upload-solid","dist-tags":{"latest":"0.0.2"},"versions":{"0.0.1":{"name":"@bunny.net/upload-solid","version":"0.0.1","_id":"@bunny.net/upload-solid@0.0.1","maintainers":[{"name":"kevin_at_bunny","email":"kevin@bunny.net"},{"name":"antho-bunny","email":"anthony@bunny.net"},{"name":"notrab","email":"jamie@notrab.dev"},{"name":"bogdan-at-bunny","email":"bogdan@bunny.net"}],"dist":{"shasum":"f192dd0f79666de58aa104702a49068619b94f8a","tarball":"https://registry.npmjs.org/@bunny.net/upload-solid/-/upload-solid-0.0.1.tgz","fileCount":8,"integrity":"sha512-22OLJaIYLUtvydzY7Sdrsa6vs+1DYjwPiQvwgyBJ8t5s76oGjfiZ9+hRlaEkRRM9/AE4xQgieF0RHK8Tw5lrYQ==","signatures":[{"sig":"MEYCIQDPlTnhRdVEAEi8xQ48YvmctU4i0KLVGVWl7JLKD4Cg0QIhAMCLuEdzagJvQf+mrAHucCrUYdp614qOmmtWE+trNydA","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":111002},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"gitHead":"e30b7b82d2997aaa97925aead3cee193bfe1935e","scripts":{"dev":"tsup --watch","build":"tsup","clean":"rm -rf dist","typecheck":"tsc --noEmit"},"_npmUser":{"name":"notrab","email":"jamie@notrab.dev"},"_npmVersion":"10.8.2","description":"SolidJS primitives and components for [bunny-upload](../../README.md).","directories":{},"_nodeVersion":"20.20.1","dependencies":{"@bunny.net/upload-core":"workspace:*"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","solid-js":"^1.9.0","typescript":"^5.5.0","tsup-preset-solid":"^2.2.0"},"peerDependencies":{"solid-js":"^1.8.0"},"_npmOperationalInternal":{"tmp":"tmp/upload-solid_0.0.1_1774534838344_0.2751600816003288","host":"s3://npm-registry-packages-npm-production"}},"0.0.2":{"name":"@bunny.net/upload-solid","publishConfig":{"access":"public"},"version":"0.0.2","type":"module","main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"scripts":{"build":"tsup","dev":"tsup --watch","typecheck":"tsc --noEmit","clean":"rm -rf dist"},"dependencies":{"@bunny.net/upload-core":"0.0.2"},"peerDependencies":{"solid-js":"^1.8.0"},"devDependencies":{"solid-js":"^1.9.0","tsup":"^8.0.0","tsup-preset-solid":"^2.2.0","typescript":"^5.5.0"},"_id":"@bunny.net/upload-solid@0.0.2","gitHead":"93aa8ca7a45d19966df2a8f738e18ca517a03e01","description":"SolidJS primitives and components for [bunny-upload](../../README.md).","_nodeVersion":"20.20.1","_npmVersion":"10.8.2","dist":{"integrity":"sha512-Q2ZBvysdnW50OkMqjWUsh/OHE5gkTP4djEf7FFg23N6vz3KIbGmsRntG/WxXDKpQKlUO9muWwAsvt7O+W9/5Cw==","shasum":"644312bc43787c2e6933f96a307c11f6ffd021e9","tarball":"https://registry.npmjs.org/@bunny.net/upload-solid/-/upload-solid-0.0.2.tgz","fileCount":8,"unpackedSize":110996,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCo5rgPPC3/pY/nK2amfIdv5Qq4cD7EQVW9LcRINVQokwIhAJoPjpX4iR4/7bh9iFre7gz/hIy2Yj4+4nskG3vkdOMb"}]},"_npmUser":{"name":"notrab","email":"jamie@notrab.dev"},"directories":{},"maintainers":[{"name":"kevin_at_bunny","email":"kevin@bunny.net"},{"name":"antho-bunny","email":"anthony@bunny.net"},{"name":"notrab","email":"jamie@notrab.dev"},{"name":"bogdan-at-bunny","email":"bogdan@bunny.net"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/upload-solid_0.0.2_1774539271322_0.5781607006729084"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-26T14:20:38.283Z","modified":"2026-03-26T15:34:31.598Z","0.0.1":"2026-03-26T14:20:38.534Z","0.0.2":"2026-03-26T15:34:31.459Z"},"description":"SolidJS primitives and components for [bunny-upload](../../README.md).","maintainers":[{"name":"kevin_at_bunny","email":"kevin@bunny.net"},{"name":"antho-bunny","email":"anthony@bunny.net"},{"name":"notrab","email":"jamie@notrab.dev"},{"name":"bogdan-at-bunny","email":"bogdan@bunny.net"}],"readme":"# @bunny.net/upload-solid\n\nSolidJS primitives and components for [bunny-upload](../../README.md).\n\n## Install\n\n```bash\nnpm install @bunny.net/upload-solid @bunny.net/upload\n```\n\n## Drop-in button\n\n```tsx\nimport { BunnyUpload } from \"@bunny.net/upload-solid\";\n\nexport default function Page() {\n  return (\n    <BunnyUpload\n      accept={[\"image/*\"]}\n      maxSize=\"10mb\"\n      maxFiles={5}\n      onComplete={(files) => console.log(\"Uploaded:\", files)}\n    />\n  );\n}\n```\n\n### Props\n\n| Prop | Type | Default | Description |\n|---|---|---|---|\n| `endpoint` | `string` | `\"/.bunny/upload\"` | Server upload endpoint |\n| `accept` | `string[]` | — | Allowed MIME types (e.g. `[\"image/*\"]`) |\n| `maxSize` | `string \\| number` | — | Max file size (e.g. `\"10mb\"`) |\n| `maxFiles` | `number` | — | Max number of files |\n| `autoUpload` | `boolean` | `true` | Upload immediately when files are added |\n| `onComplete` | `(files: UploadResult[]) => void` | — | Called when all uploads finish |\n| `onError` | `(error: Error, file?: FileState) => void` | — | Called when an upload fails |\n| `class` | `string` | — | CSS class for the container |\n\n## Upload widget\n\nA button that opens a modal with dropzone, file list, and progress:\n\n```tsx\nimport { UploadWidget } from \"@bunny.net/upload-solid\";\n\n<UploadWidget\n  accept={[\"image/*\"]}\n  maxSize=\"10mb\"\n  maxFiles={5}\n  onComplete={(files) => console.log(files)}\n/>\n```\n\nCustom trigger:\n\n```tsx\n<UploadWidget\n  accept={[\"image/*\"]}\n  trigger={({ open }) => <button onClick={open}>My custom button</button>}\n/>\n```\n\n## Custom dropzone\n\nFull control over the UI with render props. All returned values are signals:\n\n```tsx\nimport { UploadDropzone } from \"@bunny.net/upload-solid\";\n\n<UploadDropzone accept={[\"image/*\"]} maxSize=\"10mb\">\n  {({ isDragOver, openFilePicker, files, getDropzoneProps, getInputProps }) => {\n    const dzProps = getDropzoneProps();\n    const inProps = getInputProps();\n\n    return (\n      <div\n        onDrop={dzProps.onDrop}\n        onDragOver={dzProps.onDragOver}\n        onDragLeave={dzProps.onDragLeave}\n        onClick={openFilePicker}\n      >\n        <input ref={inProps.ref} type={inProps.type} multiple={inProps.multiple} accept={inProps.accept} onChange={inProps.onChange} style={inProps.style} />\n        <p>{isDragOver() ? \"Drop!\" : \"Drag files here\"}</p>\n        {files().map((f) => <div>{f.name} — {f.progress}%</div>)}\n      </div>\n    );\n  }}\n</UploadDropzone>\n```\n\n## Headless primitive\n\nMaximum flexibility — just the state and methods, zero UI:\n\n```tsx\nimport { createBunnyUpload } from \"@bunny.net/upload-solid\";\n\nconst { files, addFiles, removeFile, upload, reset, isUploading } = createBunnyUpload({\n  accept: [\"image/*\"],\n  maxSize: \"10mb\",\n  maxFiles: 5,\n  onComplete: (results) => console.log(results),\n});\n\n// files() and isUploading() are signals\nfiles().map((f) => f.name);\n```\n\n### Return values\n\n| Value | Type | Description |\n|---|---|---|\n| `files` | `() => FileState[]` | Signal — current file states |\n| `addFiles` | `(files: FileList \\| File[]) => void` | Add files to the queue |\n| `removeFile` | `(id: string) => void` | Remove a file by ID |\n| `upload` | `() => Promise<UploadResult[]>` | Start uploading |\n| `reset` | `() => void` | Clear all files |\n| `isUploading` | `() => boolean` | Signal — whether any file is uploading |\n\n## Composable file list\n\n```tsx\nimport { UploadFileList } from \"@bunny.net/upload-solid\";\n\n<UploadFileList\n  files={files()}\n  onRemove={removeFile}\n  onRetry={() => upload()}\n/>\n```\n\n## Shared defaults\n\n```tsx\nimport { configureBunnyUpload } from \"@bunny.net/upload-solid\";\n\nconst { BunnyUpload, createBunnyUpload } = configureBunnyUpload({\n  accept: [\"image/*\"],\n  maxSize: \"10mb\",\n  maxFiles: 5,\n});\n\nexport { BunnyUpload, createBunnyUpload };\n```\n\n## Server setup (SolidStart)\n\n```ts\n// src/routes/.bunny/upload.ts\nimport type { APIEvent } from \"@solidjs/start/server\";\nimport { createBunnyUploadHandler } from \"@bunny.net/upload\";\n\nconst handler = createBunnyUploadHandler({\n  restrictions: { maxFileSize: \"10mb\", allowedTypes: [\"image/*\"], maxFiles: 5 },\n  getPath: (file) => `/uploads/${Date.now()}-${file.name}`,\n});\n\nexport async function POST(event: APIEvent) {\n  return handler(event.request);\n}\n```\n\n## SSR\n\nThe `createBunnyUpload` primitive is SSR-safe — it returns inert stubs on the server and only instantiates the uploader in the browser. No `clientOnly` wrapper needed.\n","readmeFilename":"README.md"}