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.
- package/.claude/mem/TIMELINE.md +36 -0
- package/.claude/mem/notes/2026-02-11-3d-visualization-docs-fix-external-script-solution.md +24 -0
- package/.claude/mem/notes/2026-02-11-3d-visualization-docs-fix-session-summary.md +43 -0
- package/.claude/mem/notes/2026-02-11-cli-fix-editor-command-alias.md +26 -0
- package/.claude/mem/notes/2026-02-11-phase-3-developer-experience-completed.md +51 -0
- package/.claude/mem/notes/2026-02-11-phase-4-web-workers-implementation-complete.md +59 -0
- package/.claude/mem/notes/2026-02-11-visualify-phase-2-3d-visualization-complete.md +50 -0
- package/.claude/mem/notes/2026-02-11-visualify-phase-2-committed-ready-for-phase-3.md +33 -0
- package/.claude/mem/notes/2026-02-11-visualify-phase-3-complete-developer-experience.md +52 -0
- package/.claude/mem/notes/2026-02-11-visualify-repository-cleanup-complete.md +28 -0
- package/.claude/mem/notes/2026-02-18-codebase-cleanup-docsify-plugin-documentation.md +37 -0
- package/.claude/mem/notes/2026-02-19-css-grid-layout-fix-displaycontents-on-vcontroller.md +18 -0
- package/.claude/mem/notes/2026-02-19-docsify-plugin-fixes-latex-and-visualify-code-bloc.md +26 -0
- package/.claude/mem/notes/2026-02-19-page-mode-docs-update-decisions.md +23 -0
- package/.claude/mem/notes/2026-02-19-react-context-infinite-re-render-loop-fix-pattern.md +31 -0
- package/.claude/mem/notes/2026-02-19-version-300-bump-and-build-fixes.md +32 -0
- package/.claude/mem/notes/2026-02-19-visualify-build-deployment-architecture-bug-fixes.md +25 -0
- package/.claude/mem/notes/2026-02-19-visualify-dist-iife-self-contained-build-config.md +30 -0
- package/.claude/mem/notes/2026-02-19-visualify-infinite-loop-i18n-fixes.md +31 -0
- package/.claude/mem/notes/2026-02-19-visualify-v3-bundle-splitting-docs-restructuring.md +32 -0
- package/.claude/mem/notes/2026-02-20-bundle-externalization-final-architecture.md +29 -0
- package/.claude/mem/notes/2026-02-20-chromium-page-fix-unstable-keys-and-double-event-b.md +27 -0
- package/.claude/mem/notes/2026-02-20-console-cleanup-bundle-optimization-commit.md +20 -0
- package/.claude/mem/notes/2026-02-20-dotbio-dot-plot-fix-useeffect-dependency.md +21 -0
- package/.claude/mem/notes/2026-02-20-public-folder-cleanup-and-readme-rewrite.md +25 -0
- package/.claude/mem/notes/2026-02-20-v300-release-and-beta-channel-strategy.md +29 -0
- package/.claude/mem/notes/2026-02-20-visium-background-image-unknown-legend-fix.md +19 -0
- package/.claude/mem/notes/2026-02-20-visualify-cdn-loader-bundle-externalization.md +34 -0
- package/.claude/mem/sessions/session-2026-02-20-031524.md +54 -0
- package/.claude/settings.local.json +21 -0
- package/.github/workflows/static.yml.bak +51 -51
- package/.sisyphus/boulder.json +65 -0
- package/.sisyphus/plans/phase-4-advanced-optimizations.md +217 -0
- package/LICENSE +674 -674
- package/README.md +94 -59
- package/config-overrides.js +31 -31
- package/dist/stats.html +4949 -0
- package/dist/visualify-3d.esm.js +1 -0
- package/dist/visualify-3d.js +1 -0
- package/dist/visualify-core.esm.js +1 -0
- package/dist/visualify-core.js +1 -0
- package/dist/visualify-docs.esm.js +1 -0
- package/dist/visualify-docs.js +1 -0
- package/dist/visualify-loader.js +1 -0
- package/dist/visualify-pages.esm.js +1 -0
- package/dist/visualify-pages.js +1 -0
- package/dist/visualify-portal.esm.js +1 -0
- package/dist/visualify-portal.js +1 -0
- package/dist/visualify-shared.js +26571 -0
- package/dist/visualify.js +1 -188
- package/docs/CHANGELOG.md +148 -0
- package/docs/cli/commands.md +513 -0
- package/docs/configuration/visualify-json.md +474 -0
- package/docs/docs/3d-visualization.md +374 -0
- package/docs/docs/CLI.md +303 -34
- package/docs/docs/README.md +65 -65
- package/docs/docs/Rechart/bar.md +190 -190
- package/docs/docs/Rechart/funnel.md +241 -241
- package/docs/docs/Rechart/line.md +355 -355
- package/docs/docs/Rechart/pie.md +225 -225
- package/docs/docs/Rechart/radar.md +253 -253
- package/docs/docs/Rechart/scatter.md +298 -298
- package/docs/docs/_404.md +51 -51
- package/docs/docs/_coverpage.md +11 -11
- package/docs/docs/_sidebar.md +54 -44
- package/docs/docs/components/dotBio.md +87 -34
- package/docs/docs/components/echart.md +171 -82
- package/docs/docs/components/html.md +61 -34
- package/docs/docs/components/macaron.md +156 -145
- package/docs/docs/components/markdown.md +42 -0
- package/docs/docs/components/more.md +183 -142
- package/docs/docs/components/plotly.md +132 -62
- package/docs/docs/components/scatterL.md +171 -70
- package/docs/docs/components/visium.md +112 -57
- package/docs/docs/configuration.md +121 -121
- package/docs/docs/deploy.md +31 -31
- package/docs/docs/docsify-plugin.md +655 -0
- package/docs/docs/hmr.md +165 -0
- package/docs/docs/i18n.md +332 -0
- package/docs/docs/log.md +30 -9
- package/docs/docs/more-pages.md +23 -23
- package/docs/docs/quickstart.md +148 -124
- package/docs/docs/rechart-attributes.md +74 -74
- package/docs/docs/rechart-basic-usage.md +160 -162
- package/docs/docs/theme.md +5 -5
- package/docs/docs/typescript.md +306 -0
- package/docs/docs/visual-editor.md +359 -0
- package/docs/index.html +85 -71
- package/docs/manifest.json +23 -23
- package/docs/migration/v3-migration.md +392 -0
- package/docs/static/css/fluff-stuff.css +169 -169
- package/docs/static/css/font-awesome.min.css +4 -4
- package/docs/static/css/visualify.css +6 -25
- package/docs/static/js/3d-viz-examples.js +181 -0
- package/docs/static/js/configuration.js +630 -448
- package/docs/static/js/visualify.js +1 -188
- package/package.json +106 -84
- package/rollup.config.mjs +766 -76
- package/src/_css/404.css +115 -115
- package/src/_css/App.css +37 -37
- package/src/_css/autoSuggestion.css +26 -26
- package/src/_css/circular-progress.css +32 -32
- package/src/_css/index.css +36 -36
- package/src/_css/modern.css +350 -25
- package/src/_media/corner.svg +8 -8
- package/src/_media/download.svg +3 -3
- package/src/_media/logo.svg +14 -14
- package/src/_test/App.test.js +15 -15
- package/src/_utils/reportWebVitals.js +13 -13
- package/src/a11y/README.md +177 -0
- package/src/a11y/aria-labels.js +339 -0
- package/src/a11y/color-contrast.js +535 -0
- package/src/a11y/index.js +197 -0
- package/src/a11y/keyboard-nav.js +523 -0
- package/src/a11y/styles.css +165 -0
- package/src/cli/commands/dev.js +214 -0
- package/src/cli/commands/docs.js +521 -0
- package/src/cli/commands/edit.js +379 -0
- package/src/cli/commands/init.js +213 -0
- package/src/cli/commands/portal.js +236 -0
- package/src/cli/dev-server.js +530 -0
- package/src/cli/hmr.js +456 -0
- package/src/cli/index.js +180 -0
- package/src/cli/utils/config.js +207 -0
- package/src/cli/utils/logger.js +241 -0
- package/src/config/defaults.ts +122 -0
- package/src/config/index.ts +72 -0
- package/src/config/loader.ts +478 -0
- package/src/config/schema.ts +227 -0
- package/src/config/validator.ts +337 -0
- package/src/core/appContext.js +34 -27
- package/src/core/components/Bar.js +383 -0
- package/src/core/components/Bar3D.js +473 -0
- package/src/core/components/LargeDatasetChart.js +296 -0
- package/src/core/components/Line3D.js +310 -0
- package/src/core/components/Scatter.js +392 -188
- package/src/core/components/Scatter3D.js +455 -0
- package/src/core/components/ScatterBio.js +601 -572
- package/src/core/components/Surface3D.js +326 -0
- package/src/core/components/ThreeCustom.js +648 -0
- package/src/core/components/ThreeScene.js +459 -0
- package/src/core/components/VisiumPlot.js +191 -165
- package/src/core/components/browser.js +42 -42
- package/src/core/components/dotplot.js +413 -413
- package/src/core/components/html.js +29 -29
- package/src/core/components/list.js +178 -178
- package/src/core/components/macaron.js +206 -201
- package/src/core/components/markdown.js +56 -56
- package/src/core/components/parser.scatterBio.js +582 -587
- package/src/core/components/ratio.js +82 -80
- package/src/core/components/scatterL.js +206 -173
- package/src/core/components/searchbar.js +156 -131
- package/src/core/components/selection.js +310 -193
- package/src/core/components/timeline.js +236 -281
- package/src/core/components/visium.js +114 -97
- package/src/core/data-processor.js +413 -0
- package/src/core/fetch/condfetch.js +82 -82
- package/src/core/fetch/fetch.js +92 -92
- package/src/core/fetch/json.js +29 -29
- package/src/core/fetch/vfetch.js +42 -42
- package/src/core/hmr-client.js +724 -0
- package/src/core/liveEditor.js +44 -44
- package/src/core/modules/codeEditorWithPreview.js +104 -104
- package/src/core/modules/echarts/common.js +20 -20
- package/src/core/modules/echarts/gl.js +228 -0
- package/src/core/modules/echarts/presetHandler.js +41 -41
- package/src/core/modules/echarts/presets/esodev.chromium.js +172 -172
- package/src/core/modules/echarts/presets/esodev.codex.js +130 -130
- package/src/core/modules/echarts/presets/esodev.visium.js +123 -123
- package/src/core/modules/echarts/presets/mmtrbc.js +186 -186
- package/src/core/modules/echarts.js +70 -71
- package/src/core/modules/echartsUtils.js +43 -43
- package/src/core/modules/echartswitcher.js +227 -152
- package/src/core/modules/replotly/presetHandler.js +24 -24
- package/src/core/modules/replotly/presets/minimum.js +18 -18
- package/src/core/modules/replotly/presets/mmtrbc.dot.js +114 -114
- package/src/core/modules/replotly/presets/mmtrbc.violin.js +100 -100
- package/src/core/modules/replotly.js +74 -71
- package/src/core/modules/threejs/Camera.js +373 -0
- package/src/core/modules/threejs/Lighting.js +459 -0
- package/src/core/modules/threejs/Renderer.js +364 -0
- package/src/core/modules/threejs/Scene.js +266 -0
- package/src/core/modules/threejs/index.js +155 -0
- package/src/core/pages/404.js +50 -50
- package/src/core/pages/error.js +27 -27
- package/src/core/pages/jsonPage.js +62 -62
- package/src/core/pages/loading.js +44 -44
- package/src/core/parser/echart.data.js +204 -183
- package/src/core/parser/echart.features.js +125 -125
- package/src/core/parser/echart.general.js +147 -147
- package/src/core/parser/echart.hilbert.js +57 -57
- package/src/core/parser/echart.parser.js +210 -210
- package/src/core/parser/echart.series.js +67 -67
- package/src/core/parser/echart.types.js +76 -76
- package/src/core/parser/plotly.config.js +10 -10
- package/src/core/parser/plotly.data.js +132 -132
- package/src/core/parser/plotly.layout.js +9 -9
- package/src/core/parser/plotly.violin.js +18 -18
- package/src/core/recharts.js +361 -62
- package/src/core/router/alias.js +49 -49
- package/src/core/router/jsonRouter.js +31 -31
- package/src/core/themes/modern.js +32 -32
- package/src/core/themes/themeSelector.js +33 -33
- package/src/core/visualify.js +213 -47
- package/src/core/widgets/circularProgress.js +23 -23
- package/src/core/widgets/controller.js +116 -83
- package/src/core/widgets/errorBoundary.js +36 -36
- package/src/core/widgets/footer.js +185 -177
- package/src/core/widgets/header.js +238 -234
- package/src/core/widgets/layout/Grid.js +31 -31
- package/src/core/widgets/layout.js +36 -36
- package/src/core/widgets/mapping.js +56 -42
- package/src/core/workers/data-worker.js +349 -0
- package/src/core/workers/worker-pool.js +396 -0
- package/src/docsify/bundle.js +215 -0
- package/src/docsify/markdown.js +271 -0
- package/src/docsify/plugin.js +268 -0
- package/src/editor/README.md +172 -0
- package/src/editor/components/ChartBuilder.jsx +341 -0
- package/src/editor/components/ChartTypeSidebar.jsx +91 -0
- package/src/editor/components/Editor.jsx +367 -0
- package/src/editor/components/Preview.jsx +446 -0
- package/src/editor/components/PropertyPanel.jsx +468 -0
- package/src/editor/components/StatusBar.jsx +85 -0
- package/src/editor/context/EditorContext.js +248 -0
- package/src/editor/hooks/useDebounce.js +32 -0
- package/src/editor/index.js +315 -0
- package/src/editor/styles/editor.css +637 -0
- package/src/editor/utils/chartValidator.js +263 -0
- package/src/entries/charts3d.js +70 -0
- package/src/entries/core.js +78 -0
- package/src/entries/docs.js +154 -0
- package/src/entries/pages.js +93 -0
- package/src/entries/portal.js +204 -0
- package/src/entries/shared.js +50 -0
- package/src/i18n/formatters.js +455 -0
- package/src/i18n/index.js +169 -0
- package/src/i18n/locales/ar.json +137 -0
- package/src/i18n/locales/de.json +137 -0
- package/src/i18n/locales/en.json +137 -0
- package/src/i18n/locales/es.json +137 -0
- package/src/i18n/locales/he.json +137 -0
- package/src/i18n/locales/zh.json +137 -0
- package/src/i18n/rtl.css +183 -0
- package/src/index.js +82 -62
- package/src/loader.js +103 -0
- package/src/setupTests.js +5 -5
- package/tsconfig.json +51 -0
- package/types/charts.d.ts +569 -0
- package/types/components.d.ts +441 -0
- package/types/config.d.ts +199 -0
- package/types/index.d.ts +353 -0
package/src/core/liveEditor.js
CHANGED
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* @Author : Lihao leolihao@arizona.edu
|
|
3
|
-
* @Date : 2023-12-01 22:51:45
|
|
4
|
-
* @FilePath : /visualifyjs/src/core/liveEditor.js
|
|
5
|
-
* @Description :
|
|
6
|
-
* Copyright (c) 2023 by Lihao (leolihao@arizona.edu), All Rights Reserved.
|
|
7
|
-
*/
|
|
8
|
-
import React from 'react';
|
|
9
|
-
import Recharts from './recharts';
|
|
10
|
-
import { createRoot } from 'react-dom/client';
|
|
11
|
-
import CodeEditorWithPreview from './modules/codeEditorWithPreview';
|
|
12
|
-
import { VisualifyProvider } from './appContext';
|
|
13
|
-
class LiveEditor extends Recharts {
|
|
14
|
-
constructor(config) {
|
|
15
|
-
super();
|
|
16
|
-
this.config = config;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
mount(selector) {
|
|
20
|
-
const el =
|
|
21
|
-
typeof selector === 'string'
|
|
22
|
-
? document.querySelector(selector)
|
|
23
|
-
: selector;
|
|
24
|
-
|
|
25
|
-
if (!el) {
|
|
26
|
-
throw new Error(`Element not found with selector: ${selector}`);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
try {
|
|
30
|
-
// Assuming createRoot is imported from 'react-dom/client'
|
|
31
|
-
const charts = createRoot(el);
|
|
32
|
-
charts.render(
|
|
33
|
-
<VisualifyProvider>
|
|
34
|
-
<CodeEditorWithPreview config={this.config} />
|
|
35
|
-
</VisualifyProvider>,
|
|
36
|
-
);
|
|
37
|
-
console.log('mounted ' + selector, el);
|
|
38
|
-
} catch (e) {
|
|
39
|
-
console.error('Error mounting chart:', e);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export default LiveEditor;
|
|
1
|
+
/*
|
|
2
|
+
* @Author : Lihao leolihao@arizona.edu
|
|
3
|
+
* @Date : 2023-12-01 22:51:45
|
|
4
|
+
* @FilePath : /visualifyjs/src/core/liveEditor.js
|
|
5
|
+
* @Description :
|
|
6
|
+
* Copyright (c) 2023 by Lihao (leolihao@arizona.edu), All Rights Reserved.
|
|
7
|
+
*/
|
|
8
|
+
import React from 'react';
|
|
9
|
+
import Recharts from './recharts';
|
|
10
|
+
import { createRoot } from 'react-dom/client';
|
|
11
|
+
import CodeEditorWithPreview from './modules/codeEditorWithPreview';
|
|
12
|
+
import { VisualifyProvider } from './appContext';
|
|
13
|
+
class LiveEditor extends Recharts {
|
|
14
|
+
constructor(config) {
|
|
15
|
+
super();
|
|
16
|
+
this.config = config;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
mount(selector) {
|
|
20
|
+
const el =
|
|
21
|
+
typeof selector === 'string'
|
|
22
|
+
? document.querySelector(selector)
|
|
23
|
+
: selector;
|
|
24
|
+
|
|
25
|
+
if (!el) {
|
|
26
|
+
throw new Error(`Element not found with selector: ${selector}`);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
// Assuming createRoot is imported from 'react-dom/client'
|
|
31
|
+
const charts = createRoot(el);
|
|
32
|
+
charts.render(
|
|
33
|
+
<VisualifyProvider>
|
|
34
|
+
<CodeEditorWithPreview config={this.config} />
|
|
35
|
+
</VisualifyProvider>,
|
|
36
|
+
);
|
|
37
|
+
console.log('mounted ' + selector, el);
|
|
38
|
+
} catch (e) {
|
|
39
|
+
console.error('Error mounting chart:', e);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export default LiveEditor;
|
|
@@ -1,104 +1,104 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* @Author : Lihao leolihao@arizona.edu
|
|
3
|
-
* @Date : 2023-12-01 22:17:15
|
|
4
|
-
* @FilePath : /visualifyjs/src/core/modules/codeEditorWithPreview.js
|
|
5
|
-
* @Description :
|
|
6
|
-
* Copyright (c) 2023 by Lihao (leolihao@arizona.edu), All Rights Reserved.
|
|
7
|
-
*/
|
|
8
|
-
import React, { useState } from 'react';
|
|
9
|
-
import AceEditor from 'react-ace';
|
|
10
|
-
import EChartSwitcher from './echartswitcher';
|
|
11
|
-
import 'ace-builds/src-noconflict/mode-javascript';
|
|
12
|
-
import 'ace-builds/src-noconflict/theme-monokai';
|
|
13
|
-
|
|
14
|
-
const CodeEditorWithPreview = ({ config }) => {
|
|
15
|
-
const supportedThemes = ['', 'monokai'];
|
|
16
|
-
const supportedMode = ['javascript'];
|
|
17
|
-
|
|
18
|
-
const {
|
|
19
|
-
theme = '',
|
|
20
|
-
mode = 'javascript',
|
|
21
|
-
width,
|
|
22
|
-
height = '400px',
|
|
23
|
-
title = 'Rechart Preview',
|
|
24
|
-
editorProps = { $blockScrolling: true },
|
|
25
|
-
} = config;
|
|
26
|
-
|
|
27
|
-
if (!supportedThemes.includes(theme)) {
|
|
28
|
-
throw new Error(
|
|
29
|
-
`Theme '${theme}' not supported. Supported themes are: ${supportedThemes.join(
|
|
30
|
-
', ',
|
|
31
|
-
)}`,
|
|
32
|
-
);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
if (!supportedMode.includes(mode)) {
|
|
36
|
-
throw new Error(
|
|
37
|
-
`Mode '${mode}' not supported. Supported modes are: ${supportedMode.join(
|
|
38
|
-
', ',
|
|
39
|
-
)}`,
|
|
40
|
-
);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const [code, setCode] = useState(config.code);
|
|
44
|
-
|
|
45
|
-
// Function to evaluate the code and return the chart options
|
|
46
|
-
const getChartOptions = () => {
|
|
47
|
-
try {
|
|
48
|
-
// eslint-disable-next-line no-new-func
|
|
49
|
-
const func = new Function(code);
|
|
50
|
-
return func()();
|
|
51
|
-
} catch (error) {
|
|
52
|
-
console.error('Error evaluating chart options:', error);
|
|
53
|
-
return {};
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
const blockStyles = {
|
|
58
|
-
display: 'flex',
|
|
59
|
-
justifyContent: 'space-between',
|
|
60
|
-
};
|
|
61
|
-
if (width) blockStyles.width = width;
|
|
62
|
-
|
|
63
|
-
const editorStyles = {
|
|
64
|
-
flexGrow: 1,
|
|
65
|
-
border: '1px solid #ddd',
|
|
66
|
-
borderRadius: '4px',
|
|
67
|
-
marginBottom: '10px',
|
|
68
|
-
width: '50%',
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
const editorTitleStyles = {
|
|
72
|
-
backgroundColor: '#f4f4f4',
|
|
73
|
-
padding: '10px',
|
|
74
|
-
borderBottom: '1px solid #ddd',
|
|
75
|
-
width: '100%',
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
return (
|
|
79
|
-
<div style={blockStyles}>
|
|
80
|
-
<div style={editorStyles}>
|
|
81
|
-
<div style={editorTitleStyles}>{title}</div>
|
|
82
|
-
<AceEditor
|
|
83
|
-
mode={mode}
|
|
84
|
-
theme={theme}
|
|
85
|
-
value={code}
|
|
86
|
-
onChange={setCode}
|
|
87
|
-
name={title}
|
|
88
|
-
editorProps={editorProps}
|
|
89
|
-
width='100%'
|
|
90
|
-
height={height}
|
|
91
|
-
setOptions={{
|
|
92
|
-
wrap: true,
|
|
93
|
-
useWorker: false,
|
|
94
|
-
}}
|
|
95
|
-
/>
|
|
96
|
-
</div>
|
|
97
|
-
<div style={{ width: '50%' }}>
|
|
98
|
-
<EChartSwitcher props={{ config: getChartOptions() }} />
|
|
99
|
-
</div>
|
|
100
|
-
</div>
|
|
101
|
-
);
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
export default CodeEditorWithPreview;
|
|
1
|
+
/*
|
|
2
|
+
* @Author : Lihao leolihao@arizona.edu
|
|
3
|
+
* @Date : 2023-12-01 22:17:15
|
|
4
|
+
* @FilePath : /visualifyjs/src/core/modules/codeEditorWithPreview.js
|
|
5
|
+
* @Description :
|
|
6
|
+
* Copyright (c) 2023 by Lihao (leolihao@arizona.edu), All Rights Reserved.
|
|
7
|
+
*/
|
|
8
|
+
import React, { useState } from 'react';
|
|
9
|
+
import AceEditor from 'react-ace';
|
|
10
|
+
import EChartSwitcher from './echartswitcher';
|
|
11
|
+
import 'ace-builds/src-noconflict/mode-javascript';
|
|
12
|
+
import 'ace-builds/src-noconflict/theme-monokai';
|
|
13
|
+
|
|
14
|
+
const CodeEditorWithPreview = ({ config }) => {
|
|
15
|
+
const supportedThemes = ['', 'monokai'];
|
|
16
|
+
const supportedMode = ['javascript'];
|
|
17
|
+
|
|
18
|
+
const {
|
|
19
|
+
theme = '',
|
|
20
|
+
mode = 'javascript',
|
|
21
|
+
width,
|
|
22
|
+
height = '400px',
|
|
23
|
+
title = 'Rechart Preview',
|
|
24
|
+
editorProps = { $blockScrolling: true },
|
|
25
|
+
} = config;
|
|
26
|
+
|
|
27
|
+
if (!supportedThemes.includes(theme)) {
|
|
28
|
+
throw new Error(
|
|
29
|
+
`Theme '${theme}' not supported. Supported themes are: ${supportedThemes.join(
|
|
30
|
+
', ',
|
|
31
|
+
)}`,
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (!supportedMode.includes(mode)) {
|
|
36
|
+
throw new Error(
|
|
37
|
+
`Mode '${mode}' not supported. Supported modes are: ${supportedMode.join(
|
|
38
|
+
', ',
|
|
39
|
+
)}`,
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const [code, setCode] = useState(config.code);
|
|
44
|
+
|
|
45
|
+
// Function to evaluate the code and return the chart options
|
|
46
|
+
const getChartOptions = () => {
|
|
47
|
+
try {
|
|
48
|
+
// eslint-disable-next-line no-new-func
|
|
49
|
+
const func = new Function(code);
|
|
50
|
+
return func()();
|
|
51
|
+
} catch (error) {
|
|
52
|
+
console.error('Error evaluating chart options:', error);
|
|
53
|
+
return {};
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const blockStyles = {
|
|
58
|
+
display: 'flex',
|
|
59
|
+
justifyContent: 'space-between',
|
|
60
|
+
};
|
|
61
|
+
if (width) blockStyles.width = width;
|
|
62
|
+
|
|
63
|
+
const editorStyles = {
|
|
64
|
+
flexGrow: 1,
|
|
65
|
+
border: '1px solid #ddd',
|
|
66
|
+
borderRadius: '4px',
|
|
67
|
+
marginBottom: '10px',
|
|
68
|
+
width: '50%',
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const editorTitleStyles = {
|
|
72
|
+
backgroundColor: '#f4f4f4',
|
|
73
|
+
padding: '10px',
|
|
74
|
+
borderBottom: '1px solid #ddd',
|
|
75
|
+
width: '100%',
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
return (
|
|
79
|
+
<div style={blockStyles}>
|
|
80
|
+
<div style={editorStyles}>
|
|
81
|
+
<div style={editorTitleStyles}>{title}</div>
|
|
82
|
+
<AceEditor
|
|
83
|
+
mode={mode}
|
|
84
|
+
theme={theme}
|
|
85
|
+
value={code}
|
|
86
|
+
onChange={setCode}
|
|
87
|
+
name={title}
|
|
88
|
+
editorProps={editorProps}
|
|
89
|
+
width='100%'
|
|
90
|
+
height={height}
|
|
91
|
+
setOptions={{
|
|
92
|
+
wrap: true,
|
|
93
|
+
useWorker: false,
|
|
94
|
+
}}
|
|
95
|
+
/>
|
|
96
|
+
</div>
|
|
97
|
+
<div style={{ width: '50%' }}>
|
|
98
|
+
<EChartSwitcher props={{ config: getChartOptions() }} />
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
101
|
+
);
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
export default CodeEditorWithPreview;
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* @Author : Lihao leolihao@arizona.edu
|
|
3
|
-
* @Date : 2023-12-01 21:43:02
|
|
4
|
-
* @FilePath : /visualifyjs/src/core/modules/echarts/common.js
|
|
5
|
-
* @Description :
|
|
6
|
-
* Copyright (c) 2023 by Lihao (leolihao@arizona.edu), All Rights Reserved.
|
|
7
|
-
*/
|
|
8
|
-
const minimumPreset = {
|
|
9
|
-
title: {},
|
|
10
|
-
tooltip: {},
|
|
11
|
-
legend: {
|
|
12
|
-
top: 25,
|
|
13
|
-
},
|
|
14
|
-
xAxis: {},
|
|
15
|
-
yAxis: {},
|
|
16
|
-
series: [],
|
|
17
|
-
// ... other default settings for charts
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
export default minimumPreset;
|
|
1
|
+
/*
|
|
2
|
+
* @Author : Lihao leolihao@arizona.edu
|
|
3
|
+
* @Date : 2023-12-01 21:43:02
|
|
4
|
+
* @FilePath : /visualifyjs/src/core/modules/echarts/common.js
|
|
5
|
+
* @Description :
|
|
6
|
+
* Copyright (c) 2023 by Lihao (leolihao@arizona.edu), All Rights Reserved.
|
|
7
|
+
*/
|
|
8
|
+
const minimumPreset = {
|
|
9
|
+
title: {},
|
|
10
|
+
tooltip: {},
|
|
11
|
+
legend: {
|
|
12
|
+
top: 25,
|
|
13
|
+
},
|
|
14
|
+
xAxis: {},
|
|
15
|
+
yAxis: {},
|
|
16
|
+
series: [],
|
|
17
|
+
// ... other default settings for charts
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export default minimumPreset;
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ECharts GL Integration Module
|
|
3
|
+
* Provides lazy loading and WebGL support detection for 3D charts
|
|
4
|
+
* @module echarts/gl
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { toast } from 'react-toastify';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Checks if the browser supports WebGL
|
|
11
|
+
* @returns {boolean} True if WebGL is supported
|
|
12
|
+
*/
|
|
13
|
+
export function isWebGLSupported() {
|
|
14
|
+
try {
|
|
15
|
+
const canvas = document.createElement('canvas');
|
|
16
|
+
const gl =
|
|
17
|
+
canvas.getContext('webgl2') ||
|
|
18
|
+
canvas.getContext('webgl') ||
|
|
19
|
+
canvas.getContext('experimental-webgl');
|
|
20
|
+
return !!gl;
|
|
21
|
+
} catch (e) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Gets WebGL context information for debugging
|
|
28
|
+
* @returns {Object|null} WebGL context info or null if not supported
|
|
29
|
+
*/
|
|
30
|
+
export function getWebGLInfo() {
|
|
31
|
+
try {
|
|
32
|
+
const canvas = document.createElement('canvas');
|
|
33
|
+
const gl =
|
|
34
|
+
canvas.getContext('webgl2') ||
|
|
35
|
+
canvas.getContext('webgl') ||
|
|
36
|
+
canvas.getContext('experimental-webgl');
|
|
37
|
+
if (!gl) return null;
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
vendor: gl.getParameter(gl.VENDOR),
|
|
41
|
+
renderer: gl.getParameter(gl.RENDERER),
|
|
42
|
+
version: gl.getParameter(gl.VERSION),
|
|
43
|
+
shadingLanguageVersion: gl.getParameter(gl.SHADING_LANGUAGE_VERSION),
|
|
44
|
+
maxTextureSize: gl.getParameter(gl.MAX_TEXTURE_SIZE),
|
|
45
|
+
maxViewportDims: gl.getParameter(gl.MAX_VIEWPORT_DIMS),
|
|
46
|
+
};
|
|
47
|
+
} catch (e) {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Module cache for lazy loading
|
|
53
|
+
let echartsGLModule = null;
|
|
54
|
+
let loadingPromise = null;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Lazy loads ECharts GL module
|
|
58
|
+
* Only loads when 3D charts are actually rendered
|
|
59
|
+
* @returns {Promise<Object>} ECharts GL module
|
|
60
|
+
* @throws {Error} If WebGL is not supported or module fails to load
|
|
61
|
+
*/
|
|
62
|
+
export async function loadEChartsGL() {
|
|
63
|
+
// Return cached module if available
|
|
64
|
+
if (echartsGLModule) {
|
|
65
|
+
return echartsGLModule;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Return existing promise if already loading
|
|
69
|
+
if (loadingPromise) {
|
|
70
|
+
return loadingPromise;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Check WebGL support before attempting to load
|
|
74
|
+
if (!isWebGLSupported()) {
|
|
75
|
+
const error = new Error(
|
|
76
|
+
'WebGL is not supported in this browser. 3D charts require WebGL support.',
|
|
77
|
+
);
|
|
78
|
+
error.code = 'WEBGL_NOT_SUPPORTED';
|
|
79
|
+
throw error;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Check if echarts-gl is already loaded globally (e.g., from CDN)
|
|
83
|
+
if (typeof window !== 'undefined' && window['echarts-gl']) {
|
|
84
|
+
echartsGLModule = window['echarts-gl'];
|
|
85
|
+
return Promise.resolve(echartsGLModule);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Lazy load ECharts GL
|
|
89
|
+
loadingPromise = import('echarts-gl')
|
|
90
|
+
.then((module) => {
|
|
91
|
+
echartsGLModule = module;
|
|
92
|
+
return module;
|
|
93
|
+
})
|
|
94
|
+
.catch((error) => {
|
|
95
|
+
loadingPromise = null;
|
|
96
|
+
const loadError = new Error(
|
|
97
|
+
`Failed to load ECharts GL: ${error.message}`,
|
|
98
|
+
);
|
|
99
|
+
loadError.code = 'ECHARTS_GL_LOAD_ERROR';
|
|
100
|
+
loadError.originalError = error;
|
|
101
|
+
throw loadError;
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
return loadingPromise;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Preloads ECharts GL module in the background
|
|
109
|
+
* Useful for improving perceived performance when 3D charts are expected
|
|
110
|
+
*/
|
|
111
|
+
export function preloadEChartsGL() {
|
|
112
|
+
if (!echartsGLModule && !loadingPromise && isWebGLSupported()) {
|
|
113
|
+
loadEChartsGL().catch(() => {
|
|
114
|
+
// Silently fail preload - actual error handling happens at render time
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Gets the current loading state of ECharts GL
|
|
121
|
+
* @returns {Object} Loading state information
|
|
122
|
+
*/
|
|
123
|
+
export function getLoadingState() {
|
|
124
|
+
return {
|
|
125
|
+
isLoaded: !!echartsGLModule,
|
|
126
|
+
isLoading: !!loadingPromise,
|
|
127
|
+
isSupported: isWebGLSupported(),
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Displays a user-friendly error message for WebGL/3D chart errors
|
|
133
|
+
* @param {Error} error - The error object
|
|
134
|
+
* @param {Object} options - Display options
|
|
135
|
+
* @param {boolean} options.useToast - Whether to use toast notification (default: true)
|
|
136
|
+
* @param {string} options.fallbackMessage - Custom fallback message
|
|
137
|
+
*/
|
|
138
|
+
export function display3DError(error, options = {}) {
|
|
139
|
+
const { useToast = true, fallbackMessage } = options;
|
|
140
|
+
|
|
141
|
+
let message =
|
|
142
|
+
fallbackMessage || 'Unable to display 3D chart. Please try a different browser.';
|
|
143
|
+
|
|
144
|
+
if (error.code === 'WEBGL_NOT_SUPPORTED') {
|
|
145
|
+
message =
|
|
146
|
+
'Your browser does not support WebGL, which is required for 3D charts. ' +
|
|
147
|
+
'Please use a modern browser like Chrome, Firefox, Safari, or Edge.';
|
|
148
|
+
} else if (error.code === 'ECHARTS_GL_LOAD_ERROR') {
|
|
149
|
+
message =
|
|
150
|
+
'Failed to load 3D chart library. Please check your internet connection and try again.';
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (useToast && typeof toast !== 'undefined') {
|
|
154
|
+
toast.error(message, {
|
|
155
|
+
position: 'top-center',
|
|
156
|
+
autoClose: 5000,
|
|
157
|
+
hideProgressBar: false,
|
|
158
|
+
closeOnClick: true,
|
|
159
|
+
pauseOnHover: true,
|
|
160
|
+
draggable: true,
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return message;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Cleanup function to dispose of WebGL resources
|
|
169
|
+
* Should be called when 3D chart components unmount
|
|
170
|
+
* @param {Object} chartInstance - ECharts instance
|
|
171
|
+
*/
|
|
172
|
+
export function cleanupWebGL(chartInstance) {
|
|
173
|
+
if (!chartInstance) return;
|
|
174
|
+
|
|
175
|
+
try {
|
|
176
|
+
// Remove all event listeners
|
|
177
|
+
chartInstance.off();
|
|
178
|
+
|
|
179
|
+
// Dispose the chart instance
|
|
180
|
+
if (!chartInstance.isDisposed()) {
|
|
181
|
+
chartInstance.dispose();
|
|
182
|
+
}
|
|
183
|
+
} catch (error) {
|
|
184
|
+
// Silently handle cleanup errors
|
|
185
|
+
console.warn('Error during WebGL cleanup:', error);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Hook for handling WebGL context loss
|
|
191
|
+
* @param {HTMLCanvasElement} canvas - The canvas element
|
|
192
|
+
* @param {Function} onRestore - Callback when context is restored
|
|
193
|
+
* @returns {Function} Cleanup function
|
|
194
|
+
*/
|
|
195
|
+
export function handleWebGLContextLoss(canvas, onRestore) {
|
|
196
|
+
if (!canvas) return () => {};
|
|
197
|
+
|
|
198
|
+
const handleContextLost = (event) => {
|
|
199
|
+
event.preventDefault();
|
|
200
|
+
console.warn('WebGL context lost');
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
const handleContextRestored = () => {
|
|
204
|
+
console.info('WebGL context restored');
|
|
205
|
+
if (typeof onRestore === 'function') {
|
|
206
|
+
onRestore();
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
canvas.addEventListener('webglcontextlost', handleContextLost);
|
|
211
|
+
canvas.addEventListener('webglcontextrestored', handleContextRestored);
|
|
212
|
+
|
|
213
|
+
return () => {
|
|
214
|
+
canvas.removeEventListener('webglcontextlost', handleContextLost);
|
|
215
|
+
canvas.removeEventListener('webglcontextrestored', handleContextRestored);
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export default {
|
|
220
|
+
isWebGLSupported,
|
|
221
|
+
getWebGLInfo,
|
|
222
|
+
loadEChartsGL,
|
|
223
|
+
preloadEChartsGL,
|
|
224
|
+
getLoadingState,
|
|
225
|
+
display3DError,
|
|
226
|
+
cleanupWebGL,
|
|
227
|
+
handleWebGLContextLoss,
|
|
228
|
+
};
|
|
@@ -1,41 +1,41 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* @Author : Lihao leolihao@arizona.edu
|
|
3
|
-
* @Date : 2023-12-02 21:36:01
|
|
4
|
-
* @FilePath : /visualifyjs/src/core/modules/echarts/presetHandler.js
|
|
5
|
-
* @Description :
|
|
6
|
-
* Copyright (c) 2023 by Lihao (leolihao@arizona.edu), All Rights Reserved.
|
|
7
|
-
*/
|
|
8
|
-
// presetHandler.js
|
|
9
|
-
import minimumPreset from './common';
|
|
10
|
-
import mmtrbc from './presets/mmtrbc';
|
|
11
|
-
import esodev_chromium from './presets/esodev.chromium';
|
|
12
|
-
import esodev_codex from './presets/esodev.codex';
|
|
13
|
-
import esodev_visium from './presets/esodev.visium';
|
|
14
|
-
|
|
15
|
-
// Example embedded presets
|
|
16
|
-
const embeddedPresets = {
|
|
17
|
-
mmtrbc: mmtrbc,
|
|
18
|
-
esodev_chromium: esodev_chromium,
|
|
19
|
-
esodev_codex: esodev_codex,
|
|
20
|
-
esodev_visium: esodev_visium,
|
|
21
|
-
// 'presetName': { ...preset data... }
|
|
22
|
-
// Define embedded presets here
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
// Function to fetch preset data from a URL
|
|
26
|
-
export const fetchPresetFromURL = async (url) => {
|
|
27
|
-
try {
|
|
28
|
-
const response = await fetch(url);
|
|
29
|
-
const data = await response.json();
|
|
30
|
-
return data;
|
|
31
|
-
} catch (error) {
|
|
32
|
-
console.error('Error fetching preset from URL:', error);
|
|
33
|
-
return null; // Return null or appropriate error handling
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
// Function to get an embedded preset based on a string key
|
|
38
|
-
export const getEmbeddedPreset = (presetKey) => {
|
|
39
|
-
// Return minimumPreset if preset not found
|
|
40
|
-
return embeddedPresets[presetKey] || minimumPreset;
|
|
41
|
-
};
|
|
1
|
+
/*
|
|
2
|
+
* @Author : Lihao leolihao@arizona.edu
|
|
3
|
+
* @Date : 2023-12-02 21:36:01
|
|
4
|
+
* @FilePath : /visualifyjs/src/core/modules/echarts/presetHandler.js
|
|
5
|
+
* @Description :
|
|
6
|
+
* Copyright (c) 2023 by Lihao (leolihao@arizona.edu), All Rights Reserved.
|
|
7
|
+
*/
|
|
8
|
+
// presetHandler.js
|
|
9
|
+
import minimumPreset from './common';
|
|
10
|
+
import mmtrbc from './presets/mmtrbc';
|
|
11
|
+
import esodev_chromium from './presets/esodev.chromium';
|
|
12
|
+
import esodev_codex from './presets/esodev.codex';
|
|
13
|
+
import esodev_visium from './presets/esodev.visium';
|
|
14
|
+
|
|
15
|
+
// Example embedded presets
|
|
16
|
+
const embeddedPresets = {
|
|
17
|
+
mmtrbc: mmtrbc,
|
|
18
|
+
esodev_chromium: esodev_chromium,
|
|
19
|
+
esodev_codex: esodev_codex,
|
|
20
|
+
esodev_visium: esodev_visium,
|
|
21
|
+
// 'presetName': { ...preset data... }
|
|
22
|
+
// Define embedded presets here
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
// Function to fetch preset data from a URL
|
|
26
|
+
export const fetchPresetFromURL = async (url) => {
|
|
27
|
+
try {
|
|
28
|
+
const response = await fetch(url);
|
|
29
|
+
const data = await response.json();
|
|
30
|
+
return data;
|
|
31
|
+
} catch (error) {
|
|
32
|
+
console.error('Error fetching preset from URL:', error);
|
|
33
|
+
return null; // Return null or appropriate error handling
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// Function to get an embedded preset based on a string key
|
|
38
|
+
export const getEmbeddedPreset = (presetKey) => {
|
|
39
|
+
// Return minimumPreset if preset not found
|
|
40
|
+
return embeddedPresets[presetKey] || minimumPreset;
|
|
41
|
+
};
|