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.
- 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 -193
- 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 -0
- package/docs/docs/_404.md +51 -51
- package/docs/docs/_coverpage.md +11 -11
- package/docs/docs/_sidebar.md +54 -43
- 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 -123
- 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 -1
- package/docs/docs/more-pages.md +23 -23
- package/docs/docs/quickstart.md +148 -119
- 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 -579
- 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 -143
- 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
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Portal Application Entry Point
|
|
3
|
+
* @description Full data portal bundle with all visualization components
|
|
4
|
+
* Exports the complete Visualify application for standalone portals
|
|
5
|
+
* Global name: Visualify
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import CreateApp from '../core/visualify';
|
|
9
|
+
import Recharts from '../core/recharts';
|
|
10
|
+
import LiveEditor from '../core/liveEditor';
|
|
11
|
+
import { VisualifyProvider, useAppContext } from '../core/appContext';
|
|
12
|
+
|
|
13
|
+
// Import shared components directly (not via shared.js to avoid code-splitting issues with UMD)
|
|
14
|
+
// Core chart components
|
|
15
|
+
export { default as ReCharts } from '../core/modules/echarts';
|
|
16
|
+
export { default as EChartSwitcher } from '../core/modules/echartswitcher';
|
|
17
|
+
|
|
18
|
+
// Chart utilities and parsers
|
|
19
|
+
export * from '../core/parser/echart.data';
|
|
20
|
+
export * from '../core/parser/echart.features';
|
|
21
|
+
export * from '../core/parser/echart.series';
|
|
22
|
+
export * from '../core/parser/echart.types';
|
|
23
|
+
export * from '../core/parser/echart.parser';
|
|
24
|
+
export * from '../core/parser/echart.hilbert';
|
|
25
|
+
|
|
26
|
+
// Plotly support
|
|
27
|
+
export { default as Replotly } from '../core/modules/replotly';
|
|
28
|
+
export * from '../core/parser/plotly.data';
|
|
29
|
+
export * from '../core/parser/plotly.layout';
|
|
30
|
+
export * from '../core/parser/plotly.config';
|
|
31
|
+
export * from '../core/parser/plotly.violin';
|
|
32
|
+
|
|
33
|
+
// ECharts utilities and presets
|
|
34
|
+
export * from '../core/modules/echartsUtils';
|
|
35
|
+
export { fetchPresetFromURL, getEmbeddedPreset } from '../core/modules/echarts/presetHandler';
|
|
36
|
+
export * from '../core/modules/echarts/common';
|
|
37
|
+
|
|
38
|
+
// Theme system
|
|
39
|
+
export { default as ThemeSelector } from '../core/themes/themeSelector';
|
|
40
|
+
export * from '../core/themes/modern';
|
|
41
|
+
|
|
42
|
+
// Shared widgets
|
|
43
|
+
export { default as ErrorBoundary } from '../core/widgets/errorBoundary';
|
|
44
|
+
export { default as CircularProgress } from '../core/widgets/circularProgress';
|
|
45
|
+
|
|
46
|
+
// Data fetching utilities
|
|
47
|
+
export { default as fetchData } from '../core/fetch/fetch';
|
|
48
|
+
export { default as condFetch } from '../core/fetch/condfetch';
|
|
49
|
+
export { default as vfetch } from '../core/fetch/vfetch';
|
|
50
|
+
export { default as jsonFetch } from '../core/fetch/json';
|
|
51
|
+
|
|
52
|
+
// Re-export core application classes
|
|
53
|
+
export { CreateApp, Recharts, LiveEditor, VisualifyProvider, useAppContext };
|
|
54
|
+
|
|
55
|
+
// Import and re-export page components
|
|
56
|
+
export { default as JsonPage } from '../core/pages/jsonPage';
|
|
57
|
+
export { default as LoadingPage } from '../core/pages/loading';
|
|
58
|
+
export { default as ErrorPage } from '../core/pages/error';
|
|
59
|
+
export { default as NotFoundPage } from '../core/pages/404';
|
|
60
|
+
|
|
61
|
+
// Import and re-export widget components
|
|
62
|
+
export { default as Layout } from '../core/widgets/layout';
|
|
63
|
+
export { default as Header } from '../core/widgets/header';
|
|
64
|
+
export { default as Footer } from '../core/widgets/footer';
|
|
65
|
+
export { default as Controller } from '../core/widgets/controller';
|
|
66
|
+
export { default as GridLayout } from '../core/widgets/layout/Grid';
|
|
67
|
+
export { default as Mapping } from '../core/widgets/mapping';
|
|
68
|
+
|
|
69
|
+
// Import and re-export visualization components
|
|
70
|
+
export { default as Scatter } from '../core/components/Scatter';
|
|
71
|
+
export { default as ScatterBio } from '../core/components/ScatterBio';
|
|
72
|
+
export { default as ScatterL } from '../core/components/scatterL';
|
|
73
|
+
export { default as VisiumPlot } from '../core/components/VisiumPlot';
|
|
74
|
+
export { default as Visium } from '../core/components/visium';
|
|
75
|
+
export { default as DotPlot } from '../core/components/dotplot';
|
|
76
|
+
export { default as Macaron } from '../core/components/macaron';
|
|
77
|
+
export { default as Ratio } from '../core/components/ratio';
|
|
78
|
+
export { default as Timeline } from '../core/components/timeline';
|
|
79
|
+
export { default as Selection } from '../core/components/selection';
|
|
80
|
+
export { default as SearchBar } from '../core/components/searchbar';
|
|
81
|
+
export { default as Browser } from '../core/components/browser';
|
|
82
|
+
export { default as List } from '../core/components/list';
|
|
83
|
+
export { default as Html } from '../core/components/html';
|
|
84
|
+
export { default as Markdown } from '../core/components/markdown';
|
|
85
|
+
|
|
86
|
+
// Router components
|
|
87
|
+
export { default as JsonRouter } from '../core/router/jsonRouter';
|
|
88
|
+
export * from '../core/router/alias';
|
|
89
|
+
|
|
90
|
+
// Web vitals reporting
|
|
91
|
+
export { default as reportWebVitals } from '../_utils/reportWebVitals';
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Visualify Portal namespace
|
|
95
|
+
* Contains all exports for the full portal application
|
|
96
|
+
*/
|
|
97
|
+
const Visualify = {
|
|
98
|
+
// Version info (replaced during build)
|
|
99
|
+
version: process.env.VISUALIFY_VERSION || 'dev',
|
|
100
|
+
|
|
101
|
+
// Core application
|
|
102
|
+
createApp: CreateApp,
|
|
103
|
+
|
|
104
|
+
// Charting classes
|
|
105
|
+
Recharts,
|
|
106
|
+
LiveEditor,
|
|
107
|
+
|
|
108
|
+
// React context
|
|
109
|
+
VisualifyProvider,
|
|
110
|
+
useAppContext,
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Initialize the Visualify portal application
|
|
114
|
+
* @param {Object} config - Application configuration
|
|
115
|
+
* @param {string} config.el - DOM selector for mounting
|
|
116
|
+
* @param {string} config.theme - Theme name (default: 'modern')
|
|
117
|
+
* @param {Object} config.routes - Route configuration
|
|
118
|
+
* @param {Object} config.data - Initial data
|
|
119
|
+
*/
|
|
120
|
+
init(config) {
|
|
121
|
+
if (!config) {
|
|
122
|
+
throw new Error('[Visualify] Configuration object is required');
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (!config.el) {
|
|
126
|
+
throw new Error('[Visualify] config.el is required (DOM selector)');
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Set default mode to pages for portal
|
|
130
|
+
config.mode = config.mode || 'pages';
|
|
131
|
+
|
|
132
|
+
// Initialize the application
|
|
133
|
+
CreateApp(config);
|
|
134
|
+
|
|
135
|
+
// Report web vitals if enabled
|
|
136
|
+
if (config.reportWebVitals !== false) {
|
|
137
|
+
reportWebVitals();
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
console.log(`[Visualify] Portal v${this.version} initialized`);
|
|
141
|
+
},
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Create a chart instance (convenience method)
|
|
145
|
+
* @param {Object} config - Chart configuration
|
|
146
|
+
* @returns {Recharts} Recharts instance
|
|
147
|
+
*/
|
|
148
|
+
chart(config) {
|
|
149
|
+
return new Recharts(config);
|
|
150
|
+
},
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Create a live editor instance (convenience method)
|
|
154
|
+
* @param {Object} config - Editor configuration
|
|
155
|
+
* @returns {LiveEditor} LiveEditor instance
|
|
156
|
+
*/
|
|
157
|
+
editor(config) {
|
|
158
|
+
return new LiveEditor(config);
|
|
159
|
+
},
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Check if running in browser environment
|
|
163
|
+
* @returns {boolean}
|
|
164
|
+
*/
|
|
165
|
+
get isBrowser() {
|
|
166
|
+
return typeof window !== 'undefined';
|
|
167
|
+
},
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Check if running in Node.js environment
|
|
171
|
+
* @returns {boolean}
|
|
172
|
+
*/
|
|
173
|
+
get isNode() {
|
|
174
|
+
return typeof window === 'undefined';
|
|
175
|
+
},
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
// Auto-initialize if window.$visualify is already set (legacy support)
|
|
179
|
+
if (typeof window !== 'undefined' && window.$visualify) {
|
|
180
|
+
const config = window.$visualify;
|
|
181
|
+
if (config.mode === 'pages' || config.mode === undefined) {
|
|
182
|
+
Visualify.init(config);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Also support the property setter pattern for deferred initialization
|
|
187
|
+
if (typeof window !== 'undefined') {
|
|
188
|
+
let _visualifyConfig = null;
|
|
189
|
+
|
|
190
|
+
Object.defineProperty(window, '$visualify', {
|
|
191
|
+
set(config) {
|
|
192
|
+
_visualifyConfig = config;
|
|
193
|
+
if (config && (config.mode === 'pages' || config.mode === undefined)) {
|
|
194
|
+
Visualify.init(config);
|
|
195
|
+
}
|
|
196
|
+
},
|
|
197
|
+
get() {
|
|
198
|
+
return _visualifyConfig;
|
|
199
|
+
},
|
|
200
|
+
configurable: true,
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export default Visualify;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared Components Entry Point
|
|
3
|
+
* @description Exports components and utilities used by both docs and portal modes
|
|
4
|
+
* This enables code-splitting and reduces bundle duplication
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Core chart components
|
|
8
|
+
export { default as ReCharts } from '../core/modules/echarts';
|
|
9
|
+
export { default as EChartSwitcher } from '../core/modules/echartswitcher';
|
|
10
|
+
|
|
11
|
+
// Chart utilities and parsers
|
|
12
|
+
export * from '../core/parser/echart.data';
|
|
13
|
+
export * from '../core/parser/echart.features';
|
|
14
|
+
export * from '../core/parser/echart.series';
|
|
15
|
+
export * from '../core/parser/echart.types';
|
|
16
|
+
export * from '../core/parser/echart.parser';
|
|
17
|
+
export * from '../core/parser/echart.hilbert';
|
|
18
|
+
|
|
19
|
+
// Plotly support
|
|
20
|
+
export { default as Replotly } from '../core/modules/replotly';
|
|
21
|
+
export * from '../core/parser/plotly.data';
|
|
22
|
+
export * from '../core/parser/plotly.layout';
|
|
23
|
+
export * from '../core/parser/plotly.config';
|
|
24
|
+
export * from '../core/parser/plotly.violin';
|
|
25
|
+
|
|
26
|
+
// ECharts utilities and presets
|
|
27
|
+
export * from '../core/modules/echartsUtils';
|
|
28
|
+
export { fetchPresetFromURL, getEmbeddedPreset } from '../core/modules/echarts/presetHandler';
|
|
29
|
+
export * from '../core/modules/echarts/common';
|
|
30
|
+
|
|
31
|
+
// Theme system
|
|
32
|
+
export { default as ThemeSelector } from '../core/themes/themeSelector';
|
|
33
|
+
export * from '../core/themes/modern';
|
|
34
|
+
|
|
35
|
+
// Context
|
|
36
|
+
export { VisualifyProvider, useAppContext } from '../core/appContext';
|
|
37
|
+
|
|
38
|
+
// Shared widgets
|
|
39
|
+
export { default as ErrorBoundary } from '../core/widgets/errorBoundary';
|
|
40
|
+
export { default as CircularProgress } from '../core/widgets/circularProgress';
|
|
41
|
+
|
|
42
|
+
// Data fetching utilities
|
|
43
|
+
export { default as fetchData } from '../core/fetch/fetch';
|
|
44
|
+
export { default as condFetch } from '../core/fetch/condfetch';
|
|
45
|
+
export { default as vfetch } from '../core/fetch/vfetch';
|
|
46
|
+
export { default as jsonFetch } from '../core/fetch/json';
|
|
47
|
+
|
|
48
|
+
// Shared CSS (will be extracted by rollup)
|
|
49
|
+
import '../_css/index.css';
|
|
50
|
+
import 'bootstrap/dist/css/bootstrap.min.css';
|
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Locale-aware formatters for Visualify.js i18n
|
|
3
|
+
* @module i18n/formatters
|
|
4
|
+
*
|
|
5
|
+
* Provides locale-aware formatting for:
|
|
6
|
+
* - Dates and times
|
|
7
|
+
* - Numbers (decimals, percentages)
|
|
8
|
+
* - Currency
|
|
9
|
+
* - File sizes (bytes)
|
|
10
|
+
* - Relative time
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { getCurrentLanguage } from './index';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Get Intl.DateTimeFormat options based on locale
|
|
17
|
+
* @param {string} locale - Locale string
|
|
18
|
+
* @returns {Object} DateTimeFormat options
|
|
19
|
+
*/
|
|
20
|
+
function getDateTimeFormatOptions(locale) {
|
|
21
|
+
const region = locale.split('-')[1] || locale;
|
|
22
|
+
|
|
23
|
+
// Locale-specific date formats
|
|
24
|
+
const dateFormats = {
|
|
25
|
+
'en-US': { month: '2-digit', day: '2-digit', year: 'numeric' },
|
|
26
|
+
'en-GB': { day: '2-digit', month: '2-digit', year: 'numeric' },
|
|
27
|
+
'zh': { year: 'numeric', month: '2-digit', day: '2-digit' },
|
|
28
|
+
'zh-CN': { year: 'numeric', month: '2-digit', day: '2-digit' },
|
|
29
|
+
'de': { day: '2-digit', month: '2-digit', year: 'numeric' },
|
|
30
|
+
'de-DE': { day: '2-digit', month: '2-digit', year: 'numeric' },
|
|
31
|
+
'es': { day: '2-digit', month: '2-digit', year: 'numeric' },
|
|
32
|
+
'es-ES': { day: '2-digit', month: '2-digit', year: 'numeric' },
|
|
33
|
+
'ar': { year: 'numeric', month: '2-digit', day: '2-digit' },
|
|
34
|
+
'ar-SA': { year: 'numeric', month: '2-digit', day: '2-digit' },
|
|
35
|
+
'he': { day: '2-digit', month: '2-digit', year: 'numeric' },
|
|
36
|
+
'he-IL': { day: '2-digit', month: '2-digit', year: 'numeric' },
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
return dateFormats[locale] || dateFormats[region] || dateFormats['en-US'];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Format a date according to the current locale
|
|
44
|
+
* @param {Date|string|number} date - Date to format
|
|
45
|
+
* @param {Object} options - Intl.DateTimeFormat options
|
|
46
|
+
* @returns {string} Formatted date string
|
|
47
|
+
*/
|
|
48
|
+
export function formatDate(date, options = {}) {
|
|
49
|
+
const locale = getCurrentLanguage();
|
|
50
|
+
const dateObj = date instanceof Date ? date : new Date(date);
|
|
51
|
+
|
|
52
|
+
if (isNaN(dateObj.getTime())) {
|
|
53
|
+
return '';
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const defaultOptions = getDateTimeFormatOptions(locale);
|
|
57
|
+
const formatOptions = { ...defaultOptions, ...options };
|
|
58
|
+
|
|
59
|
+
return new Intl.DateTimeFormat(locale, formatOptions).format(dateObj);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Format a time according to the current locale
|
|
64
|
+
* @param {Date|string|number} time - Time to format
|
|
65
|
+
* @param {Object} options - Intl.DateTimeFormat options
|
|
66
|
+
* @returns {string} Formatted time string
|
|
67
|
+
*/
|
|
68
|
+
export function formatTime(time, options = {}) {
|
|
69
|
+
const locale = getCurrentLanguage();
|
|
70
|
+
const dateObj = time instanceof Date ? time : new Date(time);
|
|
71
|
+
|
|
72
|
+
if (isNaN(dateObj.getTime())) {
|
|
73
|
+
return '';
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const defaultOptions = {
|
|
77
|
+
hour: '2-digit',
|
|
78
|
+
minute: '2-digit',
|
|
79
|
+
...options,
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
return new Intl.DateTimeFormat(locale, defaultOptions).format(dateObj);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Format date and time together
|
|
87
|
+
* @param {Date|string|number} datetime - DateTime to format
|
|
88
|
+
* @param {Object} options - Intl.DateTimeFormat options
|
|
89
|
+
* @returns {string} Formatted datetime string
|
|
90
|
+
*/
|
|
91
|
+
export function formatDateTime(datetime, options = {}) {
|
|
92
|
+
const locale = getCurrentLanguage();
|
|
93
|
+
const dateObj = datetime instanceof Date ? datetime : new Date(datetime);
|
|
94
|
+
|
|
95
|
+
if (isNaN(dateObj.getTime())) {
|
|
96
|
+
return '';
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const defaultOptions = {
|
|
100
|
+
...getDateTimeFormatOptions(locale),
|
|
101
|
+
hour: '2-digit',
|
|
102
|
+
minute: '2-digit',
|
|
103
|
+
...options,
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
return new Intl.DateTimeFormat(locale, defaultOptions).format(dateObj);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Format a number according to the current locale
|
|
111
|
+
* @param {number} value - Number to format
|
|
112
|
+
* @param {Object} options - Intl.NumberFormat options
|
|
113
|
+
* @returns {string} Formatted number string
|
|
114
|
+
*/
|
|
115
|
+
export function formatNumber(value, options = {}) {
|
|
116
|
+
const locale = getCurrentLanguage();
|
|
117
|
+
|
|
118
|
+
if (typeof value !== 'number' || isNaN(value)) {
|
|
119
|
+
return '';
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const defaultOptions = {
|
|
123
|
+
minimumFractionDigits: 0,
|
|
124
|
+
maximumFractionDigits: 2,
|
|
125
|
+
...options,
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
return new Intl.NumberFormat(locale, defaultOptions).format(value);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Format a percentage according to the current locale
|
|
133
|
+
* @param {number} value - Value to format as percentage (0-1 or 0-100)
|
|
134
|
+
* @param {Object} options - Intl.NumberFormat options
|
|
135
|
+
* @returns {string} Formatted percentage string
|
|
136
|
+
*/
|
|
137
|
+
export function formatPercent(value, options = {}) {
|
|
138
|
+
const locale = getCurrentLanguage();
|
|
139
|
+
|
|
140
|
+
if (typeof value !== 'number' || isNaN(value)) {
|
|
141
|
+
return '';
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Normalize value to 0-1 range if it appears to be 0-100
|
|
145
|
+
const normalizedValue = value > 1 ? value / 100 : value;
|
|
146
|
+
|
|
147
|
+
const defaultOptions = {
|
|
148
|
+
style: 'percent',
|
|
149
|
+
minimumFractionDigits: 0,
|
|
150
|
+
maximumFractionDigits: 2,
|
|
151
|
+
...options,
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
return new Intl.NumberFormat(locale, defaultOptions).format(normalizedValue);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Format currency according to the current locale
|
|
159
|
+
* @param {number} value - Value to format
|
|
160
|
+
* @param {string} currency - Currency code (e.g., 'USD', 'EUR', 'CNY')
|
|
161
|
+
* @param {Object} options - Intl.NumberFormat options
|
|
162
|
+
* @returns {string} Formatted currency string
|
|
163
|
+
*/
|
|
164
|
+
export function formatCurrency(value, currency = 'USD', options = {}) {
|
|
165
|
+
const locale = getCurrentLanguage();
|
|
166
|
+
|
|
167
|
+
if (typeof value !== 'number' || isNaN(value)) {
|
|
168
|
+
return '';
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const defaultOptions = {
|
|
172
|
+
style: 'currency',
|
|
173
|
+
currency,
|
|
174
|
+
...options,
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
return new Intl.NumberFormat(locale, defaultOptions).format(value);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Format bytes to human-readable format
|
|
182
|
+
* @param {number} bytes - Bytes to format
|
|
183
|
+
* @param {Object} options - Formatting options
|
|
184
|
+
* @returns {string} Formatted bytes string
|
|
185
|
+
*/
|
|
186
|
+
export function formatBytes(bytes, options = {}) {
|
|
187
|
+
const locale = getCurrentLanguage();
|
|
188
|
+
|
|
189
|
+
if (typeof bytes !== 'number' || isNaN(bytes)) {
|
|
190
|
+
return '';
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const { decimals = 2, binary = false } = options;
|
|
194
|
+
const base = binary ? 1024 : 1000;
|
|
195
|
+
const units = binary
|
|
196
|
+
? ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB']
|
|
197
|
+
: ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
|
|
198
|
+
|
|
199
|
+
if (bytes === 0) {
|
|
200
|
+
return `0 ${units[0]}`;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const exponent = Math.min(
|
|
204
|
+
Math.floor(Math.log(bytes) / Math.log(base)),
|
|
205
|
+
units.length - 1
|
|
206
|
+
);
|
|
207
|
+
const value = bytes / Math.pow(base, exponent);
|
|
208
|
+
|
|
209
|
+
const formattedValue = new Intl.NumberFormat(locale, {
|
|
210
|
+
minimumFractionDigits: 0,
|
|
211
|
+
maximumFractionDigits: decimals,
|
|
212
|
+
}).format(value);
|
|
213
|
+
|
|
214
|
+
return `${formattedValue} ${units[exponent]}`;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Format relative time (e.g., "2 days ago", "in 3 hours")
|
|
219
|
+
* @param {Date|string|number} date - Date to compare
|
|
220
|
+
* @param {Date|string|number} [relativeTo] - Date to compare against (default: now)
|
|
221
|
+
* @returns {string} Formatted relative time string
|
|
222
|
+
*/
|
|
223
|
+
export function formatRelativeTime(date, relativeTo = new Date()) {
|
|
224
|
+
const locale = getCurrentLanguage();
|
|
225
|
+
const dateObj = date instanceof Date ? date : new Date(date);
|
|
226
|
+
const relativeObj = relativeTo instanceof Date ? relativeTo : new Date(relativeTo);
|
|
227
|
+
|
|
228
|
+
const diffMs = dateObj.getTime() - relativeObj.getTime();
|
|
229
|
+
const diffSeconds = Math.round(diffMs / 1000);
|
|
230
|
+
const diffMinutes = Math.round(diffSeconds / 60);
|
|
231
|
+
const diffHours = Math.round(diffMinutes / 60);
|
|
232
|
+
const diffDays = Math.round(diffHours / 24);
|
|
233
|
+
|
|
234
|
+
// Use Intl.RelativeTimeFormat if available
|
|
235
|
+
if (typeof Intl.RelativeTimeFormat !== 'undefined') {
|
|
236
|
+
const rtf = new Intl.RelativeTimeFormat(locale, { numeric: 'auto' });
|
|
237
|
+
|
|
238
|
+
if (Math.abs(diffSeconds) < 60) {
|
|
239
|
+
return rtf.format(diffSeconds, 'second');
|
|
240
|
+
} else if (Math.abs(diffMinutes) < 60) {
|
|
241
|
+
return rtf.format(diffMinutes, 'minute');
|
|
242
|
+
} else if (Math.abs(diffHours) < 24) {
|
|
243
|
+
return rtf.format(diffHours, 'hour');
|
|
244
|
+
} else if (Math.abs(diffDays) < 30) {
|
|
245
|
+
return rtf.format(diffDays, 'day');
|
|
246
|
+
} else if (Math.abs(diffDays) < 365) {
|
|
247
|
+
return rtf.format(Math.round(diffDays / 30), 'month');
|
|
248
|
+
} else {
|
|
249
|
+
return rtf.format(Math.round(diffDays / 365), 'year');
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Fallback for browsers without RelativeTimeFormat
|
|
254
|
+
const absSeconds = Math.abs(diffSeconds);
|
|
255
|
+
const absMinutes = Math.abs(diffMinutes);
|
|
256
|
+
const absHours = Math.abs(diffHours);
|
|
257
|
+
const absDays = Math.abs(diffDays);
|
|
258
|
+
|
|
259
|
+
let value, unit;
|
|
260
|
+
if (absSeconds < 60) {
|
|
261
|
+
value = absSeconds;
|
|
262
|
+
unit = 'second';
|
|
263
|
+
} else if (absMinutes < 60) {
|
|
264
|
+
value = absMinutes;
|
|
265
|
+
unit = 'minute';
|
|
266
|
+
} else if (absHours < 24) {
|
|
267
|
+
value = absHours;
|
|
268
|
+
unit = 'hour';
|
|
269
|
+
} else {
|
|
270
|
+
value = absDays;
|
|
271
|
+
unit = 'day';
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const suffix = diffMs > 0 ? 'from now' : 'ago';
|
|
275
|
+
return `${value} ${unit}${value !== 1 ? 's' : ''} ${suffix}`;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Format a list according to locale conventions
|
|
280
|
+
* @param {Array<string>} items - Items to format
|
|
281
|
+
* @param {Object} options - Intl.ListFormat options
|
|
282
|
+
* @returns {string} Formatted list string
|
|
283
|
+
*/
|
|
284
|
+
export function formatList(items, options = {}) {
|
|
285
|
+
const locale = getCurrentLanguage();
|
|
286
|
+
|
|
287
|
+
if (!Array.isArray(items) || items.length === 0) {
|
|
288
|
+
return '';
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Use Intl.ListFormat if available
|
|
292
|
+
if (typeof Intl.ListFormat !== 'undefined') {
|
|
293
|
+
const listFormat = new Intl.ListFormat(locale, options);
|
|
294
|
+
return listFormat.format(items);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Fallback
|
|
298
|
+
if (items.length === 1) {
|
|
299
|
+
return items[0];
|
|
300
|
+
} else if (items.length === 2) {
|
|
301
|
+
const conjunctions = {
|
|
302
|
+
'en': ' and ',
|
|
303
|
+
'zh': '和',
|
|
304
|
+
'es': ' y ',
|
|
305
|
+
'de': ' und ',
|
|
306
|
+
'ar': ' و ',
|
|
307
|
+
'he': ' ו ',
|
|
308
|
+
};
|
|
309
|
+
const lang = locale.split('-')[0];
|
|
310
|
+
return items.join(conjunctions[lang] || ' and ');
|
|
311
|
+
} else {
|
|
312
|
+
const conjunctions = {
|
|
313
|
+
'en': ', and ',
|
|
314
|
+
'zh': '和',
|
|
315
|
+
'es': ', y ',
|
|
316
|
+
'de': ', und ',
|
|
317
|
+
'ar': ', و ',
|
|
318
|
+
'he': ', ו ',
|
|
319
|
+
};
|
|
320
|
+
const lang = locale.split('-')[0];
|
|
321
|
+
const lastItem = items[items.length - 1];
|
|
322
|
+
const otherItems = items.slice(0, -1);
|
|
323
|
+
return otherItems.join(', ') + (conjunctions[lang] || ', and ') + lastItem;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Get number formatting info for the current locale
|
|
329
|
+
* @returns {Object} Formatting info (decimal separator, group separator)
|
|
330
|
+
*/
|
|
331
|
+
export function getNumberFormatInfo() {
|
|
332
|
+
const locale = getCurrentLanguage();
|
|
333
|
+
const number = 1234.5;
|
|
334
|
+
const formatted = new Intl.NumberFormat(locale).format(number);
|
|
335
|
+
|
|
336
|
+
// Extract separators from formatted number
|
|
337
|
+
const parts = formatted.split('');
|
|
338
|
+
let decimalSeparator = '.';
|
|
339
|
+
let groupSeparator = ',';
|
|
340
|
+
|
|
341
|
+
for (let i = 0; i < parts.length; i++) {
|
|
342
|
+
if (parts[i] === '4') {
|
|
343
|
+
// Found the decimal part start
|
|
344
|
+
decimalSeparator = parts[i - 1];
|
|
345
|
+
} else if (parts[i] === '1' && i > 0) {
|
|
346
|
+
// Found the group separator
|
|
347
|
+
groupSeparator = parts[i - 1];
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
return {
|
|
352
|
+
decimalSeparator,
|
|
353
|
+
groupSeparator,
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Parse a localized number string back to a number
|
|
359
|
+
* @param {string} value - Localized number string
|
|
360
|
+
* @returns {number|null} Parsed number or null if invalid
|
|
361
|
+
*/
|
|
362
|
+
export function parseNumber(value) {
|
|
363
|
+
if (typeof value !== 'string') {
|
|
364
|
+
return typeof value === 'number' ? value : null;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
const { decimalSeparator, groupSeparator } = getNumberFormatInfo();
|
|
368
|
+
|
|
369
|
+
// Remove group separators and normalize decimal separator
|
|
370
|
+
const normalized = value
|
|
371
|
+
.replace(new RegExp(`\\${groupSeparator}`, 'g'), '')
|
|
372
|
+
.replace(decimalSeparator, '.');
|
|
373
|
+
|
|
374
|
+
const parsed = parseFloat(normalized);
|
|
375
|
+
return isNaN(parsed) ? null : parsed;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Format chart axis label with locale-aware number formatting
|
|
380
|
+
* @param {number} value - Value to format
|
|
381
|
+
* @param {string} type - Axis type ('value', 'log', 'time')
|
|
382
|
+
* @returns {string} Formatted label
|
|
383
|
+
*/
|
|
384
|
+
export function formatAxisLabel(value, type = 'value') {
|
|
385
|
+
const locale = getCurrentLanguage();
|
|
386
|
+
|
|
387
|
+
if (type === 'time') {
|
|
388
|
+
return formatDate(value, { month: 'short', day: 'numeric' });
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
if (type === 'log') {
|
|
392
|
+
// For log scales, use scientific notation for very small/large numbers
|
|
393
|
+
if (Math.abs(value) < 0.001 || Math.abs(value) > 10000) {
|
|
394
|
+
return new Intl.NumberFormat(locale, {
|
|
395
|
+
notation: 'scientific',
|
|
396
|
+
maximumFractionDigits: 2,
|
|
397
|
+
}).format(value);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// Standard number formatting
|
|
402
|
+
return formatNumber(value, {
|
|
403
|
+
minimumFractionDigits: 0,
|
|
404
|
+
maximumFractionDigits: 3,
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Format data value for tooltip display
|
|
410
|
+
* @param {*} value - Value to format
|
|
411
|
+
* @param {string} dataType - Type of data ('number', 'date', 'category', 'currency')
|
|
412
|
+
* @param {Object} options - Formatting options
|
|
413
|
+
* @returns {string} Formatted value
|
|
414
|
+
*/
|
|
415
|
+
export function formatTooltipValue(value, dataType = 'number', options = {}) {
|
|
416
|
+
if (value === null || value === undefined) {
|
|
417
|
+
return '-';
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
switch (dataType) {
|
|
421
|
+
case 'date':
|
|
422
|
+
return formatDate(value, options);
|
|
423
|
+
case 'datetime':
|
|
424
|
+
return formatDateTime(value, options);
|
|
425
|
+
case 'currency':
|
|
426
|
+
return formatCurrency(value, options.currency || 'USD', options);
|
|
427
|
+
case 'percent':
|
|
428
|
+
return formatPercent(value, options);
|
|
429
|
+
case 'bytes':
|
|
430
|
+
return formatBytes(value, options);
|
|
431
|
+
case 'number':
|
|
432
|
+
default:
|
|
433
|
+
if (typeof value === 'number') {
|
|
434
|
+
return formatNumber(value, options);
|
|
435
|
+
}
|
|
436
|
+
return String(value);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// Default export with all formatters
|
|
441
|
+
export default {
|
|
442
|
+
formatDate,
|
|
443
|
+
formatTime,
|
|
444
|
+
formatDateTime,
|
|
445
|
+
formatNumber,
|
|
446
|
+
formatPercent,
|
|
447
|
+
formatCurrency,
|
|
448
|
+
formatBytes,
|
|
449
|
+
formatRelativeTime,
|
|
450
|
+
formatList,
|
|
451
|
+
getNumberFormatInfo,
|
|
452
|
+
parseNumber,
|
|
453
|
+
formatAxisLabel,
|
|
454
|
+
formatTooltipValue,
|
|
455
|
+
};
|