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
@@ -0,0 +1,337 @@
1
+ /**
2
+ * Configuration validation logic using AJV with i18n support
3
+ * @module validator
4
+ */
5
+
6
+ import Ajv from 'ajv';
7
+ import type { ErrorObject, Options as AjvOptions } from 'ajv';
8
+ import schema from './schema';
9
+ import { ValidationError, ValidationResult, VisualifyConfig } from '../../types';
10
+
11
+ // i18n support for validation messages
12
+ let currentLocale = 'en';
13
+ const translations: Record<string, Record<string, string>> = {
14
+ en: {
15
+ 'required': "Missing required property '{property}'",
16
+ 'type': "Property '{property}' should be {expected}, received {received}",
17
+ 'enum': "Property '{property}' must be one of: {values}",
18
+ 'minLength': "Property '{property}' cannot be empty",
19
+ 'format': "Property '{property}' has invalid format",
20
+ 'additionalProperties': "Unknown property '{property}'",
21
+ 'configObject': 'Configuration must be an object',
22
+ 'configObjectSuggestion': 'Provide a valid JSON object with configuration properties',
23
+ },
24
+ zh: {
25
+ 'required': "缺少必需属性'{property}'",
26
+ 'type': "属性'{property}'应为{expected},实际为{received}",
27
+ 'enum': "属性'{property}'必须是以下之一:{values}",
28
+ 'minLength': "属性'{property}'不能为空",
29
+ 'format': "属性'{property}'格式无效",
30
+ 'additionalProperties': "未知属性'{property}'",
31
+ 'configObject': '配置必须是一个对象',
32
+ 'configObjectSuggestion': '提供一个包含配置属性的有效JSON对象',
33
+ },
34
+ es: {
35
+ 'required': "Falta la propiedad obligatoria '{property}'",
36
+ 'type': "La propiedad '{property}' debería ser {expected}, se recibió {received}",
37
+ 'enum': "La propiedad '{property}' debe ser una de: {values}",
38
+ 'minLength': "La propiedad '{property}' no puede estar vacía",
39
+ 'format': "La propiedad '{property}' tiene un formato inválido",
40
+ 'additionalProperties': "Propiedad desconocida '{property}'",
41
+ 'configObject': 'La configuración debe ser un objeto',
42
+ 'configObjectSuggestion': 'Proporcione un objeto JSON válido con propiedades de configuración',
43
+ },
44
+ de: {
45
+ 'required': "Eigenschaft '{property}' ist erforderlich",
46
+ 'type': "Eigenschaft '{property}' sollte {expected} sein, empfangen wurde {received}",
47
+ 'enum': "Eigenschaft '{property}' muss einer der folgenden sein: {values}",
48
+ 'minLength': "Eigenschaft '{property}' darf nicht leer sein",
49
+ 'format': "Eigenschaft '{property}' hat ein ungültiges Format",
50
+ 'additionalProperties': "Unbekannte Eigenschaft '{property}'",
51
+ 'configObject': 'Konfiguration muss ein Objekt sein',
52
+ 'configObjectSuggestion': 'Geben Sie ein gültiges JSON-Objekt mit Konfigurationseigenschaften an',
53
+ },
54
+ };
55
+
56
+ /**
57
+ * Set the current locale for validation messages
58
+ * @param locale - Locale code
59
+ */
60
+ export function setValidationLocale(locale: string): void {
61
+ currentLocale = locale;
62
+ }
63
+
64
+ /**
65
+ * Get the current locale
66
+ * @returns Current locale code
67
+ */
68
+ export function getValidationLocale(): string {
69
+ return currentLocale;
70
+ }
71
+
72
+ /**
73
+ * Translate a key with interpolation
74
+ * @param key - Translation key
75
+ * @param params - Interpolation parameters
76
+ * @returns Translated string
77
+ */
78
+ function t(key: string, params: Record<string, string> = {}): string {
79
+ const messages = translations[currentLocale] || translations['en'];
80
+ let message = messages[key] || key;
81
+
82
+ Object.keys(params).forEach((param) => {
83
+ message = message.replace(new RegExp(`{${param}}`, 'g'), params[param]);
84
+ });
85
+
86
+ return message;
87
+ }
88
+
89
+ /**
90
+ * Error message templates for common validation errors
91
+ */
92
+ const ERROR_TEMPLATES: Record<string, string> = {
93
+ required: "Missing required property '{property}'",
94
+ type: "Property '{property}' should be {expected}, received {received}",
95
+ enum: "Property '{property}' must be one of: {values}",
96
+ minLength: "Property '{property}' cannot be empty",
97
+ format: "Property '{property}' has invalid format",
98
+ additionalProperties: "Unknown property '{property}'",
99
+ };
100
+
101
+ /**
102
+ * Suggested fixes for common errors
103
+ * Maps property paths to fix functions
104
+ */
105
+ const SUGGESTED_FIXES: Record<
106
+ string,
107
+ (error: ErrorObject) => string | null
108
+ > = {
109
+ version: (error: ErrorObject): string | null => {
110
+ if (error.keyword === 'enum') {
111
+ return "Set version to '3.0.0'";
112
+ }
113
+ return null;
114
+ },
115
+ mode: (error: ErrorObject): string | null => {
116
+ if (error.keyword === 'enum') {
117
+ return "Use one of: 'docs', 'portal', 'hybrid', 'auto'";
118
+ }
119
+ return null;
120
+ },
121
+ defaultLibrary: (error: ErrorObject): string | null => {
122
+ if (error.keyword === 'enum') {
123
+ return "Use either 'echarts' or 'plotly'";
124
+ }
125
+ return null;
126
+ },
127
+ 'docs.basePath': (): string => "Use a relative path like './docs' or './documentation'",
128
+ 'docs.theme': (): string => "Available themes: 'vue', 'modern', 'classic'",
129
+ 'portal.homepage': (): string => "Use a filename like 'home.json' or 'index.json'",
130
+ 'portal.dataSources': (error: ErrorObject): string | null => {
131
+ if (error.keyword === 'required') {
132
+ return "Each data source needs 'name' and 'type' properties";
133
+ }
134
+ return null;
135
+ },
136
+ };
137
+
138
+ /**
139
+ * Validation options
140
+ */
141
+ interface ValidateOptions {
142
+ /** Source identifier for error context */
143
+ source?: string;
144
+ }
145
+
146
+ /**
147
+ * Initialize AJV instance with configuration
148
+ * @returns Configured AJV instance
149
+ */
150
+ function createValidator(): InstanceType<typeof Ajv> {
151
+ const options: AjvOptions = {
152
+ allErrors: true,
153
+ verbose: true,
154
+ };
155
+ return new Ajv(options);
156
+ }
157
+
158
+ /**
159
+ * Format a single validation error into a readable message
160
+ * @param error - AJV error object
161
+ * @param configSource - Source of the configuration (for context)
162
+ * @returns Formatted error with message, path, and suggestion
163
+ */
164
+ function formatError(error: ErrorObject, configSource = 'config'): ValidationError {
165
+ // Handle both AJV v6 (dataPath) and v8+ (instancePath) property names
166
+ const instancePath = (error as { instancePath?: string; dataPath?: string }).instancePath
167
+ || (error as { dataPath?: string }).dataPath
168
+ || '';
169
+ const path = instancePath
170
+ ? instancePath.slice(1).replace(/\//g, '.')
171
+ : (error.params as { missingProperty?: string }).missingProperty || 'root';
172
+
173
+ const property = path.split('.').pop() || 'root';
174
+
175
+ // Build base message using i18n
176
+ const params = error.params as Record<string, unknown>;
177
+ let message = t(error.keyword, {
178
+ property: path,
179
+ expected: params.type as string,
180
+ received: typeof error.data,
181
+ values: (params.allowedValues as string[])?.join(', '),
182
+ }) || ERROR_TEMPLATES[error.keyword] || error.message || 'Validation error';
183
+
184
+ // Get suggestion if available
185
+ const suggestionKey = Object.keys(SUGGESTED_FIXES).find(
186
+ (key) => path === key || path.endsWith(`.${key}`)
187
+ );
188
+ const suggestion = suggestionKey
189
+ ? SUGGESTED_FIXES[suggestionKey](error as ErrorObject)
190
+ : null;
191
+
192
+ return {
193
+ path,
194
+ property,
195
+ message,
196
+ suggestion,
197
+ keyword: error.keyword,
198
+ value: error.data,
199
+ source: configSource,
200
+ };
201
+ }
202
+
203
+ /**
204
+ * Validate configuration against the schema
205
+ * @param config - Configuration object to validate
206
+ * @param options - Validation options
207
+ * @returns Validation result with valid flag, errors array, and summary
208
+ *
209
+ * @example
210
+ * ```typescript
211
+ * const result = validateConfig({
212
+ * version: '3.0.0',
213
+ * mode: 'docs'
214
+ * });
215
+ *
216
+ * if (!result.valid) {
217
+ * console.error(result.errors[0].message);
218
+ * if (result.errors[0].suggestion) {
219
+ * console.log('Suggestion:', result.errors[0].suggestion);
220
+ * }
221
+ * }
222
+ * ```
223
+ */
224
+ function validateConfig(
225
+ config: unknown,
226
+ options: ValidateOptions = {}
227
+ ): ValidationResult {
228
+ const { source = 'config' } = options;
229
+
230
+ // Check if config is an object
231
+ if (config === null || typeof config !== 'object') {
232
+ return {
233
+ valid: false,
234
+ errors: [
235
+ {
236
+ path: 'root',
237
+ property: 'root',
238
+ message: t('configObject'),
239
+ suggestion: t('configObjectSuggestion'),
240
+ keyword: 'type',
241
+ value: config,
242
+ source,
243
+ },
244
+ ],
245
+ summary: t('configObject'),
246
+ };
247
+ }
248
+
249
+ const ajv = createValidator();
250
+ const validate = ajv.compile(schema);
251
+ const valid = validate(config);
252
+
253
+ if (valid) {
254
+ return {
255
+ valid: true,
256
+ errors: [],
257
+ summary: null,
258
+ };
259
+ }
260
+
261
+ const errors = (validate.errors || []).map((error: ErrorObject) => formatError(error, source));
262
+
263
+ // Build summary message
264
+ const errorCount = errors.length;
265
+ const summary =
266
+ errorCount === 1
267
+ ? `1 validation error: ${errors[0].message}`
268
+ : `${errorCount} validation errors found`;
269
+
270
+ return {
271
+ valid: false,
272
+ errors,
273
+ summary,
274
+ };
275
+ }
276
+
277
+ /**
278
+ * Validate a specific configuration property
279
+ * @param path - Dot-notation path to the property
280
+ * @param value - Value to validate
281
+ * @returns Validation result for the property
282
+ */
283
+ function validateProperty(path: string, value: unknown): ValidationResult {
284
+ const pathParts = path.split('.');
285
+
286
+ // Build minimal config with the property
287
+ const config = pathParts.reduceRight((acc, part, index) => {
288
+ if (index === pathParts.length - 1) {
289
+ return { [part]: value };
290
+ }
291
+ return { [part]: acc };
292
+ }, {} as Record<string, unknown>);
293
+
294
+ // Add required version
295
+ (config as Record<string, unknown>).version = '3.0.0';
296
+
297
+ return validateConfig(config, { source: `property:${path}` });
298
+ }
299
+
300
+ /**
301
+ * Check if a version is compatible with the current schema
302
+ * @param version - Version string to check
303
+ * @returns True if compatible
304
+ */
305
+ function isVersionCompatible(version: string): boolean {
306
+ return version === '3.0.0';
307
+ }
308
+
309
+ /**
310
+ * Type guard to check if a value is a valid VisualifyConfig
311
+ * @param value - Value to check
312
+ * @returns True if value is a valid VisualifyConfig
313
+ */
314
+ function isValidConfig(value: unknown): value is VisualifyConfig {
315
+ const result = validateConfig(value);
316
+ return result.valid;
317
+ }
318
+
319
+ export {
320
+ validateConfig,
321
+ validateProperty,
322
+ isVersionCompatible,
323
+ isValidConfig,
324
+ ERROR_TEMPLATES,
325
+ SUGGESTED_FIXES,
326
+ };
327
+
328
+ export default {
329
+ validateConfig,
330
+ validateProperty,
331
+ isVersionCompatible,
332
+ isValidConfig,
333
+ setValidationLocale,
334
+ getValidationLocale,
335
+ ERROR_TEMPLATES,
336
+ SUGGESTED_FIXES,
337
+ };
@@ -1,27 +1,34 @@
1
- /*
2
- * @Author : Lihao leolihao@arizona.edu
3
- * @Date : 2023-12-23 15:50:00
4
- * @FilePath : /visualifyjs/src/core/appContext.js
5
- * @Description :
6
- * Copyright (c) 2023 by Lihao (leolihao@arizona.edu), All Rights Reserved.
7
- */
8
- import React, { createContext, useContext, useState } from 'react';
9
-
10
- // Create the AppContext
11
- const Visualify = createContext();
12
-
13
- // Create a custom hook for accessing the AppContext
14
- export function useAppContext() {
15
- return useContext(Visualify);
16
- }
17
-
18
- // Create the AppProvider component to wrap your app with the context
19
- export function VisualifyProvider({ children }) {
20
- const [sharedData, setSharedData] = useState({}); // Initialize your shared data here
21
-
22
- return (
23
- <Visualify.Provider value={{ sharedData, setSharedData }}>
24
- {children}
25
- </Visualify.Provider>
26
- );
27
- }
1
+ /*
2
+ * @Author : Lihao leolihao@arizona.edu
3
+ * @Date : 2023-12-23 15:50:00
4
+ * @FilePath : /visualifyjs/src/core/appContext.js
5
+ * @Description :
6
+ * Copyright (c) 2023 by Lihao (leolihao@arizona.edu), All Rights Reserved.
7
+ */
8
+ import React, { createContext, useContext, useState, useMemo } from 'react';
9
+
10
+ // Create the AppContext
11
+ const Visualify = createContext();
12
+
13
+ // Create a custom hook for accessing the AppContext
14
+ export function useAppContext() {
15
+ return useContext(Visualify);
16
+ }
17
+
18
+ // Create the AppProvider component to wrap your app with the context
19
+ export function VisualifyProvider({ children }) {
20
+ const [sharedData, setSharedData] = useState({}); // Initialize your shared data here
21
+
22
+ // Memoize the context value to prevent unnecessary re-renders
23
+ // Only creates a new object when sharedData actually changes
24
+ const contextValue = useMemo(
25
+ () => ({ sharedData, setSharedData }),
26
+ [sharedData],
27
+ );
28
+
29
+ return (
30
+ <Visualify.Provider value={contextValue}>
31
+ {children}
32
+ </Visualify.Provider>
33
+ );
34
+ }