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
@@ -1,62 +1,361 @@
1
- /*
2
- * @Author : Lihao leolihao@arizona.edu
3
- * @Date : 2023-11-29 16:02:42
4
- * @FilePath : /visualifyjs/src/core/recharts.js
5
- * @Description :
6
- * Copyright (c) 2023 by Lihao (leolihao@arizona.edu), All Rights Reserved.
7
- */
8
- import React from 'react';
9
- import { createRoot } from 'react-dom/client';
10
- import EChartSwitcher from './modules/echartswitcher';
11
- import { VisualifyProvider } from './appContext';
12
-
13
- class Recharts {
14
- constructor(config = {}) {
15
- //console.log('config', config);
16
- const { el = null } = config;
17
- // Default to empty object if nothing is passed
18
- if (typeof el === 'string') {
19
- this.selector = document.querySelector(el);
20
- if (!this.selector) {
21
- throw new Error(`Element not found with selector: ${el}`);
22
- }
23
- } else {
24
- this.selector = el;
25
- }
26
- const { parser = null, advanced = null, ...rest } = config;
27
- this.config = rest;
28
- this.parser = parser;
29
- this.advanced = advanced;
30
- }
31
-
32
- mount(selector = this.selector) {
33
- const el =
34
- typeof selector === 'string'
35
- ? document.querySelector(selector)
36
- : selector;
37
-
38
- if (!el)
39
- throw new Error(`Element not found with selector: ${selector}`);
40
-
41
- try {
42
- // Assuming createRoot is imported from 'react-dom/client'
43
- const charts = createRoot(el);
44
- charts.render(
45
- <VisualifyProvider>
46
- <EChartSwitcher
47
- props={{
48
- config: this.config,
49
- parser: this.parser,
50
- advanced: this.advanced,
51
- }}
52
- />
53
- </VisualifyProvider>,
54
- );
55
- //console.log('mounted ' + selector, el);
56
- } catch (e) {
57
- console.error('Error mounting chart:', e);
58
- }
59
- }
60
- }
61
-
62
- export default Recharts;
1
+ /*
2
+ * @Author : Lihao leolihao@arizona.edu
3
+ * @Date : 2023-11-29 16:02:42
4
+ * @FilePath : /visualifyjs/src/core/recharts.js
5
+ * @Description :
6
+ * Copyright (c) 2023 by Lihao (leolihao@arizona.edu), All Rights Reserved.
7
+ */
8
+ import React, { useEffect, useRef, useState, useCallback } from 'react';
9
+ import { createRoot } from 'react-dom/client';
10
+ import EChartSwitcher from './modules/echartswitcher';
11
+ import { VisualifyProvider } from './appContext';
12
+ import { initHMR, useHMR, preserveChartState, restoreChartState } from './hmr-client';
13
+
14
+ // Import 3D components for docs mode support
15
+ import Scatter3D from './components/Scatter3D';
16
+ import Bar3D from './components/Bar3D';
17
+ import Surface3D from './components/Surface3D';
18
+ import Line3D from './components/Line3D';
19
+
20
+ /**
21
+ * Map of 3D chart types to their components
22
+ * @type {Object<string, React.Component>}
23
+ */
24
+ const CHART_3D_COMPONENTS = {
25
+ scatter3d: Scatter3D,
26
+ bar3d: Bar3D,
27
+ surface3d: Surface3D,
28
+ line3d: Line3D,
29
+ };
30
+
31
+ /**
32
+ * Check if a chart type is a 3D chart
33
+ * @param {string} type - Chart type from config
34
+ * @returns {boolean} True if 3D chart type
35
+ */
36
+ function is3DChartType(type) {
37
+ if (!type) return false;
38
+ const normalizedType = type.toLowerCase();
39
+ return Object.keys(CHART_3D_COMPONENTS).includes(normalizedType);
40
+ }
41
+
42
+ /**
43
+ * Global registry of chart instances for HMR state preservation
44
+ * @type {Map<string, Object>}
45
+ */
46
+ const chartRegistry = new Map();
47
+
48
+ /**
49
+ * Chart wrapper component with HMR support
50
+ * Renders either standard ECharts or 3D components based on config type
51
+ * @param {Object} props - Component props
52
+ * @param {Object} props.config - Chart configuration
53
+ * @param {Object} [props.parser] - Data parser
54
+ * @param {Object} [props.advanced] - Advanced options
55
+ * @param {string} [props.chartId] - Unique chart identifier
56
+ */
57
+ function ChartWithHMR({ config, parser, advanced, chartId }) {
58
+ const chartRef = useRef(null);
59
+ const [currentConfig, setCurrentConfig] = useState(config);
60
+ const preservedStateRef = useRef(null);
61
+
62
+ // Determine if this is a 3D chart
63
+ const is3D = is3DChartType(currentConfig.type);
64
+
65
+ // Preserve chart state before updates
66
+ const preserveState = useCallback(() => {
67
+ if (chartRef.current) {
68
+ const instance = chartRef.current.getEchartsInstance?.() || chartRef.current;
69
+ preservedStateRef.current = preserveChartState(instance);
70
+
71
+ // Also store in global registry
72
+ if (chartId) {
73
+ chartRegistry.set(chartId, preservedStateRef.current);
74
+ }
75
+
76
+ return preservedStateRef.current;
77
+ }
78
+ return null;
79
+ }, [chartId]);
80
+
81
+ // Setup HMR integration
82
+ useHMR({
83
+ configType: 'component',
84
+ onUpdate: (update) => {
85
+ if (update.config) {
86
+ // Preserve current state before updating
87
+ preserveState();
88
+
89
+ // Update config
90
+ setCurrentConfig(update.config);
91
+ }
92
+ },
93
+ onError: (error) => {
94
+ console.error('[Recharts] HMR error:', error.message);
95
+ },
96
+ preserveState,
97
+ });
98
+
99
+ // Restore state after config update
100
+ useEffect(() => {
101
+ if (preservedStateRef.current && chartRef.current) {
102
+ // Small delay to ensure chart is rendered
103
+ const timer = setTimeout(() => {
104
+ const instance = chartRef.current.getEchartsInstance?.() || chartRef.current;
105
+ restoreChartState(instance, preservedStateRef.current);
106
+ }, 100);
107
+
108
+ return () => clearTimeout(timer);
109
+ }
110
+ }, [currentConfig]);
111
+
112
+ // Render 3D chart component
113
+ if (is3D) {
114
+ const Component3D = CHART_3D_COMPONENTS[currentConfig.type.toLowerCase()];
115
+ return (
116
+ <Component3D
117
+ ref={chartRef}
118
+ props={{
119
+ config: currentConfig,
120
+ parser: parser,
121
+ advanced: advanced,
122
+ id: chartId,
123
+ }}
124
+ />
125
+ );
126
+ }
127
+
128
+ // Render standard EChart
129
+ return (
130
+ <EChartSwitcher
131
+ ref={chartRef}
132
+ props={{
133
+ config: currentConfig,
134
+ parser: parser,
135
+ advanced: advanced,
136
+ }}
137
+ />
138
+ );
139
+ }
140
+
141
+ class Recharts {
142
+ constructor(config = {}) {
143
+ const { el = null, id = null } = config;
144
+ // Default to empty object if nothing is passed
145
+ if (typeof el === 'string') {
146
+ this.selector = document.querySelector(el);
147
+ if (!this.selector) {
148
+ throw new Error(`Element not found with selector: ${el}`);
149
+ }
150
+ } else {
151
+ this.selector = el;
152
+ }
153
+ const { parser = null, advanced = null, ...rest } = config;
154
+ this.config = rest;
155
+ this.parser = parser;
156
+ this.advanced = advanced;
157
+ this.chartId = id || `chart-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
158
+ this.root = null;
159
+ this.isMounted = false;
160
+
161
+ // Initialize HMR if available
162
+ if (typeof window !== 'undefined' && window.__VISUALIFY_HMR__?.enabled) {
163
+ initHMR();
164
+ }
165
+ }
166
+
167
+ /**
168
+ * Mount the chart to the DOM
169
+ * @param {string|Element} [selector=this.selector] - Selector or element to mount to
170
+ * @returns {Recharts} This instance for chaining
171
+ */
172
+ mount(selector = this.selector) {
173
+ const el =
174
+ typeof selector === 'string'
175
+ ? document.querySelector(selector)
176
+ : selector;
177
+
178
+ if (!el)
179
+ throw new Error(`Element not found with selector: ${selector}`);
180
+
181
+ try {
182
+ // Check for preserved state from HMR
183
+ const preservedState = chartRegistry.get(this.chartId);
184
+
185
+ // Create or reuse root
186
+ if (!this.root) {
187
+ this.root = createRoot(el);
188
+ }
189
+
190
+ this.root.render(
191
+ <VisualifyProvider>
192
+ <ChartWithHMR
193
+ config={this.config}
194
+ parser={this.parser}
195
+ advanced={this.advanced}
196
+ chartId={this.chartId}
197
+ />
198
+ </VisualifyProvider>,
199
+ );
200
+
201
+ this.isMounted = true;
202
+
203
+ // Register for HMR updates
204
+ this.registerHMR();
205
+ } catch (e) {
206
+ console.error('Error mounting chart:', e);
207
+ }
208
+
209
+ return this;
210
+ }
211
+
212
+ /**
213
+ * Unmount the chart and cleanup
214
+ * @returns {Recharts} This instance for chaining
215
+ */
216
+ unmount() {
217
+ if (this.root) {
218
+ // Preserve state before unmounting
219
+ this.preserveState();
220
+
221
+ this.root.unmount();
222
+ this.root = null;
223
+ this.isMounted = false;
224
+ }
225
+
226
+ // Unregister from HMR
227
+ this.unregisterHMR();
228
+
229
+ return this;
230
+ }
231
+
232
+ /**
233
+ * Update the chart configuration (for HMR)
234
+ * @param {Object} newConfig - New configuration
235
+ * @returns {Recharts} This instance for chaining
236
+ */
237
+ update(newConfig) {
238
+ // Preserve current state
239
+ this.preserveState();
240
+
241
+ // Update config
242
+ const { parser, advanced, ...rest } = newConfig;
243
+ this.config = { ...this.config, ...rest };
244
+ if (parser) this.parser = parser;
245
+ if (advanced) this.advanced = advanced;
246
+
247
+ // Re-mount if already mounted
248
+ if (this.isMounted) {
249
+ this.mount();
250
+ }
251
+
252
+ return this;
253
+ }
254
+
255
+ /**
256
+ * Preserve the current chart state
257
+ * @returns {Object|null} The preserved state
258
+ */
259
+ preserveState() {
260
+ // State is preserved in the ChartWithHMR component
261
+ // This method is for external access
262
+ const state = chartRegistry.get(this.chartId);
263
+ return state || null;
264
+ }
265
+
266
+ /**
267
+ * Restore chart state
268
+ * @param {Object} state - State to restore
269
+ * @returns {Recharts} This instance for chaining
270
+ */
271
+ restoreState(state) {
272
+ if (state) {
273
+ chartRegistry.set(this.chartId, state);
274
+ }
275
+ return this;
276
+ }
277
+
278
+ /**
279
+ * Register this chart for HMR updates
280
+ * @private
281
+ */
282
+ registerHMR() {
283
+ if (typeof window === 'undefined') return;
284
+
285
+ // Store reference for HMR updates
286
+ if (!window.__VISUALIFY_CHARTS__) {
287
+ window.__VISUALIFY_CHARTS__ = new Map();
288
+ }
289
+ window.__VISUALIFY_CHARTS__.set(this.chartId, this);
290
+ }
291
+
292
+ /**
293
+ * Unregister this chart from HMR updates
294
+ * @private
295
+ */
296
+ unregisterHMR() {
297
+ if (typeof window === 'undefined') return;
298
+
299
+ window.__VISUALIFY_CHARTS__?.delete(this.chartId);
300
+ chartRegistry.delete(this.chartId);
301
+ }
302
+
303
+ /**
304
+ * Get the chart ID
305
+ * @returns {string} The chart ID
306
+ */
307
+ getId() {
308
+ return this.chartId;
309
+ }
310
+
311
+ /**
312
+ * Check if the chart is mounted
313
+ * @returns {boolean} Whether the chart is mounted
314
+ */
315
+ getIsMounted() {
316
+ return this.isMounted;
317
+ }
318
+ }
319
+
320
+ /**
321
+ * Reload all mounted charts (for HMR)
322
+ * @param {Object} [configUpdate] - Optional configuration update
323
+ */
324
+ export function reloadAllCharts(configUpdate) {
325
+ if (typeof window === 'undefined') return;
326
+
327
+ const charts = window.__VISUALIFY_CHARTS__;
328
+ if (!charts) return;
329
+
330
+ charts.forEach((chart) => {
331
+ if (chart.getIsMounted() && configUpdate) {
332
+ chart.update(configUpdate);
333
+ }
334
+ });
335
+ }
336
+
337
+ /**
338
+ * Preserve state of all charts
339
+ * @returns {Map<string, Object>} Map of chart IDs to preserved states
340
+ */
341
+ export function preserveAllChartStates() {
342
+ const states = new Map();
343
+
344
+ chartRegistry.forEach((state, chartId) => {
345
+ states.set(chartId, state);
346
+ });
347
+
348
+ return states;
349
+ }
350
+
351
+ /**
352
+ * Restore state to all charts
353
+ * @param {Map<string, Object>} states - Map of chart IDs to states
354
+ */
355
+ export function restoreAllChartStates(states) {
356
+ states.forEach((state, chartId) => {
357
+ chartRegistry.set(chartId, state);
358
+ });
359
+ }
360
+
361
+ export default Recharts;
@@ -1,49 +1,49 @@
1
- /*
2
- * @Author : Lihao leolihao@arizona.edu
3
- * @Date : 2023-12-04 12:47:02
4
- * @FilePath : /visualifyjs/src/core/router/alias.js
5
- * @Description :
6
- * Copyright (c) 2023 by Lihao (leolihao@arizona.edu), All Rights Reserved.
7
- */
8
- import { Navigate, useLocation } from 'react-router-dom';
9
-
10
- const AliasRoute = ({ alias, children }) => {
11
- const location = useLocation();
12
-
13
- for (const pattern in alias) {
14
- const regex = new RegExp(pattern);
15
- if (regex.test(location.pathname)) {
16
- const target = alias[pattern];
17
-
18
- // Check if the target is defined and is a string
19
- if (typeof target === 'string') {
20
- // Check if target is a URL or a path
21
- if (
22
- target.startsWith('http://') ||
23
- target.startsWith('https://')
24
- ) {
25
- window.location.href = target;
26
- return null;
27
- }
28
-
29
- // Redirect to the matched route
30
- const newPath = location.pathname.replace(regex, target);
31
- return (
32
- <Navigate
33
- to={newPath}
34
- replace
35
- />
36
- );
37
- } else {
38
- console.error(
39
- `Alias target for pattern '${pattern}' is not defined or not a string.`,
40
- );
41
- continue; // Skip to the next pattern
42
- }
43
- }
44
- }
45
-
46
- return children;
47
- };
48
-
49
- export default AliasRoute;
1
+ /*
2
+ * @Author : Lihao leolihao@arizona.edu
3
+ * @Date : 2023-12-04 12:47:02
4
+ * @FilePath : /visualifyjs/src/core/router/alias.js
5
+ * @Description :
6
+ * Copyright (c) 2023 by Lihao (leolihao@arizona.edu), All Rights Reserved.
7
+ */
8
+ import { Navigate, useLocation } from 'react-router-dom';
9
+
10
+ const AliasRoute = ({ alias, children }) => {
11
+ const location = useLocation();
12
+
13
+ for (const pattern in alias) {
14
+ const regex = new RegExp(pattern);
15
+ if (regex.test(location.pathname)) {
16
+ const target = alias[pattern];
17
+
18
+ // Check if the target is defined and is a string
19
+ if (typeof target === 'string') {
20
+ // Check if target is a URL or a path
21
+ if (
22
+ target.startsWith('http://') ||
23
+ target.startsWith('https://')
24
+ ) {
25
+ window.location.href = target;
26
+ return null;
27
+ }
28
+
29
+ // Redirect to the matched route
30
+ const newPath = location.pathname.replace(regex, target);
31
+ return (
32
+ <Navigate
33
+ to={newPath}
34
+ replace
35
+ />
36
+ );
37
+ } else {
38
+ console.error(
39
+ `Alias target for pattern '${pattern}' is not defined or not a string.`,
40
+ );
41
+ continue; // Skip to the next pattern
42
+ }
43
+ }
44
+ }
45
+
46
+ return children;
47
+ };
48
+
49
+ export default AliasRoute;
@@ -1,31 +1,31 @@
1
- /*
2
- * @Author : Lihao leolihao@arizona.edu
3
- * @Date : 2023-11-29 21:58:14
4
- * @FilePath : /visualifyjs/src/core/router/jsonRouter.js
5
- * @Description :
6
- * Copyright (c) 2023 by Lihao (leolihao@arizona.edu), All Rights Reserved.
7
- */
8
- import React from 'react';
9
- import { HashRouter, Route, Routes } from 'react-router-dom';
10
- import AliasRoute from './alias';
11
-
12
- function JsonRouter({ config, children }) {
13
- const { alias } = config;
14
-
15
- return (
16
- <HashRouter>
17
- <Routes>
18
- <Route
19
- path='/'
20
- element={children}
21
- />
22
- <Route
23
- path='/*'
24
- element={<AliasRoute alias={alias}>{children}</AliasRoute>}
25
- />
26
- </Routes>
27
- </HashRouter>
28
- );
29
- }
30
-
31
- export default JsonRouter;
1
+ /*
2
+ * @Author : Lihao leolihao@arizona.edu
3
+ * @Date : 2023-11-29 21:58:14
4
+ * @FilePath : /visualifyjs/src/core/router/jsonRouter.js
5
+ * @Description :
6
+ * Copyright (c) 2023 by Lihao (leolihao@arizona.edu), All Rights Reserved.
7
+ */
8
+ import React from 'react';
9
+ import { HashRouter, Route, Routes } from 'react-router-dom';
10
+ import AliasRoute from './alias';
11
+
12
+ function JsonRouter({ config, children }) {
13
+ const { alias } = config;
14
+
15
+ return (
16
+ <HashRouter>
17
+ <Routes>
18
+ <Route
19
+ path='/'
20
+ element={children}
21
+ />
22
+ <Route
23
+ path='/*'
24
+ element={<AliasRoute alias={alias}>{children}</AliasRoute>}
25
+ />
26
+ </Routes>
27
+ </HashRouter>
28
+ );
29
+ }
30
+
31
+ export default JsonRouter;
@@ -1,32 +1,32 @@
1
- /*
2
- * @Author : Lihao leolihao@arizona.edu
3
- * @Date : 2023-11-29 22:03:28
4
- * @FilePath : /visualifyjs/src/core/themes/modern.js
5
- * @Description :
6
- * Copyright (c) 2023 by Lihao (leolihao@arizona.edu), All Rights Reserved.
7
- */
8
-
9
- import React from 'react';
10
- import Vheader from '../widgets/header';
11
- import Vfooter from '../widgets/footer';
12
- import { Container } from 'react-bootstrap';
13
- import JsonPage from '../pages/jsonPage';
14
-
15
- import '../../_css/modern.css';
16
-
17
- function Modern({ config, children }) {
18
- //console.log('Modern config', config);
19
- const { homepage = 'home.json' } = config;
20
- return (
21
- <>
22
- <Vheader config={config} />
23
- <Container className='text-center'>
24
- <JsonPage homepage={homepage} />
25
- {children}
26
- </Container>
27
- <Vfooter config={config} />
28
- </>
29
- );
30
- }
31
-
32
- export default Modern;
1
+ /*
2
+ * @Author : Lihao leolihao@arizona.edu
3
+ * @Date : 2023-11-29 22:03:28
4
+ * @FilePath : /visualifyjs/src/core/themes/modern.js
5
+ * @Description :
6
+ * Copyright (c) 2023 by Lihao (leolihao@arizona.edu), All Rights Reserved.
7
+ */
8
+
9
+ import React from 'react';
10
+ import Vheader from '../widgets/header';
11
+ import Vfooter from '../widgets/footer';
12
+ import { Container } from 'react-bootstrap';
13
+ import JsonPage from '../pages/jsonPage';
14
+
15
+ import '../../_css/modern.css';
16
+
17
+ function Modern({ config, children }) {
18
+ //console.log('Modern config', config);
19
+ const { homepage = 'home.json' } = config;
20
+ return (
21
+ <>
22
+ <Vheader config={config} />
23
+ <Container className='text-center'>
24
+ <JsonPage homepage={homepage} />
25
+ {children}
26
+ </Container>
27
+ <Vfooter config={config} />
28
+ </>
29
+ );
30
+ }
31
+
32
+ export default Modern;