visualifyjs 2.5.3 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (252) hide show
  1. package/.claude/mem/TIMELINE.md +36 -0
  2. package/.claude/mem/notes/2026-02-11-3d-visualization-docs-fix-external-script-solution.md +24 -0
  3. package/.claude/mem/notes/2026-02-11-3d-visualization-docs-fix-session-summary.md +43 -0
  4. package/.claude/mem/notes/2026-02-11-cli-fix-editor-command-alias.md +26 -0
  5. package/.claude/mem/notes/2026-02-11-phase-3-developer-experience-completed.md +51 -0
  6. package/.claude/mem/notes/2026-02-11-phase-4-web-workers-implementation-complete.md +59 -0
  7. package/.claude/mem/notes/2026-02-11-visualify-phase-2-3d-visualization-complete.md +50 -0
  8. package/.claude/mem/notes/2026-02-11-visualify-phase-2-committed-ready-for-phase-3.md +33 -0
  9. package/.claude/mem/notes/2026-02-11-visualify-phase-3-complete-developer-experience.md +52 -0
  10. package/.claude/mem/notes/2026-02-11-visualify-repository-cleanup-complete.md +28 -0
  11. package/.claude/mem/notes/2026-02-18-codebase-cleanup-docsify-plugin-documentation.md +37 -0
  12. package/.claude/mem/notes/2026-02-19-css-grid-layout-fix-displaycontents-on-vcontroller.md +18 -0
  13. package/.claude/mem/notes/2026-02-19-docsify-plugin-fixes-latex-and-visualify-code-bloc.md +26 -0
  14. package/.claude/mem/notes/2026-02-19-page-mode-docs-update-decisions.md +23 -0
  15. package/.claude/mem/notes/2026-02-19-react-context-infinite-re-render-loop-fix-pattern.md +31 -0
  16. package/.claude/mem/notes/2026-02-19-version-300-bump-and-build-fixes.md +32 -0
  17. package/.claude/mem/notes/2026-02-19-visualify-build-deployment-architecture-bug-fixes.md +25 -0
  18. package/.claude/mem/notes/2026-02-19-visualify-dist-iife-self-contained-build-config.md +30 -0
  19. package/.claude/mem/notes/2026-02-19-visualify-infinite-loop-i18n-fixes.md +31 -0
  20. package/.claude/mem/notes/2026-02-19-visualify-v3-bundle-splitting-docs-restructuring.md +32 -0
  21. package/.claude/mem/notes/2026-02-20-bundle-externalization-final-architecture.md +29 -0
  22. package/.claude/mem/notes/2026-02-20-chromium-page-fix-unstable-keys-and-double-event-b.md +27 -0
  23. package/.claude/mem/notes/2026-02-20-console-cleanup-bundle-optimization-commit.md +20 -0
  24. package/.claude/mem/notes/2026-02-20-dotbio-dot-plot-fix-useeffect-dependency.md +21 -0
  25. package/.claude/mem/notes/2026-02-20-public-folder-cleanup-and-readme-rewrite.md +25 -0
  26. package/.claude/mem/notes/2026-02-20-v300-release-and-beta-channel-strategy.md +29 -0
  27. package/.claude/mem/notes/2026-02-20-visium-background-image-unknown-legend-fix.md +19 -0
  28. package/.claude/mem/notes/2026-02-20-visualify-cdn-loader-bundle-externalization.md +34 -0
  29. package/.claude/mem/sessions/session-2026-02-20-031524.md +54 -0
  30. package/.claude/settings.local.json +21 -0
  31. package/.github/workflows/static.yml.bak +51 -51
  32. package/.sisyphus/boulder.json +65 -0
  33. package/.sisyphus/plans/phase-4-advanced-optimizations.md +217 -0
  34. package/LICENSE +674 -674
  35. package/README.md +94 -59
  36. package/config-overrides.js +31 -31
  37. package/dist/stats.html +4949 -0
  38. package/dist/visualify-3d.esm.js +1 -0
  39. package/dist/visualify-3d.js +1 -0
  40. package/dist/visualify-core.esm.js +1 -0
  41. package/dist/visualify-core.js +1 -0
  42. package/dist/visualify-docs.esm.js +1 -0
  43. package/dist/visualify-docs.js +1 -0
  44. package/dist/visualify-loader.js +1 -0
  45. package/dist/visualify-pages.esm.js +1 -0
  46. package/dist/visualify-pages.js +1 -0
  47. package/dist/visualify-portal.esm.js +1 -0
  48. package/dist/visualify-portal.js +1 -0
  49. package/dist/visualify-shared.js +26571 -0
  50. package/dist/visualify.js +1 -188
  51. package/docs/CHANGELOG.md +148 -0
  52. package/docs/cli/commands.md +513 -0
  53. package/docs/configuration/visualify-json.md +474 -0
  54. package/docs/docs/3d-visualization.md +374 -0
  55. package/docs/docs/CLI.md +303 -34
  56. package/docs/docs/README.md +65 -65
  57. package/docs/docs/Rechart/bar.md +190 -190
  58. package/docs/docs/Rechart/funnel.md +241 -193
  59. package/docs/docs/Rechart/line.md +355 -355
  60. package/docs/docs/Rechart/pie.md +225 -225
  61. package/docs/docs/Rechart/radar.md +253 -253
  62. package/docs/docs/Rechart/scatter.md +298 -0
  63. package/docs/docs/_404.md +51 -51
  64. package/docs/docs/_coverpage.md +11 -11
  65. package/docs/docs/_sidebar.md +54 -43
  66. package/docs/docs/components/dotBio.md +87 -34
  67. package/docs/docs/components/echart.md +171 -82
  68. package/docs/docs/components/html.md +61 -34
  69. package/docs/docs/components/macaron.md +156 -145
  70. package/docs/docs/components/markdown.md +42 -0
  71. package/docs/docs/components/more.md +183 -142
  72. package/docs/docs/components/plotly.md +132 -62
  73. package/docs/docs/components/scatterL.md +171 -70
  74. package/docs/docs/components/visium.md +112 -57
  75. package/docs/docs/configuration.md +121 -123
  76. package/docs/docs/deploy.md +31 -31
  77. package/docs/docs/docsify-plugin.md +655 -0
  78. package/docs/docs/hmr.md +165 -0
  79. package/docs/docs/i18n.md +332 -0
  80. package/docs/docs/log.md +30 -1
  81. package/docs/docs/more-pages.md +23 -23
  82. package/docs/docs/quickstart.md +148 -119
  83. package/docs/docs/rechart-attributes.md +74 -74
  84. package/docs/docs/rechart-basic-usage.md +160 -162
  85. package/docs/docs/theme.md +5 -5
  86. package/docs/docs/typescript.md +306 -0
  87. package/docs/docs/visual-editor.md +359 -0
  88. package/docs/index.html +85 -71
  89. package/docs/manifest.json +23 -23
  90. package/docs/migration/v3-migration.md +392 -0
  91. package/docs/static/css/fluff-stuff.css +169 -169
  92. package/docs/static/css/font-awesome.min.css +4 -4
  93. package/docs/static/css/visualify.css +6 -25
  94. package/docs/static/js/3d-viz-examples.js +181 -0
  95. package/docs/static/js/configuration.js +630 -448
  96. package/docs/static/js/visualify.js +1 -188
  97. package/package.json +106 -84
  98. package/rollup.config.mjs +766 -76
  99. package/src/_css/404.css +115 -115
  100. package/src/_css/App.css +37 -37
  101. package/src/_css/autoSuggestion.css +26 -26
  102. package/src/_css/circular-progress.css +32 -32
  103. package/src/_css/index.css +36 -36
  104. package/src/_css/modern.css +350 -25
  105. package/src/_media/corner.svg +8 -8
  106. package/src/_media/download.svg +3 -3
  107. package/src/_media/logo.svg +14 -14
  108. package/src/_test/App.test.js +15 -15
  109. package/src/_utils/reportWebVitals.js +13 -13
  110. package/src/a11y/README.md +177 -0
  111. package/src/a11y/aria-labels.js +339 -0
  112. package/src/a11y/color-contrast.js +535 -0
  113. package/src/a11y/index.js +197 -0
  114. package/src/a11y/keyboard-nav.js +523 -0
  115. package/src/a11y/styles.css +165 -0
  116. package/src/cli/commands/dev.js +214 -0
  117. package/src/cli/commands/docs.js +521 -0
  118. package/src/cli/commands/edit.js +379 -0
  119. package/src/cli/commands/init.js +213 -0
  120. package/src/cli/commands/portal.js +236 -0
  121. package/src/cli/dev-server.js +530 -0
  122. package/src/cli/hmr.js +456 -0
  123. package/src/cli/index.js +180 -0
  124. package/src/cli/utils/config.js +207 -0
  125. package/src/cli/utils/logger.js +241 -0
  126. package/src/config/defaults.ts +122 -0
  127. package/src/config/index.ts +72 -0
  128. package/src/config/loader.ts +478 -0
  129. package/src/config/schema.ts +227 -0
  130. package/src/config/validator.ts +337 -0
  131. package/src/core/appContext.js +34 -27
  132. package/src/core/components/Bar.js +383 -0
  133. package/src/core/components/Bar3D.js +473 -0
  134. package/src/core/components/LargeDatasetChart.js +296 -0
  135. package/src/core/components/Line3D.js +310 -0
  136. package/src/core/components/Scatter.js +392 -188
  137. package/src/core/components/Scatter3D.js +455 -0
  138. package/src/core/components/ScatterBio.js +601 -572
  139. package/src/core/components/Surface3D.js +326 -0
  140. package/src/core/components/ThreeCustom.js +648 -0
  141. package/src/core/components/ThreeScene.js +459 -0
  142. package/src/core/components/VisiumPlot.js +191 -165
  143. package/src/core/components/browser.js +42 -42
  144. package/src/core/components/dotplot.js +413 -413
  145. package/src/core/components/html.js +29 -29
  146. package/src/core/components/list.js +178 -178
  147. package/src/core/components/macaron.js +206 -201
  148. package/src/core/components/markdown.js +56 -56
  149. package/src/core/components/parser.scatterBio.js +582 -579
  150. package/src/core/components/ratio.js +82 -80
  151. package/src/core/components/scatterL.js +206 -173
  152. package/src/core/components/searchbar.js +156 -131
  153. package/src/core/components/selection.js +310 -193
  154. package/src/core/components/timeline.js +236 -281
  155. package/src/core/components/visium.js +114 -97
  156. package/src/core/data-processor.js +413 -0
  157. package/src/core/fetch/condfetch.js +82 -82
  158. package/src/core/fetch/fetch.js +92 -92
  159. package/src/core/fetch/json.js +29 -29
  160. package/src/core/fetch/vfetch.js +42 -42
  161. package/src/core/hmr-client.js +724 -0
  162. package/src/core/liveEditor.js +44 -44
  163. package/src/core/modules/codeEditorWithPreview.js +104 -104
  164. package/src/core/modules/echarts/common.js +20 -20
  165. package/src/core/modules/echarts/gl.js +228 -0
  166. package/src/core/modules/echarts/presetHandler.js +41 -41
  167. package/src/core/modules/echarts/presets/esodev.chromium.js +172 -172
  168. package/src/core/modules/echarts/presets/esodev.codex.js +130 -130
  169. package/src/core/modules/echarts/presets/esodev.visium.js +123 -123
  170. package/src/core/modules/echarts/presets/mmtrbc.js +186 -186
  171. package/src/core/modules/echarts.js +70 -71
  172. package/src/core/modules/echartsUtils.js +43 -43
  173. package/src/core/modules/echartswitcher.js +227 -152
  174. package/src/core/modules/replotly/presetHandler.js +24 -24
  175. package/src/core/modules/replotly/presets/minimum.js +18 -18
  176. package/src/core/modules/replotly/presets/mmtrbc.dot.js +114 -114
  177. package/src/core/modules/replotly/presets/mmtrbc.violin.js +100 -100
  178. package/src/core/modules/replotly.js +74 -71
  179. package/src/core/modules/threejs/Camera.js +373 -0
  180. package/src/core/modules/threejs/Lighting.js +459 -0
  181. package/src/core/modules/threejs/Renderer.js +364 -0
  182. package/src/core/modules/threejs/Scene.js +266 -0
  183. package/src/core/modules/threejs/index.js +155 -0
  184. package/src/core/pages/404.js +50 -50
  185. package/src/core/pages/error.js +27 -27
  186. package/src/core/pages/jsonPage.js +62 -62
  187. package/src/core/pages/loading.js +44 -44
  188. package/src/core/parser/echart.data.js +204 -183
  189. package/src/core/parser/echart.features.js +125 -125
  190. package/src/core/parser/echart.general.js +147 -143
  191. package/src/core/parser/echart.hilbert.js +57 -57
  192. package/src/core/parser/echart.parser.js +210 -210
  193. package/src/core/parser/echart.series.js +67 -67
  194. package/src/core/parser/echart.types.js +76 -76
  195. package/src/core/parser/plotly.config.js +10 -10
  196. package/src/core/parser/plotly.data.js +132 -132
  197. package/src/core/parser/plotly.layout.js +9 -9
  198. package/src/core/parser/plotly.violin.js +18 -18
  199. package/src/core/recharts.js +361 -62
  200. package/src/core/router/alias.js +49 -49
  201. package/src/core/router/jsonRouter.js +31 -31
  202. package/src/core/themes/modern.js +32 -32
  203. package/src/core/themes/themeSelector.js +33 -33
  204. package/src/core/visualify.js +213 -47
  205. package/src/core/widgets/circularProgress.js +23 -23
  206. package/src/core/widgets/controller.js +116 -83
  207. package/src/core/widgets/errorBoundary.js +36 -36
  208. package/src/core/widgets/footer.js +185 -177
  209. package/src/core/widgets/header.js +238 -234
  210. package/src/core/widgets/layout/Grid.js +31 -31
  211. package/src/core/widgets/layout.js +36 -36
  212. package/src/core/widgets/mapping.js +56 -42
  213. package/src/core/workers/data-worker.js +349 -0
  214. package/src/core/workers/worker-pool.js +396 -0
  215. package/src/docsify/bundle.js +215 -0
  216. package/src/docsify/markdown.js +271 -0
  217. package/src/docsify/plugin.js +268 -0
  218. package/src/editor/README.md +172 -0
  219. package/src/editor/components/ChartBuilder.jsx +341 -0
  220. package/src/editor/components/ChartTypeSidebar.jsx +91 -0
  221. package/src/editor/components/Editor.jsx +367 -0
  222. package/src/editor/components/Preview.jsx +446 -0
  223. package/src/editor/components/PropertyPanel.jsx +468 -0
  224. package/src/editor/components/StatusBar.jsx +85 -0
  225. package/src/editor/context/EditorContext.js +248 -0
  226. package/src/editor/hooks/useDebounce.js +32 -0
  227. package/src/editor/index.js +315 -0
  228. package/src/editor/styles/editor.css +637 -0
  229. package/src/editor/utils/chartValidator.js +263 -0
  230. package/src/entries/charts3d.js +70 -0
  231. package/src/entries/core.js +78 -0
  232. package/src/entries/docs.js +154 -0
  233. package/src/entries/pages.js +93 -0
  234. package/src/entries/portal.js +204 -0
  235. package/src/entries/shared.js +50 -0
  236. package/src/i18n/formatters.js +455 -0
  237. package/src/i18n/index.js +169 -0
  238. package/src/i18n/locales/ar.json +137 -0
  239. package/src/i18n/locales/de.json +137 -0
  240. package/src/i18n/locales/en.json +137 -0
  241. package/src/i18n/locales/es.json +137 -0
  242. package/src/i18n/locales/he.json +137 -0
  243. package/src/i18n/locales/zh.json +137 -0
  244. package/src/i18n/rtl.css +183 -0
  245. package/src/index.js +82 -62
  246. package/src/loader.js +103 -0
  247. package/src/setupTests.js +5 -5
  248. package/tsconfig.json +51 -0
  249. package/types/charts.d.ts +569 -0
  250. package/types/components.d.ts +441 -0
  251. package/types/config.d.ts +199 -0
  252. package/types/index.d.ts +353 -0
