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,131 +1,156 @@
1
- import React, { useState, useEffect } from 'react';
2
- import '../../_css/autoSuggestion.css';
3
- import { useAppContext } from '../appContext';
4
- import conditionalFetch from '../fetch/condfetch';
5
-
6
- function SearchBar({ props, style }) {
7
- const [suggestions, setSuggestions] = useState([]);
8
- const [wordlist, setWordlist] = useState([]);
9
- const [inputValue, setInputValue] = useState('');
10
-
11
- const { sharedData, setSharedData } = useAppContext();
12
-
13
- const {
14
- id,
15
- title = 'Search',
16
- className,
17
- style: _style = { height: '130px', width: '200px' },
18
- placeholder = 'Search...',
19
- wordlimit = 15,
20
- suggestLen = 3,
21
- searchStyle = {
22
- borderRadius: '15px',
23
- width: '100%',
24
- },
25
- config = {},
26
- debug,
27
- } = props;
28
-
29
- if (config.save && typeof config.save !== 'string') config.save = id;
30
-
31
- useEffect(() => {
32
- if (config.source) {
33
- const fetchWordlist = async () => {
34
- const response = await conditionalFetch(
35
- config.source,
36
- sharedData,
37
- null,
38
- null,
39
- );
40
- if (response) {
41
- const newWordlist =
42
- response[config.source.responseKey] || response;
43
- setWordlist(newWordlist);
44
- } else if (config.source.trigger) {
45
- console.log('wait for trigger');
46
- } else {
47
- console.error('Error fetching wordlist.');
48
- }
49
- };
50
-
51
- if (Array.isArray(config.source)) {
52
- setWordlist(config.source);
53
- } else if (typeof config.source === 'object') {
54
- fetchWordlist();
55
- }
56
- }
57
- }, [config.source, debug, sharedData]);
58
-
59
- useEffect(() => {
60
- // 更新inputValue,但不要影响其他组件的共享数据
61
- setInputValue(sharedData[id] || '');
62
- }, [sharedData, id]);
63
-
64
- const handleInputChange = (e) => {
65
- const inputValue = e.target.value;
66
- const inputValueLowerCase = inputValue.trim().toLowerCase();
67
- setInputValue(inputValue);
68
-
69
- if (inputValue.length >= suggestLen) {
70
- setSuggestions(
71
- wordlist
72
- .filter((word) =>
73
- word.toLowerCase().includes(inputValueLowerCase),
74
- )
75
- .slice(0, wordlimit),
76
- );
77
- }
78
-
79
- if (
80
- config.save &&
81
- (wordlist.includes(inputValue) || inputValue === '')
82
- ) {
83
- setSharedData((prevSharedData) => ({
84
- ...prevSharedData,
85
- [config.save]: inputValue,
86
- }));
87
- }
88
- };
89
-
90
- const handleSuggestionClick = (suggestion) => {
91
- setInputValue(suggestion);
92
- setSuggestions([]);
93
-
94
- if (config.save) {
95
- setSharedData((prevSharedData) => ({
96
- ...prevSharedData,
97
- [config.save]: suggestion,
98
- }));
99
- }
100
- };
101
-
102
- return (
103
- <div
104
- id={id}
105
- style={{ ...style, ..._style }}
106
- className={className}>
107
- {title && <h3>{title}</h3>}
108
- <div className='autosuggestion'>
109
- <input
110
- type='text'
111
- placeholder={placeholder}
112
- style={searchStyle}
113
- value={inputValue}
114
- onChange={handleInputChange}
115
- />
116
- <ul className='suggestion-list'>
117
- {suggestions.map((suggestion, index) => (
118
- <li
119
- key={index}
120
- className='suggestion-item'
121
- onClick={() => handleSuggestionClick(suggestion)}>
122
- {suggestion}
123
- </li>
124
- ))}
125
- </ul>
126
- </div>
127
- </div>
128
- );
129
- }
130
-
131
- export default SearchBar;
1
+ import React, { useState, useEffect, useRef } from 'react';
2
+ import '../../_css/autoSuggestion.css';
3
+ import { useAppContext } from '../appContext';
4
+ import conditionalFetch from '../fetch/condfetch';
5
+
6
+ function SearchBar({ props, style }) {
7
+ const [suggestions, setSuggestions] = useState([]);
8
+ const [wordlist, setWordlist] = useState([]);
9
+ const [inputValue, setInputValue] = useState('');
10
+
11
+ const { sharedData, setSharedData } = useAppContext();
12
+
13
+ const {
14
+ id,
15
+ title = 'Search',
16
+ className,
17
+ style: _style = { height: '130px', width: '200px' },
18
+ placeholder = 'Search...',
19
+ wordlimit = 15,
20
+ suggestLen = 3,
21
+ config = {},
22
+ debug,
23
+ } = props;
24
+
25
+ if (config.save && typeof config.save !== 'string') config.save = id;
26
+
27
+ // Stabilize config.source reference to prevent infinite re-renders
28
+ const sourceRef = useRef(config.source);
29
+ sourceRef.current = config.source;
30
+
31
+ // Extract the trigger key to narrow the dependency
32
+ const triggerKey = config.source?.trigger;
33
+ // Support both string triggers and object triggers with .name
34
+ const triggerName = typeof triggerKey === 'object' ? triggerKey.name || triggerKey : triggerKey;
35
+ const rawTriggerValue = triggerName ? sharedData[triggerName] : undefined;
36
+ // Serialize trigger value to a stable string for dependency comparison
37
+ // This prevents re-renders from array/object reference changes (e.g., [] vs [])
38
+ const triggerValueKey = JSON.stringify(rawTriggerValue);
39
+
40
+ // Use a ref to access latest sharedData in the fetch effect without depending on it
41
+ const sharedDataRef = useRef(sharedData);
42
+ sharedDataRef.current = sharedData;
43
+
44
+ // Stable source URL for dependency tracking (avoids object reference changes)
45
+ const sourceUrl = config.source?.url;
46
+ const sourceName = config.source?.name;
47
+ const isArraySource = Array.isArray(config.source);
48
+
49
+ useEffect(() => {
50
+ const source = sourceRef.current;
51
+ if (source) {
52
+ const fetchWordlist = async () => {
53
+ const response = await conditionalFetch(
54
+ source,
55
+ sharedDataRef.current,
56
+ null,
57
+ null,
58
+ );
59
+ if (response) {
60
+ const newWordlist =
61
+ response[source.responseKey] || response;
62
+ setWordlist(newWordlist);
63
+ } else if (source.trigger) {
64
+ if (debug) console.log('wait for trigger');
65
+ } else {
66
+ console.error('Error fetching wordlist.');
67
+ }
68
+ };
69
+
70
+ if (isArraySource) {
71
+ setWordlist(source);
72
+ } else if (typeof source === 'object') {
73
+ fetchWordlist();
74
+ }
75
+ }
76
+ // Depend on stable primitives — triggerValueKey is a serialized string,
77
+ // not an object/array reference, preventing spurious re-runs
78
+ // eslint-disable-next-line react-hooks/exhaustive-deps
79
+ }, [sourceUrl, sourceName, isArraySource, debug, triggerValueKey]);
80
+
81
+ // Sync input value from sharedData only when it externally changes
82
+ const savedValue = sharedData[id];
83
+ useEffect(() => {
84
+ setInputValue(savedValue || '');
85
+ }, [savedValue]);
86
+
87
+ const handleInputChange = (e) => {
88
+ const inputValue = e.target.value;
89
+ const inputValueLowerCase = inputValue.trim().toLowerCase();
90
+ setInputValue(inputValue);
91
+
92
+ if (inputValue.length >= suggestLen) {
93
+ setSuggestions(
94
+ wordlist
95
+ .filter((word) =>
96
+ word.toLowerCase().includes(inputValueLowerCase),
97
+ )
98
+ .slice(0, wordlimit),
99
+ );
100
+ }
101
+
102
+ if (
103
+ config.save &&
104
+ (wordlist.includes(inputValue) || inputValue === '')
105
+ ) {
106
+ setSharedData((prevSharedData) => ({
107
+ ...prevSharedData,
108
+ [config.save]: inputValue,
109
+ }));
110
+ }
111
+ };
112
+
113
+ const handleSuggestionClick = (suggestion) => {
114
+ setInputValue(suggestion);
115
+ setSuggestions([]);
116
+
117
+ if (config.save) {
118
+ setSharedData((prevSharedData) => ({
119
+ ...prevSharedData,
120
+ [config.save]: suggestion,
121
+ }));
122
+ }
123
+ };
124
+
125
+ return (
126
+ <div
127
+ id={id}
128
+ style={{ ...style, ..._style }}
129
+ className={`v-searchbar-container${className ? ' ' + className : ''}`}>
130
+ {title && <h3 className='v-control-title'>{title}</h3>}
131
+ <div className='autosuggestion'>
132
+ <div className='v-searchbar-wrapper'>
133
+ <input
134
+ type='text'
135
+ placeholder={placeholder}
136
+ className='v-searchbar-input'
137
+ value={inputValue}
138
+ onChange={handleInputChange}
139
+ />
140
+ </div>
141
+ <ul className='suggestion-list'>
142
+ {suggestions.map((suggestion, index) => (
143
+ <li
144
+ key={index}
145
+ className='suggestion-item'
146
+ onClick={() => handleSuggestionClick(suggestion)}>
147
+ {suggestion}
148
+ </li>
149
+ ))}
150
+ </ul>
151
+ </div>
152
+ </div>
153
+ );
154
+ }
155
+
156
+ export default SearchBar;