{"_id":"@axiommachine/slide-anywhere-player","_rev":"5-0d355d0198cd6a5dbc70983de11ba7d6","name":"@axiommachine/slide-anywhere-player","dist-tags":{"latest":"0.1.43"},"versions":{"0.1.3":{"name":"@axiommachine/slide-anywhere-player","version":"0.1.3","keywords":["pptx","slides","svg","player","presentation"],"author":{"name":"Zexi Mo"},"license":"MIT","_id":"@axiommachine/slide-anywhere-player@0.1.3","maintainers":[{"name":"sunzhongshan","email":"sunzhongshan1988@gmail.com"}],"dist":{"shasum":"c28969a4691b0e3debdd72ac54979038dd09f072","tarball":"https://registry.npmjs.org/@axiommachine/slide-anywhere-player/-/slide-anywhere-player-0.1.3.tgz","fileCount":11,"integrity":"sha512-BxUTQLYG2RHzKuiMPFAFUn1izdmQG48OcSw4jQBgnrLbwgM50Hytsc6UPnJ4zhVd4HvpLvd+mgwONaGK5BUrFw==","signatures":[{"sig":"MEYCIQDx73JnBeRfVC7URV1evVfycFJ0d1/VwFtbNjNm4NJluQIhAPiMfQNVguHvj2ycj0fNrF3ER6MG/rn2Wr0Y/anX8vq7","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":59327},"main":"dist/slide-anywhere-player.cjs","type":"module","types":"dist/index.d.ts","module":"dist/slide-anywhere-player.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/slide-anywhere-player.js","require":"./dist/slide-anywhere-player.cjs"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js","require":"./dist/react.cjs"},"./style.css":"./dist/style.css","./theme.css":"./dist/theme.css","./theme-dark.css":"./dist/theme-dark.css"},"gitHead":"11089ec3786f3aaa8818f0015af59bd1eccc0293","scripts":{"dev":"vite","build":"node scripts/clean-dist.mjs && tsc && vite build && node scripts/prepare-css.mjs","preview":"vite preview"},"_npmUser":{"name":"sunzhongshan","email":"sunzhongshan1988@gmail.com"},"_npmVersion":"11.12.1","description":"Browser player for slide-anywhere PPTX bundles that renders SVG slides with animations, video, and audio","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.15.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^6.0.0","react":"^19.2.0","typescript":"^5.5.0","@types/react":"^19.2.2","vite-plugin-dts":"^4.0.0"},"peerDependencies":{"react":">=18"},"peerDependenciesMeta":{"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/slide-anywhere-player_0.1.3_1776860335383_0.44063603296580833","host":"s3://npm-registry-packages-npm-production"}},"0.1.4":{"name":"@axiommachine/slide-anywhere-player","version":"0.1.4","keywords":["pptx","slides","svg","player","presentation"],"author":{"name":"Zexi Mo"},"license":"MIT","_id":"@axiommachine/slide-anywhere-player@0.1.4","maintainers":[{"name":"sunzhongshan","email":"sunzhongshan1988@gmail.com"}],"dist":{"shasum":"4917972ce0d0fd29467944eea5eeb28a229c4bc7","tarball":"https://registry.npmjs.org/@axiommachine/slide-anywhere-player/-/slide-anywhere-player-0.1.4.tgz","fileCount":11,"integrity":"sha512-VT8fZ7OV2niI1sChbjMrtA33kBDjk79on94gmxO770e0SYvxKOKRNaUl3T34gkg/LfY09kD078qJaPZPR/Yfbw==","signatures":[{"sig":"MEUCIQDEzozYuRjNBaTxebwbbVv4EBumwxx1mM78/+cbad2+qwIgfH9tfby4fluO1fAi9Ez4Iymrqe11yttcEu3QVIjwOCk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":64055},"main":"dist/slide-anywhere-player.cjs","type":"module","types":"dist/index.d.ts","module":"dist/slide-anywhere-player.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/slide-anywhere-player.js","require":"./dist/slide-anywhere-player.cjs"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js","require":"./dist/react.cjs"},"./style.css":"./dist/style.css","./theme.css":"./dist/theme.css","./theme-dark.css":"./dist/theme-dark.css"},"gitHead":"390bc9f09c40ef1094e79f2536daee96f3474a3c","scripts":{"dev":"vite","build":"node scripts/clean-dist.mjs && tsc && vite build && node scripts/prepare-css.mjs","preview":"vite preview"},"_npmUser":{"name":"sunzhongshan","email":"sunzhongshan1988@gmail.com"},"_npmVersion":"11.12.1","description":"Browser player for slide-anywhere PPTX bundles that renders SVG slides with animations, video, and audio","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.15.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^6.0.0","react":"^19.2.0","typescript":"^5.5.0","@types/react":"^19.2.2","vite-plugin-dts":"^4.0.0"},"peerDependencies":{"react":">=18"},"peerDependenciesMeta":{"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/slide-anywhere-player_0.1.4_1776929948569_0.08500810490179322","host":"s3://npm-registry-packages-npm-production"}},"0.1.41":{"name":"@axiommachine/slide-anywhere-player","version":"0.1.41","keywords":["pptx","slides","svg","player","presentation"],"author":{"name":"Zexi Mo"},"license":"MIT","_id":"@axiommachine/slide-anywhere-player@0.1.41","maintainers":[{"name":"sunzhongshan","email":"sunzhongshan1988@gmail.com"}],"dist":{"shasum":"886bc3023942b894af089286f0f492f26a4ff660","tarball":"https://registry.npmjs.org/@axiommachine/slide-anywhere-player/-/slide-anywhere-player-0.1.41.tgz","fileCount":11,"integrity":"sha512-gfN/LwDcoXcrPAtDwdhNi0xQERO5nE6uzWZCqk6wWl4yDYjfQa3/yLa1pDUauP52NpSyP9obKt3yTN5t1N2aCA==","signatures":[{"sig":"MEUCIQCqsWwN7lCDvf7MPzXbJm8KPixB23S15BhRBSfC3wVIIQIgOsFu3ZqayE1HeF9NQYpIAGLC3RmAMhCbuIvMqqJJksM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":69955},"main":"dist/slide-anywhere-player.cjs","type":"module","types":"dist/index.d.ts","module":"dist/slide-anywhere-player.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/slide-anywhere-player.js","require":"./dist/slide-anywhere-player.cjs"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js","require":"./dist/react.cjs"},"./style.css":"./dist/style.css","./theme.css":"./dist/theme.css","./theme-dark.css":"./dist/theme-dark.css"},"gitHead":"37f9db5ce2b23e1a0bea5ec2139480844f9910a6","scripts":{"dev":"vite","build":"node scripts/clean-dist.mjs && tsc && vite build && node scripts/prepare-css.mjs","preview":"vite preview"},"_npmUser":{"name":"sunzhongshan","email":"sunzhongshan1988@gmail.com"},"_npmVersion":"11.12.1","description":"Browser player for slide-anywhere PPTX bundles that renders SVG slides with animations, video, and audio","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.15.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^6.0.0","react":"^19.2.0","typescript":"^5.5.0","@types/react":"^19.2.2","vite-plugin-dts":"^4.0.0"},"peerDependencies":{"react":">=18"},"peerDependenciesMeta":{"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/slide-anywhere-player_0.1.41_1778489243175_0.05971811708601127","host":"s3://npm-registry-packages-npm-production"}},"0.1.42":{"name":"@axiommachine/slide-anywhere-player","version":"0.1.42","keywords":["pptx","slides","svg","player","presentation"],"author":{"name":"Zexi Mo"},"license":"MIT","_id":"@axiommachine/slide-anywhere-player@0.1.42","maintainers":[{"name":"sunzhongshan","email":"sunzhongshan1988@gmail.com"}],"dist":{"shasum":"c5b8af7520bfca6a68129bfd10e15e3091096a99","tarball":"https://registry.npmjs.org/@axiommachine/slide-anywhere-player/-/slide-anywhere-player-0.1.42.tgz","fileCount":11,"integrity":"sha512-0xtICKRieEH5HkoaKN5PEK0MEPIJlCY04GC90ne8Qth6MVBFjmpotNtRxzVwvII34BhZ2P72JcqAfdPFgTueRw==","signatures":[{"sig":"MEUCIQCtO6rZ7HMzV2hOQgi4Z58IPc2Q9AAZXCp0+ZvgA3Ks6QIgMhUC+Ke6W+suN5O9nnfugi5JS1DPRe0deglay+JAxA8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":69955},"main":"dist/slide-anywhere-player.cjs","type":"module","types":"dist/index.d.ts","module":"dist/slide-anywhere-player.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/slide-anywhere-player.js","require":"./dist/slide-anywhere-player.cjs"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js","require":"./dist/react.cjs"},"./style.css":"./dist/style.css","./theme.css":"./dist/theme.css","./theme-dark.css":"./dist/theme-dark.css"},"gitHead":"d97029f3e21982834165d9491bc637684e89991d","scripts":{"dev":"vite","build":"node scripts/clean-dist.mjs && tsc && vite build && node scripts/prepare-css.mjs","preview":"vite preview"},"_npmUser":{"name":"sunzhongshan","email":"sunzhongshan1988@gmail.com"},"_npmVersion":"11.12.1","description":"Browser player for slide-anywhere PPTX bundles that renders SVG slides with animations, video, and audio","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.15.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^6.0.0","react":"^19.2.0","typescript":"^5.5.0","@types/react":"^19.2.2","vite-plugin-dts":"^4.0.0"},"peerDependencies":{"react":">=18"},"peerDependenciesMeta":{"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/slide-anywhere-player_0.1.42_1779069588502_0.0833767915585868","host":"s3://npm-registry-packages-npm-production"}},"0.1.43":{"_id":"@axiommachine/slide-anywhere-player@0.1.43","dist":{"shasum":"f5b956c56b005613dd74b268f8e19fc31aeb53ca","tarball":"https://registry.npmjs.org/@axiommachine/slide-anywhere-player/-/slide-anywhere-player-0.1.43.tgz","fileCount":11,"integrity":"sha512-v1E+WPkndF080RoHGvH3K8jJn1qDChV8xfljHNJo1XB5vaQqMCSjMp5WLN4wXhpIWx/l+lk0HlKZe7b9anczhg==","signatures":[{"sig":"MEUCIQCxGNuVMyc3YS/TsijssMrbth4+xFeDJeBqzP/Cc/12FAIgdcTIInNV3JVCHnfltAiN1QCTziRqsi/3g6R0I4E+k9k=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCe++FGwwLKDxZttEm4LDmq4z9pcxoFwi4FWvVjv21FowIhAOVzpFS9xZd9ILD2qw1IeYahFR5oZcnyYt1cUBpJKNt6"}],"unpackedSize":99714},"main":"dist/slide-anywhere-player.cjs","name":"@axiommachine/slide-anywhere-player","type":"module","types":"dist/index.d.ts","author":{"name":"Zexi Mo"},"module":"dist/slide-anywhere-player.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/slide-anywhere-player.js","require":"./dist/slide-anywhere-player.cjs"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js","require":"./dist/react.cjs"},"./style.css":"./dist/style.css","./theme.css":"./dist/theme.css","./theme-dark.css":"./dist/theme-dark.css"},"gitHead":"70dc75fa3105dd4ccd4928df882707aead9de25b","license":"MIT","scripts":{"dev":"vite","build":"node scripts/clean-dist.mjs && tsc && vite build && node scripts/prepare-css.mjs","preview":"vite preview"},"version":"0.1.43","_npmUser":{"name":"sunzhongshan","email":"sunzhongshan1988@gmail.com"},"keywords":["pptx","slides","svg","player","presentation"],"_npmVersion":"11.12.1","description":"Browser player for slide-anywhere PPTX bundles that renders SVG slides with animations, video, and audio","directories":{},"maintainers":[{"name":"sunzhongshan","email":"sunzhongshan1988@gmail.com"}],"sideEffects":["*.css"],"_nodeVersion":"24.15.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^6.0.0","react":"^19.2.0","typescript":"^5.5.0","@types/react":"^19.2.2","vite-plugin-dts":"^4.0.0"},"peerDependencies":{"react":">=18"},"peerDependenciesMeta":{"react":{"optional":true}},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/slide-anywhere-player_0.1.43_1789530607413_0.025864091053867"}}},"time":{"created":"2026-04-22T12:18:55.243Z","modified":"2026-09-16T03:50:07.692Z","0.1.3":"2026-04-22T12:18:55.543Z","0.1.4":"2026-04-23T07:39:08.703Z","0.1.41":"2026-05-11T08:47:23.340Z","0.1.42":"2026-05-18T01:59:48.657Z","0.1.43":"2026-09-16T03:50:07.507Z"},"author":{"name":"Zexi Mo"},"license":"MIT","keywords":["pptx","slides","svg","player","presentation"],"description":"Browser player for slide-anywhere PPTX bundles that renders SVG slides with animations, video, and audio","maintainers":[{"name":"sunzhongshan","email":"sunzhongshan1988@gmail.com"}],"readme":"# @axiommachine/slide-anywhere-player\n\n`@axiommachine/slide-anywhere-player` is a lightweight browser player for slide bundles generated by `slide-anywhere-rs`.\nIt works in plain browser apps and also ships a React wrapper via `@axiommachine/slide-anywhere-player/react`.\n\n## Install\n\n```bash\nnpm install @axiommachine/slide-anywhere-player\n```\n\n## What `baseUrl` Should Point To\n\n`baseUrl` must point at a published bundle directory that contains:\n\n```text\nmanifest.json\nslides/*\nmedia/*\n```\n\nExample:\n\n```text\nhttps://cdn.example.com/ai/pptx/<task_id>/bundle/\n```\n\n## 播放流程实现\n\n该例子展示了一个基于浏览器播放由 WeMeet PPTX 转换重渲染系统转换的 PPTX 文件，首先在 WEB 页面集成 `slide-anywhere-player` 的 npm 包，然后将转换服务产出的 `bundle_base_url` 作为播放器的数据入口传入。播放器会从该目录加载 `manifest.json`，再根据 manifest 中的幻灯片、媒体资源和动画脚本信息按页渲染 SVG，并在浏览器端完成翻页、动画触发、媒体播放、缓存和预加载。\n\n整体流程如下：\n\n1. 业务侧将 PPTX 文件提交给 WeMeet PPTX 转换重渲染系统，转换服务解析原始 PPTX，生成可被浏览器直接读取的播放 bundle。\n2. bundle 发布到 CDN 或静态资源服务后，会形成一个 `bundle_base_url`，该目录下包含 `manifest.json`、`slides/*`、`media/*` 等播放资源。\n3. WEB 页面安装并引入 `@axiommachine/slide-anywhere-player`，同时引入结构样式 `style.css` 和默认主题 `theme.css`。\n4. 页面创建播放器挂载容器，并用 `bundle_base_url` 初始化 `SlidePlayer`。\n5. 播放器启动后拉取 `manifest.json`，读取总页数、每页 SVG 地址、媒体映射和动画脚本。\n6. 播放器加载当前页 SVG，修正 SVG 内部相对资源路径，嵌入音视频等媒体资源，并按 SVG `viewBox` 自动保持原始幻灯片比例。\n7. 用户点击下一页、上一页、输入页码或使用键盘操作时，播放器优先执行当前页剩余的点击触发动画；当前页动画执行完后，再切换到目标页。\n8. 每次页面切换后，播放器会触发 `slidechange` 事件，并按 `prefetchAhead` 配置预加载后续页面资源，减少连续翻页时的等待。\n\nVanilla implementation:\n\n```html\n<div id=\"player\"></div>\n```\n\n```ts\nimport { SlidePlayer } from \"@axiommachine/slide-anywhere-player\";\nimport \"@axiommachine/slide-anywhere-player/style.css\";\nimport \"@axiommachine/slide-anywhere-player/theme.css\";\n\nconst bundleBaseUrl = \"https://cdn.example.com/ai/pptx/<task_id>/bundle/\";\n\nconst player = new SlidePlayer({\n  container: \"#player\",\n  baseUrl: bundleBaseUrl,\n  controls: true,\n  keyboard: true,\n  clickToAdvance: true,\n  cache: true,\n  prefetchAhead: 2,\n});\n\nplayer.on(\"ready\", ({ currentPage, totalPages }) => {\n  console.log(`ready: ${currentPage}/${totalPages}`);\n});\n\nplayer.on(\"slidechange\", ({ currentPage, totalPages }) => {\n  console.log(`slide changed: ${currentPage}/${totalPages}`);\n});\n\nplayer.on(\"error\", ({ message }) => {\n  console.error(\"player error:\", message);\n});\n```\n\nReact implementation:\n\n```tsx\nimport { useState } from \"react\";\nimport { SlidePlayer } from \"@axiommachine/slide-anywhere-player/react\";\nimport \"@axiommachine/slide-anywhere-player/style.css\";\nimport \"@axiommachine/slide-anywhere-player/theme.css\";\n\nexport function WeMeetDeckPlayer() {\n  const [page, setPage] = useState(1);\n  const bundleBaseUrl = \"https://cdn.example.com/ai/pptx/<task_id>/bundle/\";\n\n  return (\n    <SlidePlayer\n      baseUrl={bundleBaseUrl}\n      page={page}\n      controls\n      keyboard\n      clickToAdvance\n      onReady={({ currentPage }) => {\n        setPage(currentPage);\n      }}\n      onSlideChange={({ currentPage }) => {\n        setPage(currentPage);\n      }}\n      onError={({ message }) => {\n        console.error(\"player error:\", message);\n      }}\n    />\n  );\n}\n```\n\n## Vanilla Usage\n\n```ts\nimport { SlidePlayer } from \"@axiommachine/slide-anywhere-player\";\nimport \"@axiommachine/slide-anywhere-player/style.css\";\nimport \"@axiommachine/slide-anywhere-player/theme.css\";\n\nconst player = new SlidePlayer({\n  container: \"#player\",\n  baseUrl: \"https://cdn.example.com/ai/pptx/<task_id>/bundle/\",\n  controls: true,\n  keyboard: true,\n});\n```\n\n## React Usage\n\n```tsx\nimport { SlidePlayer } from \"@axiommachine/slide-anywhere-player/react\";\nimport \"@axiommachine/slide-anywhere-player/style.css\";\nimport \"@axiommachine/slide-anywhere-player/theme.css\";\n\nexport function Deck() {\n  return (\n    <SlidePlayer\n      baseUrl=\"https://cdn.example.com/ai/pptx/<task_id>/bundle/\"\n      controls\n      keyboard\n    />\n  );\n}\n```\n\n## Custom Page Images with Video Overlays\n\nPass `slideImages` to use images exported by PowerPoint or your own renderer as\npage backgrounds. The player still loads the converted bundle's manifest and\noverlays its video/audio elements using the original slide coordinates and media\nscripts. This lets you preserve the exported page appearance while playing the\nvideos extracted from the same PPTX.\n\n### Default Usage: Images without Width or Height\n\nProvide `baseUrl` and `slideImages`; **you do not need to pass `slideSize`**.\nFull HTTPS image URLs are supported and used directly, without prepending\n`baseUrl`. The images may be hosted separately from the converted bundle.\n\nFor each replaced page, the player:\n\n1. Reads the bundle manifest for page order, media files, shape coordinates, and\n   playback scripts.\n2. Fetches that page's original SVG only to read its page dimensions. The SVG\n   stays detached: its artwork is not rendered, and its images/fonts are not\n   loaded.\n3. Displays your image as the page and overlays the bundle's video/audio at the\n   original coordinates. The image and media share the same scaling when the\n   player resizes or enters fullscreen.\n\nKeep the bundle's `manifest.json`, corresponding `slides/*`, and `media/*`\naccessible when using this default mode. Use images exported from the same deck\nin the same page order and aspect ratio; their pixel resolution may differ from\nthe original slide dimensions.\n\nVanilla example (no width or height required):\n\n```ts\nimport { SlidePlayer } from \"@axiommachine/slide-anywhere-player\";\nimport \"@axiommachine/slide-anywhere-player/style.css\";\nimport \"@axiommachine/slide-anywhere-player/theme.css\";\n\nconst player = new SlidePlayer({\n  container: \"#player\",\n  baseUrl: \"https://cdn.example.com/deck/bundle/\",\n  slideImages: [\n    \"https://images.example.com/deck/page-1.png\",\n    \"https://images.example.com/deck/page-2.png\",\n    \"https://images.example.com/deck/page-3.png\",\n  ],\n  controls: true,\n  keyboard: true,\n  clickToAdvance: true,\n});\n\nplayer.on(\"error\", ({ message }) => console.error(message));\n```\n\nReact example:\n\n```tsx\nimport { useState } from \"react\";\nimport { SlidePlayer } from \"@axiommachine/slide-anywhere-player/react\";\nimport \"@axiommachine/slide-anywhere-player/style.css\";\nimport \"@axiommachine/slide-anywhere-player/theme.css\";\n\n// Keep this reference stable; changing it recreates the player.\nconst slideImages = [\n  \"https://images.example.com/deck/page-1.png\",\n  \"https://images.example.com/deck/page-2.png\",\n] as const;\n\nexport function ImageDeck() {\n  const [page, setPage] = useState(1);\n\n  return (\n    <SlidePlayer\n      baseUrl=\"https://cdn.example.com/deck/bundle/\"\n      slideImages={slideImages}\n      page={page}\n      controls\n      keyboard\n      clickToAdvance\n      onSlideChange={({ currentPage }) => setPage(currentPage)}\n      onError={({ message }) => console.error(message)}\n    />\n  );\n}\n```\n\n### Navigation and Playback\n\nReplacing page images preserves page order, page count, previous/next controls,\npage-number input, keyboard navigation, `clickToAdvance`, `autoPlay`, imperative\nnavigation (`next()`, `prev()`, `goToPage()`), React's controlled `page`, and\n`slidechange` events.\n\nThere is one intentional difference in click progression: a static page image\ncannot run separate shape/text animations, so those animation steps are skipped\nand do not consume clicks. Media playback triggers are retained. If the page has\na pending click-triggered video action, `next()` still runs that action before\nadvancing to the next page. Clicking a video's native controls does not advance\nthe slide. Navigating away pauses and removes the previous page's media.\n\n### Optional: Skip SVG Requests Entirely\n\nIf you already know the original PPT page dimensions, provide `slideSize` to\navoid even the geometry-only SVG requests on replaced pages:\n\n```ts\nconst player = new SlidePlayer({\n  container: \"#player\",\n  baseUrl: \"https://cdn.example.com/deck/bundle/\",\n  slideImages: [\"https://images.example.com/deck/page-1.png\"],\n  // Original PPT dimensions at 96 dpi, not the exported image resolution.\n  // Example: 13⅓ × 7½ inches. A 2560 × 1440 export still uses this slideSize.\n  slideSize: { width: 1280, height: 720 },\n});\n```\n\nReact accepts the same optional `slideSize` prop. Keep its object reference\nstable, as changing it recreates the player.\n\n### Image and Bundle Requirements\n\n- `slideImages` follows **manifest slide order**, regardless of `slide_id`:\n  index `0` replaces page 1. Missing entries, `null`, `undefined`, and `\"\"` keep\n  that page's converted SVG. Entries beyond the number of slides are ignored.\n- Full HTTPS image URLs are used as-is; relative image URLs such as\n  `../images/page-3.png` resolve against `baseUrl`. `data:` and `blob:` image URLs\n  are also supported. Keep blob URLs valid until the player is destroyed or the\n  images are replaced. Image URLs must be accessible from the browser.\n- `slideSize` describes the **original PPT coordinate system at 96 dpi**, not\n  the exported image resolution. One inch is 96 units. Both dimensions must be\n  finite and positive. The same size applies to every replaced page; pages using\n  SVG still use their own SVG geometry.\n- When `slideSize` is supplied, replaced pages do not fetch their SVG. When it\n  is omitted, the player reads the original SVG only to determine page geometry;\n  it does not render the SVG or fetch its dependent images/fonts. This is useful\n  when you do not know the original PPT dimensions.\n- Each image fills the original page rectangle and resizes with the video\n  overlays. Use an image of the same slide and aspect ratio to keep its content\n  aligned with the media. A different image aspect ratio will be stretched.\n- Replaced pages retain media playback scripts, including click-triggered media\n  actions. Shape/text animations are skipped because the image is a flattened\n  page; they do not consume navigation clicks. Animations on SVG pages continue\n  to work as usual. Existing media positioning/playback limitations still apply.\n- A replacement image that fails to load emits `error` (`onError` in React);\n  the player does not silently switch that page back to SVG.\n- `prefetchAhead` also preloads replacement images. Their caching uses the\n  browser's normal image/HTTP cache, rather than the bundle Cache Storage cache\n  controlled by `cache`.\n\n## Custom Navigation\n\nYou can hide the built-in controls and drive the player from your own UI.\n\n### Controlled Page in React\n\n```tsx\nimport { useState } from \"react\";\nimport { SlidePlayer } from \"@axiommachine/slide-anywhere-player/react\";\nimport \"@axiommachine/slide-anywhere-player/style.css\";\nimport \"@axiommachine/slide-anywhere-player/theme.css\";\n\nexport function Deck() {\n  const [page, setPage] = useState(1);\n\n  return (\n    <>\n      <button onClick={() => setPage((value) => Math.max(1, value - 1))}>\n        Prev\n      </button>\n      <button onClick={() => setPage((value) => value + 1)}>Next</button>\n      <SlidePlayer\n        page={page}\n        baseUrl=\"https://cdn.example.com/ai/pptx/<task_id>/bundle/\"\n        controls={false}\n        onSlideChange={({ currentPage }) => {\n          setPage(currentPage);\n        }}\n      />\n    </>\n  );\n}\n```\n\n## React Ref Usage\n\n```tsx\nimport { useRef } from \"react\";\nimport {\n  SlidePlayer,\n  type SlidePlayerRef,\n} from \"@axiommachine/slide-anywhere-player/react\";\nimport \"@axiommachine/slide-anywhere-player/style.css\";\nimport \"@axiommachine/slide-anywhere-player/theme.css\";\n\nexport function Deck() {\n  const ref = useRef<SlidePlayerRef>(null);\n\n  return (\n    <>\n      <button onClick={() => ref.current?.next()}>Next</button>\n      <SlidePlayer\n        ref={ref}\n        baseUrl=\"https://cdn.example.com/ai/pptx/<task_id>/bundle/\"\n      />\n    </>\n  );\n}\n```\n\nThe React ref exposes:\n\n- `next()`\n- `prev()`\n- `goToPage(page)`\n- `getCurrentPage()`\n- `getTotalPages()`\n\n## Vanilla Events and Imperative Control\n\n```ts\nimport { SlidePlayer } from \"@axiommachine/slide-anywhere-player\";\nimport \"@axiommachine/slide-anywhere-player/style.css\";\nimport \"@axiommachine/slide-anywhere-player/theme.css\";\n\nconst player = new SlidePlayer({\n  container: \"#player\",\n  baseUrl: \"https://cdn.example.com/ai/pptx/<task_id>/bundle/\",\n  controls: false,\n});\n\nplayer.on(\"ready\", ({ currentPage, totalPages }) => {\n  console.log(\"ready\", currentPage, totalPages);\n});\n\nplayer.on(\"slidechange\", ({ currentPage, totalPages }) => {\n  console.log(\"slide changed\", currentPage, totalPages);\n});\n\ndocument.querySelector(\"#jump-5\")?.addEventListener(\"click\", () => {\n  player.goToPage(5);\n});\n```\n\n## Core Options\n\n- `container`: HTMLElement or CSS selector, vanilla API only\n- `baseUrl`: bundle base URL\n- `manifest`: optional preloaded manifest JSON\n- `slideImages`: optional replacement image URLs in manifest slide order; empty entries retain SVG\n- `slideSize`: optional original PPT page dimensions at 96 dpi; omit to read dimensions from bundle SVGs without rendering them\n- `startSlide`: 1-based starting slide number\n- `autoPlay`: auto-advance interval in milliseconds\n- `controls`: show previous/next controls\n- `keyboard`: enable keyboard navigation\n- `counter`: show slide counter\n- `cache`: cache bundle resources in Cache Storage when available\n- `prefetchAhead`: number of slides to prefetch in the background\n\n## React Props\n\nIn addition to the core player options above, the React wrapper also supports:\n\n- `page`: controlled current page number, 1-based\n- `className`\n- `style`\n- `onReady`\n- `onSlideChange`\n- `onAnimationStart`\n- `onAnimationEnd`\n- `onError`\n\n## Events\n\nThe player emits:\n\n- `ready`\n- `slidechange`\n- `animationstart`\n- `animationend`\n- `error`\n\n`ready` and `slidechange` include:\n\n- `slideIndex`\n- `slideId`\n- `currentPage`\n- `totalPages`\n\n## Exports\n\n```ts\nimport { SlidePlayer } from \"@axiommachine/slide-anywhere-player\";\nimport { SlidePlayer as ReactSlidePlayer } from \"@axiommachine/slide-anywhere-player/react\";\nimport \"@axiommachine/slide-anywhere-player/style.css\";\nimport \"@axiommachine/slide-anywhere-player/theme.css\";\n```\n\n## Styling\n\n`style.css` is the structural layer. It gives the player its layout, media sizing, controls layout, and responsive stage behavior without forcing a heavy visual skin.\n\n`theme.css` and `theme-dark.css` both point to the bundled dark theme overrides.\n\nThe stage keeps the slide's original aspect ratio and automatically rescales when the container changes size.\n\nUseful CSS variables include:\n\n- `--sa-bg`\n- `--sa-radius`\n- `--sa-font-family`\n- `--sa-stage-bg`\n- `--sa-control-bg`\n- `--sa-control-color`\n- `--sa-counter-bg`\n- `--sa-counter-color`\n- `--sa-btn-hover-bg`\n- `--sa-focus-ring`\n- `--sa-media-bg`\n- `--sa-media-radius`\n\nExample:\n\n```css\n.my-deck {\n  --sa-bg: transparent;\n  --sa-radius: 0;\n  --sa-stage-bg: #f8fafc;\n  --sa-control-bg: rgba(255, 255, 255, 0.88);\n  --sa-control-color: #0f172a;\n}\n```\n\n## Notes\n\n- The package expects required bundle assets to be readable from the browser, including `manifest.json` and `media/*`; replaced pages can omit `slides/*` when `slideSize` is supplied\n- The player supports caching and background prefetch to improve slide navigation\n- The React wrapper is a thin layer around the same core player used by the vanilla API\n- `onReady` and `onSlideChange` both include `currentPage` and `totalPages`\n- The player reads the actual slide aspect ratio from the SVG viewBox, or from `slideSize` for replaced pages, and keeps that ratio when the container resizes\n- `style.css` contains the structural styles and a light default skin\n- `theme.css` and `theme-dark.css` both point to the bundled dark theme overrides\n","readmeFilename":"README.md"}