{"_id":"@danieljamestronca/app-icon-3d","_rev":"3-5e26a6526cb4f76155fd47557b332ba5","name":"@danieljamestronca/app-icon-3d","dist-tags":{"latest":"0.2.0"},"versions":{"0.1.0":{"name":"@danieljamestronca/app-icon-3d","version":"0.1.0","license":"MIT","_id":"@danieljamestronca/app-icon-3d@0.1.0","maintainers":[{"name":"danieljamestronca","email":"danieljames.forwork@gmail.com"}],"homepage":"https://app-icon-3d-demo.vercel.app","bugs":{"url":"https://github.com/DanielJamesTronca/app-icon-3d/issues"},"dist":{"shasum":"dac902ed738c4a3b571641f7faba1ccfa695634f","tarball":"https://registry.npmjs.org/@danieljamestronca/app-icon-3d/-/app-icon-3d-0.1.0.tgz","fileCount":5,"integrity":"sha512-+F9dESy3iDg1pqNUrkd616YmHEMiE1Lmh+j51liDoz+rr6K+2RqNJjeWY7J0gg7+XV3YrhgrHDdDbw4h9CcQTg==","signatures":[{"sig":"MEQCIAhHDvPwAg9VN8KS6kGvbWg+5USkqGfMpozBgzFtdfklAiBRxDqPS0RfQ5gE7oHtEf0dj953SnCgj/7TTVJjWCLuTA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@danieljamestronca%2fapp-icon-3d@0.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":14474},"main":"./dist/index.js","type":"module","_from":"file:danieljamestronca-app-icon-3d-0.1.0.tgz","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"build":"tsup --config tsup.config.ts","typecheck":"tsc --noEmit"},"_npmUser":{"name":"danieljamestronca","email":"danieljames.forwork@gmail.com"},"_resolved":"/tmp/3e3f8463d99d71fd28a65907cdf1f3a1/danieljamestronca-app-icon-3d-0.1.0.tgz","_integrity":"sha512-+F9dESy3iDg1pqNUrkd616YmHEMiE1Lmh+j51liDoz+rr6K+2RqNJjeWY7J0gg7+XV3YrhgrHDdDbw4h9CcQTg==","repository":{"url":"git+https://github.com/DanielJamesTronca/app-icon-3d.git","type":"git"},"_npmVersion":"11.19.0","description":"A polished 3D app icon renderer for React Three Fiber.","directories":{},"sideEffects":false,"_nodeVersion":"24.18.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"react":"^19.1.0","three":"^0.179.1","react-dom":"^19.1.0","@types/three":"^0.179.0","@react-three/fiber":"^9.1.2","@danieljamestronca/app-icon-3d-core":"0.1.0"},"peerDependencies":{"react":"^19.0.0","three":"^0.179.0","react-dom":"^19.0.0","@react-three/fiber":"^9.0.0"},"_npmOperationalInternal":{"tmp":"tmp/app-icon-3d_0.1.0_1786446447631_0.8807838957873007","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@danieljamestronca/app-icon-3d","version":"0.1.1","keywords":["three","threejs","react-three-fiber","r3f","3d","app-icon","icon","webgl","squircle","ios-icon"],"author":{"name":"Daniel James Tronca"},"license":"MIT","_id":"@danieljamestronca/app-icon-3d@0.1.1","maintainers":[{"name":"danieljamestronca","email":"danieljames.forwork@gmail.com"}],"homepage":"https://app-icon-3d-demo.vercel.app","bugs":{"url":"https://github.com/DanielJamesTronca/app-icon-3d/issues"},"dist":{"shasum":"6a247b3a79d054d6ec6d7d3781aa656e7fbded1b","tarball":"https://registry.npmjs.org/@danieljamestronca/app-icon-3d/-/app-icon-3d-0.1.1.tgz","fileCount":6,"integrity":"sha512-t+1jok0gzF4AtpYoJwwJ4BNXomLidug5t17inTaKEvn64PzGwoIiVoeCIwO6fyVRUwpU36gTy6mkhSDtH9vx3A==","signatures":[{"sig":"MEUCIQD2N/wPtSz6aXFVJdfV44zMjc3Boj5G8iNvxoycGxcFdwIgIkRtL4Yq2MkO3iHh4g5tiPPv/BsNnYZDzt4B0mwCMDI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@danieljamestronca%2fapp-icon-3d@0.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":37899},"main":"./dist/index.js","type":"module","_from":"file:danieljamestronca-app-icon-3d-0.1.1.tgz","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"build":"tsup --config tsup.config.ts","typecheck":"tsc --noEmit"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:760c38fe-6b1a-4a0a-aae3-9839c172c460"}},"_resolved":"/tmp/c9d5e6081f1f3d2d3f9854607489831b/danieljamestronca-app-icon-3d-0.1.1.tgz","_integrity":"sha512-t+1jok0gzF4AtpYoJwwJ4BNXomLidug5t17inTaKEvn64PzGwoIiVoeCIwO6fyVRUwpU36gTy6mkhSDtH9vx3A==","repository":{"url":"git+https://github.com/DanielJamesTronca/app-icon-3d.git","type":"git","directory":"packages/react"},"_npmVersion":"11.19.0","description":"A polished 3D app icon renderer for React Three Fiber.","directories":{},"sideEffects":false,"_nodeVersion":"24.18.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jsdom":"^30.0.1","react":"^19.1.0","three":"^0.179.1","react-dom":"^19.1.0","@types/three":"^0.179.0","@react-three/fiber":"^9.1.2","@react-three/test-renderer":"^9.1.1","@danieljamestronca/app-icon-3d-core":"0.1.0"},"peerDependencies":{"react":"^19.0.0","three":">=0.179.0 <1.0.0","react-dom":"^19.0.0","@react-three/fiber":"^9.0.0"},"_npmOperationalInternal":{"tmp":"tmp/app-icon-3d_0.1.1_1786455823944_0.6932314341753572","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@danieljamestronca/app-icon-3d","version":"0.2.0","description":"A polished 3D app icon renderer for React Three Fiber.","keywords":["three","threejs","react-three-fiber","r3f","3d","app-icon","icon","webgl","squircle","ios-icon"],"license":"MIT","author":{"name":"Daniel James Tronca"},"homepage":"https://app-icon-3d-demo.vercel.app","repository":{"type":"git","url":"git+https://github.com/DanielJamesTronca/app-icon-3d.git","directory":"packages/react"},"bugs":{"url":"https://github.com/DanielJamesTronca/app-icon-3d/issues"},"publishConfig":{"access":"public"},"type":"module","sideEffects":false,"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"main":"./dist/index.js","types":"./dist/index.d.ts","peerDependencies":{"@react-three/fiber":"^9.0.0","react":"^19.0.0","react-dom":"^19.0.0","three":">=0.179.0 <1.0.0"},"devDependencies":{"@react-three/fiber":"^9.1.2","@react-three/test-renderer":"^9.1.1","@types/three":"^0.179.0","jsdom":"^30.0.1","react":"^19.1.0","react-dom":"^19.1.0","three":"^0.179.1","@danieljamestronca/app-icon-3d-core":"0.1.0"},"scripts":{"build":"tsup --config tsup.config.ts","typecheck":"tsc --noEmit"},"_id":"@danieljamestronca/app-icon-3d@0.2.0","_integrity":"sha512-gygQGnW+9ZtsZPulHsGf/KZuppgo2QiFSf5jy4oIzek/g2ibCCK9857xmky7mnqfzrFWQps19+0Mt07o4LQARg==","_resolved":"/tmp/70152361dd5645418ae3c8d85dbfbc00/danieljamestronca-app-icon-3d-0.2.0.tgz","_from":"file:danieljamestronca-app-icon-3d-0.2.0.tgz","_nodeVersion":"24.18.0","_npmVersion":"11.19.0","dist":{"integrity":"sha512-gygQGnW+9ZtsZPulHsGf/KZuppgo2QiFSf5jy4oIzek/g2ibCCK9857xmky7mnqfzrFWQps19+0Mt07o4LQARg==","shasum":"825d20f101b2633af92a007c2637d50a2d95a864","tarball":"https://registry.npmjs.org/@danieljamestronca/app-icon-3d/-/app-icon-3d-0.2.0.tgz","fileCount":6,"unpackedSize":114118,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@danieljamestronca%2fapp-icon-3d@0.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQClRWcy77OTPEpD3/p1FFClB8+ObCNNMiRwcJ+d449k+wIgDQS/tNYIQ072ImvsEnNNnR72V4lLIXZkOit/0YTyt9I="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:760c38fe-6b1a-4a0a-aae3-9839c172c460"}},"directories":{},"maintainers":[{"name":"danieljamestronca","email":"danieljames.forwork@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/app-icon-3d_0.2.0_1786462681175_0.35411931605888713"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-11T11:07:27.481Z","modified":"2026-08-11T15:38:01.637Z","0.1.0":"2026-08-11T11:07:27.771Z","0.1.1":"2026-08-11T13:43:44.065Z","0.2.0":"2026-08-11T15:38:01.314Z"},"bugs":{"url":"https://github.com/DanielJamesTronca/app-icon-3d/issues"},"author":{"name":"Daniel James Tronca"},"license":"MIT","homepage":"https://app-icon-3d-demo.vercel.app","keywords":["three","threejs","react-three-fiber","r3f","3d","app-icon","icon","webgl","squircle","ios-icon"],"repository":{"type":"git","url":"git+https://github.com/DanielJamesTronca/app-icon-3d.git","directory":"packages/react"},"description":"A polished 3D app icon renderer for React Three Fiber.","maintainers":[{"name":"danieljamestronca","email":"danieljames.forwork@gmail.com"}],"readme":"# @danieljamestronca/app-icon-3d\n\nRender a local or remote app-icon image as a polished, interactive 3D object inside React Three Fiber — no backend, no telemetry, all image work stays in the browser.\n\n[Live demo](https://app-icon-3d-demo.vercel.app) · [Repository](https://github.com/DanielJamesTronca/app-icon-3d) · [CLI package](https://www.npmjs.com/package/@danieljamestronca/app-icon-3d-cli)\n\n![Rotating empty 3D app icon](https://raw.githubusercontent.com/DanielJamesTronca/app-icon-3d/main/media/app-icon-3d.gif)\n\n## Install\n\n```sh\nnpm install three @react-three/fiber @danieljamestronca/app-icon-3d\n```\n\n## Usage\n\nFor a self-contained canvas:\n\n```tsx\nimport { AppIcon3DCanvas } from '@danieljamestronca/app-icon-3d';\n\nexport function Icon() {\n  return <AppIcon3DCanvas src=\"/icon.png\" preset=\"ceramic\" autoRotate interactive />;\n}\n```\n\nOr place `AppIcon3D` inside an existing React Three Fiber `<Canvas>`:\n\n```tsx\n<Canvas>\n  <AppIcon3D src=\"/icon.png\" preset=\"aluminum\" edgeColor=\"#657089\" />\n</Canvas>\n```\n\nThe framework-free geometry and material helpers are exported too: `createAppIconGeometry`, `createAppIconMaterials`, `createSquircleShape`, and `getPresetMaterialValues`.\n\n## `AppIcon3D` props\n\n| Prop          | Type                                                  | Default              | Description                                                                      |\n| ------------- | ----------------------------------------------------- | -------------------- | -------------------------------------------------------------------------------- |\n| `src`         | `string`                                              | _(required)_         | Browser-reachable image URL, subject to CORS.                                    |\n| `preset`      | `'ceramic' \\| 'aluminum' \\| 'glass'`                  | `'ceramic'`          | Material preset — see [Presets](#presets).                                       |\n| `edgeColor`   | `string`                                              | sampled from artwork | Hex color for the icon's edge; omit to sample from the source image's perimeter. |\n| `autoRotate`  | `boolean`                                             | `true`               | Spins the icon when idle. Respects `prefers-reduced-motion`.                     |\n| `interactive` | `boolean`                                             | `true`               | Enables pointer-drag rotation with inertia.                                      |\n| `quality`     | `'low' \\| 'medium' \\| 'high'`                         | `'medium'`           | Mesh smoothness / segment count.                                                 |\n| `onReady`     | `(event: { mesh: Mesh; textureUrl: string }) => void` | —                    | Called once the mesh and texture are ready.                                      |\n\n`AppIcon3DCanvas` accepts all `AppIcon3D` props plus `canvasProps` (forwarded to the underlying React Three Fiber `<Canvas>`), `className`, and `style`.\n\n## Rendering multiple icons\n\n`AppIcon3DCollection` mirrors consumer-owned DOM slots into one shared WebGL canvas. It does not\nrender cards, labels, links, or a specific CSS layout, so the same component can back a grid, list,\nor any responsive collection. Give each visual slot `data-app-icon-id={item.id}`, keep interaction\nand accessibility on the DOM, and drive the mutable motion objects with `useIconPointer`.\n\n```tsx\nimport { useRef, useState } from 'react';\nimport {\n  AppIcon3DCollection,\n  createIconMotion,\n  useIconPointer,\n  type IconMotion\n} from '@danieljamestronca/app-icon-3d';\n\nconst items = [\n  { id: 'weather', src: '/icons/weather.png', edgeColor: '#3a6ff7' },\n  { id: 'notes', src: '/icons/notes.png', edgeColor: '#f7b23a' }\n];\n\nexport function IconCollection() {\n  const containerRef = useRef<HTMLDivElement>(null);\n  const [motions] = useState(\n    () => new Map(items.map((item, index) => [item.id, createIconMotion(index * 1.17)]))\n  );\n  const pointer = useIconPointer();\n\n  return (\n    <div ref={containerRef} className=\"relative grid grid-cols-2 gap-4\">\n      {items.map((item) => {\n        const motion = motions.get(item.id) as IconMotion;\n        return (\n          <button key={item.id} className=\"relative aspect-square\">\n            <div\n              data-app-icon-id={item.id}\n              className=\"absolute inset-0\"\n              onPointerEnter={() => pointer.onPointerEnter(motion)}\n              onPointerLeave={() => pointer.onPointerLeave(motion)}\n              onPointerDown={(event) => pointer.onPointerDown(event, motion)}\n              onPointerMove={(event) => pointer.onPointerMove(event, motion)}\n              onPointerUp={(event) => pointer.onPointerUp(event, motion)}\n              onPointerCancel={() => pointer.onPointerCancel(motion)}\n            />\n          </button>\n        );\n      })}\n      <AppIcon3DCollection containerRef={containerRef} items={items} motions={motions} />\n    </div>\n  );\n}\n```\n\nThe collection pauses off-screen, on hidden tabs, when `paused` is true, and after context loss.\nUse `onItemReady`, `onItemError`, and `onContextLost` to coordinate flat-image fallbacks. Shared\nscene defaults can be adjusted with geometry, material, lighting, camera, shadow, DPR, motion,\nand `iconScale` props; individual items can override their preset, edge material, and optical scale.\n\n## Presets\n\n| Ceramic                             | Aluminum                               | Glass                                        |\n| ----------------------------------- | -------------------------------------- | -------------------------------------------- |\n| Glossy dielectric with a soft bevel | Brushed-metal feel with high metalness | Clear-coated, partially transmissive surface |\n\nTry each in the [interactive demo](https://app-icon-3d-demo.vercel.app).\n\n## Accessibility\n\nThe renderer respects `prefers-reduced-motion`; automatic spinning stops when users request less motion. Keep a text alternative or nearby app name for meaningful artwork, and do not make a 3D preview the only way to access important information. Provide an accessible label for the canvas in your product context.\n\n## Supported formats and limits\n\n- Browser-reachable image URLs supported by the browser and allowed by CORS.\n- V1 makes a polished extruded icon object; it does not infer deep, semantic 3D geometry from arbitrary artwork.\n\nSee the [repository](https://github.com/DanielJamesTronca/app-icon-3d) for the CLI exporter, contribution guide, and license.\n","readmeFilename":"README.md"}