visualifyjs 2.5.3-2.dev → 3.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 (252) hide show
  1. package/.claude/mem/TIMELINE.md +36 -0
  2. package/.claude/mem/notes/2026-02-11-3d-visualization-docs-fix-external-script-solution.md +24 -0
  3. package/.claude/mem/notes/2026-02-11-3d-visualization-docs-fix-session-summary.md +43 -0
  4. package/.claude/mem/notes/2026-02-11-cli-fix-editor-command-alias.md +26 -0
  5. package/.claude/mem/notes/2026-02-11-phase-3-developer-experience-completed.md +51 -0
  6. package/.claude/mem/notes/2026-02-11-phase-4-web-workers-implementation-complete.md +59 -0
  7. package/.claude/mem/notes/2026-02-11-visualify-phase-2-3d-visualization-complete.md +50 -0
  8. package/.claude/mem/notes/2026-02-11-visualify-phase-2-committed-ready-for-phase-3.md +33 -0
  9. package/.claude/mem/notes/2026-02-11-visualify-phase-3-complete-developer-experience.md +52 -0
  10. package/.claude/mem/notes/2026-02-11-visualify-repository-cleanup-complete.md +28 -0
  11. package/.claude/mem/notes/2026-02-18-codebase-cleanup-docsify-plugin-documentation.md +37 -0
  12. package/.claude/mem/notes/2026-02-19-css-grid-layout-fix-displaycontents-on-vcontroller.md +18 -0
  13. package/.claude/mem/notes/2026-02-19-docsify-plugin-fixes-latex-and-visualify-code-bloc.md +26 -0
  14. package/.claude/mem/notes/2026-02-19-page-mode-docs-update-decisions.md +23 -0
  15. package/.claude/mem/notes/2026-02-19-react-context-infinite-re-render-loop-fix-pattern.md +31 -0
  16. package/.claude/mem/notes/2026-02-19-version-300-bump-and-build-fixes.md +32 -0
  17. package/.claude/mem/notes/2026-02-19-visualify-build-deployment-architecture-bug-fixes.md +25 -0
  18. package/.claude/mem/notes/2026-02-19-visualify-dist-iife-self-contained-build-config.md +30 -0
  19. package/.claude/mem/notes/2026-02-19-visualify-infinite-loop-i18n-fixes.md +31 -0
  20. package/.claude/mem/notes/2026-02-19-visualify-v3-bundle-splitting-docs-restructuring.md +32 -0
  21. package/.claude/mem/notes/2026-02-20-bundle-externalization-final-architecture.md +29 -0
  22. package/.claude/mem/notes/2026-02-20-chromium-page-fix-unstable-keys-and-double-event-b.md +27 -0
  23. package/.claude/mem/notes/2026-02-20-console-cleanup-bundle-optimization-commit.md +20 -0
  24. package/.claude/mem/notes/2026-02-20-dotbio-dot-plot-fix-useeffect-dependency.md +21 -0
  25. package/.claude/mem/notes/2026-02-20-public-folder-cleanup-and-readme-rewrite.md +25 -0
  26. package/.claude/mem/notes/2026-02-20-v300-release-and-beta-channel-strategy.md +29 -0
  27. package/.claude/mem/notes/2026-02-20-visium-background-image-unknown-legend-fix.md +19 -0
  28. package/.claude/mem/notes/2026-02-20-visualify-cdn-loader-bundle-externalization.md +34 -0
  29. package/.claude/mem/sessions/session-2026-02-20-031524.md +54 -0
  30. package/.claude/settings.local.json +21 -0
  31. package/.github/workflows/static.yml.bak +51 -51
  32. package/.sisyphus/boulder.json +65 -0
  33. package/.sisyphus/plans/phase-4-advanced-optimizations.md +217 -0
  34. package/LICENSE +674 -674
  35. package/README.md +94 -59
  36. package/config-overrides.js +31 -31
  37. package/dist/stats.html +4949 -0
  38. package/dist/visualify-3d.esm.js +1 -0
  39. package/dist/visualify-3d.js +1 -0
  40. package/dist/visualify-core.esm.js +1 -0
  41. package/dist/visualify-core.js +1 -0
  42. package/dist/visualify-docs.esm.js +1 -0
  43. package/dist/visualify-docs.js +1 -0
  44. package/dist/visualify-loader.js +1 -0
  45. package/dist/visualify-pages.esm.js +1 -0
  46. package/dist/visualify-pages.js +1 -0
  47. package/dist/visualify-portal.esm.js +1 -0
  48. package/dist/visualify-portal.js +1 -0
  49. package/dist/visualify-shared.js +26571 -0
  50. package/dist/visualify.js +1 -188
  51. package/docs/CHANGELOG.md +148 -0
  52. package/docs/cli/commands.md +513 -0
  53. package/docs/configuration/visualify-json.md +474 -0
  54. package/docs/docs/3d-visualization.md +374 -0
  55. package/docs/docs/CLI.md +303 -34
  56. package/docs/docs/README.md +65 -65
  57. package/docs/docs/Rechart/bar.md +190 -190
  58. package/docs/docs/Rechart/funnel.md +241 -241
  59. package/docs/docs/Rechart/line.md +355 -355
  60. package/docs/docs/Rechart/pie.md +225 -225
  61. package/docs/docs/Rechart/radar.md +253 -253
  62. package/docs/docs/Rechart/scatter.md +298 -298
  63. package/docs/docs/_404.md +51 -51
  64. package/docs/docs/_coverpage.md +11 -11
  65. package/docs/docs/_sidebar.md +54 -44
  66. package/docs/docs/components/dotBio.md +87 -34
  67. package/docs/docs/components/echart.md +171 -82
  68. package/docs/docs/components/html.md +61 -34
  69. package/docs/docs/components/macaron.md +156 -145
  70. package/docs/docs/components/markdown.md +42 -0
  71. package/docs/docs/components/more.md +183 -142
  72. package/docs/docs/components/plotly.md +132 -62
  73. package/docs/docs/components/scatterL.md +171 -70
  74. package/docs/docs/components/visium.md +112 -57
  75. package/docs/docs/configuration.md +121 -121
  76. package/docs/docs/deploy.md +31 -31
  77. package/docs/docs/docsify-plugin.md +655 -0
  78. package/docs/docs/hmr.md +165 -0
  79. package/docs/docs/i18n.md +332 -0
  80. package/docs/docs/log.md +30 -9
  81. package/docs/docs/more-pages.md +23 -23
  82. package/docs/docs/quickstart.md +148 -124
  83. package/docs/docs/rechart-attributes.md +74 -74
  84. package/docs/docs/rechart-basic-usage.md +160 -162
  85. package/docs/docs/theme.md +5 -5
  86. package/docs/docs/typescript.md +306 -0
  87. package/docs/docs/visual-editor.md +359 -0
  88. package/docs/index.html +85 -71
  89. package/docs/manifest.json +23 -23
  90. package/docs/migration/v3-migration.md +392 -0
  91. package/docs/static/css/fluff-stuff.css +169 -169
  92. package/docs/static/css/font-awesome.min.css +4 -4
  93. package/docs/static/css/visualify.css +6 -25
  94. package/docs/static/js/3d-viz-examples.js +181 -0
  95. package/docs/static/js/configuration.js +630 -448
  96. package/docs/static/js/visualify.js +1 -188
  97. package/package.json +106 -84
  98. package/rollup.config.mjs +766 -76
  99. package/src/_css/404.css +115 -115
  100. package/src/_css/App.css +37 -37
  101. package/src/_css/autoSuggestion.css +26 -26
  102. package/src/_css/circular-progress.css +32 -32
  103. package/src/_css/index.css +36 -36
  104. package/src/_css/modern.css +350 -25
  105. package/src/_media/corner.svg +8 -8
  106. package/src/_media/download.svg +3 -3
  107. package/src/_media/logo.svg +14 -14
  108. package/src/_test/App.test.js +15 -15
  109. package/src/_utils/reportWebVitals.js +13 -13
  110. package/src/a11y/README.md +177 -0
  111. package/src/a11y/aria-labels.js +339 -0
  112. package/src/a11y/color-contrast.js +535 -0
  113. package/src/a11y/index.js +197 -0
  114. package/src/a11y/keyboard-nav.js +523 -0
  115. package/src/a11y/styles.css +165 -0
  116. package/src/cli/commands/dev.js +214 -0
  117. package/src/cli/commands/docs.js +521 -0
  118. package/src/cli/commands/edit.js +379 -0
  119. package/src/cli/commands/init.js +213 -0
  120. package/src/cli/commands/portal.js +236 -0
  121. package/src/cli/dev-server.js +530 -0
  122. package/src/cli/hmr.js +456 -0
  123. package/src/cli/index.js +180 -0
  124. package/src/cli/utils/config.js +207 -0
  125. package/src/cli/utils/logger.js +241 -0
  126. package/src/config/defaults.ts +122 -0
  127. package/src/config/index.ts +72 -0
  128. package/src/config/loader.ts +478 -0
  129. package/src/config/schema.ts +227 -0
  130. package/src/config/validator.ts +337 -0
  131. package/src/core/appContext.js +34 -27
  132. package/src/core/components/Bar.js +383 -0
  133. package/src/core/components/Bar3D.js +473 -0
  134. package/src/core/components/LargeDatasetChart.js +296 -0
  135. package/src/core/components/Line3D.js +310 -0
  136. package/src/core/components/Scatter.js +392 -188
  137. package/src/core/components/Scatter3D.js +455 -0
  138. package/src/core/components/ScatterBio.js +601 -572
  139. package/src/core/components/Surface3D.js +326 -0
  140. package/src/core/components/ThreeCustom.js +648 -0
  141. package/src/core/components/ThreeScene.js +459 -0
  142. package/src/core/components/VisiumPlot.js +191 -165
  143. package/src/core/components/browser.js +42 -42
  144. package/src/core/components/dotplot.js +413 -413
  145. package/src/core/components/html.js +29 -29
  146. package/src/core/components/list.js +178 -178
  147. package/src/core/components/macaron.js +206 -201
  148. package/src/core/components/markdown.js +56 -56
  149. package/src/core/components/parser.scatterBio.js +582 -587
  150. package/src/core/components/ratio.js +82 -80
  151. package/src/core/components/scatterL.js +206 -173
  152. package/src/core/components/searchbar.js +156 -131
  153. package/src/core/components/selection.js +310 -193
  154. package/src/core/components/timeline.js +236 -281
  155. package/src/core/components/visium.js +114 -97
  156. package/src/core/data-processor.js +413 -0
  157. package/src/core/fetch/condfetch.js +82 -82
  158. package/src/core/fetch/fetch.js +92 -92
  159. package/src/core/fetch/json.js +29 -29
  160. package/src/core/fetch/vfetch.js +42 -42
  161. package/src/core/hmr-client.js +724 -0
  162. package/src/core/liveEditor.js +44 -44
  163. package/src/core/modules/codeEditorWithPreview.js +104 -104
  164. package/src/core/modules/echarts/common.js +20 -20
  165. package/src/core/modules/echarts/gl.js +228 -0
  166. package/src/core/modules/echarts/presetHandler.js +41 -41
  167. package/src/core/modules/echarts/presets/esodev.chromium.js +172 -172
  168. package/src/core/modules/echarts/presets/esodev.codex.js +130 -130
  169. package/src/core/modules/echarts/presets/esodev.visium.js +123 -123
  170. package/src/core/modules/echarts/presets/mmtrbc.js +186 -186
  171. package/src/core/modules/echarts.js +70 -71
  172. package/src/core/modules/echartsUtils.js +43 -43
  173. package/src/core/modules/echartswitcher.js +227 -152
  174. package/src/core/modules/replotly/presetHandler.js +24 -24
  175. package/src/core/modules/replotly/presets/minimum.js +18 -18
  176. package/src/core/modules/replotly/presets/mmtrbc.dot.js +114 -114
  177. package/src/core/modules/replotly/presets/mmtrbc.violin.js +100 -100
  178. package/src/core/modules/replotly.js +74 -71
  179. package/src/core/modules/threejs/Camera.js +373 -0
  180. package/src/core/modules/threejs/Lighting.js +459 -0
  181. package/src/core/modules/threejs/Renderer.js +364 -0
  182. package/src/core/modules/threejs/Scene.js +266 -0
  183. package/src/core/modules/threejs/index.js +155 -0
  184. package/src/core/pages/404.js +50 -50
  185. package/src/core/pages/error.js +27 -27
  186. package/src/core/pages/jsonPage.js +62 -62
  187. package/src/core/pages/loading.js +44 -44
  188. package/src/core/parser/echart.data.js +204 -183
  189. package/src/core/parser/echart.features.js +125 -125
  190. package/src/core/parser/echart.general.js +147 -147
  191. package/src/core/parser/echart.hilbert.js +57 -57
  192. package/src/core/parser/echart.parser.js +210 -210
  193. package/src/core/parser/echart.series.js +67 -67
  194. package/src/core/parser/echart.types.js +76 -76
  195. package/src/core/parser/plotly.config.js +10 -10
  196. package/src/core/parser/plotly.data.js +132 -132
  197. package/src/core/parser/plotly.layout.js +9 -9
  198. package/src/core/parser/plotly.violin.js +18 -18
  199. package/src/core/recharts.js +361 -62
  200. package/src/core/router/alias.js +49 -49
  201. package/src/core/router/jsonRouter.js +31 -31
  202. package/src/core/themes/modern.js +32 -32
  203. package/src/core/themes/themeSelector.js +33 -33
  204. package/src/core/visualify.js +213 -47
  205. package/src/core/widgets/circularProgress.js +23 -23
  206. package/src/core/widgets/controller.js +116 -83
  207. package/src/core/widgets/errorBoundary.js +36 -36
  208. package/src/core/widgets/footer.js +185 -177
  209. package/src/core/widgets/header.js +238 -234
  210. package/src/core/widgets/layout/Grid.js +31 -31
  211. package/src/core/widgets/layout.js +36 -36
  212. package/src/core/widgets/mapping.js +56 -42
  213. package/src/core/workers/data-worker.js +349 -0
  214. package/src/core/workers/worker-pool.js +396 -0
  215. package/src/docsify/bundle.js +215 -0
  216. package/src/docsify/markdown.js +271 -0
  217. package/src/docsify/plugin.js +268 -0
  218. package/src/editor/README.md +172 -0
  219. package/src/editor/components/ChartBuilder.jsx +341 -0
  220. package/src/editor/components/ChartTypeSidebar.jsx +91 -0
  221. package/src/editor/components/Editor.jsx +367 -0
  222. package/src/editor/components/Preview.jsx +446 -0
  223. package/src/editor/components/PropertyPanel.jsx +468 -0
  224. package/src/editor/components/StatusBar.jsx +85 -0
  225. package/src/editor/context/EditorContext.js +248 -0
  226. package/src/editor/hooks/useDebounce.js +32 -0
  227. package/src/editor/index.js +315 -0
  228. package/src/editor/styles/editor.css +637 -0
  229. package/src/editor/utils/chartValidator.js +263 -0
  230. package/src/entries/charts3d.js +70 -0
  231. package/src/entries/core.js +78 -0
  232. package/src/entries/docs.js +154 -0
  233. package/src/entries/pages.js +93 -0
  234. package/src/entries/portal.js +204 -0
  235. package/src/entries/shared.js +50 -0
  236. package/src/i18n/formatters.js +455 -0
  237. package/src/i18n/index.js +169 -0
  238. package/src/i18n/locales/ar.json +137 -0
  239. package/src/i18n/locales/de.json +137 -0
  240. package/src/i18n/locales/en.json +137 -0
  241. package/src/i18n/locales/es.json +137 -0
  242. package/src/i18n/locales/he.json +137 -0
  243. package/src/i18n/locales/zh.json +137 -0
  244. package/src/i18n/rtl.css +183 -0
  245. package/src/index.js +82 -62
  246. package/src/loader.js +103 -0
  247. package/src/setupTests.js +5 -5
  248. package/tsconfig.json +51 -0
  249. package/types/charts.d.ts +569 -0
  250. package/types/components.d.ts +441 -0
  251. package/types/config.d.ts +199 -0
  252. package/types/index.d.ts +353 -0
