{"_id":"@cut.media/vue-gif-player","_rev":"3-bf87195daf130cfa83f17353164b3a31","name":"@cut.media/vue-gif-player","dist-tags":{"latest":"1.1.0"},"versions":{"1.0.2":{"name":"@cut.media/vue-gif-player","version":"1.0.2","keywords":["vue","vue3","gif","player","animation","component"],"author":"","_id":"@cut.media/vue-gif-player@1.0.2","maintainers":[{"name":"airyland","email":"iaminwinter@gmail.com"}],"homepage":"https://github.com/cut-media-hq/vue-gif-player#readme","bugs":{"url":"https://github.com/cut-media-hq/vue-gif-player/issues"},"dist":{"shasum":"ccde7fc3ee4d1b4d9d0f0cb0b913995fa391fe66","tarball":"https://registry.npmjs.org/@cut.media/vue-gif-player/-/vue-gif-player-1.0.2.tgz","fileCount":5,"integrity":"sha512-JWX6HEdV+5MX9TuyEBxfq6q7HR1rXRf4YQ8jLNosvyiw/IpPtCN0k+biVJ5vi6s/EbCebPFhuUYH0ue7WaieWA==","signatures":[{"sig":"MEUCIBo6Wv1TOWoZ2W7UKOPPV4dm2BpGsxx7kL5EW1uO1AFwAiEA/x57Th45FaoX5oXZxM7gahKG0L0g4RZM8Mk1LbGR+B8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":59311},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","module":"dist/index.esm.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.esm.js","require":"./dist/index.js"},"./style.css":"./dist/style.css"},"gitHead":"f7bbbadaa4f4065780564a9cf119784beb73fa41","scripts":{"dev":"vite build --watch","test":"vitest","build":"vite build","test:ui":"vitest --ui","test:coverage":"vitest --coverage"},"_npmUser":{"name":"airyland","email":"iaminwinter@gmail.com"},"repository":{"url":"git+https://github.com/cut-media-hq/vue-gif-player.git","type":"git"},"_npmVersion":"10.9.2","description":"Vue 3 component for high-performance GIF playback","directories":{},"_nodeVersion":"23.11.0","dependencies":{"@cut.media/gif-player":"workspace:*"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.3.4","vite":"^6.0.0","rollup":"^4.29.0","vitest":"^3.0.0","happy-dom":"^16.5.4","typescript":"^5.3.3","@vue/tsconfig":"^0.7.0","@vue/test-utils":"^2.4.6","rollup-plugin-dts":"^6.1.1","rollup-plugin-vue":"^6.0.0","@vitejs/plugin-vue":"^5.0.0","@rollup/plugin-terser":"^0.4.4","rollup-plugin-postcss":"^4.0.2","@rollup/plugin-commonjs":"^28.0.2","@rollup/plugin-typescript":"^12.0.0","@rollup/plugin-node-resolve":"^16.0.0"},"peerDependencies":{"vue":"^3.0.0"},"_npmOperationalInternal":{"tmp":"tmp/vue-gif-player_1.0.2_1758173844080_0.1105282935767089","host":"s3://npm-registry-packages-npm-production"}},"1.0.3":{"name":"@cut.media/vue-gif-player","version":"1.0.3","keywords":["vue","vue3","gif","player","animation","component"],"author":"","_id":"@cut.media/vue-gif-player@1.0.3","maintainers":[{"name":"airyland","email":"iaminwinter@gmail.com"}],"homepage":"https://github.com/cut-media-hq/vue-gif-player#readme","bugs":{"url":"https://github.com/cut-media-hq/vue-gif-player/issues"},"dist":{"shasum":"26a6a3936398aca0fa45b21da00d80c110003c04","tarball":"https://registry.npmjs.org/@cut.media/vue-gif-player/-/vue-gif-player-1.0.3.tgz","fileCount":5,"integrity":"sha512-6KQklYJghe2FG8BC8uyDCLFv1cep6zRvvOxdM+ASHrZv3kHP3NhkPRzwgUTXYFEwuzJ0kqFz9QbDPfBBiWQ6MQ==","signatures":[{"sig":"MEQCHw4sdatHOWe/t4jlyjUCf20t+YI4mSDXg28ymlpcaz4CIQDffInW2/vzJizfNK6csYTcit5KRrrQ8tW4b18VRIEnIA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":59306},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","module":"dist/index.esm.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.esm.js","require":"./dist/index.js"},"./style.css":"./dist/style.css"},"gitHead":"f7bbbadaa4f4065780564a9cf119784beb73fa41","scripts":{"dev":"vite build --watch","test":"vitest","build":"vite build","test:ui":"vitest --ui","test:coverage":"vitest --coverage"},"_npmUser":{"name":"airyland","email":"iaminwinter@gmail.com"},"repository":{"url":"git+https://github.com/cut-media-hq/vue-gif-player.git","type":"git"},"_npmVersion":"10.9.2","description":"Vue 3 component for high-performance GIF playback","directories":{},"_nodeVersion":"23.11.0","dependencies":{"@cut.media/gif-player":"^1.1.3"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.3.4","vite":"^6.0.0","rollup":"^4.29.0","vitest":"^3.0.0","happy-dom":"^16.5.4","typescript":"^5.3.3","@vue/tsconfig":"^0.7.0","@vue/test-utils":"^2.4.6","rollup-plugin-dts":"^6.1.1","rollup-plugin-vue":"^6.0.0","@vitejs/plugin-vue":"^5.0.0","@rollup/plugin-terser":"^0.4.4","rollup-plugin-postcss":"^4.0.2","@rollup/plugin-commonjs":"^28.0.2","@rollup/plugin-typescript":"^12.0.0","@rollup/plugin-node-resolve":"^16.0.0"},"peerDependencies":{"vue":"^3.0.0"},"_npmOperationalInternal":{"tmp":"tmp/vue-gif-player_1.0.3_1758175354094_0.12318007095459849","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@cut.media/vue-gif-player","version":"1.1.0","description":"Vue 3 component for high-performance GIF playback","type":"module","main":"dist/vue-gif-player.umd.js","module":"dist/vue-gif-player.es.js","types":"dist/index.d.ts","exports":{".":{"import":"./dist/vue-gif-player.es.js","require":"./dist/vue-gif-player.umd.js","types":"./dist/index.d.ts"},"./style.css":"./dist/vue-gif-player.css"},"scripts":{"build":"vite build","dev":"vite build --watch","test":"vitest","test:ui":"vitest --ui","test:coverage":"vitest --coverage"},"keywords":["vue","vue3","gif","player","animation","component"],"author":"","peerDependencies":{"vue":"^3.0.0"},"dependencies":{"@cut.media/gif-player":"^1.1.3"},"devDependencies":{"@rollup/plugin-commonjs":"^28.0.2","@rollup/plugin-node-resolve":"^16.0.0","@rollup/plugin-terser":"^0.4.4","@rollup/plugin-typescript":"^12.0.0","@vitejs/plugin-vue":"^5.0.0","@vue/test-utils":"^2.4.6","@vue/tsconfig":"^0.7.0","happy-dom":"^16.5.4","rollup":"^4.29.0","rollup-plugin-dts":"^6.1.1","rollup-plugin-postcss":"^4.0.2","rollup-plugin-vue":"^6.0.0","typescript":"^5.3.3","vite":"^6.0.0","vite-plugin-dts":"^4.5.4","vitest":"^3.0.0","vue":"^3.3.4"},"repository":{"type":"git","url":"git+https://github.com/cut-media-hq/vue-gif-player.git"},"bugs":{"url":"https://github.com/cut-media-hq/vue-gif-player/issues"},"homepage":"https://github.com/cut-media-hq/vue-gif-player#readme","_id":"@cut.media/vue-gif-player@1.1.0","gitHead":"f7bbbadaa4f4065780564a9cf119784beb73fa41","_nodeVersion":"23.11.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-BO0nhdbQc/y9bkjW3DdjO3aPfxQ359kS/luX28S0C30vTbMPh4tClVDIKAsjPDosD+SXmrUrGumTSvURyhhHGQ==","shasum":"1acfed481a010e950d1af0ab7d08f901a9533c96","tarball":"https://registry.npmjs.org/@cut.media/vue-gif-player/-/vue-gif-player-1.1.0.tgz","fileCount":6,"unpackedSize":55081,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQD0XxCj+kEvcJkx/bajMLmSmgWQCv3bLydEfVak8r52bwIgNy+pu8tQNjAXW+qNMjwnfYQBwZYQt6RbX0JtHeRifDQ="}]},"_npmUser":{"name":"airyland","email":"iaminwinter@gmail.com"},"directories":{},"maintainers":[{"name":"airyland","email":"iaminwinter@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/vue-gif-player_1.1.0_1758210650655_0.12703717518086077"},"_hasShrinkwrap":false}},"time":{"created":"2025-09-18T05:37:23.998Z","modified":"2025-09-18T15:50:51.072Z","1.0.2":"2025-09-18T05:37:24.281Z","1.0.3":"2025-09-18T06:02:34.282Z","1.1.0":"2025-09-18T15:50:50.850Z"},"bugs":{"url":"https://github.com/cut-media-hq/vue-gif-player/issues"},"homepage":"https://github.com/cut-media-hq/vue-gif-player#readme","keywords":["vue","vue3","gif","player","animation","component"],"repository":{"type":"git","url":"git+https://github.com/cut-media-hq/vue-gif-player.git"},"description":"Vue 3 component for high-performance GIF playback","maintainers":[{"name":"airyland","email":"iaminwinter@gmail.com"}],"readme":"# @cut.media/vue-gif-player\n\nVue 3 component for high-performance GIF playback, built on top of [@cut.media/gif-player](https://www.npmjs.com/package/@cut.media/gif-player).\n\nPart of the [Cut.media](https://cut.media) online video editor project.\n\n## Features\n\n- 🎬 **High-performance GIF playback** - Optimized frame rendering\n- 🎮 **Two UI modes** - Simple controls or full-featured player interface\n- 📊 **Metadata extraction** - Get frame count, dimensions, FPS\n- 🖼️ **Frame extraction** - Extract individual frames as images\n- 📱 **Responsive sizing** - Support for various sizing options\n- 🎨 **Customizable UI** - Slots for loading, error, and control states\n- 📡 **Rich events** - Load, play, pause, frame, error events\n- ⏩ **Speed control** - Adjust playback speed (with full controls)\n- 📺 **Fullscreen support** - Native fullscreen mode (with full controls)\n- 🔄 **Timeline scrubbing** - Seek to any frame (with full controls)\n- ⚡ **Vue 3 optimized** - Built with Vue 3 Composition API\n- 📦 **TypeScript support** - Full type definitions included\n\n## Installation\n\n```bash\nnpm install @cut.media/vue-gif-player\n# or\nyarn add @cut.media/vue-gif-player\n# or\npnpm add @cut.media/vue-gif-player\n```\n\n## Usage\n\n### Quick Start - Simple Player\n\n```vue\n<template>\n  <gif-player\n    src=\"/path/to/animation.gif\"\n    :autoplay=\"true\"\n    :loop=\"true\"\n    :width=\"400\"\n    :height=\"300\"\n  />\n</template>\n\n<script setup>\nimport { GifPlayer } from '@cut.media/vue-gif-player'\nimport '@cut.media/vue-gif-player/dist/style.css'\n</script>\n```\n\n### Professional Player with Full Controls\n\nEnable the complete player interface with timeline scrubbing, speed control, and more:\n\n```vue\n<template>\n  <gif-player\n    src=\"/path/to/animation.gif\"\n    :with-controls=\"true\"\n    :autoplay=\"false\"\n    width=\"800\"\n    height=\"450\"\n  />\n</template>\n\n<script setup>\nimport { GifPlayer } from '@cut.media/vue-gif-player'\nimport '@cut.media/vue-gif-player/dist/style.css'\n</script>\n```\n\n### As a Plugin (Global Registration)\n\n```javascript\nimport { createApp } from 'vue'\nimport VueGifPlayer from '@cut.media/vue-gif-player'\nimport '@cut.media/vue-gif-player/dist/style.css'\n\nconst app = createApp(App)\napp.use(VueGifPlayer) // Registers GifPlayer globally\napp.mount('#app')\n```\n\n## Component Props\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `src` | `string` | - | **Required.** URL of the GIF to play |\n| `autoplay` | `boolean` | `false` | Start playing automatically when loaded |\n| `loop` | `boolean` | `true` | Loop the animation |\n| `width` | `number \\| string` | - | Canvas width (number for pixels, string for CSS units) |\n| `height` | `number \\| string` | - | Canvas height (number for pixels, string for CSS units) |\n| `fit` | `string` | `'contain'` | Object fit mode: `contain`, `cover`, `fill`, `none`, `scale-down` |\n| `withControls` | `boolean` | `false` | Enable full player UI with timeline, speed control, etc. |\n| `showControls` | `boolean` | `true` | Show play/pause controls on hover (when withControls is false) |\n| `showProgress` | `boolean` | `false` | Show progress bar (when withControls is false) |\n| `showCenterPlayButton` | `boolean` | `true` | Show large play button in center (when withControls is true) |\n| `hideControlsOnMouseLeave` | `boolean` | `true` | Auto-hide controls when mouse leaves (when withControls is true) |\n| `controlsTimeout` | `number` | `3000` | Time in ms before controls auto-hide (when withControls is true) |\n| `clickToToggle` | `boolean` | `true` | Toggle play/pause on click |\n| `playLabel` | `string` | `'Play'` | Aria label for play button |\n| `pauseLabel` | `string` | `'Pause'` | Aria label for pause button |\n| `preload` | `boolean` | `true` | Load the GIF on mount |\n| `fps` | `number` | - | Override the GIF's native FPS |\n| `speed` | `number` | `1` | Playback speed (0.1 to 10) |\n| `reverse` | `boolean` | `false` | Play animation in reverse |\n\n## Events\n\n| Event | Payload | Description |\n|-------|---------|-------------|\n| `load` | `GifMetadata` | Fired when GIF is loaded with metadata |\n| `play` | - | Fired when playback starts |\n| `pause` | - | Fired when playback is paused |\n| `stop` | - | Fired when playback is stopped |\n| `frame` | `number` | Fired on each frame with frame index |\n| `error` | `string` | Fired when an error occurs |\n| `click` | `MouseEvent` | Fired when canvas is clicked |\n| `speedChange` | `number` | Fired when playback speed changes (with full controls) |\n| `loopChange` | `boolean` | Fired when loop setting changes (with full controls) |\n| `reverseChange` | `boolean` | Fired when reverse playback is toggled (with full controls) |\n\n## Methods\n\nAccess component methods using template refs:\n\n```vue\n<template>\n  <gif-player ref=\"player\" src=\"animation.gif\" />\n  <button @click=\"player.play()\">Play</button>\n</template>\n\n<script setup>\nimport { ref } from 'vue'\n\nconst player = ref(null)\n\n// Available methods:\n// player.value.play()       - Start playback\n// player.value.pause()      - Pause playback\n// player.value.stop()       - Stop and reset\n// player.value.reset()      - Reset to first frame\n// player.value.toggle()     - Toggle play/pause\n// player.value.load()       - Load/reload the GIF\n// player.value.extractFrame(index)  - Extract specific frame\n// player.value.extractFrames()      - Extract all frames\n\n// With full controls (withControls=true), additional methods:\n// player.value.seekToFrame(index)   - Seek to specific frame\n// player.value.setSpeed(speed)      - Set playback speed\n// player.value.toggleReverse()      - Toggle reverse playback\n// player.value.toggleFullscreen()   - Toggle fullscreen mode\n</script>\n```\n\n## Slots\n\n### Loading Slot\n\n```vue\n<gif-player src=\"animation.gif\">\n  <template #loading>\n    <div class=\"custom-loader\">Loading...</div>\n  </template>\n</gif-player>\n```\n\n### Error Slot\n\n```vue\n<gif-player src=\"animation.gif\">\n  <template #error=\"{ error }\">\n    <div class=\"custom-error\">Error: {{ error }}</div>\n  </template>\n</gif-player>\n```\n\n### Control Icons (Simple Mode)\n\n```vue\n<gif-player src=\"animation.gif\">\n  <template #play-icon>\n    <svg><!-- Custom play icon --></svg>\n  </template>\n  <template #pause-icon>\n    <svg><!-- Custom pause icon --></svg>\n  </template>\n</gif-player>\n```\n\n## Advanced Examples\n\n### Extract Frames\n\n```vue\n<script setup>\nimport { ref } from 'vue'\nimport { GifPlayer } from '@cut.media/vue-gif-player'\n\nconst player = ref(null)\n\nconst extractAllFrames = async () => {\n  const frames = await player.value.extractFrames()\n  console.log(`Extracted ${frames.length} frames`)\n\n  // Each frame has canvas, imageData, and blob\n  frames.forEach((frame, index) => {\n    document.body.appendChild(frame.canvas)\n  })\n}\n\nconst extractSingleFrame = async () => {\n  const frame = await player.value.extractFrame(10) // Extract frame 10\n  console.log('Frame extracted:', frame)\n}\n</script>\n```\n\n### Get Metadata\n\n```vue\n<script setup>\nimport { parseGif, calculateFPS } from '@cut.media/vue-gif-player'\n\nconst analyzeGif = async (url) => {\n  const { metadata } = await parseGif(url)\n  console.log('Dimensions:', metadata.width, 'x', metadata.height)\n  console.log('Frames:', metadata.frameCount)\n  console.log('FPS:', calculateFPS(metadata))\n  console.log('Duration:', metadata.duration, 'ms')\n}\n</script>\n```\n\n### Responsive Player\n\n```vue\n<template>\n  <gif-player\n    src=\"animation.gif\"\n    width=\"100%\"\n    height=\"auto\"\n    fit=\"cover\"\n    :autoplay=\"true\"\n    :loop=\"true\"\n  />\n</template>\n```\n\n### Full-Featured Player with All Controls\n\n```vue\n<template>\n  <gif-player\n    ref=\"player\"\n    src=\"animation.gif\"\n    :with-controls=\"true\"\n    width=\"100%\"\n    height=\"500\"\n    fit=\"contain\"\n    :autoplay=\"false\"\n    :loop=\"true\"\n    :show-center-play-button=\"true\"\n    :hide-controls-on-mouse-leave=\"true\"\n    :controls-timeout=\"3000\"\n    :speed=\"1\"\n    :reverse=\"false\"\n    @load=\"onLoad\"\n    @speedChange=\"onSpeedChange\"\n    @loopChange=\"onLoopChange\"\n    @reverseChange=\"onReverseChange\"\n  />\n</template>\n\n<script setup>\nimport { ref } from 'vue'\nimport { GifPlayer } from '@cut.media/vue-gif-player'\n\nconst player = ref(null)\n\nconst onLoad = (metadata) => {\n  console.log('GIF loaded:', metadata)\n  console.log('Duration:', metadata.duration, 'ms')\n  console.log('Frames:', metadata.frameCount)\n}\n\nconst onSpeedChange = (speed) => {\n  console.log('Speed changed to:', speed)\n}\n\nconst onLoopChange = (enabled) => {\n  console.log('Loop:', enabled ? 'enabled' : 'disabled')\n}\n\nconst onReverseChange = (enabled) => {\n  console.log('Reverse:', enabled ? 'enabled' : 'disabled')\n}\n\n// You can also control the player programmatically\nconst playFromStart = () => {\n  player.value.reset()\n  player.value.play()\n}\n\nconst jumpToMiddle = () => {\n  if (player.value.metadata) {\n    const middleFrame = Math.floor(player.value.metadata.frameCount / 2)\n    player.value.seekToFrame(middleFrame)\n  }\n}\n\nconst doubleSpeed = () => {\n  player.value.setSpeed(2)\n}\n</script>\n```\n\n### Comparison: Simple vs Full Controls\n\n```vue\n<template>\n  <!-- Simple player - minimal UI, perfect for backgrounds or decorations -->\n  <gif-player\n    src=\"animation.gif\"\n    :autoplay=\"true\"\n    :show-controls=\"false\"\n  />\n\n  <!-- Full-featured player - complete controls for user interaction -->\n  <gif-player\n    src=\"animation.gif\"\n    :with-controls=\"true\"\n    :autoplay=\"false\"\n  />\n</template>\n```\n\n## Browser Support\n\n- Chrome/Edge (latest)\n- Firefox (latest)\n- Safari (latest)\n- Mobile browsers with canvas support\n\n## Who's Using This\n\n- [GifPlayer.app](https://gifplayer.app) - Online GIF player and editor\n- [Cut.media](https://cut.media) - Online video editor","readmeFilename":"README.md"}