@@ -1,42 +1,56 @@
1
- /*
2
- * @Author : Lihao leolihao@arizona.edu
3
- * @Date : 2023-12-21 13:52:36
4
- * @FilePath : /visualifyjs/src/core/widgets/mapping.js
5
- * @Description :
6
- * Copyright (c) 2023 by Lihao (leolihao@arizona.edu), All Rights Reserved.
7
- */
8
-
9
- import SearchBar from '../components/searchbar';
10
- import NaiveHTML from '../components/html';
11
- import Markdown from '../components/markdown';
12
- import Browser from '../components/browser';
13
- import Macaron from '../components/macaron';
14
- import EChartSwitcher from '../modules/echartswitcher';
15
- import ScatterL from '../components/scatterL';
16
- import RatioBox from '../components/ratio';
17
- import Selection from '../components/selection';
18
- import Timeline from '../components/timeline';
19
- import VisiumPlot from '../components/VisiumPlot';
20
- import RePlotly from '../modules/replotly';
21
- import List from '../components/list';
22
- import DotBio from '../components/dotplot';
23
-
24
- const widgetMapping = {
25
- // Add components here
26
- SearchBar,
27
- Echart: EChartSwitcher,
28
- HTML: NaiveHTML,
29
- Markdown,
30
- Browser,
31
- Macaron,
32
- ScatterL,
33
- RatioBox,
34
- Selection,
35
- Timeline,
36
- Visium: VisiumPlot,
37
- Plotly: RePlotly,
38
- List,
39
- DotBio,
40
- };
41
-
42
- export default widgetMapping;
1
+ /*
2
+ * @Author : Lihao leolihao@arizona.edu
3
+ * @Date : 2023-12-21 13:52:36
4
+ * @FilePath : /visualifyjs/src/core/widgets/mapping.js
5
+ * @Description :
6
+ * Copyright (c) 2023 by Lihao (leolihao@arizona.edu), All Rights Reserved.
7
+ */
8
+
9
+ import SearchBar from '../components/searchbar';
10
+ import NaiveHTML from '../components/html';
11
+ import Markdown from '../components/markdown';
12
+ import Browser from '../components/browser';
13
+ import Macaron from '../components/macaron';
14
+ import EChartSwitcher from '../modules/echartswitcher';
15
+ import ScatterL from '../components/scatterL';
16
+ import RatioBox from '../components/ratio';
17
+ import Selection from '../components/selection';
18
+ import Timeline from '../components/timeline';
19
+ import VisiumPlot from '../components/VisiumPlot';
20
+ import RePlotly from '../modules/replotly';
21
+ import List from '../components/list';
22
+ import DotBio from '../components/dotplot';
23
+ import Scatter3D from '../components/Scatter3D';
24
+ import Bar3D from '../components/Bar3D';
25
+ import Surface3D from '../components/Surface3D';
26
+ import Line3D from '../components/Line3D';
27
+ import ThreeScene from '../components/ThreeScene';
28
+ import ThreeCustom from '../components/ThreeCustom';
29
+
30
+ const widgetMapping = {
31
+ // Add components here
32
+ SearchBar,
33
+ Echart: EChartSwitcher,
34
+ HTML: NaiveHTML,
35
+ Markdown,
36
+ Browser,
37
+ Macaron,
38
+ ScatterL,
39
+ RatioBox,
40
+ Selection,
41
+ Timeline,
42
+ Visium: VisiumPlot,
43
+ Plotly: RePlotly,
44
+ List,
45
+ DotBio,
46
+ // 3D Chart Components
47
+ scatter3d: Scatter3D,
48
+ bar3d: Bar3D,
49
+ surface3d: Surface3D,
50
+ line3d: Line3D,
51
+ // Three.js Components
52
+ threejs: ThreeScene,
53
+ threecustom: ThreeCustom,
54
+ };
55
+
56
+ export default widgetMapping;
@@ -0,0 +1,349 @@
1
+ /**
2
+ * @fileoverview Data Processing Web Worker
3
+ * @module core/workers/data-worker
4
+ *
5
+ * Handles data transformations, aggregations, and computations
6
+ * off the main thread for improved performance with large datasets.
7
+ */
8
+
9
+ /**
10
+ * Data transformation operations
11
+ */
12
+ const DataOperations = {
13
+ /**
14
+ * Aggregate data using specified method
15
+ * @param {Array} data - Input data array
16
+ * @param {Object} config - Aggregation config
17
+ * @returns {number} Aggregated value
18
+ */
19
+ aggregate(data, config) {
20
+ const { method = 'sum', field } = config;
21
+ const values = field ? data.map((item) => item[field]) : data;
22
+
23
+ switch (method) {
24
+ case 'sum':
25
+ return values.reduce((a, b) => a + (b || 0), 0);
26
+ case 'avg':
27
+ case 'mean':
28
+ return values.reduce((a, b) => a + (b || 0), 0) / values.length;
29
+ case 'min':
30
+ return Math.min(...values);
31
+ case 'max':
32
+ return Math.max(...values);
33
+ case 'count':
34
+ return values.length;
35
+ case 'median': {
36
+ const sorted = [...values].sort((a, b) => a - b);
37
+ const mid = Math.floor(sorted.length / 2);
38
+ return sorted.length % 2 !== 0
39
+ ? sorted[mid]
40
+ : (sorted[mid - 1] + sorted[mid]) / 2;
41
+ }
42
+ case 'std': {
43
+ const mean = values.reduce((a, b) => a + b, 0) / values.length;
44
+ const variance =
45
+ values.reduce((sum, val) => sum + Math.pow(val - mean, 2), 0) /
46
+ values.length;
47
+ return Math.sqrt(variance);
48
+ }
49
+ default:
50
+ throw new Error(`Unknown aggregation method: ${method}`);
51
+ }
52
+ },
53
+
54
+ /**
55
+ * Filter data based on criteria
56
+ * @param {Array} data - Input data array
57
+ * @param {Object} criteria - Filter criteria
58
+ * @returns {Array} Filtered data
59
+ */
60
+ filter(data, criteria) {
61
+ return data.filter((item) => {
62
+ for (const [field, condition] of Object.entries(criteria)) {
63
+ const value = item[field];
64
+
65
+ if (typeof condition === 'object') {
66
+ // Range filter: { min: 0, max: 100 }
67
+ if ('min' in condition && value < condition.min) return false;
68
+ if ('max' in condition && value > condition.max) return false;
69
+
70
+ // Comparison operators
71
+ if ('gt' in condition && !(value > condition.gt)) return false;
72
+ if ('gte' in condition && !(value >= condition.gte)) return false;
73
+ if ('lt' in condition && !(value < condition.lt)) return false;
74
+ if ('lte' in condition && !(value <= condition.lte)) return false;
75
+ if ('eq' in condition && value !== condition.eq) return false;
76
+ if ('ne' in condition && value === condition.ne) return false;
77
+
78
+ // Array includes
79
+ if ('in' in condition && !condition.in.includes(value))
80
+ return false;
81
+ if ('nin' in condition && condition.nin.includes(value))
82
+ return false;
83
+ } else {
84
+ // Direct equality
85
+ if (value !== condition) return false;
86
+ }
87
+ }
88
+ return true;
89
+ });
90
+ },
91
+
92
+ /**
93
+ * Sort data by fields
94
+ * @param {Array} data - Input data array
95
+ * @param {Array} sortConfig - Sort configuration
96
+ * @returns {Array} Sorted data
97
+ */
98
+ sort(data, sortConfig) {
99
+ const sorts = Array.isArray(sortConfig) ? sortConfig : [sortConfig];
100
+
101
+ return [...data].sort((a, b) => {
102
+ for (const { field, order = 'asc' } of sorts) {
103
+ const aVal = a[field];
104
+ const bVal = b[field];
105
+
106
+ if (aVal === bVal) continue;
107
+
108
+ const comparison =
109
+ aVal < bVal ? -1 : aVal > bVal ? 1 : 0;
110
+
111
+ return order === 'desc' ? -comparison : comparison;
112
+ }
113
+ return 0;
114
+ });
115
+ },
116
+
117
+ /**
118
+ * Group data by field(s)
119
+ * @param {Array} data - Input data array
120
+ * @param {string|Array} fields - Field(s) to group by
121
+ * @returns {Object} Grouped data
122
+ */
123
+ groupBy(data, fields) {
124
+ const fieldArray = Array.isArray(fields) ? fields : [fields];
125
+ const groups = {};
126
+
127
+ for (const item of data) {
128
+ const key = fieldArray.map((f) => item[f]).join('|');
129
+ if (!groups[key]) {
130
+ groups[key] = [];
131
+ }
132
+ groups[key].push(item);
133
+ }
134
+
135
+ return groups;
136
+ },
137
+
138
+ /**
139
+ * Sample data for preview (stratified sampling)
140
+ * @param {Array} data - Input data array
141
+ * @param {number} sampleSize - Desired sample size
142
+ * @returns {Array} Sampled data
143
+ */
144
+ sample(data, sampleSize) {
145
+ if (data.length <= sampleSize) return data;
146
+
147
+ const step = data.length / sampleSize;
148
+ const sampled = [];
149
+
150
+ for (let i = 0; i < sampleSize; i++) {
151
+ const index = Math.floor(i * step);
152
+ sampled.push(data[index]);
153
+ }
154
+
155
+ return sampled;
156
+ },
157
+
158
+ /**
159
+ * Calculate statistics for numeric data
160
+ * @param {Array} data - Input data array
161
+ * @param {string} field - Field to analyze
162
+ * @returns {Object} Statistics
163
+ */
164
+ statistics(data, field) {
165
+ const values = data.map((item) => item[field]).filter((v) => typeof v === 'number');
166
+
167
+ if (values.length === 0) {
168
+ return null;
169
+ }
170
+
171
+ const sum = values.reduce((a, b) => a + b, 0);
172
+ const mean = sum / values.length;
173
+ const sorted = [...values].sort((a, b) => a - b);
174
+
175
+ // Calculate variance and standard deviation
176
+ const variance =
177
+ values.reduce((acc, val) => acc + Math.pow(val - mean, 2), 0) /
178
+ values.length;
179
+ const std = Math.sqrt(variance);
180
+
181
+ return {
182
+ count: values.length,
183
+ sum,
184
+ mean,
185
+ min: sorted[0],
186
+ max: sorted[sorted.length - 1],
187
+ median:
188
+ sorted.length % 2 === 0
189
+ ? (sorted[sorted.length / 2 - 1] + sorted[sorted.length / 2]) / 2
190
+ : sorted[Math.floor(sorted.length / 2)],
191
+ variance,
192
+ std,
193
+ q1: sorted[Math.floor(sorted.length * 0.25)],
194
+ q3: sorted[Math.floor(sorted.length * 0.75)],
195
+ };
196
+ },
197
+
198
+ /**
199
+ * Parse CSV string to array
200
+ * @param {string} csv - CSV content
201
+ * @param {Object} options - Parse options
202
+ * @returns {Array} Parsed data
203
+ */
204
+ parseCSV(csv, options = {}) {
205
+ const { delimiter = ',', header = true } = options;
206
+ const lines = csv.trim().split('\n');
207
+
208
+ if (lines.length === 0) return [];
209
+
210
+ const headers = header
211
+ ? lines[0].split(delimiter).map((h) => h.trim())
212
+ : null;
213
+ const startRow = header ? 1 : 0;
214
+
215
+ return lines.slice(startRow).map((line) => {
216
+ const values = line.split(delimiter).map((v) => v.trim());
217
+
218
+ if (headers) {
219
+ const obj = {};
220
+ headers.forEach((h, i) => {
221
+ obj[h] = this._parseValue(values[i]);
222
+ });
223
+ return obj;
224
+ }
225
+ return values.map((v) => this._parseValue(v));
226
+ });
227
+ },
228
+
229
+ /**
230
+ * Try to parse a value to appropriate type
231
+ * @private
232
+ * @param {string} value - String value
233
+ * @returns {any} Parsed value
234
+ */
235
+ _parseValue(value) {
236
+ if (value === '' || value === undefined) return null;
237
+ if (value === 'true') return true;
238
+ if (value === 'false') return false;
239
+
240
+ const num = Number(value);
241
+ if (!isNaN(num) && value !== '') return num;
242
+
243
+ // Try date
244
+ const date = new Date(value);
245
+ if (!isNaN(date.getTime())) return date;
246
+
247
+ return value;
248
+ },
249
+
250
+ /**
251
+ * Transform data using pipeline of operations
252
+ * @param {Array} data - Input data
253
+ * @param {Array} operations - Array of operations to apply
254
+ * @returns {Array} Transformed data
255
+ */
256
+ pipeline(data, operations) {
257
+ let result = data;
258
+
259
+ for (const op of operations) {
260
+ const { type, config } = op;
261
+
262
+ switch (type) {
263
+ case 'filter':
264
+ result = this.filter(result, config);
265
+ break;
266
+ case 'sort':
267
+ result = this.sort(result, config);
268
+ break;
269
+ case 'groupBy':
270
+ result = this.groupBy(result, config);
271
+ break;
272
+ case 'sample':
273
+ result = this.sample(result, config.size);
274
+ break;
275
+ case 'map':
276
+ result = result.map(config.fn);
277
+ break;
278
+ default:
279
+ throw new Error(`Unknown operation: ${type}`);
280
+ }
281
+ }
282
+
283
+ return result;
284
+ },
285
+ };
286
+
287
+ /**
288
+ * Handle incoming messages from main thread
289
+ */
290
+ self.onmessage = function (event) {
291
+ const { type, taskId, payload } = event.data;
292
+
293
+ if (type !== 'task') {
294
+ self.postMessage({
295
+ type: 'error',
296
+ taskId,
297
+ error: { message: 'Unknown message type' },
298
+ });
299
+ return;
300
+ }
301
+
302
+ try {
303
+ const { operation, data, config } = payload;
304
+ let result;
305
+
306
+ switch (operation) {
307
+ case 'aggregate':
308
+ result = DataOperations.aggregate(data, config);
309
+ break;
310
+ case 'filter':
311
+ result = DataOperations.filter(data, config);
312
+ break;
313
+ case 'sort':
314
+ result = DataOperations.sort(data, config);
315
+ break;
316
+ case 'groupBy':
317
+ result = DataOperations.groupBy(data, config);
318
+ break;
319
+ case 'sample':
320
+ result = DataOperations.sample(data, config.size);
321
+ break;
322
+ case 'statistics':
323
+ result = DataOperations.statistics(data, config.field);
324
+ break;
325
+ case 'parseCSV':
326
+ result = DataOperations.parseCSV(data, config);
327
+ break;
328
+ case 'pipeline':
329
+ result = DataOperations.pipeline(data, config);
330
+ break;
331
+ default:
332
+ throw new Error(`Unknown operation: ${operation}`);
333
+ }
334
+
335
+ self.postMessage({
336
+ type: 'result',
337
+ taskId,
338
+ payload: result,
339
+ });
340
+ } catch (error) {
341
+ self.postMessage({
342
+ type: 'error',
343
+ taskId,
344
+ error: { message: error.message, stack: error.stack },
345
+ });
346
+ }
347
+ };
348
+
349
+ export default DataOperations;