immersive-media-spots 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +30 -0
  2. package/.github/ISSUE_TEMPLATE/feature_request.md +19 -0
  3. package/.github/workflows/ci.yml +31 -0
  4. package/CHANGELOG.md +31 -0
  5. package/CONTRIBUTING.md +71 -0
  6. package/LICENSE +21 -0
  7. package/README.md +115 -0
  8. package/docs/audio.md +44 -0
  9. package/docs/dependencies.md +69 -0
  10. package/docs/diff.md +68 -0
  11. package/docs/events.md +29 -0
  12. package/docs/gallery.md +79 -0
  13. package/docs/hotspots.md +119 -0
  14. package/docs/model.md +43 -0
  15. package/docs/pano.md +42 -0
  16. package/docs/spinner.md +49 -0
  17. package/docs/video.md +51 -0
  18. package/docs/viewer.md +95 -0
  19. package/lib/FullscreenMgr.js +99 -0
  20. package/lib/ImageReader.js +56 -0
  21. package/lib/ImsBaseClass.js +324 -0
  22. package/lib/ResizeController.js +30 -0
  23. package/lib/createErrorPlaceholder.js +28 -0
  24. package/lib/dataToImage.js +41 -0
  25. package/lib/getVariantFit.js +22 -0
  26. package/lib/globalDataCtx.js +14 -0
  27. package/lib/imageToData.js +35 -0
  28. package/lib/ims-button.js +100 -0
  29. package/lib/ims-preloader.js +37 -0
  30. package/lib/ims-progress-bar.js +45 -0
  31. package/lib/ims-range.js +119 -0
  32. package/lib/imsCtxName.js +2 -0
  33. package/lib/loadSourceData.js +18 -0
  34. package/lib/plugins/analytics.js +30 -0
  35. package/lib/plugins/watermark.js +71 -0
  36. package/lib/themes/light.css +15 -0
  37. package/lib/themes/minimal.css +14 -0
  38. package/lib/tokens.css +35 -0
  39. package/lib/validateConfig.js +35 -0
  40. package/lib/version.js +3 -0
  41. package/package.json +58 -0
  42. package/playwright.config.js +22 -0
  43. package/test-results/.last-run.json +4 -0
  44. package/tests/e2e/audio.spec.js +26 -0
  45. package/tests/e2e/diff.spec.js +49 -0
  46. package/tests/e2e/gallery.spec.js +84 -0
  47. package/tests/e2e/hotspots.spec.js +54 -0
  48. package/tests/e2e/model.spec.js +23 -0
  49. package/tests/e2e/pano.spec.js +23 -0
  50. package/tests/e2e/spinner.spec.js +48 -0
  51. package/tests/e2e/video.spec.js +26 -0
  52. package/tests/e2e/viewer.spec.js +108 -0
  53. package/tests/getVariantFit.test.js +53 -0
  54. package/tests/validateConfig.test.js +68 -0
  55. package/types/globals.d.ts +132 -0
  56. package/video/test-track.vtt +10 -0
  57. package/wgt/audio/ImsAudioData.js +27 -0
  58. package/wgt/audio/ims-audio-toolbar.js +53 -0
  59. package/wgt/audio/index.js +235 -0
  60. package/wgt/audio/styles.js +34 -0
  61. package/wgt/audio/template.js +7 -0
  62. package/wgt/diff/ImsDiffData.js +34 -0
  63. package/wgt/diff/ims-diff-toolbar.js +68 -0
  64. package/wgt/diff/index.js +345 -0
  65. package/wgt/diff/styles.js +59 -0
  66. package/wgt/diff/template.js +11 -0
  67. package/wgt/gallery/ImsGalleryData.js +30 -0
  68. package/wgt/gallery/ims-gallery-toolbar.js +58 -0
  69. package/wgt/gallery/index.js +273 -0
  70. package/wgt/gallery/styles.js +45 -0
  71. package/wgt/gallery/template.js +10 -0
  72. package/wgt/hotspots/ImsHotspotsData.js +5 -0
  73. package/wgt/hotspots/index.js +181 -0
  74. package/wgt/hotspots/styles.js +54 -0
  75. package/wgt/model/ImsModelData.js +27 -0
  76. package/wgt/model/ims-model-toolbar.js +37 -0
  77. package/wgt/model/index.js +220 -0
  78. package/wgt/model/styles.js +50 -0
  79. package/wgt/model/template.js +6 -0
  80. package/wgt/pano/ImsPanoData.js +28 -0
  81. package/wgt/pano/ims-pano-toolbar.js +37 -0
  82. package/wgt/pano/index.js +177 -0
  83. package/wgt/pano/styles.js +51 -0
  84. package/wgt/pano/template.js +9 -0
  85. package/wgt/spinner/ImsSpinnerData.js +36 -0
  86. package/wgt/spinner/ims-spinner-toolbar.js +42 -0
  87. package/wgt/spinner/index.js +428 -0
  88. package/wgt/spinner/styles.js +73 -0
  89. package/wgt/spinner/template.js +11 -0
  90. package/wgt/video/ImsVideoData.js +24 -0
  91. package/wgt/video/ims-video-toolbar.js +65 -0
  92. package/wgt/video/index.js +233 -0
  93. package/wgt/video/styles.js +60 -0
  94. package/wgt/video/template.js +22 -0
  95. package/wgt/viewer/ims-viewer-toolbar.js +38 -0
  96. package/wgt/viewer/index.js +145 -0
  97. package/wgt/viewer/styles.js +39 -0
  98. package/wgt/viewer/template.js +7 -0