@@ -0,0 +1,373 @@
1
+ /**
2
+ * Camera.js - Three.js Camera Manager for Visualify.js
3
+ * Handles perspective and orthographic cameras with animation helpers
4
+ */
5
+
6
+ import * as THREE from 'three';
7
+
8
+ /**
9
+ * Camera types
10
+ */
11
+ export const CameraType = {
12
+ PERSPECTIVE: 'perspective',
13
+ ORTHOGRAPHIC: 'orthographic',
14
+ };
15
+
16
+ /**
17
+ * CameraManager class for managing cameras
18
+ */
19
+ export class CameraManager {
20
+ constructor(options = {}) {
21
+ this.cameras = new Map();
22
+ this.activeCameraId = null;
23
+ this.defaultOptions = {
24
+ type: CameraType.PERSPECTIVE,
25
+ position: [0, 0, 100],
26
+ target: [0, 0, 0],
27
+ up: [0, 1, 0],
28
+ ...options,
29
+ };
30
+ }
31
+
32
+ /**
33
+ * Create a perspective camera
34
+ * @param {string} id - Camera identifier
35
+ * @param {Object} options - Camera options
36
+ * @returns {THREE.PerspectiveCamera}
37
+ */
38
+ createPerspectiveCamera(id, options = {}) {
39
+ const config = {
40
+ fov: 75,
41
+ near: 0.1,
42
+ far: 1000,
43
+ aspect: window.innerWidth / window.innerHeight,
44
+ ...this.defaultOptions,
45
+ ...options,
46
+ };
47
+
48
+ const camera = new THREE.PerspectiveCamera(
49
+ config.fov,
50
+ config.aspect,
51
+ config.near,
52
+ config.far
53
+ );
54
+
55
+ this.setupCamera(camera, config);
56
+ this.storeCamera(id, camera, config);
57
+
58
+ return camera;
59
+ }
60
+
61
+ /**
62
+ * Create an orthographic camera
63
+ * @param {string} id - Camera identifier
64
+ * @param {Object} options - Camera options
65
+ * @returns {THREE.OrthographicCamera}
66
+ */
67
+ createOrthographicCamera(id, options = {}) {
68
+ const config = {
69
+ left: -50,
70
+ right: 50,
71
+ top: 50,
72
+ bottom: -50,
73
+ near: 0.1,
74
+ far: 1000,
75
+ ...this.defaultOptions,
76
+ ...options,
77
+ };
78
+
79
+ const camera = new THREE.OrthographicCamera(
80
+ config.left,
81
+ config.right,
82
+ config.top,
83
+ config.bottom,
84
+ config.near,
85
+ config.far
86
+ );
87
+
88
+ this.setupCamera(camera, config);
89
+ this.storeCamera(id, camera, config);
90
+
91
+ return camera;
92
+ }
93
+
94
+ /**
95
+ * Setup camera position and orientation
96
+ * @param {THREE.Camera} camera
97
+ * @param {Object} config
98
+ */
99
+ setupCamera(camera, config) {
100
+ // Set position
101
+ if (config.position) {
102
+ camera.position.set(...config.position);
103
+ }
104
+
105
+ // Set up vector
106
+ if (config.up) {
107
+ camera.up.set(...config.up);
108
+ }
109
+
110
+ // Look at target
111
+ if (config.target) {
112
+ camera.lookAt(...config.target);
113
+ }
114
+ }
115
+
116
+ /**
117
+ * Store camera in manager
118
+ * @param {string} id
119
+ * @param {THREE.Camera} camera
120
+ * @param {Object} config
121
+ */
122
+ storeCamera(id, camera, config) {
123
+ if (this.cameras.has(id)) {
124
+ console.warn(`Camera with id "${id}" already exists. Replacing.`);
125
+ this.disposeCamera(id);
126
+ }
127
+
128
+ this.cameras.set(id, {
129
+ camera,
130
+ config,
131
+ createdAt: Date.now(),
132
+ });
133
+
134
+ // Set as active if it's the first camera
135
+ if (!this.activeCameraId) {
136
+ this.activeCameraId = id;
137
+ }
138
+ }
139
+
140
+ /**
141
+ * Create a camera from configuration
142
+ * @param {string} id - Camera identifier
143
+ * @param {Object} config - Camera configuration
144
+ * @returns {THREE.Camera}
145
+ */
146
+ createCamera(id, config = {}) {
147
+ const type = config.type || this.defaultOptions.type;
148
+
149
+ switch (type) {
150
+ case CameraType.PERSPECTIVE:
151
+ return this.createPerspectiveCamera(id, config);
152
+ case CameraType.ORTHOGRAPHIC:
153
+ return this.createOrthographicCamera(id, config);
154
+ default:
155
+ throw new Error(`Unknown camera type: ${type}`);
156
+ }
157
+ }
158
+
159
+ /**
160
+ * Get a camera by ID
161
+ * @param {string} id - Camera identifier
162
+ * @returns {THREE.Camera|null}
163
+ */
164
+ getCamera(id) {
165
+ const cameraData = this.cameras.get(id);
166
+ return cameraData ? cameraData.camera : null;
167
+ }
168
+
169
+ /**
170
+ * Get the currently active camera
171
+ * @returns {THREE.Camera|null}
172
+ */
173
+ getActiveCamera() {
174
+ return this.activeCameraId ? this.getCamera(this.activeCameraId) : null;
175
+ }
176
+
177
+ /**
178
+ * Set the active camera
179
+ * @param {string} id - Camera identifier
180
+ */
181
+ setActiveCamera(id) {
182
+ if (!this.cameras.has(id)) {
183
+ throw new Error(`Camera with id "${id}" does not exist`);
184
+ }
185
+ this.activeCameraId = id;
186
+ }
187
+
188
+ /**
189
+ * Update camera aspect ratio (for perspective cameras)
190
+ * @param {string} id - Camera identifier
191
+ * @param {number} aspect - Aspect ratio
192
+ */
193
+ updateAspectRatio(id, aspect) {
194
+ const cameraData = this.cameras.get(id);
195
+ if (!cameraData) return;
196
+
197
+ const camera = cameraData.camera;
198
+ if (camera.isPerspectiveCamera) {
199
+ camera.aspect = aspect;
200
+ camera.updateProjectionMatrix();
201
+ }
202
+ }
203
+
204
+ /**
205
+ * Update orthographic camera bounds
206
+ * @param {string} id - Camera identifier
207
+ * @param {Object} bounds - Bounds { left, right, top, bottom }
208
+ */
209
+ updateOrthographicBounds(id, bounds) {
210
+ const cameraData = this.cameras.get(id);
211
+ if (!cameraData) return;
212
+
213
+ const camera = cameraData.camera;
214
+ if (camera.isOrthographicCamera) {
215
+ Object.assign(camera, bounds);
216
+ camera.updateProjectionMatrix();
217
+ }
218
+ }
219
+
220
+ /**
221
+ * Animate camera to a new position
222
+ * @param {string} id - Camera identifier
223
+ * @param {Object} target - Target position and lookAt
224
+ * @param {number} duration - Animation duration in milliseconds
225
+ * @returns {Promise<void>}
226
+ */
227
+ async animateTo(id, target, duration = 1000) {
228
+ const camera = this.getCamera(id);
229
+ if (!camera) throw new Error(`Camera with id "${id}" does not exist`);
230
+
231
+ const startPosition = camera.position.clone();
232
+ const startTarget = new THREE.Vector3(0, 0, -1).applyQuaternion(camera.quaternion).add(camera.position);
233
+
234
+ const endPosition = new THREE.Vector3(...(target.position || [0, 0, 100]));
235
+ const endTarget = new THREE.Vector3(...(target.target || [0, 0, 0]));
236
+
237
+ const startTime = Date.now();
238
+
239
+ return new Promise((resolve) => {
240
+ const animate = () => {
241
+ const elapsed = Date.now() - startTime;
242
+ const progress = Math.min(elapsed / duration, 1);
243
+
244
+ // Easing function (ease-in-out cubic)
245
+ const eased = progress < 0.5
246
+ ? 4 * progress * progress * progress
247
+ : 1 - Math.pow(-2 * progress + 2, 3) / 2;
248
+
249
+ // Interpolate position
250
+ camera.position.lerpVectors(startPosition, endPosition, eased);
251
+
252
+ // Interpolate target and look at it
253
+ const currentTarget = new THREE.Vector3().lerpVectors(startTarget, endTarget, eased);
254
+ camera.lookAt(currentTarget);
255
+
256
+ if (progress < 1) {
257
+ requestAnimationFrame(animate);
258
+ } else {
259
+ resolve();
260
+ }
261
+ };
262
+
263
+ animate();
264
+ });
265
+ }
266
+
267
+ /**
268
+ * Reset camera to initial configuration
269
+ * @param {string} id - Camera identifier
270
+ * @param {number} duration - Animation duration
271
+ */
272
+ async resetCamera(id, duration = 1000) {
273
+ const cameraData = this.cameras.get(id);
274
+ if (!cameraData) return;
275
+
276
+ const config = cameraData.config;
277
+ await this.animateTo(id, {
278
+ position: config.position,
279
+ target: config.target,
280
+ }, duration);
281
+ }
282
+
283
+ /**
284
+ * Remove a camera
285
+ * @param {string} id - Camera identifier
286
+ */
287
+ removeCamera(id) {
288
+ this.disposeCamera(id);
289
+
290
+ this.cameras.delete(id);
291
+
292
+ // Update active camera if needed
293
+ if (this.activeCameraId === id) {
294
+ const remainingCameras = Array.from(this.cameras.keys());
295
+ this.activeCameraId = remainingCameras.length > 0 ? remainingCameras[0] : null;
296
+ }
297
+ }
298
+
299
+ /**
300
+ * Dispose camera resources
301
+ * @param {string} id - Camera identifier
302
+ */
303
+ disposeCamera(id) {
304
+ const cameraData = this.cameras.get(id);
305
+ if (!cameraData) return;
306
+
307
+ // Cameras don't have much to dispose, but we clean up references
308
+ cameraData.camera = null;
309
+ }
310
+
311
+ /**
312
+ * Get all camera IDs
313
+ * @returns {string[]}
314
+ */
315
+ getCameraIds() {
316
+ return Array.from(this.cameras.keys());
317
+ }
318
+
319
+ /**
320
+ * Dispose all cameras
321
+ */
322
+ dispose() {
323
+ this.getCameraIds().forEach((id) => this.removeCamera(id));
324
+ this.activeCameraId = null;
325
+ }
326
+ }
327
+
328
+ /**
329
+ * Create a camera from configuration object
330
+ * @param {Object} config - Camera configuration
331
+ * @returns {THREE.Camera}
332
+ */
333
+ export function createCameraFromConfig(config = {}) {
334
+ const type = config.type || CameraType.PERSPECTIVE;
335
+ let camera;
336
+
337
+ if (type === CameraType.PERSPECTIVE) {
338
+ camera = new THREE.PerspectiveCamera(
339
+ config.fov || 75,
340
+ config.aspect || window.innerWidth / window.innerHeight,
341
+ config.near || 0.1,
342
+ config.far || 1000
343
+ );
344
+ } else {
345
+ camera = new THREE.OrthographicCamera(
346
+ config.left || -50,
347
+ config.right || 50,
348
+ config.top || 50,
349
+ config.bottom || -50,
350
+ config.near || 0.1,
351
+ config.far || 1000
352
+ );
353
+ }
354
+
355
+ // Set position
356
+ if (config.position) {
357
+ camera.position.set(...config.position);
358
+ }
359
+
360
+ // Set up vector
361
+ if (config.up) {
362
+ camera.up.set(...config.up);
363
+ }
364
+
365
+ // Look at target
366
+ if (config.target) {
367
+ camera.lookAt(...config.target);
368
+ }
369
+
370
+ return camera;
371
+ }
372
+
373
+ export default CameraManager;