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
@@ -1,234 +1,238 @@
1
- import React, { useState, useEffect, useRef } from 'react';
2
- import { Container } from 'react-bootstrap';
3
- import { ReactComponent as Corner } from '../../_media/corner.svg';
4
- import { useLocation, Link } from 'react-router-dom';
5
- import { ReactComponent as Logo } from '../../_media/logo.svg';
6
-
7
- function Vheader({ config }) {
8
- const location = useLocation();
9
- const [Navgation, setNavgation] = useState(null);
10
- const [activeNav, setActiveNav] = useState('home');
11
-
12
- const {
13
- logo = <Logo />,
14
- logolink = 'https://www.lgcyaxi.net/visualify',
15
- name = 'Visualify',
16
- nav = false,
17
- alias = {},
18
- nav_alignment = 'start',
19
- repo,
20
- } = config;
21
-
22
- // Function to get the current directory path
23
- const getCurrentDirectoryPath = () => {
24
- // Extract the path from the hash, removing the leading '#/'
25
- const hashPath = window.location.hash.slice(2);
26
- const pathSegments = hashPath.split('/');
27
- // Remove the last segment (file name or empty string if it ends with '/')
28
- pathSegments.pop();
29
- // Rejoin the remaining segments to form the directory path
30
- let directoryPath = pathSegments.join('/');
31
- // Ensure the directory path ends with '/'
32
- if (!directoryPath.endsWith('/')) {
33
- directoryPath += '/';
34
- }
35
- return directoryPath;
36
- };
37
-
38
- const renderLogo = () => {
39
- return (
40
- <a
41
- className='navbar-brand d-flex align-items-center'
42
- href={logolink}
43
- target='_blank'
44
- rel='noreferrer'>
45
- {typeof logo === 'string' ? (
46
- <img
47
- src={logo}
48
- alt='logo'
49
- width='65'
50
- height='65'
51
- className='d-inline-block align-top'
52
- />
53
- ) : (
54
- logo
55
- )}
56
- </a>
57
- );
58
- };
59
-
60
- const renderTitle = () => {
61
- if (typeof name === 'string') {
62
- return <h1 className='rainbow-text'>{name}</h1>;
63
- }
64
- const {
65
- text = 'Visualify',
66
- font_weight = 'bold',
67
- color = 'rainbow',
68
- ...rest
69
- } = name;
70
-
71
- if (color === 'rainbow') {
72
- return (
73
- <h1
74
- className='rainbow-text'
75
- style={{ fontWeight: font_weight }}>
76
- {text}
77
- </h1>
78
- );
79
- } else {
80
- return (
81
- <h1 style={{ fontWeight: font_weight, color: color, ...rest }}>
82
- {text}
83
- </h1>
84
- );
85
- }
86
- };
87
-
88
- useEffect(() => {
89
- const resolveNavUrl = () => {
90
- let pathSegments = location.pathname.split('/');
91
- //console.log('pathseg:' + pathSegments);
92
- pathSegments.pop();
93
- let directoryPath = pathSegments.join('/');
94
-
95
- if (directoryPath === '') directoryPath = window.location.pathname;
96
- //console.log('directoryPath:' + directoryPath,'windows.pathname:' + window.location.pathname,);
97
-
98
- if (!directoryPath.endsWith('/')) directoryPath += '/';
99
-
100
- const fullNavPath = directoryPath + '_nav.json';
101
- const aliasPath = alias && alias[fullNavPath];
102
-
103
- return aliasPath ? aliasPath : fullNavPath;
104
- };
105
-
106
- if (nav && typeof nav === 'boolean') {
107
- const navUrl = resolveNavUrl();
108
-
109
- // Fetch the navigation data only if the URL has changed
110
- if (navUrl !== previousNavUrl.current) {
111
- fetch(navUrl)
112
- .then((res) => res.json())
113
- .then((data) => {
114
- // Check if the fetched data is different from the current state
115
- if (
116
- JSON.stringify(data) !== JSON.stringify(Navgation)
117
- ) {
118
- setNavgation(data);
119
- }
120
- })
121
- .catch((err) => {
122
- console.error(
123
- `Failed to fetch navigation data: ${err}`,
124
- );
125
- setNavgation(null);
126
- });
127
-
128
- // Update the ref with the new URL
129
- previousNavUrl.current = navUrl;
130
- }
131
- } else if (
132
- nav &&
133
- typeof nav === 'object' &&
134
- JSON.stringify(nav) !== JSON.stringify(Navgation)
135
- ) {
136
- setNavgation(nav);
137
- } else if (!nav) {
138
- setNavgation(null);
139
- }
140
- }, [nav, alias, Navgation, location.pathname]); // Use location.pathname if only the path is relevant
141
-
142
- // Use a ref to store the previous navigation URL
143
- const previousNavUrl = useRef();
144
-
145
- useEffect(() => {
146
- // Update the active nav item based on the current location
147
- let path = location.pathname === '/' ? '/home' : location.pathname;
148
- setActiveNav(path.slice(1));
149
- }, [location]);
150
-
151
- const renderNav = () => {
152
- if (!Navgation) return <Container />;
153
- const currentDirectoryPath = getCurrentDirectoryPath();
154
- const navs = Navgation.map((navItem, index) => {
155
- let fullPath = `${currentDirectoryPath}${navItem.link}`;
156
- if (fullPath.startsWith('/')) {
157
- fullPath = fullPath.slice(1);
158
- }
159
- const isActive = activeNav === fullPath;
160
- let navLinkClass = 'nav-link';
161
- if (navItem.type === 'primary')
162
- navLinkClass = 'btn btn-primary shadow no-border-radius';
163
- if (isActive) navLinkClass += ' active';
164
- const isExternal = navItem.link.startsWith('http');
165
-
166
- return (
167
- <li
168
- className='nav-item'
169
- key={index}>
170
- {isExternal ? (
171
- <a
172
- className={navLinkClass}
173
- href={fullPath}
174
- target='_blank'
175
- rel='noreferrer'>
176
- {navItem.title}
177
- </a>
178
- ) : (
179
- <Link
180
- className={navLinkClass}
181
- to={fullPath}>
182
- {navItem.title}
183
- </Link>
184
- )}
185
- </li>
186
- );
187
- });
188
-
189
- return (
190
- <Container>
191
- <ul
192
- className={`navbar-nav d-flex justify-content-${nav_alignment} mx-auto`}
193
- id='navtabs'>
194
- {navs}
195
- </ul>
196
- </Container>
197
- );
198
- };
199
-
200
- const renderGitHubCorner = () => {
201
- if (!repo) return null;
202
-
203
- // Check if it's a full URL or a "username/repo" string
204
- const isFullUrl =
205
- repo.startsWith('http://') || repo.startsWith('https://');
206
- const githubUrl = isFullUrl ? repo : `https://github.com/${repo}`;
207
-
208
- return (
209
- <a
210
- href={githubUrl}
211
- className='github-corner'
212
- aria-label='View source on GitHub'
213
- target='_blank'
214
- rel='noreferrer'>
215
- {<Corner />}
216
- </a>
217
- );
218
- };
219
-
220
- return (
221
- <header className='v-header'>
222
- <nav className='navbar navbar-light navbar-expand-md py-3'>
223
- <Container>
224
- {renderLogo()}
225
- {renderTitle()}
226
- {renderNav()}
227
- </Container>
228
- </nav>
229
- {renderGitHubCorner()}
230
- </header>
231
- );
232
- }
233
-
234
- export default Vheader;
1
+ import React, { useState, useEffect, useRef } from 'react';
2
+ import { Container } from 'react-bootstrap';
3
+ import { ReactComponent as Corner } from '../../_media/corner.svg';
4
+ import { useLocation, Link } from 'react-router-dom';
5
+ import { ReactComponent as Logo } from '../../_media/logo.svg';
6
+ import { useTranslation } from 'react-i18next';
7
+
8
+ function Vheader({ config }) {
9
+ const { t } = useTranslation();
10
+ const location = useLocation();
11
+ const [Navgation, setNavgation] = useState(null);
12
+ const [activeNav, setActiveNav] = useState('home');
13
+
14
+ const {
15
+ logo = <Logo />,
16
+ logolink = 'https://www.lgcyaxi.net/visualify',
17
+ name = 'Visualify',
18
+ nav = false,
19
+ alias = {},
20
+ nav_alignment = 'start',
21
+ repo,
22
+ } = config;
23
+
24
+ // Function to get the current directory path
25
+ const getCurrentDirectoryPath = () => {
26
+ // Extract the path from the hash, removing the leading '#/'
27
+ const hashPath = window.location.hash.slice(2);
28
+ const pathSegments = hashPath.split('/');
29
+ // Remove the last segment (file name or empty string if it ends with '/')
30
+ pathSegments.pop();
31
+ // Rejoin the remaining segments to form the directory path
32
+ let directoryPath = pathSegments.join('/');
33
+ // Ensure the directory path ends with '/'
34
+ if (!directoryPath.endsWith('/')) {
35
+ directoryPath += '/';
36
+ }
37
+ return directoryPath;
38
+ };
39
+
40
+ const renderLogo = () => {
41
+ return (
42
+ <a
43
+ className='navbar-brand d-flex align-items-center'
44
+ href={logolink}
45
+ target='_blank'
46
+ rel='noreferrer'>
47
+ {typeof logo === 'string' ? (
48
+ <img
49
+ src={logo}
50
+ alt={t('header.logo') || 'logo'}
51
+ width='65'
52
+ height='65'
53
+ className='d-inline-block align-top'
54
+ />
55
+ ) : (
56
+ logo
57
+ )}
58
+ </a>
59
+ );
60
+ };
61
+
62
+ const renderTitle = () => {
63
+ if (typeof name === 'string') {
64
+ return <h1 className='rainbow-text'>{name}</h1>;
65
+ }
66
+ const {
67
+ text = 'Visualify',
68
+ font_weight = 'bold',
69
+ color = 'rainbow',
70
+ ...rest
71
+ } = name;
72
+
73
+ if (color === 'rainbow') {
74
+ return (
75
+ <h1
76
+ className='rainbow-text'
77
+ style={{ fontWeight: font_weight }}>
78
+ {text}
79
+ </h1>
80
+ );
81
+ } else {
82
+ return (
83
+ <h1 style={{ fontWeight: font_weight, color: color, ...rest }}>
84
+ {text}
85
+ </h1>
86
+ );
87
+ }
88
+ };
89
+
90
+ useEffect(() => {
91
+ const resolveNavUrl = () => {
92
+ let pathSegments = location.pathname.split('/');
93
+ //console.log('pathseg:' + pathSegments);
94
+ pathSegments.pop();
95
+ let directoryPath = pathSegments.join('/');
96
+
97
+ if (directoryPath === '') directoryPath = window.location.pathname;
98
+ //console.log('directoryPath:' + directoryPath,'windows.pathname:' + window.location.pathname,);
99
+
100
+ if (!directoryPath.endsWith('/')) directoryPath += '/';
101
+
102
+ const fullNavPath = directoryPath + '_nav.json';
103
+ const aliasPath = alias && alias[fullNavPath];
104
+
105
+ return aliasPath ? aliasPath : fullNavPath;
106
+ };
107
+
108
+ if (nav && typeof nav === 'boolean') {
109
+ const navUrl = resolveNavUrl();
110
+
111
+ // Fetch the navigation data only if the URL has changed
112
+ if (navUrl !== previousNavUrl.current) {
113
+ fetch(navUrl)
114
+ .then((res) => res.json())
115
+ .then((data) => {
116
+ // Check if the fetched data is different from the current state
117
+ if (
118
+ JSON.stringify(data) !== JSON.stringify(Navgation)
119
+ ) {
120
+ setNavgation(data);
121
+ }
122
+ })
123
+ .catch((err) => {
124
+ console.error(
125
+ t('errors.dataLoadError') + `: ${err}`,
126
+ );
127
+ setNavgation(null);
128
+ });
129
+
130
+ // Update the ref with the new URL
131
+ previousNavUrl.current = navUrl;
132
+ }
133
+ } else if (
134
+ nav &&
135
+ typeof nav === 'object' &&
136
+ JSON.stringify(nav) !== JSON.stringify(Navgation)
137
+ ) {
138
+ setNavgation(nav);
139
+ } else if (!nav) {
140
+ setNavgation(null);
141
+ }
142
+ }, [nav, alias, Navgation, location.pathname]); // Use location.pathname if only the path is relevant
143
+
144
+ // Use a ref to store the previous navigation URL
145
+ const previousNavUrl = useRef();
146
+
147
+ useEffect(() => {
148
+ // Update the active nav item based on the current location
149
+ let path = location.pathname === '/' ? '/home' : location.pathname;
150
+ setActiveNav(path.slice(1));
151
+ }, [location]);
152
+
153
+ const renderNav = () => {
154
+ if (!Navgation) return <Container />;
155
+ const currentDirectoryPath = getCurrentDirectoryPath();
156
+ const navs = Navgation.map((navItem, index) => {
157
+ let fullPath = `${currentDirectoryPath}${navItem.link}`;
158
+ if (fullPath.startsWith('/')) {
159
+ fullPath = fullPath.slice(1);
160
+ }
161
+ const isActive = activeNav === fullPath;
162
+ let navLinkClass = 'nav-link';
163
+ if (navItem.type === 'primary')
164
+ navLinkClass = 'btn btn-primary shadow no-border-radius';
165
+ if (isActive) navLinkClass += ' active';
166
+ const isExternal = navItem.link.startsWith('http');
167
+
168
+ return (
169
+ <li
170
+ className='nav-item'
171
+ key={index}>
172
+ {isExternal ? (
173
+ <a
174
+ className={navLinkClass}
175
+ href={fullPath}
176
+ target='_blank'
177
+ rel='noreferrer'>
178
+ {navItem.title}
179
+ </a>
180
+ ) : (
181
+ <Link
182
+ className={navLinkClass}
183
+ to={fullPath}>
184
+ {navItem.title}
185
+ </Link>
186
+ )}
187
+ </li>
188
+ );
189
+ });
190
+
191
+ return (
192
+ <Container>
193
+ <nav aria-label={t('header.navigation')}>
194
+ <ul
195
+ className={`navbar-nav d-flex justify-content-${nav_alignment} mx-auto`}
196
+ id='navtabs'>
197
+ {navs}
198
+ </ul>
199
+ </nav>
200
+ </Container>
201
+ );
202
+ };
203
+
204
+ const renderGitHubCorner = () => {
205
+ if (!repo) return null;
206
+
207
+ // Check if it's a full URL or a "username/repo" string
208
+ const isFullUrl =
209
+ repo.startsWith('http://') || repo.startsWith('https://');
210
+ const githubUrl = isFullUrl ? repo : `https://github.com/${repo}`;
211
+
212
+ return (
213
+ <a
214
+ href={githubUrl}
215
+ className='github-corner'
216
+ aria-label={t('header.viewSource')}
217
+ target='_blank'
218
+ rel='noreferrer'>
219
+ {<Corner />}
220
+ </a>
221
+ );
222
+ };
223
+
224
+ return (
225
+ <header className='v-header'>
226
+ <nav className='navbar navbar-light navbar-expand-md py-3'>
227
+ <Container>
228
+ {renderLogo()}
229
+ {renderTitle()}
230
+ {renderNav()}
231
+ </Container>
232
+ </nav>
233
+ {renderGitHubCorner()}
234
+ </header>
235
+ );
236
+ }
237
+
238
+ export default Vheader;
@@ -1,31 +1,31 @@
1
- /*
2
- * @Author : Lihao leolihao@arizona.edu
3
- * @Date : 2023-12-20 22:21:11
4
- * @FilePath : /visualifyjs/src/core/widgets/layout/Grid.js
5
- * @Description :
6
- * Copyright (c) 2023 by Lihao (leolihao@arizona.edu), All Rights Reserved.
7
- */
8
- import React from 'react';
9
-
10
- function DynamicGrid({ config = {}, children }) {
11
- const {
12
- rows = 2,
13
- cols = 2,
14
- gap = '1px',
15
- style = {},
16
- debug = false,
17
- } = config;
18
- // Custom styles for the grid
19
- const gridStyles = {
20
- display: 'grid',
21
- gridTemplateRows: `repeat(${rows}, auto)`,
22
- gridTemplateColumns: `repeat(${cols}, 1fr)`,
23
- gap: gap,
24
- border: debug ? '1px solid red' : 'none',
25
- ...style,
26
- };
27
-
28
- return <div style={gridStyles}>{children}</div>;
29
- }
30
-
31
- export default DynamicGrid;
1
+ /*
2
+ * @Author : Lihao leolihao@arizona.edu
3
+ * @Date : 2023-12-20 22:21:11
4
+ * @FilePath : /visualifyjs/src/core/widgets/layout/Grid.js
5
+ * @Description :
6
+ * Copyright (c) 2023 by Lihao (leolihao@arizona.edu), All Rights Reserved.
7
+ */
8
+ import React from 'react';
9
+
10
+ function DynamicGrid({ config = {}, children }) {
11
+ const {
12
+ rows = 2,
13
+ cols = 2,
14
+ gap = '1px',
15
+ style = {},
16
+ debug = false,
17
+ } = config;
18
+ // Custom styles for the grid
19
+ const gridStyles = {
20
+ display: 'grid',
21
+ gridTemplateRows: `repeat(${rows}, auto)`,
22
+ gridTemplateColumns: `repeat(${cols}, 1fr)`,
23
+ gap: gap,
24
+ border: debug ? '1px solid red' : 'none',
25
+ ...style,
26
+ };
27
+
28
+ return <div style={gridStyles}>{children}</div>;
29
+ }
30
+
31
+ export default DynamicGrid;
@@ -1,36 +1,36 @@
1
- /*
2
- * @Author : Lihao leolihao@arizona.edu
3
- * @Date : 2023-12-20 21:48:29
4
- * @FilePath : /visualifyjs/src/core/widgets/layout.js
5
- * @Description :
6
- * Copyright (c) 2023 by Lihao (leolihao@arizona.edu), All Rights Reserved.
7
- */
8
- import React from 'react';
9
- import DynamicGrid from './layout/Grid';
10
-
11
- function LayoutParser({ config = {}, children }) {
12
- const { type = 'grid', ...rest } = config;
13
-
14
- if (type === 'grid') {
15
- return (
16
- <>
17
- <DynamicGrid config={{ ...rest }}>
18
- {React.cloneElement(children, { layout: type })}
19
- </DynamicGrid>
20
- </>
21
- );
22
- }
23
-
24
- return (
25
- <div>
26
- <h1>LayoutParser</h1>
27
- <span>
28
- We are not support <b>{type}</b> layout type yet
29
- </span>
30
- <br></br>
31
- {children}
32
- </div>
33
- );
34
- }
35
-
36
- export default LayoutParser;
1
+ /*
2
+ * @Author : Lihao leolihao@arizona.edu
3
+ * @Date : 2023-12-20 21:48:29
4
+ * @FilePath : /visualifyjs/src/core/widgets/layout.js
5
+ * @Description :
6
+ * Copyright (c) 2023 by Lihao (leolihao@arizona.edu), All Rights Reserved.
7
+ */
8
+ import React from 'react';
9
+ import DynamicGrid from './layout/Grid';
10
+
11
+ function LayoutParser({ config = {}, children }) {
12
+ const { type = 'grid', ...rest } = config;
13
+
14
+ if (type === 'grid') {
15
+ return (
16
+ <>
17
+ <DynamicGrid config={{ ...rest }}>
18
+ {React.cloneElement(children, { layout: type })}
19
+ </DynamicGrid>
20
+ </>
21
+ );
22
+ }
23
+
24
+ return (
25
+ <div>
26
+ <h1>LayoutParser</h1>
27
+ <span>
28
+ We are not support <b>{type}</b> layout type yet
29
+ </span>
30
+ <br></br>
31
+ {children}
32
+ </div>
33
+ );
34
+ }
35
+
36
+ export default LayoutParser;