visualifyjs 2.5.3 → 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 -193
  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 -0
  63. package/docs/docs/_404.md +51 -51
  64. package/docs/docs/_coverpage.md +11 -11
  65. package/docs/docs/_sidebar.md +54 -43
  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 -123
  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 -1
  81. package/docs/docs/more-pages.md +23 -23
  82. package/docs/docs/quickstart.md +148 -119
  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 -579
  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 -143
  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,364 @@
1
+ /**
2
+ * Renderer.js - Three.js WebGL Renderer for Visualify.js
3
+ * Handles renderer setup, antialiasing, resize handling, and pixel ratio support
4
+ */
5
+
6
+ import * as THREE from 'three';
7
+
8
+ /**
9
+ * RendererManager class for managing WebGL renderers
10
+ */
11
+ export class RendererManager {
12
+ constructor(options = {}) {
13
+ this.renderers = new Map();
14
+ this.activeRendererId = null;
15
+
16
+ this.defaultOptions = {
17
+ antialias: true,
18
+ alpha: true,
19
+ powerPreference: 'high-performance',
20
+ precision: 'highp',
21
+ stencil: false,
22
+ depth: true,
23
+ logarithmicDepthBuffer: false,
24
+ ...options,
25
+ };
26
+ }
27
+
28
+ /**
29
+ * Create a new WebGL renderer
30
+ * @param {string} id - Renderer identifier
31
+ * @param {HTMLCanvasElement} canvas - Canvas element
32
+ * @param {Object} options - Renderer options
33
+ * @returns {THREE.WebGLRenderer}
34
+ */
35
+ createRenderer(id, canvas, options = {}) {
36
+ if (this.renderers.has(id)) {
37
+ console.warn(`Renderer with id "${id}" already exists. Returning existing renderer.`);
38
+ return this.renderers.get(id).renderer;
39
+ }
40
+
41
+ const config = { ...this.defaultOptions, ...options };
42
+
43
+ // Create renderer
44
+ const renderer = new THREE.WebGLRenderer({
45
+ canvas,
46
+ antialias: config.antialias,
47
+ alpha: config.alpha,
48
+ powerPreference: config.powerPreference,
49
+ stencil: config.stencil,
50
+ depth: config.depth,
51
+ logarithmicDepthBuffer: config.logarithmicDepthBuffer,
52
+ });
53
+
54
+ // Configure renderer
55
+ this.configureRenderer(renderer, config);
56
+
57
+ // Store renderer
58
+ this.renderers.set(id, {
59
+ renderer,
60
+ config,
61
+ canvas,
62
+ resizeObserver: null,
63
+ createdAt: Date.now(),
64
+ });
65
+
66
+ // Set as active if it's the first renderer
67
+ if (!this.activeRendererId) {
68
+ this.activeRendererId = id;
69
+ }
70
+
71
+ return renderer;
72
+ }
73
+
74
+ /**
75
+ * Configure renderer settings
76
+ * @param {THREE.WebGLRenderer} renderer
77
+ * @param {Object} config
78
+ */
79
+ configureRenderer(renderer, config) {
80
+ // Set pixel ratio (capped at 2 for performance)
81
+ const pixelRatio = Math.min(window.devicePixelRatio, 2);
82
+ renderer.setPixelRatio(pixelRatio);
83
+
84
+ // Set size
85
+ if (config.width && config.height) {
86
+ renderer.setSize(config.width, config.height);
87
+ }
88
+
89
+ // Set precision
90
+ if (config.precision) {
91
+ renderer.capabilities.precision = config.precision;
92
+ }
93
+
94
+ // Configure shadow map
95
+ if (config.shadowMap !== false) {
96
+ renderer.shadowMap.enabled = true;
97
+ renderer.shadowMap.type = config.shadowMapType || THREE.PCFSoftShadowMap;
98
+ }
99
+
100
+ // Set output color space
101
+ renderer.outputColorSpace = THREE.SRGBColorSpace;
102
+
103
+ // Set tone mapping
104
+ if (config.toneMapping) {
105
+ renderer.toneMapping = config.toneMapping;
106
+ if (config.toneMappingExposure) {
107
+ renderer.toneMappingExposure = config.toneMappingExposure;
108
+ }
109
+ }
110
+
111
+ // Set clear color
112
+ if (config.clearColor !== undefined) {
113
+ renderer.setClearColor(config.clearColor, config.clearAlpha ?? 1);
114
+ }
115
+ }
116
+
117
+ /**
118
+ * Get a renderer by ID
119
+ * @param {string} id - Renderer identifier
120
+ * @returns {THREE.WebGLRenderer|null}
121
+ */
122
+ getRenderer(id) {
123
+ const rendererData = this.renderers.get(id);
124
+ return rendererData ? rendererData.renderer : null;
125
+ }
126
+
127
+ /**
128
+ * Get the currently active renderer
129
+ * @returns {THREE.WebGLRenderer|null}
130
+ */
131
+ getActiveRenderer() {
132
+ return this.activeRendererId ? this.getRenderer(this.activeRendererId) : null;
133
+ }
134
+
135
+ /**
136
+ * Set the active renderer
137
+ * @param {string} id - Renderer identifier
138
+ */
139
+ setActiveRenderer(id) {
140
+ if (!this.renderers.has(id)) {
141
+ throw new Error(`Renderer with id "${id}" does not exist`);
142
+ }
143
+ this.activeRendererId = id;
144
+ }
145
+
146
+ /**
147
+ * Update renderer size
148
+ * @param {string} id - Renderer identifier
149
+ * @param {number} width
150
+ * @param {number} height
151
+ */
152
+ updateSize(id, width, height) {
153
+ const rendererData = this.renderers.get(id);
154
+ if (!rendererData) return;
155
+
156
+ const renderer = rendererData.renderer;
157
+ renderer.setSize(width, height);
158
+
159
+ // Update config
160
+ rendererData.config.width = width;
161
+ rendererData.config.height = height;
162
+ }
163
+
164
+ /**
165
+ * Update pixel ratio
166
+ * @param {string} id - Renderer identifier
167
+ * @param {number} pixelRatio
168
+ */
169
+ updatePixelRatio(id, pixelRatio) {
170
+ const rendererData = this.renderers.get(id);
171
+ if (!rendererData) return;
172
+
173
+ const renderer = rendererData.renderer;
174
+ renderer.setPixelRatio(Math.min(pixelRatio, 2));
175
+ }
176
+
177
+ /**
178
+ * Enable automatic resize handling
179
+ * @param {string} id - Renderer identifier
180
+ * @param {HTMLElement} container - Container element
181
+ */
182
+ enableAutoResize(id, container) {
183
+ const rendererData = this.renderers.get(id);
184
+ if (!rendererData) return;
185
+
186
+ // Clean up existing observer
187
+ if (rendererData.resizeObserver) {
188
+ rendererData.resizeObserver.disconnect();
189
+ }
190
+
191
+ // Create resize observer
192
+ const resizeObserver = new ResizeObserver((entries) => {
193
+ for (const entry of entries) {
194
+ const { width, height } = entry.contentRect;
195
+ this.updateSize(id, width, height);
196
+ }
197
+ });
198
+
199
+ resizeObserver.observe(container);
200
+ rendererData.resizeObserver = resizeObserver;
201
+ }
202
+
203
+ /**
204
+ * Disable automatic resize handling
205
+ * @param {string} id - Renderer identifier
206
+ */
207
+ disableAutoResize(id) {
208
+ const rendererData = this.renderers.get(id);
209
+ if (!rendererData || !rendererData.resizeObserver) return;
210
+
211
+ rendererData.resizeObserver.disconnect();
212
+ rendererData.resizeObserver = null;
213
+ }
214
+
215
+ /**
216
+ * Render a scene with a camera
217
+ * @param {string} id - Renderer identifier
218
+ * @param {THREE.Scene} scene
219
+ * @param {THREE.Camera} camera
220
+ */
221
+ render(id, scene, camera) {
222
+ const renderer = this.getRenderer(id);
223
+ if (!renderer) return;
224
+
225
+ renderer.render(scene, camera);
226
+ }
227
+
228
+ /**
229
+ * Take a screenshot
230
+ * @param {string} id - Renderer identifier
231
+ * @param {string} mimeType - Image mime type
232
+ * @param {number} quality - Image quality (0-1)
233
+ * @returns {string} Data URL
234
+ */
235
+ takeScreenshot(id, mimeType = 'image/png', quality = 1) {
236
+ const renderer = this.getRenderer(id);
237
+ if (!renderer) return null;
238
+
239
+ return renderer.domElement.toDataURL(mimeType, quality);
240
+ }
241
+
242
+ /**
243
+ * Get WebGL info
244
+ * @param {string} id - Renderer identifier
245
+ * @returns {Object|null}
246
+ */
247
+ getWebGLInfo(id) {
248
+ const renderer = this.getRenderer(id);
249
+ if (!renderer) return null;
250
+
251
+ return {
252
+ renderer: renderer.info.render,
253
+ memory: renderer.info.memory,
254
+ programs: renderer.info.programs?.length || 0,
255
+ };
256
+ }
257
+
258
+ /**
259
+ * Reset WebGL info counters
260
+ * @param {string} id - Renderer identifier
261
+ */
262
+ resetInfo(id) {
263
+ const renderer = this.getRenderer(id);
264
+ if (!renderer) return;
265
+
266
+ renderer.info.reset();
267
+ }
268
+
269
+ /**
270
+ * Compile shaders for a scene
271
+ * @param {string} id - Renderer identifier
272
+ * @param {THREE.Scene} scene
273
+ * @param {THREE.Camera} camera
274
+ */
275
+ compile(id, scene, camera) {
276
+ const renderer = this.getRenderer(id);
277
+ if (!renderer) return;
278
+
279
+ renderer.compile(scene, camera);
280
+ }
281
+
282
+ /**
283
+ * Dispose of a renderer
284
+ * @param {string} id - Renderer identifier
285
+ */
286
+ removeRenderer(id) {
287
+ const rendererData = this.renderers.get(id);
288
+ if (!rendererData) return;
289
+
290
+ // Disable auto resize
291
+ this.disableAutoResize(id);
292
+
293
+ // Dispose renderer
294
+ rendererData.renderer.dispose();
295
+
296
+ // Remove from map
297
+ this.renderers.delete(id);
298
+
299
+ // Update active renderer if needed
300
+ if (this.activeRendererId === id) {
301
+ const remainingRenderers = Array.from(this.renderers.keys());
302
+ this.activeRendererId = remainingRenderers.length > 0 ? remainingRenderers[0] : null;
303
+ }
304
+ }
305
+
306
+ /**
307
+ * Get all renderer IDs
308
+ * @returns {string[]}
309
+ */
310
+ getRendererIds() {
311
+ return Array.from(this.renderers.keys());
312
+ }
313
+
314
+ /**
315
+ * Dispose all renderers
316
+ */
317
+ dispose() {
318
+ this.getRendererIds().forEach((id) => this.removeRenderer(id));
319
+ this.activeRendererId = null;
320
+ }
321
+ }
322
+
323
+ /**
324
+ * Create a renderer from configuration
325
+ * @param {HTMLCanvasElement} canvas
326
+ * @param {Object} config
327
+ * @returns {THREE.WebGLRenderer}
328
+ */
329
+ export function createRendererFromConfig(canvas, config = {}) {
330
+ const manager = new RendererManager(config);
331
+ return manager.createRenderer('default', canvas, config);
332
+ }
333
+
334
+ /**
335
+ * Handle window resize for a renderer
336
+ * @param {THREE.WebGLRenderer} renderer
337
+ * @param {THREE.Camera} camera
338
+ * @param {HTMLElement} container
339
+ */
340
+ export function handleResize(renderer, camera, container) {
341
+ const width = container.clientWidth;
342
+ const height = container.clientHeight;
343
+
344
+ renderer.setSize(width, height);
345
+
346
+ if (camera.isPerspectiveCamera) {
347
+ camera.aspect = width / height;
348
+ camera.updateProjectionMatrix();
349
+ } else if (camera.isOrthographicCamera) {
350
+ const aspect = width / height;
351
+ const frustumSize = Math.max(
352
+ camera.right - camera.left,
353
+ camera.top - camera.bottom
354
+ );
355
+
356
+ camera.left = -frustumSize * aspect / 2;
357
+ camera.right = frustumSize * aspect / 2;
358
+ camera.top = frustumSize / 2;
359
+ camera.bottom = -frustumSize / 2;
360
+ camera.updateProjectionMatrix();
361
+ }
362
+ }
363
+
364
+ export default RendererManager;
@@ -0,0 +1,266 @@
1
+ /**
2
+ * Scene.js - Three.js Scene Manager for Visualify.js
3
+ * Handles scene creation, scene graph operations, and multiple viewport support
4
+ */
5
+
6
+ import * as THREE from 'three';
7
+
8
+ /**
9
+ * SceneManager class for managing Three.js scenes
10
+ */
11
+ export class SceneManager {
12
+ constructor(options = {}) {
13
+ this.scenes = new Map();
14
+ this.activeSceneId = null;
15
+ this.defaultOptions = {
16
+ backgroundColor: 0x000000,
17
+ fog: null,
18
+ ...options,
19
+ };
20
+ }
21
+
22
+ /**
23
+ * Create a new scene
24
+ * @param {string} id - Unique scene identifier
25
+ * @param {Object} options - Scene configuration options
26
+ * @returns {THREE.Scene} The created scene
27
+ */
28
+ createScene(id, options = {}) {
29
+ if (this.scenes.has(id)) {
30
+ console.warn(`Scene with id "${id}" already exists. Returning existing scene.`);
31
+ return this.scenes.get(id).scene;
32
+ }
33
+
34
+ const scene = new THREE.Scene();
35
+ const config = { ...this.defaultOptions, ...options };
36
+
37
+ // Set background
38
+ if (config.backgroundColor !== undefined) {
39
+ scene.background = new THREE.Color(config.backgroundColor);
40
+ }
41
+
42
+ // Set fog if provided
43
+ if (config.fog) {
44
+ scene.fog = new THREE.Fog(
45
+ config.fog.color || 0x000000,
46
+ config.fog.near || 1,
47
+ config.fog.far || 1000
48
+ );
49
+ }
50
+
51
+ // Store scene with metadata
52
+ this.scenes.set(id, {
53
+ scene,
54
+ config,
55
+ objects: new Map(),
56
+ createdAt: Date.now(),
57
+ });
58
+
59
+ // Set as active if it's the first scene
60
+ if (!this.activeSceneId) {
61
+ this.activeSceneId = id;
62
+ }
63
+
64
+ return scene;
65
+ }
66
+
67
+ /**
68
+ * Get a scene by ID
69
+ * @param {string} id - Scene identifier
70
+ * @returns {THREE.Scene|null}
71
+ */
72
+ getScene(id) {
73
+ const sceneData = this.scenes.get(id);
74
+ return sceneData ? sceneData.scene : null;
75
+ }
76
+
77
+ /**
78
+ * Get the currently active scene
79
+ * @returns {THREE.Scene|null}
80
+ */
81
+ getActiveScene() {
82
+ return this.activeSceneId ? this.getScene(this.activeSceneId) : null;
83
+ }
84
+
85
+ /**
86
+ * Set the active scene
87
+ * @param {string} id - Scene identifier
88
+ */
89
+ setActiveScene(id) {
90
+ if (!this.scenes.has(id)) {
91
+ throw new Error(`Scene with id "${id}" does not exist`);
92
+ }
93
+ this.activeSceneId = id;
94
+ }
95
+
96
+ /**
97
+ * Add an object to a scene
98
+ * @param {string} sceneId - Scene identifier
99
+ * @param {string} objectId - Object identifier
100
+ * @param {THREE.Object3D} object - Three.js object
101
+ */
102
+ addObject(sceneId, objectId, object) {
103
+ const sceneData = this.scenes.get(sceneId);
104
+ if (!sceneData) {
105
+ throw new Error(`Scene with id "${sceneId}" does not exist`);
106
+ }
107
+
108
+ sceneData.scene.add(object);
109
+ sceneData.objects.set(objectId, object);
110
+ }
111
+
112
+ /**
113
+ * Remove an object from a scene
114
+ * @param {string} sceneId - Scene identifier
115
+ * @param {string} objectId - Object identifier
116
+ */
117
+ removeObject(sceneId, objectId) {
118
+ const sceneData = this.scenes.get(sceneId);
119
+ if (!sceneData) return;
120
+
121
+ const object = sceneData.objects.get(objectId);
122
+ if (object) {
123
+ sceneData.scene.remove(object);
124
+ this.disposeObject(object);
125
+ sceneData.objects.delete(objectId);
126
+ }
127
+ }
128
+
129
+ /**
130
+ * Get an object from a scene
131
+ * @param {string} sceneId - Scene identifier
132
+ * @param {string} objectId - Object identifier
133
+ * @returns {THREE.Object3D|null}
134
+ */
135
+ getObject(sceneId, objectId) {
136
+ const sceneData = this.scenes.get(sceneId);
137
+ return sceneData ? sceneData.objects.get(objectId) || null : null;
138
+ }
139
+
140
+ /**
141
+ * Clear all objects from a scene
142
+ * @param {string} sceneId - Scene identifier
143
+ */
144
+ clearScene(sceneId) {
145
+ const sceneData = this.scenes.get(sceneId);
146
+ if (!sceneData) return;
147
+
148
+ // Remove and dispose all objects
149
+ sceneData.objects.forEach((object, objectId) => {
150
+ sceneData.scene.remove(object);
151
+ this.disposeObject(object);
152
+ });
153
+ sceneData.objects.clear();
154
+ }
155
+
156
+ /**
157
+ * Remove a scene and dispose all resources
158
+ * @param {string} id - Scene identifier
159
+ */
160
+ removeScene(id) {
161
+ const sceneData = this.scenes.get(id);
162
+ if (!sceneData) return;
163
+
164
+ // Clear all objects
165
+ this.clearScene(id);
166
+
167
+ // Dispose scene
168
+ if (sceneData.scene.background) {
169
+ if (sceneData.scene.background.dispose) {
170
+ sceneData.scene.background.dispose();
171
+ }
172
+ }
173
+
174
+ this.scenes.delete(id);
175
+
176
+ // Update active scene if needed
177
+ if (this.activeSceneId === id) {
178
+ const remainingScenes = Array.from(this.scenes.keys());
179
+ this.activeSceneId = remainingScenes.length > 0 ? remainingScenes[0] : null;
180
+ }
181
+ }
182
+
183
+ /**
184
+ * Dispose a Three.js object and its resources
185
+ * @param {THREE.Object3D} object
186
+ */
187
+ disposeObject(object) {
188
+ if (!object) return;
189
+
190
+ // Traverse and dispose geometries and materials
191
+ object.traverse((child) => {
192
+ if (child.geometry) {
193
+ child.geometry.dispose();
194
+ }
195
+
196
+ if (child.material) {
197
+ if (Array.isArray(child.material)) {
198
+ child.material.forEach((material) => this.disposeMaterial(material));
199
+ } else {
200
+ this.disposeMaterial(child.material);
201
+ }
202
+ }
203
+ });
204
+ }
205
+
206
+ /**
207
+ * Dispose material and its textures
208
+ * @param {THREE.Material} material
209
+ */
210
+ disposeMaterial(material) {
211
+ if (!material) return;
212
+
213
+ // Dispose textures
214
+ Object.keys(material).forEach((key) => {
215
+ const value = material[key];
216
+ if (value && value.isTexture) {
217
+ value.dispose();
218
+ }
219
+ });
220
+
221
+ material.dispose();
222
+ }
223
+
224
+ /**
225
+ * Get all scene IDs
226
+ * @returns {string[]}
227
+ */
228
+ getSceneIds() {
229
+ return Array.from(this.scenes.keys());
230
+ }
231
+
232
+ /**
233
+ * Dispose all scenes and resources
234
+ */
235
+ dispose() {
236
+ this.getSceneIds().forEach((id) => this.removeScene(id));
237
+ this.activeSceneId = null;
238
+ }
239
+ }
240
+
241
+ /**
242
+ * Create a scene from configuration
243
+ * @param {Object} config - Scene configuration
244
+ * @returns {THREE.Scene}
245
+ */
246
+ export function createSceneFromConfig(config = {}) {
247
+ const scene = new THREE.Scene();
248
+
249
+ // Set background color
250
+ if (config.backgroundColor) {
251
+ scene.background = new THREE.Color(config.backgroundColor);
252
+ }
253
+
254
+ // Set fog
255
+ if (config.fog) {
256
+ scene.fog = new THREE.Fog(
257
+ config.fog.color || 0x000000,
258
+ config.fog.near || 1,
259
+ config.fog.far || 1000
260
+ );
261
+ }
262
+
263
+ return scene;
264
+ }
265
+
266
+ export default SceneManager;