visualifyjs 2.5.3-2.dev → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (252) hide show
  1. package/.claude/mem/TIMELINE.md +36 -0
  2. package/.claude/mem/notes/2026-02-11-3d-visualization-docs-fix-external-script-solution.md +24 -0
  3. package/.claude/mem/notes/2026-02-11-3d-visualization-docs-fix-session-summary.md +43 -0
  4. package/.claude/mem/notes/2026-02-11-cli-fix-editor-command-alias.md +26 -0
  5. package/.claude/mem/notes/2026-02-11-phase-3-developer-experience-completed.md +51 -0
  6. package/.claude/mem/notes/2026-02-11-phase-4-web-workers-implementation-complete.md +59 -0
  7. package/.claude/mem/notes/2026-02-11-visualify-phase-2-3d-visualization-complete.md +50 -0
  8. package/.claude/mem/notes/2026-02-11-visualify-phase-2-committed-ready-for-phase-3.md +33 -0
  9. package/.claude/mem/notes/2026-02-11-visualify-phase-3-complete-developer-experience.md +52 -0
  10. package/.claude/mem/notes/2026-02-11-visualify-repository-cleanup-complete.md +28 -0
  11. package/.claude/mem/notes/2026-02-18-codebase-cleanup-docsify-plugin-documentation.md +37 -0
  12. package/.claude/mem/notes/2026-02-19-css-grid-layout-fix-displaycontents-on-vcontroller.md +18 -0
  13. package/.claude/mem/notes/2026-02-19-docsify-plugin-fixes-latex-and-visualify-code-bloc.md +26 -0
  14. package/.claude/mem/notes/2026-02-19-page-mode-docs-update-decisions.md +23 -0
  15. package/.claude/mem/notes/2026-02-19-react-context-infinite-re-render-loop-fix-pattern.md +31 -0
  16. package/.claude/mem/notes/2026-02-19-version-300-bump-and-build-fixes.md +32 -0
  17. package/.claude/mem/notes/2026-02-19-visualify-build-deployment-architecture-bug-fixes.md +25 -0
  18. package/.claude/mem/notes/2026-02-19-visualify-dist-iife-self-contained-build-config.md +30 -0
  19. package/.claude/mem/notes/2026-02-19-visualify-infinite-loop-i18n-fixes.md +31 -0
  20. package/.claude/mem/notes/2026-02-19-visualify-v3-bundle-splitting-docs-restructuring.md +32 -0
  21. package/.claude/mem/notes/2026-02-20-bundle-externalization-final-architecture.md +29 -0
  22. package/.claude/mem/notes/2026-02-20-chromium-page-fix-unstable-keys-and-double-event-b.md +27 -0
  23. package/.claude/mem/notes/2026-02-20-console-cleanup-bundle-optimization-commit.md +20 -0
  24. package/.claude/mem/notes/2026-02-20-dotbio-dot-plot-fix-useeffect-dependency.md +21 -0
  25. package/.claude/mem/notes/2026-02-20-public-folder-cleanup-and-readme-rewrite.md +25 -0
  26. package/.claude/mem/notes/2026-02-20-v300-release-and-beta-channel-strategy.md +29 -0
  27. package/.claude/mem/notes/2026-02-20-visium-background-image-unknown-legend-fix.md +19 -0
  28. package/.claude/mem/notes/2026-02-20-visualify-cdn-loader-bundle-externalization.md +34 -0
  29. package/.claude/mem/sessions/session-2026-02-20-031524.md +54 -0
  30. package/.claude/settings.local.json +21 -0
  31. package/.github/workflows/static.yml.bak +51 -51
  32. package/.sisyphus/boulder.json +65 -0
  33. package/.sisyphus/plans/phase-4-advanced-optimizations.md +217 -0
  34. package/LICENSE +674 -674
  35. package/README.md +94 -59
  36. package/config-overrides.js +31 -31
  37. package/dist/stats.html +4949 -0
  38. package/dist/visualify-3d.esm.js +1 -0
  39. package/dist/visualify-3d.js +1 -0
  40. package/dist/visualify-core.esm.js +1 -0
  41. package/dist/visualify-core.js +1 -0
  42. package/dist/visualify-docs.esm.js +1 -0
  43. package/dist/visualify-docs.js +1 -0
  44. package/dist/visualify-loader.js +1 -0
  45. package/dist/visualify-pages.esm.js +1 -0
  46. package/dist/visualify-pages.js +1 -0
  47. package/dist/visualify-portal.esm.js +1 -0
  48. package/dist/visualify-portal.js +1 -0
  49. package/dist/visualify-shared.js +26571 -0
  50. package/dist/visualify.js +1 -188
  51. package/docs/CHANGELOG.md +148 -0
  52. package/docs/cli/commands.md +513 -0
  53. package/docs/configuration/visualify-json.md +474 -0
  54. package/docs/docs/3d-visualization.md +374 -0
  55. package/docs/docs/CLI.md +303 -34
  56. package/docs/docs/README.md +65 -65
  57. package/docs/docs/Rechart/bar.md +190 -190
  58. package/docs/docs/Rechart/funnel.md +241 -241
  59. package/docs/docs/Rechart/line.md +355 -355
  60. package/docs/docs/Rechart/pie.md +225 -225
  61. package/docs/docs/Rechart/radar.md +253 -253
  62. package/docs/docs/Rechart/scatter.md +298 -298
  63. package/docs/docs/_404.md +51 -51
  64. package/docs/docs/_coverpage.md +11 -11
  65. package/docs/docs/_sidebar.md +54 -44
  66. package/docs/docs/components/dotBio.md +87 -34
  67. package/docs/docs/components/echart.md +171 -82
  68. package/docs/docs/components/html.md +61 -34
  69. package/docs/docs/components/macaron.md +156 -145
  70. package/docs/docs/components/markdown.md +42 -0
  71. package/docs/docs/components/more.md +183 -142
  72. package/docs/docs/components/plotly.md +132 -62
  73. package/docs/docs/components/scatterL.md +171 -70
  74. package/docs/docs/components/visium.md +112 -57
  75. package/docs/docs/configuration.md +121 -121
  76. package/docs/docs/deploy.md +31 -31
  77. package/docs/docs/docsify-plugin.md +655 -0
  78. package/docs/docs/hmr.md +165 -0
  79. package/docs/docs/i18n.md +332 -0
  80. package/docs/docs/log.md +30 -9
  81. package/docs/docs/more-pages.md +23 -23
  82. package/docs/docs/quickstart.md +148 -124
  83. package/docs/docs/rechart-attributes.md +74 -74
  84. package/docs/docs/rechart-basic-usage.md +160 -162
  85. package/docs/docs/theme.md +5 -5
  86. package/docs/docs/typescript.md +306 -0
  87. package/docs/docs/visual-editor.md +359 -0
  88. package/docs/index.html +85 -71
  89. package/docs/manifest.json +23 -23
  90. package/docs/migration/v3-migration.md +392 -0
  91. package/docs/static/css/fluff-stuff.css +169 -169
  92. package/docs/static/css/font-awesome.min.css +4 -4
  93. package/docs/static/css/visualify.css +6 -25
  94. package/docs/static/js/3d-viz-examples.js +181 -0
  95. package/docs/static/js/configuration.js +630 -448
  96. package/docs/static/js/visualify.js +1 -188
  97. package/package.json +106 -84
  98. package/rollup.config.mjs +766 -76
  99. package/src/_css/404.css +115 -115
  100. package/src/_css/App.css +37 -37
  101. package/src/_css/autoSuggestion.css +26 -26
  102. package/src/_css/circular-progress.css +32 -32
  103. package/src/_css/index.css +36 -36
  104. package/src/_css/modern.css +350 -25
  105. package/src/_media/corner.svg +8 -8
  106. package/src/_media/download.svg +3 -3
  107. package/src/_media/logo.svg +14 -14
  108. package/src/_test/App.test.js +15 -15
  109. package/src/_utils/reportWebVitals.js +13 -13
  110. package/src/a11y/README.md +177 -0
  111. package/src/a11y/aria-labels.js +339 -0
  112. package/src/a11y/color-contrast.js +535 -0
  113. package/src/a11y/index.js +197 -0
  114. package/src/a11y/keyboard-nav.js +523 -0
  115. package/src/a11y/styles.css +165 -0
  116. package/src/cli/commands/dev.js +214 -0
  117. package/src/cli/commands/docs.js +521 -0
  118. package/src/cli/commands/edit.js +379 -0
  119. package/src/cli/commands/init.js +213 -0
  120. package/src/cli/commands/portal.js +236 -0
  121. package/src/cli/dev-server.js +530 -0
  122. package/src/cli/hmr.js +456 -0
  123. package/src/cli/index.js +180 -0
  124. package/src/cli/utils/config.js +207 -0
  125. package/src/cli/utils/logger.js +241 -0
  126. package/src/config/defaults.ts +122 -0
  127. package/src/config/index.ts +72 -0
  128. package/src/config/loader.ts +478 -0
  129. package/src/config/schema.ts +227 -0
  130. package/src/config/validator.ts +337 -0
  131. package/src/core/appContext.js +34 -27
  132. package/src/core/components/Bar.js +383 -0
  133. package/src/core/components/Bar3D.js +473 -0
  134. package/src/core/components/LargeDatasetChart.js +296 -0
  135. package/src/core/components/Line3D.js +310 -0
  136. package/src/core/components/Scatter.js +392 -188
  137. package/src/core/components/Scatter3D.js +455 -0
  138. package/src/core/components/ScatterBio.js +601 -572
  139. package/src/core/components/Surface3D.js +326 -0
  140. package/src/core/components/ThreeCustom.js +648 -0
  141. package/src/core/components/ThreeScene.js +459 -0
  142. package/src/core/components/VisiumPlot.js +191 -165
  143. package/src/core/components/browser.js +42 -42
  144. package/src/core/components/dotplot.js +413 -413
  145. package/src/core/components/html.js +29 -29
  146. package/src/core/components/list.js +178 -178
  147. package/src/core/components/macaron.js +206 -201
  148. package/src/core/components/markdown.js +56 -56
  149. package/src/core/components/parser.scatterBio.js +582 -587
  150. package/src/core/components/ratio.js +82 -80
  151. package/src/core/components/scatterL.js +206 -173
  152. package/src/core/components/searchbar.js +156 -131
  153. package/src/core/components/selection.js +310 -193
  154. package/src/core/components/timeline.js +236 -281
  155. package/src/core/components/visium.js +114 -97
  156. package/src/core/data-processor.js +413 -0
  157. package/src/core/fetch/condfetch.js +82 -82
  158. package/src/core/fetch/fetch.js +92 -92
  159. package/src/core/fetch/json.js +29 -29
  160. package/src/core/fetch/vfetch.js +42 -42
  161. package/src/core/hmr-client.js +724 -0
  162. package/src/core/liveEditor.js +44 -44
  163. package/src/core/modules/codeEditorWithPreview.js +104 -104
  164. package/src/core/modules/echarts/common.js +20 -20
  165. package/src/core/modules/echarts/gl.js +228 -0
  166. package/src/core/modules/echarts/presetHandler.js +41 -41
  167. package/src/core/modules/echarts/presets/esodev.chromium.js +172 -172
  168. package/src/core/modules/echarts/presets/esodev.codex.js +130 -130
  169. package/src/core/modules/echarts/presets/esodev.visium.js +123 -123
  170. package/src/core/modules/echarts/presets/mmtrbc.js +186 -186
  171. package/src/core/modules/echarts.js +70 -71
  172. package/src/core/modules/echartsUtils.js +43 -43
  173. package/src/core/modules/echartswitcher.js +227 -152
  174. package/src/core/modules/replotly/presetHandler.js +24 -24
  175. package/src/core/modules/replotly/presets/minimum.js +18 -18
  176. package/src/core/modules/replotly/presets/mmtrbc.dot.js +114 -114
  177. package/src/core/modules/replotly/presets/mmtrbc.violin.js +100 -100
  178. package/src/core/modules/replotly.js +74 -71
  179. package/src/core/modules/threejs/Camera.js +373 -0
  180. package/src/core/modules/threejs/Lighting.js +459 -0
  181. package/src/core/modules/threejs/Renderer.js +364 -0
  182. package/src/core/modules/threejs/Scene.js +266 -0
  183. package/src/core/modules/threejs/index.js +155 -0
  184. package/src/core/pages/404.js +50 -50
  185. package/src/core/pages/error.js +27 -27
  186. package/src/core/pages/jsonPage.js +62 -62
  187. package/src/core/pages/loading.js +44 -44
  188. package/src/core/parser/echart.data.js +204 -183
  189. package/src/core/parser/echart.features.js +125 -125
  190. package/src/core/parser/echart.general.js +147 -147
  191. package/src/core/parser/echart.hilbert.js +57 -57
  192. package/src/core/parser/echart.parser.js +210 -210
  193. package/src/core/parser/echart.series.js +67 -67
  194. package/src/core/parser/echart.types.js +76 -76
  195. package/src/core/parser/plotly.config.js +10 -10
  196. package/src/core/parser/plotly.data.js +132 -132
  197. package/src/core/parser/plotly.layout.js +9 -9
  198. package/src/core/parser/plotly.violin.js +18 -18
  199. package/src/core/recharts.js +361 -62
  200. package/src/core/router/alias.js +49 -49
  201. package/src/core/router/jsonRouter.js +31 -31
  202. package/src/core/themes/modern.js +32 -32
  203. package/src/core/themes/themeSelector.js +33 -33
  204. package/src/core/visualify.js +213 -47
  205. package/src/core/widgets/circularProgress.js +23 -23
  206. package/src/core/widgets/controller.js +116 -83
  207. package/src/core/widgets/errorBoundary.js +36 -36
  208. package/src/core/widgets/footer.js +185 -177
  209. package/src/core/widgets/header.js +238 -234
  210. package/src/core/widgets/layout/Grid.js +31 -31
  211. package/src/core/widgets/layout.js +36 -36
  212. package/src/core/widgets/mapping.js +56 -42
  213. package/src/core/workers/data-worker.js +349 -0
  214. package/src/core/workers/worker-pool.js +396 -0
  215. package/src/docsify/bundle.js +215 -0
  216. package/src/docsify/markdown.js +271 -0
  217. package/src/docsify/plugin.js +268 -0
  218. package/src/editor/README.md +172 -0
  219. package/src/editor/components/ChartBuilder.jsx +341 -0
  220. package/src/editor/components/ChartTypeSidebar.jsx +91 -0
  221. package/src/editor/components/Editor.jsx +367 -0
  222. package/src/editor/components/Preview.jsx +446 -0
  223. package/src/editor/components/PropertyPanel.jsx +468 -0
  224. package/src/editor/components/StatusBar.jsx +85 -0
  225. package/src/editor/context/EditorContext.js +248 -0
  226. package/src/editor/hooks/useDebounce.js +32 -0
  227. package/src/editor/index.js +315 -0
  228. package/src/editor/styles/editor.css +637 -0
  229. package/src/editor/utils/chartValidator.js +263 -0
  230. package/src/entries/charts3d.js +70 -0
  231. package/src/entries/core.js +78 -0
  232. package/src/entries/docs.js +154 -0
  233. package/src/entries/pages.js +93 -0
  234. package/src/entries/portal.js +204 -0
  235. package/src/entries/shared.js +50 -0
  236. package/src/i18n/formatters.js +455 -0
  237. package/src/i18n/index.js +169 -0
  238. package/src/i18n/locales/ar.json +137 -0
  239. package/src/i18n/locales/de.json +137 -0
  240. package/src/i18n/locales/en.json +137 -0
  241. package/src/i18n/locales/es.json +137 -0
  242. package/src/i18n/locales/he.json +137 -0
  243. package/src/i18n/locales/zh.json +137 -0
  244. package/src/i18n/rtl.css +183 -0
  245. package/src/index.js +82 -62
  246. package/src/loader.js +103 -0
  247. package/src/setupTests.js +5 -5
  248. package/tsconfig.json +51 -0
  249. package/types/charts.d.ts +569 -0
  250. package/types/components.d.ts +441 -0
  251. package/types/config.d.ts +199 -0
  252. package/types/index.d.ts +353 -0
@@ -0,0 +1,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
+ };