{"_id":"quarks.r3f","name":"quarks.r3f","dist-tags":{"latest":"0.17.1"},"versions":{"0.17.1":{"name":"quarks.r3f","version":"0.17.1","description":"React Three Fiber integration for three.quarks particle systems","type":"module","types":"./dist/types/index.d.ts","main":"./dist/quarks.r3f.cjs","module":"./dist/quarks.r3f.esm.js","exports":{".":{"import":"./dist/quarks.r3f.esm.js","require":"./dist/quarks.r3f.cjs","types":"./dist/types/index.d.ts"}},"scripts":{"clean":"rimraf dist .rollup.cache tsconfig.tsbuildinfo","type-check":"tsc --noEmit","dev":"rollup -c -w","build:types":"tsc --emitDeclarationOnly && node ../../scripts/fix-dts-extensions.mjs dist/types","build:js":"rollup -c","build":"npm run clean && npm run build:types && cross-env NODE_ENV=production npm run build:js","test":"jest --passWithNoTests","test:coverage":"jest --coverage","prettier":"prettier --write --ignore-unknown"},"repository":{"type":"git","url":"git+https://github.com/Alchemist0823/three.quarks.git"},"keywords":["particle","react","three","react-three-fiber","r3f","3d","vfx","effects"],"author":{"name":"Alchemist0823","email":"the.forrest.sun@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/Alchemist0823/three.quarks/issues"},"homepage":"https://quarks.art","peerDependencies":{"react":">=18.0.0","@react-three/fiber":">=8.0.0","three":">=0.182.0","three.quarks":">=0.17.0"},"dependencies":{},"devDependencies":{"@types/react":"^18.0.0","react":"^18.0.0","@react-three/fiber":"^8.0.0","three":"^0.182.0","@types/three":"^0.182.0","three.quarks":"*"},"gitHead":"4d7898e21a2c3ee888c1c4615dfd035f2133dd3e","_id":"quarks.r3f@0.17.1","_nodeVersion":"22.22.0","_npmVersion":"11.15.0","dist":{"integrity":"sha512-vxoDEqbW5gH9Yf+UEKjPfGq98L6OuLGU7OUtlacqF+NNYstf92lkYPrIQTD07OJFH2lXVqB4WUzjviEy5If+Hw==","shasum":"bd98ba64f215faafe692ad79aa67101175f81078","tarball":"https://registry.npmjs.org/quarks.r3f/-/quarks.r3f-0.17.1.tgz","fileCount":24,"unpackedSize":71752,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIGFTXjk0JKXyT+mPlbd7HpPFQrb9qKOZyfKPPePJ4oQSAiEAs0QMsK6LuTfwW1CpuGlUwvLIFEqm5gatzr6Hpkv+Oig="}]},"_npmUser":{"name":"forrestsun","email":"the.forrest.sun@gmail.com"},"directories":{},"maintainers":[{"name":"forrestsun","email":"the.forrest.sun@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/quarks.r3f_0.17.1_1779328068509_0.04356685066437338"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-21T01:47:48.460Z","0.17.1":"2026-05-21T01:47:48.669Z","modified":"2026-05-21T01:47:48.843Z"},"maintainers":[{"name":"forrestsun","email":"the.forrest.sun@gmail.com"}],"description":"React Three Fiber integration for three.quarks particle systems","homepage":"https://quarks.art","keywords":["particle","react","three","react-three-fiber","r3f","3d","vfx","effects"],"repository":{"type":"git","url":"git+https://github.com/Alchemist0823/three.quarks.git"},"author":{"name":"Alchemist0823","email":"the.forrest.sun@gmail.com"},"bugs":{"url":"https://github.com/Alchemist0823/three.quarks/issues"},"license":"MIT","readme":"# quarks.r3f\r\n\r\nReact Three Fiber integration for [three.quarks](https://github.com/Alchemist0823/three.quarks) particle systems.\r\n\r\n## Installation\r\n\r\n```bash\r\nnpm install quarks.r3f three.quarks\r\n```\r\n\r\n## Quick Start\r\n\r\n```tsx\r\nimport { Canvas } from '@react-three/fiber'\r\nimport { QuarksProvider, ParticleSystem } from 'quarks.r3f'\r\nimport { ConeEmitter, SizeOverLife, PiecewiseBezier, Bezier, RenderMode } from 'three.quarks'\r\n\r\nfunction FireEffect() {\r\n    const shape = useMemo(() => new ConeEmitter({ angle: 0.3, radius: 0.2 }), [])\r\n    const behaviors = useMemo(() => [\r\n        new SizeOverLife(new PiecewiseBezier([[new Bezier(1, 0.8, 0.4, 0), 0]]))\r\n    ], [])\r\n\r\n    return (\r\n        <ParticleSystem\r\n            duration={5}\r\n            looping\r\n            startLife={[1, 2]}\r\n            startSpeed={[2, 4]}\r\n            startSize={[0.3, 0.6]}\r\n            startColor={{ r: 1, g: 0.5, b: 0.2, a: 1 }}\r\n            emissionOverTime={40}\r\n            shape={shape}\r\n            renderMode={RenderMode.BillBoard}\r\n            behaviors={behaviors}\r\n            position={[0, 0, 0]}\r\n            rotation={[-Math.PI / 2, 0, 0]}\r\n            autoPlay\r\n        />\r\n    )\r\n}\r\n\r\nfunction App() {\r\n    return (\r\n        <Canvas>\r\n            <QuarksProvider>\r\n                <FireEffect />\r\n            </QuarksProvider>\r\n        </Canvas>\r\n    )\r\n}\r\n```\r\n\r\n## Components\r\n\r\n### `<QuarksProvider>`\r\n\r\nRequired wrapper component that manages the `BatchedRenderer` for all child particle systems.\r\n\r\n```tsx\r\n<Canvas>\r\n    <QuarksProvider>\r\n        {/* All particle systems must be children of QuarksProvider */}\r\n        <ParticleSystem ... />\r\n    </QuarksProvider>\r\n</Canvas>\r\n```\r\n\r\n### `<ParticleSystem>`\r\n\r\nDeclarative particle system component with flexible prop types.\r\n\r\n**Props:**\r\n\r\n| Prop | Type | Description |\r\n|------|------|-------------|\r\n| `duration` | `number` | System duration in seconds |\r\n| `looping` | `boolean` | Whether to loop the system |\r\n| `startLife` | `number \\| [min, max] \\| ValueGenerator` | Particle lifetime |\r\n| `startSpeed` | `number \\| [min, max] \\| ValueGenerator` | Initial particle speed |\r\n| `startSize` | `number \\| [min, max] \\| ValueGenerator` | Initial particle size |\r\n| `startColor` | `{r,g,b,a} \\| ColorGenerator` | Initial particle color |\r\n| `startRotation` | `number \\| [min, max] \\| ValueGenerator` | Initial rotation |\r\n| `emissionOverTime` | `number \\| [min, max] \\| ValueGenerator` | Particles per second |\r\n| `shape` | `EmitterShape` | Emitter shape (ConeEmitter, SphereEmitter, etc.) |\r\n| `material` | `Material` | Three.js material for particles |\r\n| `renderMode` | `RenderMode` | BillBoard, StretchedBillBoard, Mesh, Trail |\r\n| `behaviors` | `Behavior[]` | Array of particle behaviors |\r\n| `uTileCount` | `number` | Texture atlas horizontal tiles |\r\n| `vTileCount` | `number` | Texture atlas vertical tiles |\r\n| `worldSpace` | `boolean` | Emit in world space |\r\n| `position` | `[x, y, z]` | Emitter position |\r\n| `rotation` | `[x, y, z]` | Emitter rotation (Euler angles) |\r\n| `scale` | `[x, y, z]` | Emitter scale |\r\n| `autoPlay` | `boolean` | Start playing automatically (default: true) |\r\n\r\n**Ref API:**\r\n\r\n```tsx\r\nconst systemRef = useRef<ParticleSystemRef>(null)\r\n\r\n<ParticleSystem ref={systemRef} ... />\r\n\r\n// Control methods\r\nsystemRef.current.play()\r\nsystemRef.current.pause()\r\nsystemRef.current.restart()\r\nsystemRef.current.stop()\r\n\r\n// Access underlying objects\r\nsystemRef.current.system   // ParticleSystem instance\r\nsystemRef.current.emitter  // ParticleEmitter (Object3D)\r\n```\r\n\r\n### `<QuarksEffect>`\r\n\r\nLoad particle effects from JSON files with React Suspense support.\r\n\r\n```tsx\r\nimport { Suspense } from 'react'\r\nimport { QuarksEffect } from 'quarks.r3f'\r\n\r\nfunction MyEffect() {\r\n    return (\r\n        <Suspense fallback={null}>\r\n            <QuarksEffect\r\n                url=\"/effects/explosion.json\"\r\n                position={[0, 0, 0]}\r\n                autoPlay\r\n            />\r\n        </Suspense>\r\n    )\r\n}\r\n\r\n// Preload effects\r\nQuarksEffect.preload('/effects/explosion.json')\r\n```\r\n\r\n## Hooks\r\n\r\n### `useQuarks()`\r\n\r\nAccess the BatchedRenderer from context.\r\n\r\n```tsx\r\nimport { useQuarks } from 'quarks.r3f'\r\n\r\nfunction MyComponent() {\r\n    const { batchedRenderer } = useQuarks()\r\n    // Use for advanced operations\r\n}\r\n```\r\n\r\n### `useParticleSystem(props)`\r\n\r\nImperative hook for creating particle systems.\r\n\r\n```tsx\r\nimport { useParticleSystem } from 'quarks.r3f'\r\n\r\nfunction MyParticles() {\r\n    const { system, emitter, play, pause, restart } = useParticleSystem({\r\n        duration: 5,\r\n        looping: true,\r\n        startLife: [1, 2],\r\n        // ... other props\r\n    })\r\n\r\n    return <primitive object={emitter} position={[0, 1, 0]} />\r\n}\r\n```\r\n\r\n### `useQuarksEffect(url)`\r\n\r\nHook for loading JSON effects with Suspense.\r\n\r\n```tsx\r\nimport { useQuarksEffect } from 'quarks.r3f'\r\n\r\nfunction MyEffect() {\r\n    const { group, systems, play, pause, restart } = useQuarksEffect('/effect.json')\r\n    return <primitive object={group} />\r\n}\r\n\r\n// Preload\r\nuseQuarksEffect.preload('/effect.json')\r\n```\r\n\r\n## Flexible Prop Types\r\n\r\nProps like `startLife`, `startSpeed`, `startSize`, and `emissionOverTime` accept flexible types:\r\n\r\n```tsx\r\n// Constant value\r\nstartLife={2}\r\n\r\n// Random range [min, max]\r\nstartLife={[1, 3]}\r\n\r\n// ValueGenerator from three.quarks\r\nstartLife={new IntervalValue(1, 3)}\r\nstartLife={new PiecewiseBezier([[new Bezier(1, 2, 3, 4), 0]])}\r\n```\r\n\r\n## Behaviors\r\n\r\nUse behaviors from `three.quarks` to animate particles over their lifetime:\r\n\r\n```tsx\r\nimport {\r\n    SizeOverLife,\r\n    ColorOverLife,\r\n    SpeedOverLife,\r\n    RotationOverLife,\r\n    Gradient,\r\n    PiecewiseBezier,\r\n    Bezier,\r\n    Vector4,\r\n} from 'three.quarks'\r\n\r\nconst behaviors = useMemo(() => [\r\n    // Size fades out\r\n    new SizeOverLife(new PiecewiseBezier([[new Bezier(1, 0.8, 0.4, 0), 0]])),\r\n\r\n    // Color gradient\r\n    new ColorOverLife(new Gradient([\r\n        [new Vector4(1, 0.8, 0.2, 1), 0],\r\n        [new Vector4(1, 0.3, 0.1, 1), 0.5],\r\n        [new Vector4(0.5, 0.1, 0.1, 0), 1],\r\n    ])),\r\n\r\n    // Speed decay\r\n    new SpeedOverLife(new PiecewiseBezier([[new Bezier(1, 0.5, 0.2, 0), 0]])),\r\n], [])\r\n\r\n<ParticleSystem behaviors={behaviors} ... />\r\n```\r\n\r\n## Emitter Shapes\r\n\r\n```tsx\r\nimport { ConeEmitter, SphereEmitter, PointEmitter } from 'three.quarks'\r\n\r\n// Cone emitter (good for fire, fountains)\r\nconst cone = new ConeEmitter({ angle: 0.3, radius: 0.2, arc: Math.PI * 2 })\r\n\r\n// Sphere emitter (good for explosions, magic effects)\r\nconst sphere = new SphereEmitter({ radius: 0.5, thickness: 0.2 })\r\n\r\n// Point emitter\r\nconst point = new PointEmitter()\r\n```\r\n\r\n## License\r\n\r\nMIT\r\n","readmeFilename":"README.md","_rev":"1-5b47fe0ae0b7c1afeb0cef8f6104eda2"}