{"_id":"@busyexplore/zotonic-player","name":"@busyexplore/zotonic-player","dist-tags":{"beta":"0.0.0-beta.1","latest":"0.0.0-beta.1"},"versions":{"0.0.0-beta.1":{"name":"@busyexplore/zotonic-player","private":false,"version":"0.0.0-beta.1","type":"module","main":"dist/zotonic-player.umd.js","module":"dist/zotonic-player.es.js","scripts":{"dev":"set NODE_OPTIONS=--openssl-legacy-provider && vite","build":"vite build","lint":"eslint .","preview":"vite preview","deploy":"npm version prerelease --preid=beta --no-git-tag-version && npm publish --tag beta"},"dependencies":{"react":"^16.8 || ^17 || ^18","react-dom":"^16.8 || ^17 || ^18"},"peerDependencies":{"react":"^16.8 || ^17 || ^18","react-dom":"^16.8 || ^17 || ^18"},"devDependencies":{"@eslint/js":"^9.29.0","@types/react":"^19.1.8","@types/react-dom":"^19.1.6","@vitejs/plugin-react":"^4.6.0","eslint":"^9.29.0","eslint-plugin-react-hooks":"^5.2.0","eslint-plugin-react-refresh":"^0.4.20","globals":"^16.2.0","vite":"^6.3.5"},"_id":"@busyexplore/zotonic-player@0.0.0-beta.1","gitHead":"2fd584140e3a1fd6e3a91355ed2df5da09f9ba75","description":"A React hook for frame-based animations with easing, looping, triggers, and optional custom ticker support.","_nodeVersion":"20.9.0","_npmVersion":"10.1.0","dist":{"integrity":"sha512-zLF0409vTJJK+Q52+rwyVT5WlpJj8QT+6tEMq06Psvd19mFqZ0zC2ET/wcB6v6UsojofYMXqmEiZ4hdKO1Z6Fw==","shasum":"b8aac19d566d6080da82746f3cdc397e40b0abae","tarball":"https://registry.npmjs.org/@busyexplore/zotonic-player/-/zotonic-player-0.0.0-beta.1.tgz","fileCount":4,"unpackedSize":12466,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDFeXK2QIDYdiayZX71JbLbcXhkIuW4ZUgv2t8XBqWIeQIgCzmMUJOQ2sauRRKRG/fMF68x+2QuRK1VEsiK6C8Vqrc="}]},"_npmUser":{"name":"busyexplore","email":"suprise.mlimi97@gmail.com","actor":{"name":"busyexplore","email":"suprise.mlimi97@gmail.com","type":"user"}},"directories":{},"maintainers":[{"name":"busyexplore","email":"suprise.mlimi97@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/zotonic-player_0.0.0-beta.1_1751710494238_0.29147716255609946"},"_hasShrinkwrap":false}},"time":{"created":"2025-07-05T10:14:54.150Z","0.0.0-beta.1":"2025-07-05T10:14:54.438Z","modified":"2025-07-05T10:14:54.797Z"},"maintainers":[{"name":"busyexplore","email":"suprise.mlimi97@gmail.com"}],"description":"A React hook for frame-based animations with easing, looping, triggers, and optional custom ticker support.","readme":"\n# 🎬 ReactZotonicPlayer\n\nA React hook for frame-based animations with easing, looping, triggers, and optional custom ticker support.\n\n---\n\n## ✨ Features\n\n- ▶️ Play, ⏸️ pause, ⏹️ stop, and 🔍 seek animations by frame\n- 🎢 Supports multiple easing functions (linear, easeInQuad, easeOutQuad, easeInOutQuad, steps)\n- 🔁 Loop animations from any frame\n- ⚙️ Custom ticker support (to sync animation with external tickers)\n- 🚦 Trigger callbacks for animation start and end events\n- 📊 Returns interpolated animated values grouped by animation ID\n\n---\n\n## 📦 Installation\n\nnpm i @busyexplore/zotonic-player\n\n---\n\n## 🚀 Usage\n\n```jsx\nimport React, { useEffect } from \"react\";\nimport ReactZotonicPlayer from \"@busyexplore/zotonic-player\"\n\n\nconst animations = [\n  {\n    id: 1,\n    startTime: 0,\n    duration: 24,\n    data: { x: 0, y: 0 },\n    ease: \"easeInOutQuad\",\n  },\n  {\n    id: 1,\n    startTime: 24,\n    duration: 24,\n    data: { x: 100, y: 100 },\n    ease: \"linear\",\n  },\n];\n\nfunction AnimatedComponent() {\n  const {\n    cursor,\n    animatedValue,\n    isPlaying,\n    play,\n    pause,\n    stop,\n    seek,\n    loadAnimation,\n    setLoopEnabled,\n    setTriggerCallback,\n  } = ReactZotonicPlayer();\n\n  useEffect(() => {\n    loadAnimation(animations);\n  }, []);\n\n  useEffect(() => {\n    setTriggerCallback((events) => {\n      events.forEach(({ id, type, frame }) => {\n        console.log(`Animation ${id} ${type} at frame ${frame}`);\n      });\n    });\n  }, []);\n\n  return (\n    <div>\n      <button onClick={() => play()}>▶️ Play</button>\n      <button onClick={pause}>⏸️ Pause</button>\n      <button onClick={stop}>⏹️ Stop</button>\n      <button onClick={() => seek(12)}>🔍 Seek to frame 12</button>\n      <label>\n        🔁 Loop:\n        <input type=\"checkbox\" onChange={e => setLoopEnabled(e.target.checked)} />\n      </label>\n      <div>🎞️ Frame: {cursor}</div>\n      <pre>{JSON.stringify(animatedValue, null, 2)}</pre>\n    </div>\n  );\n}\n```\n\n---\n\n## 🛠️ API\n\n### `ReactZotonicPlayer(options?)`\n\n| Option            | Type       | Default | Description                                      |\n|-------------------|------------|---------|------------------------------------------------|\n| `useCustomTicker` | `boolean`  | `false` | Use a custom ticker function instead of RAF.    |\n| `ticker`          | `function` | `() => {}` | Custom ticker function called each frame if enabled. Receives a callback to advance the frame. |\n\n### Returned Object\n\n| Property            | Type       | Description                                     |\n|---------------------|------------|------------------------------------------------|\n| `cursor`            | `number`   | Current frame number.                           |\n| `totalDuration`     | `number`   | Total animation duration in frames.            |\n| `animatedValue`     | `Array`    | Array of `{ id, props }` objects for current frame. |\n| `isPlaying`         | `boolean`  | Indicates if the animation is playing.         |\n| `setLoopEnabled`    | `function` | Enable or disable looping.                      |\n| `setTriggerCallback`| `function` | Set callback for animation start/end triggers. Receives an array of trigger events. |\n| `play(fromFrame?)`  | `function` | Start playing optionally from a specific frame.|\n| `pause()`           | `function` | Pause animation playback.                       |\n| `stop()`            | `function` | Stop and reset animation to frame 0.           |\n| `seek(frame)`       | `function` | Jump to a specific frame number.                |\n| `loadAnimation(data)` | `function` | Load animation keyframe data.                   |\n\n---\n\n## 🎨 Animation Data Structure\n\nThe animation data is an array of keyframe objects:\n\n```js\n[\n  {\n    id: number,          // unique animation id\n    startTime: number,   // start frame\n    duration: number,    // duration in frames\n    data: object,        // properties to animate, e.g., { x: 0, y: 0 }\n    ease: string,        // easing function (\"linear\", \"easeInOutQuad\", \"steps\", etc.)\n    steps?: number,      // number of steps for \"steps\" easing\n    triggerOnlyWhenStartAndEnd?: boolean // enable trigger events for this keyframe\n  }\n]\n```\n\n---\n\n## 🎢 Easing Functions & Usage\n\nThe hook supports the following easing functions. Specify the easing in your animation keyframe objects using the `ease` property:\n\n| Easing Name    | Description                                   | Usage Example             |\n|----------------|-----------------------------------------------|---------------------------|\n| `linear`       | Straight linear interpolation, no easing.    | `{ ease: \"linear\" }`       |\n| `easeInQuad`   | Accelerating from zero velocity (quadratic). | `{ ease: \"easeInQuad\" }`   |\n| `easeOutQuad`  | Decelerating to zero velocity (quadratic).   | `{ ease: \"easeOutQuad\" }`  |\n| `easeInOutQuad`| Accelerates until halfway, then decelerates. | `{ ease: \"easeInOutQuad\" }`|\n| `steps`       | Discrete steps instead of smooth interpolation. Requires `steps` parameter specifying number of steps. | `{ ease: \"steps\", steps: 5 }` |\n\n### Example animation keyframe with easing:\n\n```js\nconst animation = [\n  {\n    id: 1,\n    startTime: 0,\n    duration: 24,\n    data: { x: 0, opacity: 0 },\n    ease: \"easeInOutQuad\",\n  },\n  {\n    id: 1,\n    startTime: 24,\n    duration: 24,\n    data: { x: 100, opacity: 1 },\n    ease: \"steps\",\n    steps: 4,\n  },\n];\n```\n\n---\n\n## 📋 Notes\n\n- The default frame rate is fixed at 24 FPS when using the internal RAF ticker.\n- Looping will restart the animation from the last seek frame.\n- Triggers only fire on animations with `triggerOnlyWhenStartAndEnd` enabled.\n- Custom ticker mode allows integrating with external animation loops or libraries.\n\n---\n\nIf you have any questions or want to contribute, feel free to open an issue or pull request!\n\n---\n\n**Happy animating!** 🎨✨\n","readmeFilename":"README.md","_rev":"1-0cb873d9edb0e6ef4c8dca7e8adfc508"}