@@ -0,0 +1,30 @@
1
+ ---
2
+ name: Bug Report
3
+ about: Report a problem with an IMS widget
4
+ labels: bug
5
+ ---
6
+
7
+ **Widget**: (e.g., ims-spinner, ims-video, ims-pano)
8
+
9
+ **Version**:
10
+
11
+ **Browser**:
12
+
13
+ **Description**:
14
+ A clear description of the bug.
15
+
16
+ **Steps to Reproduce**:
17
+ 1.
18
+ 2.
19
+ 3.
20
+
21
+ **Expected Behavior**:
22
+
23
+ **Actual Behavior**:
24
+
25
+ **Config JSON** (if applicable):
26
+ ```json
27
+
28
+ ```
29
+
30
+ **Screenshots** (if applicable):
@@ -0,0 +1,19 @@
1
+ ---
2
+ name: Feature Request
3
+ about: Suggest a new feature or enhancement
4
+ labels: enhancement
5
+ ---
6
+
7
+ **Widget**: (e.g., ims-spinner, ims-video, ims-pano, new widget, all)
8
+
9
+ **Description**:
10
+ A clear description of the feature you'd like.
11
+
12
+ **Use Case**:
13
+ Why would this feature be useful?
14
+
15
+ **Proposed Solution** (optional):
16
+ How you'd approach implementing this.
17
+
18
+ **Alternatives Considered** (optional):
19
+ Other approaches you've considered.
@@ -0,0 +1,31 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ node-version: [20, 22]
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+ - uses: actions/setup-node@v4
18
+ with:
19
+ node-version: ${{ matrix.node-version }}
20
+ - run: npm install
21
+ - run: npm test
22
+
23
+ typecheck:
24
+ runs-on: ubuntu-latest
25
+ steps:
26
+ - uses: actions/checkout@v4
27
+ - uses: actions/setup-node@v4
28
+ with:
29
+ node-version: 22
30
+ - run: npm install
31
+ - run: npm run types
package/CHANGELOG.md ADDED
@@ -0,0 +1,31 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ### Added
11
+ - Package exports map for clean subpath imports
12
+ - `.npmignore` to reduce published package size
13
+ - CSS custom properties design system for theming
14
+ - TypeScript type definitions for all public APIs and data classes
15
+
16
+ ### Fixed
17
+ - README importmap version mismatch (Symbiote.js 2.x → 3.x)
18
+
19
+ ## [0.2.2] - 2024-12-01
20
+
21
+ ### Added
22
+ - `ims-video` widget with HLS support, captions, and customizable controls
23
+ - `ims-viewer` universal component with dynamic CDN loading
24
+ - `ims-diff` image comparison widget
25
+ - `ims-gallery` interactive image gallery
26
+ - `ims-pano` 360° panorama viewer
27
+ - `ims-spinner` 360° object viewer
28
+ - Adaptive content loading and DPI support
29
+ - Full-screen display mode
30
+ - Data-to-image steganographic encoding utilities
31
+ - Mobile device compatibility
@@ -0,0 +1,71 @@
1
+ # Contributing to IMS
2
+
3
+ Thank you for your interest in contributing to Interactive Media Spots!
4
+
5
+ ## Development Setup
6
+
7
+ ```bash
8
+ git clone https://github.com/rnd-pro/immersive-media-spots.git
9
+ cd immersive-media-spots
10
+ npm install
11
+ ```
12
+
13
+ ## Project Structure
14
+
15
+ ```
16
+ lib/ — Shared base classes and utilities
17
+ ImsBaseClass.js — Base class for all widgets
18
+ FullscreenMgr.js — Fullscreen API manager
19
+ ImageReader.js — Image sequence loader with progress
20
+ tokens.css — CSS design tokens
21
+ validateConfig.js — Runtime config validation
22
+
23
+ wgt/ — Widget implementations
24
+ diff/ — Image comparison
25
+ gallery/ — Image gallery
26
+ pano/ — 360° panorama viewer
27
+ spinner/ — 360° object viewer
28
+ video/ — Video player with HLS
29
+ viewer/ — Universal CDN-driven loader
30
+
31
+ tests/ — Unit tests (Node.js test runner)
32
+ ```
33
+
34
+ ## Widget Anatomy
35
+
36
+ Each widget follows this structure:
37
+ - `index.js` — Component class extending `ImsBaseClass`
38
+ - `template.js` — HTML template
39
+ - `styles.js` — Shadow DOM styles
40
+ - `ImsXxxData.js` — Data schema class
41
+ - `test.html` — Manual test page
42
+ - `test-data.json` — Test fixture data
43
+
44
+ ## Running Tests
45
+
46
+ ```bash
47
+ npm test
48
+ ```
49
+
50
+ ## Code Style
51
+
52
+ - Single quotes for strings
53
+ - 2-space indentation
54
+ - Semicolons required
55
+ - ESM only (no `require`)
56
+ - Use `#` for private class fields
57
+ - JSDoc for type annotations
58
+ - Modern CSS nesting
59
+ - No external CSS frameworks
60
+
61
+ ## Submitting Changes
62
+
63
+ 1. Fork and create a feature branch
64
+ 2. Make your changes following the code style above
65
+ 3. Add/update tests for new functionality
66
+ 4. Ensure `npm test` passes
67
+ 5. Submit a PR with a clear description
68
+
69
+ ## License
70
+
71
+ By contributing, you agree that your contributions will be licensed under the MIT License.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 RND-PRO.com (team@rnd-pro.com). All rights reserved.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,115 @@
1
+ [![npm version](https://badge.fury.io/js/immersive-media-spots.svg)](https://badge.fury.io/js/immersive-media-spots)
2
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
3
+
4
+ # IMS — Immersive Media Spots
5
+
6
+ <img src="https://rnd-pro.com/svg/ims/index.svg" width="200" alt="IMS: Immersive Media Spots">
7
+
8
+ **Simple web components that turn static pages into immersive, interactive media experiences.** Drop a single HTML tag — get a full-featured 360° spinner, panorama viewer, image comparison slider, or video player.
9
+
10
+ ## ✨ Why IMS?
11
+
12
+ - **One tag — one widget.** Just `<ims-viewer src-data="data.json">` and you're done.
13
+ - **Universal.** Works in any stack: vanilla HTML, React, Vue, Angular, Svelte — anything that renders DOM.
14
+ - **Smart loading.** Adaptive resolution based on viewport & DPI, lazy loading via IntersectionObserver, on-demand dependency imports.
15
+ - **Hypermedia navigation.** Link widgets together with interactive hotspots — let users explore 3D products, then dive into 360° interiors, then watch a demo video, all in one seamless flow.
16
+ - **Themeable.** Full CSS custom properties for colors, sizing, and layout. No CSS framework lock-in.
17
+ - **Lightweight.** Built on [Symbiote.js](https://github.com/nicothed/symbiote.js) — each widget loads only what it needs.
18
+
19
+ ## 🧩 Widgets
20
+
21
+ | Widget | Description | Docs |
22
+ |--------|-------------|------|
23
+ | **ims-spinner** | 360° product viewer with frame-by-frame rotation, autoplay, and drag interaction | [docs](./docs/spinner.md) |
24
+ | **ims-gallery** | Touch-friendly image gallery with navigation, looping, and fullscreen | [docs](./docs/gallery.md) |
25
+ | **ims-diff** | Before/after image comparison with a draggable slider | [docs](./docs/diff.md) |
26
+ | **ims-pano** | 360° panorama with inertia-based pan, zoom, and auto-rotation (Three.js) | [docs](./docs/pano.md) |
27
+ | **ims-model** | 3D model viewer for GLTF/GLB with orbit controls and auto-rotation (Three.js) | [docs](./docs/model.md) |
28
+ | **ims-video** | Video player with HLS adaptive streaming, subtitles, and quality switching | [docs](./docs/video.md) |
29
+ | **ims-audio** | Audio player with real-time waveform visualization (Web Audio API) | [docs](./docs/audio.md) |
30
+ | **ims-hotspots** | Interactive overlay spots with state-bound positioning and keyframe animation | [docs](./docs/hotspots.md) |
31
+ | **ims-viewer** | Universal loader — auto-imports any widget by type with version control, manages hotspot navigation and history | [docs](./docs/viewer.md) |
32
+
33
+ ## 🚀 Quick Start
34
+
35
+ **1.** Set up [dependencies](./docs/dependencies.md) — add an importmap or install via npm (only Symbiote.js is required; Three.js and hls.js are needed only for the widgets that use them)
36
+
37
+ **2. Load the viewer** (it pulls widget code on demand):
38
+
39
+ ```html
40
+ <script type="module" src="https://cdn.jsdelivr.net/npm/immersive-media-spots@<VERSION>/viewer/+esm"></script>
41
+ ```
42
+
43
+ **3. Use it:**
44
+
45
+ ```html
46
+ <ims-viewer src-data="./product.json"></ims-viewer>
47
+ ```
48
+
49
+ That's it. The viewer reads `imsType` from `product.json` and dynamically imports the right widget.
50
+
51
+ ### Direct widget usage
52
+
53
+ Skip the viewer and load a specific widget directly:
54
+
55
+ ```html
56
+ <script type="module" src="https://cdn.jsdelivr.net/npm/immersive-media-spots@<VERSION>/spinner/+esm"></script>
57
+
58
+ <ims-spinner src-data="./data.json" autoplay="true"></ims-spinner>
59
+ ```
60
+
61
+ ### npm
62
+
63
+ ```bash
64
+ npm install immersive-media-spots
65
+ ```
66
+
67
+ ## 🔗 Hypermedia Navigation
68
+
69
+ Combine `ims-viewer` with `ims-hotspots` to create connected experiences:
70
+
71
+ ```html
72
+ <ims-viewer
73
+ src-data="./exterior-spin.json"
74
+ url-template="./{{imsType}}/index.js"
75
+ hotspots="./exterior-hotspots.json">
76
+ </ims-viewer>
77
+ ```
78
+
79
+ Hotspots link widgets together — click a spot on a 360° product to open a detail gallery, then jump to a panoramic interior, all with animated back navigation. [→ Hotspots docs](./docs/hotspots.md)
80
+
81
+ ## ⚙️ Common Features
82
+
83
+ All widgets share a base architecture that provides:
84
+
85
+ - 🎯 **Adaptive loading** — automatically selects the best resolution variant for the viewport and DPI
86
+ - 🔄 **Lazy loading** — `lazy` attribute defers initialization until the element enters the viewport
87
+ - 🖥️ **Fullscreen** — native Fullscreen API with CSS fallback
88
+ - 📱 **Mobile-ready** — touch gestures, responsive sizing, pointer event support
89
+ - 🎨 **CSS theming** — design tokens for toolbar, colors, spacing, and transitions
90
+ - 🔌 **Plugin system** — extend lifecycle hooks with custom plugins
91
+ - 📡 **Events** — standard lifecycle events: `ims-load`, `ims-ready`, `ims-error` ([→ events docs](./docs/events.md))
92
+ - 🏷️ **Attribute overrides** — override any JSON config property via HTML attributes
93
+
94
+ ## 📚 Documentation
95
+
96
+ Full per-widget API reference, config schemas, and CSS custom properties:
97
+
98
+ | | | |
99
+ |---|---|---|
100
+ | [Spinner](./docs/spinner.md) | [Gallery](./docs/gallery.md) | [Diff](./docs/diff.md) |
101
+ | [Pano](./docs/pano.md) | [Model](./docs/model.md) | [Video](./docs/video.md) |
102
+ | [Audio](./docs/audio.md) | [Hotspots](./docs/hotspots.md) | [Viewer](./docs/viewer.md) |
103
+ | [Events](./docs/events.md) | [Dependencies](./docs/dependencies.md) | |
104
+
105
+ ## 📰 Articles & Demos
106
+
107
+ - [Concept details and live demo](https://rnd-pro.com/pulse/immersive-media-spots/)
108
+
109
+ ## Contributing
110
+
111
+ Contributions are welcome! Please feel free to submit a Pull Request.
112
+
113
+ ## License
114
+
115
+ MIT © [rnd-pro.com](https://rnd-pro.com)
package/docs/audio.md ADDED
@@ -0,0 +1,44 @@
1
+ # ims-audio
2
+
3
+ Audio player with waveform visualization.
4
+
5
+ ## Tag
6
+
7
+ ```html
8
+ <ims-audio src-data="path/to/data.json"></ims-audio>
9
+ ```
10
+
11
+ ## Attributes
12
+
13
+ | Attribute | Description |
14
+ |---|---|
15
+ | `src-data` | URL to JSON config |
16
+ | `lazy` | Enable lazy loading |
17
+ | `no-preloader` | Disable loading spinner |
18
+
19
+ ## Config (`ImsAudioData`)
20
+
21
+ | Property | Type | Default | Description |
22
+ |---|---|---|---|
23
+ | `imsType` | `string` | `'audio'` | Widget type identifier |
24
+ | `srcList` | `string[]` | — | Audio file URL(s) |
25
+ | `autoplay` | `boolean` | `false` | Auto-play on load |
26
+ | `loop` | `boolean` | `false` | Loop playback |
27
+ | `waveformColor` | `string` | — | Waveform fill color |
28
+ | `progressColor` | `string` | — | Progress indicator color |
29
+ | `hideUi` | `boolean` | `false` | Hide toolbar |
30
+
31
+ ## Public API
32
+
33
+ | Method | Description |
34
+ |---|---|
35
+ | `play()` | Start playback |
36
+ | `pause()` | Pause playback |
37
+ | `togglePlay()` | Toggle play/pause |
38
+ | `seek(seconds)` | Seek to position in seconds |
39
+ | `setVolume(val)` | Set volume (0–100) |
40
+ | `toggleMute()` | Toggle mute |
41
+
42
+ ## Events
43
+
44
+ See [events.md](./events.md) for standard IMS lifecycle events.
@@ -0,0 +1,69 @@
1
+ # Dependencies
2
+
3
+ IMS widgets are designed to keep a minimal footprint. Heavy third-party libraries are **only required by the widgets that actually use them** — if you never render a panorama or 3D model, Three.js is never loaded.
4
+
5
+ ## Core
6
+
7
+ | Package | Specifier | Used by |
8
+ |---------|-----------|---------|
9
+ | [Symbiote.js](https://github.com/nicothed/symbiote.js) | `@symbiotejs/symbiote` | All widgets |
10
+
11
+ Symbiote.js is the only mandatory dependency. It provides the reactive web component base class used by every IMS widget.
12
+
13
+ ## Optional (per-widget)
14
+
15
+ | Package | Specifier | Used by | Purpose |
16
+ |---------|-----------|---------|---------|
17
+ | [Three.js](https://threejs.org/) | `three` | ims-pano, ims-model | WebGL rendering for 360° panoramas and 3D models |
18
+ | Three.js addons | `three/addons/` | ims-model | GLTFLoader for `.glb`/`.gltf` model files |
19
+ | [hls.js](https://github.com/nicothed/hls.js/) | `hls.js/dist/hls.mjs` | ims-video | HLS adaptive streaming (only when `hlsSrc` is configured) |
20
+
21
+ > **If you only use `ims-spinner`, `ims-gallery`, `ims-diff`, `ims-audio`, or `ims-hotspots` — no optional dependencies are needed at all.**
22
+
23
+ ## Setup via importmap
24
+
25
+ The simplest way to provide dependencies is an [importmap](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap) — no build step needed:
26
+
27
+ ```html
28
+ <script type="importmap">
29
+ {
30
+ "imports": {
31
+ "@symbiotejs/symbiote": "https://cdn.jsdelivr.net/npm/@symbiotejs/symbiote@3/+esm",
32
+ "three": "https://cdn.jsdelivr.net/npm/three@0.170.0/+esm",
33
+ "three/addons/": "https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/",
34
+ "hls.js/dist/hls.mjs": "https://cdn.jsdelivr.net/npm/hls.js@1.5/+esm"
35
+ }
36
+ }
37
+ </script>
38
+ ```
39
+
40
+ Only include the entries you actually need. For example, if you only use `ims-spinner`:
41
+
42
+ ```html
43
+ <script type="importmap">
44
+ {
45
+ "imports": {
46
+ "@symbiotejs/symbiote": "https://cdn.jsdelivr.net/npm/@symbiotejs/symbiote@3/+esm"
47
+ }
48
+ }
49
+ </script>
50
+ ```
51
+
52
+ ## Bundled setup
53
+
54
+ When using a bundler (Vite, esbuild, Webpack, etc.), install the required packages via npm and let the bundler resolve them:
55
+
56
+ ```bash
57
+ # Core (required)
58
+ npm install @symbiotejs/symbiote
59
+
60
+ # Optional — only if you use the corresponding widgets
61
+ npm install three # ims-pano, ims-model
62
+ npm install hls.js # ims-video with HLS
63
+ ```
64
+
65
+ The bundler will tree-shake unused widgets and their dependencies automatically.
66
+
67
+ ## CDN resolution (ims-viewer)
68
+
69
+ When using `ims-viewer`, widget code is **loaded dynamically** at runtime based on the `imsType` field in the source data. The importmap must be present at page load so that dynamically imported modules can resolve their dependencies correctly.
package/docs/diff.md ADDED
@@ -0,0 +1,68 @@
1
+ # ims-diff
2
+
3
+ Before/after image comparison with multiple modes.
4
+
5
+ ## Tag
6
+
7
+ ```html
8
+ <ims-diff src-data="path/to/data.json"></ims-diff>
9
+ ```
10
+
11
+ ## Attributes
12
+
13
+ | Attribute | Description |
14
+ |---|---|
15
+ | `src-data` | URL to JSON config |
16
+ | `lazy` | Enable lazy loading |
17
+ | `no-preloader` | Disable loading spinner |
18
+ | `vertical` | Set automatically when orientation is vertical |
19
+
20
+ ## Config (`ImsDiffData`)
21
+
22
+ | Property | Type | Default | Description |
23
+ |---|---|---|---|
24
+ | `imsType` | `string` | `'diff'` | Widget type identifier |
25
+ | `srcList` | `string[]` | — | Image URLs (pairs for comparison) |
26
+ | `mode` | `string` | `'slider'` | Comparison mode: `'slider'` or `'onion'` |
27
+ | `orientation` | `string` | `'horizontal'` | Split orientation: `'horizontal'` or `'vertical'` |
28
+ | `startPosition` | `number` | `50` | Initial slider position (0–100) |
29
+ | `animateSpeed` | `number` | `2000` | Animated sweep duration (ms per full sweep) |
30
+ | `filters` | `string[]` | — | CSS filter strings per image |
31
+ | `hideUi` | `boolean` | `false` | Hide toolbar |
32
+ | `urlTemplate` | `string` | — | URL template with placeholders |
33
+ | `variants` | `string[]` | — | Available size variants |
34
+
35
+ ## Comparison Modes
36
+
37
+ ### Slider (default)
38
+ Drag to reveal — splits images with a movable divider line. In horizontal mode the split is left/right, in vertical mode it's top/bottom.
39
+
40
+ ### Onion-skin
41
+ Overlays the second image on top of the first. Drag controls the opacity (0–1) of the overlay.
42
+
43
+ ## Public API
44
+
45
+ | Method | Description |
46
+ |---|---|
47
+ | `setShare(percent)` | Set slider/opacity position (0–100) |
48
+ | `goTo(index)` | Switch to a specific diff pair (0-based) |
49
+ | `setMode(mode)` | Set mode: `'slider'` or `'onion'` |
50
+ | `toggleMode()` | Toggle between slider and onion |
51
+ | `toggleOrientation()` | Toggle horizontal/vertical split |
52
+ | `startAnimate()` | Start animated sweep |
53
+ | `stopAnimate()` | Stop animated sweep |
54
+ | `toggleAnimate()` | Toggle animated sweep |
55
+
56
+ ## Toolbar
57
+
58
+ | Button | Action |
59
+ |---|---|
60
+ | Mode | Toggle slider ↔ onion |
61
+ | Orientation | Toggle horizontal ↔ vertical |
62
+ | Play/Pause | Toggle animated sweep |
63
+ | ◀ / ▶ | Previous/next pair (visible when `srcList > 2`) |
64
+ | Fullscreen | Toggle fullscreen |
65
+
66
+ ## Events
67
+
68
+ See [events.md](./events.md) for standard IMS lifecycle events.
package/docs/events.md ADDED
@@ -0,0 +1,29 @@
1
+ # Events
2
+
3
+ All IMS widgets emit standard lifecycle events via `CustomEvent`. Enable with `dispatchEvents: true` in config or listen directly on the widget element.
4
+
5
+ ## Event Types
6
+
7
+ | Event | Constant | Detail | Description |
8
+ |---|---|---|---|
9
+ | `ims-load` | `ImsEvents.LOAD` | `{ progress: number }` | Data loading started |
10
+ | `ims-ready` | `ImsEvents.READY` | `{ srcData }` | Widget initialized and ready |
11
+ | `ims-error` | `ImsEvents.ERROR` | `{ error }` | Loading or initialization error |
12
+ | `ims-resize` | `ImsEvents.RESIZE` | — | Widget resized |
13
+ | `ims-destroy` | `ImsEvents.DESTROY` | — | Widget removed from DOM |
14
+
15
+ ## Usage
16
+
17
+ ```js
18
+ import { ImsEvents } from 'immersive-media-spots';
19
+
20
+ let spinner = document.querySelector('ims-spinner');
21
+
22
+ spinner.addEventListener(ImsEvents.READY, (e) => {
23
+ console.log('Widget ready:', e.detail.srcData);
24
+ });
25
+
26
+ spinner.addEventListener(ImsEvents.ERROR, (e) => {
27
+ console.error('Widget error:', e.detail.error);
28
+ });
29
+ ```
@@ -0,0 +1,79 @@
1
+ # ims-gallery
2
+
3
+ Image gallery with navigation, crossfade transitions, and optional captions.
4
+
5
+ ## Tag
6
+
7
+ ```html
8
+ <ims-gallery src-data="path/to/data.json"></ims-gallery>
9
+ ```
10
+
11
+ ## Attributes
12
+
13
+ | Attribute | Description |
14
+ |---|---|
15
+ | `src-data` | URL to JSON config |
16
+ | `lazy` | Enable lazy loading |
17
+ | `no-preloader` | Disable loading spinner |
18
+
19
+ ## Config (`ImsGalleryData`)
20
+
21
+ | Property | Type | Default | Description |
22
+ |---|---|---|---|
23
+ | `imsType` | `string` | `'gallery'` | Widget type identifier |
24
+ | `srcList` | `string[]` | — | Image URLs |
25
+ | `captions` | `string[]` | `[]` | Per-image captions (parallel to srcList) |
26
+ | `transitionDuration` | `number` | `300` | Crossfade duration in ms |
27
+ | `autoplayInterval` | `number` | `3000` | Autoplay slide interval in ms |
28
+ | `loop` | `boolean` | `true` | Wrap around at ends |
29
+ | `hideUi` | `boolean` | `false` | Hide toolbar |
30
+ | `urlTemplate` | `string` | — | URL template with placeholders |
31
+ | `variants` | `string[]` | — | Available size variants |
32
+
33
+ ## Public API
34
+
35
+ | Method | Description |
36
+ |---|---|
37
+ | `goTo(index)` | Go to image by 0-based index |
38
+ | `next()` | Next image (wraps if `loop: true`) |
39
+ | `prev()` | Previous image (wraps if `loop: true`) |
40
+ | `startAutoplay()` | Start slideshow |
41
+ | `stopAutoplay()` | Stop slideshow |
42
+ | `toggleAutoplay()` | Toggle slideshow |
43
+
44
+ ## Features
45
+
46
+ ### Crossfade Transitions
47
+ Images crossfade using canvas globalAlpha blending. Duration controlled by `transitionDuration`.
48
+
49
+ ### Touch Swipe
50
+ Horizontal swipe on the canvas triggers `next()`/`prev()`. Threshold: 50px.
51
+
52
+ ### Image Counter
53
+ Toolbar shows current position (e.g. "3 / 12").
54
+
55
+ ### Captions
56
+ Per-image captions from the `captions` config array are set as the widget's `title` attribute (browser tooltip). A `<slot>` element is available for custom caption components:
57
+
58
+ ```html
59
+ <ims-gallery src-data="data.json">
60
+ <my-custom-caption></my-custom-caption>
61
+ </ims-gallery>
62
+ ```
63
+
64
+ ### Autoplay
65
+ Timer-based auto-advance, toggleable from toolbar.
66
+
67
+ ## Toolbar
68
+
69
+ | Button | Action |
70
+ |---|---|
71
+ | ◀ | Previous image |
72
+ | Counter | Shows position |
73
+ | ▶ | Next image |
74
+ | Play/Pause | Toggle autoplay |
75
+ | Fullscreen | Toggle fullscreen |
76
+
77
+ ## Events
78
+
79
+ See [events.md](./events.md) for standard IMS lifecycle events.