{"_id":"@ansonphong/360-viewer-library","_rev":"2-295e7047ece55742c393b36055960fc2","name":"@ansonphong/360-viewer-library","dist-tags":{"latest":"6.0.1"},"versions":{"6.0.0":{"name":"@ansonphong/360-viewer-library","version":"6.0.0","license":"MIT","_id":"@ansonphong/360-viewer-library@6.0.0","maintainers":[{"name":"ansonphong","email":"phong@phong.com"}],"dist":{"shasum":"26c64072d93c62094a68b8df5e644362f1136aea","tarball":"https://registry.npmjs.org/@ansonphong/360-viewer-library/-/360-viewer-library-6.0.0.tgz","fileCount":6,"integrity":"sha512-69krxcLzggz1F7a3V52qglTUHCg1eByhrwKt3fVWAarLsAOdx95ElAxXe96DhOs57HA3VcEfrBriCb/AJ+Zrug==","signatures":[{"sig":"MEUCID0PZE/dKdXSwObCJbtyE96ey2VcI/3a4wgThrHi0P9oAiEAjD75zLKEDnzWGdctOHtdwxEp/Tn3ec1Y4QZUW1TtUME=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":255871},"main":"./dist/viewer-library.umd.js","style":"./dist/viewer-library.css","module":"./dist/viewer-library.esm.js","exports":{".":{"import":"./dist/viewer-library.esm.js","require":"./dist/viewer-library.umd.js"},"./viewer-library.css":"./dist/viewer-library.css"},"gitHead":"6cc7ef71ea0c95dfc70a9768b3cb2592cda11248","scripts":{"build":"node build.mjs","build:types":"tsc -p tsconfig.json"},"_npmUser":{"name":"ansonphong","email":"phong@phong.com"},"_npmVersion":"10.9.4","description":"Batteries-included sidebar/toolbar/info-bar for 360 panorama experiences","directories":{},"_nodeVersion":"22.22.1","dependencies":{"@ansonphong/360-viewer":"^6.0.0"},"_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.0","typescript":"^5.7.0"},"_npmOperationalInternal":{"tmp":"tmp/360-viewer-library_6.0.0_1778850577340_0.40550088609753243","host":"s3://npm-registry-packages-npm-production"}},"6.0.1":{"name":"@ansonphong/360-viewer-library","version":"6.0.1","description":"Batteries-included sidebar / toolbar / info-bar chrome for 360 panorama experiences — drop-in UI for @ansonphong/360-viewer","license":"MIT","author":{"name":"Phong","url":"https://phong.com"},"homepage":"https://github.com/ansonphong/360-VIEWER#readme","repository":{"type":"git","url":"git+https://github.com/ansonphong/360-VIEWER.git"},"bugs":{"url":"https://github.com/ansonphong/360-VIEWER/issues"},"keywords":["360","panorama","viewer","gallery","sidebar","toolbar","ui","threejs","webgl","immersive","photography"],"main":"./dist/viewer-library.umd.js","module":"./dist/viewer-library.esm.js","style":"./dist/viewer-library.css","exports":{".":{"import":"./dist/viewer-library.esm.js","require":"./dist/viewer-library.umd.js"},"./viewer-library.css":"./dist/viewer-library.css"},"dependencies":{"@ansonphong/360-viewer":"^6.0.0"},"scripts":{"build":"node build.mjs","build:types":"tsc -p tsconfig.json"},"devDependencies":{"esbuild":"^0.25.0","typescript":"^5.7.0"},"_id":"@ansonphong/360-viewer-library@6.0.1","gitHead":"6cc7ef71ea0c95dfc70a9768b3cb2592cda11248","_nodeVersion":"22.22.1","_npmVersion":"10.9.4","dist":{"integrity":"sha512-/hIWX1MO5TUkvviMK6/bvMwncdenIC1xKWS2ewAOTd+BARpG+Xnrt4HivZXoRNVlA3ihZE3ftWDIQfePQtEffA==","shasum":"72393561b1a71af45ba3a73b21cfe97e88e578d1","tarball":"https://registry.npmjs.org/@ansonphong/360-viewer-library/-/360-viewer-library-6.0.1.tgz","fileCount":8,"unpackedSize":275911,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDhm47gqUEcYxM26OFVhLyjR1a6/dqo06HZzwJgjK342gIgMmUgIBxcQtudVCA8B4r2p3ihKLQscr/FbgsgaJ+KWkM="}]},"_npmUser":{"name":"ansonphong","email":"phong@phong.com"},"directories":{},"maintainers":[{"name":"ansonphong","email":"phong@phong.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/360-viewer-library_6.0.1_1779036666653_0.8330225207334361"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-15T13:09:37.264Z","modified":"2026-05-17T16:51:06.933Z","6.0.0":"2026-05-15T13:09:38.724Z","6.0.1":"2026-05-17T16:51:06.811Z"},"license":"MIT","description":"Batteries-included sidebar / toolbar / info-bar chrome for 360 panorama experiences — drop-in UI for @ansonphong/360-viewer","maintainers":[{"name":"ansonphong","email":"phong@phong.com"}],"readme":"# @ansonphong/360-viewer-library\n\n**Batteries-included sidebar / toolbar / info-bar chrome for 360° panorama experiences.**\n\nDrop-in UI layer that sits on top of [`@ansonphong/360-viewer`](https://www.npmjs.com/package/@ansonphong/360-viewer) — adds section-based browsing, toolbar with controls, glassmorphic info bar, help modal, deep-linking, theme toggle, and a slot/decorator extension system. No framework dependencies.\n\n[![npm version](https://img.shields.io/npm/v/@ansonphong/360-viewer-library?color=blue)](https://www.npmjs.com/package/@ansonphong/360-viewer-library)\n[![npm downloads](https://img.shields.io/npm/dm/@ansonphong/360-viewer-library?color=blue)](https://www.npmjs.com/package/@ansonphong/360-viewer-library)\n[![License: MIT](https://img.shields.io/badge/license-MIT-green)](https://github.com/ansonphong/360-VIEWER/blob/master/LICENSE)\n[![Engine](https://img.shields.io/badge/engine-%40ansonphong%2F360--viewer%20%5E6.0.0-blue)](https://www.npmjs.com/package/@ansonphong/360-viewer)\n[![Bundle size](https://img.shields.io/badge/library--ui-25KB-brightgreen)](https://github.com/ansonphong/360-VIEWER)\n\n**[Live demo →](https://360.phong.com)** · **[Full docs →](https://github.com/ansonphong/360-VIEWER)** · **[Engine package →](https://www.npmjs.com/package/@ansonphong/360-viewer)**\n\n---\n\n## What this gives you\n\n- **Section-based sidebar** with 9 built-in templates (`grid`, `feed`, `accordion`, `hero`, `list`, `carousel`, `avatar-row`, `avatar-grid`, `empty`)\n- **Toolbar** with projection toggle, resolution switcher, theme toggle, fullscreen, info, help\n- **Glassmorphic info bar** with prev/next navigation, image title/caption\n- **Help modal** triggered by the `pv-help` keyboard event and toolbar button\n- **Deep-linking** — `?img=<slug>` reads/writes by default, fully configurable\n- **Theme system** — light / dark / auto with CSS custom properties + accent-color\n- **Decorator API** — extend thumbnails, section headings, sidebar, info bar, toolbar without forking\n- **Slot system** — replace named UI regions with your own factory functions\n- **JSON-driven config** — one `360-viewer.json` controls title, theme, accent, panel width, favicon, social links\n\nUse the engine alone if you're embedding a panorama into a marketing hero or wiring up your own chrome. Use this package when you want a full gallery experience out of the box.\n\n---\n\n## Install\n\n```bash\nnpm install @ansonphong/360-viewer @ansonphong/360-viewer-library three\n```\n\nThe engine and Three.js r128 are peer-resolved dependencies. The library-ui pins the engine version to ensure CSS prefixes and event names stay in sync.\n\n---\n\n## Quick start\n\n### Plain HTML + UMD (no build step)\n\n```html\n<!-- Peer deps -->\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js\"></script>\n<link rel=\"stylesheet\" href=\"https://unpkg.com/@phosphor-icons/web@2.1.1/src/regular/style.css\" />\n\n<!-- Engine + Library UI -->\n<link rel=\"stylesheet\" href=\"https://unpkg.com/@ansonphong/360-viewer@6/dist/viewer.css\" />\n<link rel=\"stylesheet\" href=\"https://unpkg.com/@ansonphong/360-viewer-library@6/dist/viewer-library.css\" />\n<script src=\"https://unpkg.com/@ansonphong/360-viewer@6/dist/viewer.umd.js\"></script>\n<script src=\"https://unpkg.com/@ansonphong/360-viewer-library@6/dist/viewer-library.umd.js\"></script>\n\n<div id=\"viewer\" style=\"width: 100%; height: 100vh;\"></div>\n\n<script>\n  const gallery = new Phong360ViewerLibrary({\n    containerId: 'viewer',\n    libraryUrl: 'library/library.json',\n    configUrl: '360-viewer.json',\n    baseUrl: 'library/',\n    theme: 'auto',\n  });\n</script>\n```\n\n### ESM (Vite / webpack / Rollup / Next.js)\n\n```js\nimport 'three';\nimport { Phong360ViewerLibrary } from '@ansonphong/360-viewer-library';\nimport '@ansonphong/360-viewer/dist/viewer.css';\nimport '@ansonphong/360-viewer-library/dist/viewer-library.css';\n\nconst gallery = new Phong360ViewerLibrary({\n  containerId: 'viewer',\n  libraryUrl: '/library.json',\n  configUrl: '/360-viewer.json',\n  theme: 'auto',\n});\n```\n\n> **Phosphor Icons** is required for the toolbar / sidebar / info-bar glyphs. Without it you'll see empty boxes where icons should be — there is no built-in fallback.\n\n---\n\n## Configuration via `360-viewer.json`\n\nEverything visible — title, theme, accent, sections, layout — is driven by a single JSON file:\n\n```json\n{\n  \"context\": {\n    \"type\": \"profile\",\n    \"title\": \"Your Name\",\n    \"subtitle\": \"360 Photography\",\n    \"avatar\": \"assets/avatar.jpg\",\n    \"theme\": \"dark\",\n    \"accent\": \"#6366f1\",\n    \"panelWidth\": 420,\n    \"infoBar\": \"center\",\n    \"favicon\": \"🎨\",\n    \"links\": [\n      { \"url\": \"https://yoursite.com\", \"label\": \"Website\" },\n      { \"url\": \"https://instagram.com/you\", \"label\": \"Instagram\" }\n    ]\n  },\n  \"sections\": {\n    \"Landscapes\": { \"title\": \"Landscapes\", \"icon\": \"mountains\", \"template\": \"grid\" },\n    \"Cities\":     { \"title\": \"Cities\",     \"icon\": \"city\",      \"template\": \"feed\" }\n  }\n}\n```\n\n`library.json` (v4.0) carries the actual image manifest — the library-ui reads it through the engine. See [LIBRARY-FORMAT.md](https://github.com/ansonphong/360-VIEWER/blob/master/docs/LIBRARY-FORMAT.md).\n\n---\n\n## Public API\n\n### Constructor\n\n```js\nnew Phong360ViewerLibrary({\n  containerId,          // string id of the container element (required)\n  libraryUrl,           // path to library.json (v4.0 manifest)\n  configUrl,            // path to 360-viewer.json\n  baseUrl,              // base path prepended to relative image URLs\n  theme: 'auto',        // 'dark' | 'light' | 'auto'\n  accent: '#e13e13',\n  urlSync: true,        // true | false | { read, write } for custom deep-linking\n  panelWidth: 420,\n  infoBar: 'center',    // 'center' | 'left' | 'right' | 'off'\n  // ...all engine config also forwarded\n})\n```\n\n### Decorator API\n\nExtend the UI without forking:\n\n```js\n// Add a custom decorator to every thumbnail (e.g. owner badge, view count)\ngallery.addThumbnailDecorator(({ image, el }) => {\n  if (image.featured) el.classList.add('is-featured');\n});\n\n// Decorate section headings\ngallery.addSectionHeadingDecorator(({ section, el }) => { /* ... */ });\n\n// Inject a custom sidebar section\ngallery.addSidebarSection({\n  id: 'about',\n  title: 'About',\n  template: 'hero',\n  render: (root) => { /* paint into root */ },\n});\n\n// Mount custom content into the info bar\ngallery.setInfoBarSlot('left',  document.querySelector('#left-extras'));\ngallery.setInfoBarSlot('right', document.querySelector('#right-extras'));\n\n// Add a toolbar button\ngallery.addToolbarButton({\n  id: 'share',\n  icon: 'share-network',\n  title: 'Share',\n  onClick: () => navigator.share?.({ url: location.href }),\n});\n```\n\n**Memory bounds:** decorators are capped — warning at 20 per kind, hard cap at 100. This protects against accidental N² registration in re-render loops.\n\n### Slot system\n\nSwap out entire UI regions with your own factory functions:\n\n```js\nimport { SLOT_NAMES } from '@ansonphong/360-viewer-library';\n\ngallery.setSlot(SLOT_NAMES.SIDEBAR, ({ container, gallery }) => {\n  // return cleanup fn, or undefined\n  const el = document.createElement('aside');\n  el.innerHTML = '<nav>...</nav>';\n  container.appendChild(el);\n  return () => container.removeChild(el);\n});\n\ngallery.clearSlot(SLOT_NAMES.SIDEBAR);\n```\n\nAvailable slot names: `SIDEBAR`, `TOOLBAR`, `INFO_BAR`, `HELP`, plus per-template slots.\n\n### Methods\n\n```js\ngallery.getViewer()                // underlying Phong360Viewer instance\ngallery.selectImage(id)\ngallery.openSidebar() / closeSidebar() / toggleSidebar()\ngallery.openHelp() / closeHelp()\ngallery.setTheme('light')\ngallery.setAccent('#6366f1')\ngallery.refresh()                  // re-fetch library.json + 360-viewer.json\ngallery.destroy()\n```\n\n### Events\n\nThe library-ui re-emits engine events and adds its own:\n\n| Event | Source | Payload |\n|---|---|---|\n| `image:visible` | engine | `{ url, image }` |\n| `image:loaded` | engine | `{ url, image }` |\n| `section:click` | library-ui | `{ section }` |\n| `sidebar:open` / `sidebar:close` | library-ui | — |\n| `help:open` / `help:close` | library-ui | — |\n| `theme:change` | engine | `{ theme }` |\n\nPlus the bubbling CustomEvent on the container: `pv-help` toggles the help modal.\n\n---\n\n## Templates\n\nThe sidebar renders sections via a pluggable template engine. Pick a template per section in your `360-viewer.json`:\n\n| Template | Description | Use case |\n|---|---|---|\n| `grid` | Responsive thumbnail grid | Default browsing |\n| `feed` | Vertical list with large thumbnails | Recent / featured |\n| `accordion` | Collapsible group containing an inner template | Category organization |\n| `hero` | Single large featured image | Spotlight |\n| `list` | Compact rows with small thumbnails | Search results, dense lists |\n| `carousel` | Horizontal scrolling strip | Trending, related |\n| `avatar-row` | Horizontal circular avatars | Creator highlights |\n| `avatar-grid` | Grid of avatar cards | Creator directory |\n| `empty` | Placeholder | No-content state |\n\nCustom templates can be registered — see [TEMPLATES.md](https://github.com/ansonphong/360-VIEWER/blob/master/docs/TEMPLATES.md).\n\n---\n\n## Theming\n\nAll visuals key off CSS custom properties under the `--pv-*` namespace (shared with the engine):\n\n```css\n.my-gallery {\n  --pv-accent: #e13e13;\n  --pv-bg: #0a0a0a;\n  --pv-surface: rgba(20, 20, 20, 0.85);\n  --pv-text: #fff;\n  --pv-text-muted: rgba(255, 255, 255, 0.6);\n  --pv-border: rgba(255, 255, 255, 0.1);\n  --pv-panel-width: 420px;\n}\n```\n\nOr swap built-in themes at runtime: `gallery.setTheme('dark' | 'light' | 'auto')`.\n\nSee [THEMING.md](https://github.com/ansonphong/360-VIEWER/blob/master/docs/THEMING.md) for the full custom-property reference.\n\n---\n\n## Bundles in `dist/`\n\n| File | Purpose | Engine |\n|---|---|---|\n| `viewer-library.esm.js` | ESM | peer dep |\n| `viewer-library.umd.js` | UMD | reads `window.Phong360Viewer` |\n| `viewer-library.standalone.umd.js` | Self-contained UMD | reads `window.Phong360Viewer` |\n| `viewer-library.css` | Sidebar / toolbar / info-bar styles | — |\n\nAll bundles expose `Phong360ViewerLibrary` as a global (UMD) or named export (ESM).\n\n---\n\n## Migration from 5.x → 6.x\n\nPure rename, no behavior changes:\n\n| 5.x | 6.x |\n|---|---|\n| `@ansonphong/360-library-ui` | `@ansonphong/360-viewer-library` |\n| `Phong360LibraryUI` class | `Phong360ViewerLibrary` class |\n| `dist/library-ui.*` | `dist/viewer-library.*` |\n| `--p360-*` / `.p360-*` CSS | `--pv-*` / `.pv-*` |\n| `p360-help` event | `pv-help` |\n| peer engine `@ansonphong/360-engine@5.x` | `@ansonphong/360-viewer@^6.0.0` |\n\n```bash\nnpm uninstall @ansonphong/360-library-ui @ansonphong/360-engine\nnpm install @ansonphong/360-viewer-library @ansonphong/360-viewer\n```\n\n```diff\n- import { Phong360LibraryUI } from '@ansonphong/360-library-ui';\n+ import { Phong360ViewerLibrary } from '@ansonphong/360-viewer-library';\n```\n\n```bash\nsed -i 's/--p360-/--pv-/g; s/\\.p360-/.pv-/g' your-styles.css\n```\n\nThe old package remains installable indefinitely with a deprecation notice — existing lockfiles do not break.\n\n---\n\n## Browser support\n\nModern evergreen browsers (Chrome, Firefox, Safari, Edge). Requires WebGL 1.0 and ES2017+.\n\n---\n\n## Links\n\n- **GitHub:** [ansonphong/360-VIEWER](https://github.com/ansonphong/360-VIEWER) — full docs, examples, gallery template, deploy scripts\n- **Live demo:** [360.phong.com](https://360.phong.com)\n- **Engine package:** [`@ansonphong/360-viewer`](https://www.npmjs.com/package/@ansonphong/360-viewer)\n- **Fork Guide (build your own gallery):** [docs/FORK-GUIDE.md](https://github.com/ansonphong/360-VIEWER/blob/master/docs/FORK-GUIDE.md)\n- **Issues:** [GitHub issues](https://github.com/ansonphong/360-VIEWER/issues)\n- **Author:** [Phong](https://phong.com)\n\n---\n\n## License\n\nMIT — see [LICENSE](https://github.com/ansonphong/360-VIEWER/blob/master/LICENSE).\n","readmeFilename":"README.md","homepage":"https://github.com/ansonphong/360-VIEWER#readme","keywords":["360","panorama","viewer","gallery","sidebar","toolbar","ui","threejs","webgl","immersive","photography"],"repository":{"type":"git","url":"git+https://github.com/ansonphong/360-VIEWER.git"},"author":{"name":"Phong","url":"https://phong.com"},"bugs":{"url":"https://github.com/ansonphong/360-VIEWER/issues"}}