visualifyjs 2.5.3-2.dev → 2.5.3-9-dev
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.
Potentially problematic release.
This version of visualifyjs might be problematic. Click here for more details.
- package/.github/workflows/{static.yml.bak → build.yaml} +51 -51
- package/LICENSE +674 -674
- package/README.md +40 -58
- package/config-overrides.js +31 -31
- package/dist/visualify.js +3 -3
- package/docs/CLI.md +15 -0
- package/docs/{docs/README.md → README.md} +41 -65
- package/docs/{docs/Rechart → Rechart}/bar.md +190 -190
- package/docs/{docs/Rechart → Rechart}/funnel.md +193 -241
- package/docs/{docs/Rechart → Rechart}/line.md +355 -355
- package/docs/{docs/Rechart → Rechart}/pie.md +225 -225
- package/docs/{docs/Rechart → Rechart}/radar.md +253 -253
- package/docs/{docs/_404.md → _404.md} +51 -51
- package/docs/{docs/_coverpage.md → _coverpage.md} +11 -11
- package/docs/{docs/_sidebar.md → _sidebar.md} +42 -44
- package/docs/{docs/components → components}/dotBio.md +34 -34
- package/docs/{docs/components → components}/echart.md +82 -82
- package/docs/{docs/components → components}/html.md +34 -34
- package/docs/{docs/components → components}/macaron.md +145 -145
- package/docs/components/markdown.md +0 -0
- package/docs/{docs/components → components}/more.md +142 -142
- package/docs/{docs/components → components}/plotly.md +62 -62
- package/docs/{docs/components → components}/scatterL.md +70 -70
- package/docs/{docs/components → components}/visium.md +56 -56
- package/docs/{docs/configuration.md → configuration.md} +123 -121
- package/docs/{docs/deploy.md → deploy.md} +23 -31
- package/docs/index.html +70 -70
- package/docs/log.md +1 -0
- package/docs/manifest.json +23 -23
- package/docs/{docs/more-pages.md → more-pages.md} +23 -23
- package/docs/{docs/quickstart.md → quickstart.md} +115 -124
- package/docs/{docs/rechart-attributes.md → rechart-attributes.md} +74 -74
- package/docs/{docs/rechart-basic-usage.md → rechart-basic-usage.md} +162 -162
- package/docs/static/css/fluff-stuff.css +169 -169
- package/docs/static/css/font-awesome.min.css +4 -4
- package/docs/static/css/visualify.css +25 -25
- package/docs/static/js/configuration.js +448 -448
- package/docs/static/js/visualify.js +24 -23
- package/docs/theme.md +3 -0
- package/package.json +74 -83
- package/rollup.config.mjs +75 -75
- package/src/_css/404.css +115 -115
- package/src/_css/App.css +37 -37
- package/src/_css/autoSuggestion.css +26 -26
- package/src/_css/circular-progress.css +32 -32
- package/src/_css/index.css +36 -36
- package/src/_css/modern.css +24 -24
- package/src/_media/corner.svg +8 -8
- package/src/_media/download.svg +3 -3
- package/src/_media/logo.svg +14 -14
- package/src/_test/App.test.js +15 -15
- package/src/_utils/reportWebVitals.js +13 -13
- package/src/core/appContext.js +27 -27
- package/src/core/components/Scatter.js +188 -188
- package/src/core/components/ScatterBio.js +572 -572
- package/src/core/components/VisiumPlot.js +165 -165
- package/src/core/components/browser.js +42 -42
- package/src/core/components/dotplot.js +413 -413
- package/src/core/components/html.js +29 -29
- package/src/core/components/list.js +178 -178
- package/src/core/components/macaron.js +201 -201
- package/src/core/components/markdown.js +56 -56
- package/src/core/components/parser.scatterBio.js +579 -587
- package/src/core/components/ratio.js +80 -80
- package/src/core/components/scatterL.js +173 -173
- package/src/core/components/searchbar.js +131 -131
- package/src/core/components/selection.js +193 -193
- package/src/core/components/timeline.js +281 -281
- package/src/core/components/visium.js +97 -97
- package/src/core/fetch/condfetch.js +82 -82
- package/src/core/fetch/fetch.js +92 -92
- package/src/core/fetch/json.js +29 -29
- package/src/core/fetch/vfetch.js +42 -42
- package/src/core/liveEditor.js +44 -44
- package/src/core/modules/codeEditorWithPreview.js +104 -104
- package/src/core/modules/echarts/common.js +20 -20
- package/src/core/modules/echarts/presetHandler.js +41 -41
- package/src/core/modules/echarts/presets/esodev.chromium.js +172 -172
- package/src/core/modules/echarts/presets/esodev.codex.js +130 -130
- package/src/core/modules/echarts/presets/esodev.visium.js +123 -123
- package/src/core/modules/echarts/presets/mmtrbc.js +186 -186
- package/src/core/modules/echarts.js +71 -71
- package/src/core/modules/echartsUtils.js +43 -43
- package/src/core/modules/echartswitcher.js +152 -152
- package/src/core/modules/replotly/presetHandler.js +24 -24
- package/src/core/modules/replotly/presets/minimum.js +18 -18
- package/src/core/modules/replotly/presets/mmtrbc.dot.js +114 -114
- package/src/core/modules/replotly/presets/mmtrbc.violin.js +100 -100
- package/src/core/modules/replotly.js +71 -71
- package/src/core/pages/404.js +50 -50
- package/src/core/pages/error.js +27 -27
- package/src/core/pages/jsonPage.js +62 -62
- package/src/core/pages/loading.js +44 -44
- package/src/core/parser/echart.data.js +183 -183
- package/src/core/parser/echart.features.js +125 -125
- package/src/core/parser/echart.general.js +143 -147
- package/src/core/parser/echart.hilbert.js +57 -57
- package/src/core/parser/echart.parser.js +210 -210
- package/src/core/parser/echart.series.js +67 -67
- package/src/core/parser/echart.types.js +76 -76
- package/src/core/parser/plotly.config.js +10 -10
- package/src/core/parser/plotly.data.js +132 -132
- package/src/core/parser/plotly.layout.js +9 -9
- package/src/core/parser/plotly.violin.js +18 -18
- package/src/core/recharts.js +62 -62
- package/src/core/router/alias.js +49 -49
- package/src/core/router/jsonRouter.js +31 -31
- package/src/core/themes/modern.js +32 -32
- package/src/core/themes/themeSelector.js +33 -33
- package/src/core/visualify.js +47 -47
- package/src/core/widgets/circularProgress.js +23 -23
- package/src/core/widgets/controller.js +83 -83
- package/src/core/widgets/errorBoundary.js +36 -36
- package/src/core/widgets/footer.js +177 -177
- package/src/core/widgets/header.js +234 -234
- package/src/core/widgets/layout/Grid.js +31 -31
- package/src/core/widgets/layout.js +36 -36
- package/src/core/widgets/mapping.js +42 -42
- package/src/index.js +62 -62
- package/src/setupTests.js +5 -5
- package/docs/docs/CLI.md +0 -34
- package/docs/docs/Rechart/scatter.md +0 -298
- package/docs/docs/log.md +0 -9
- package/docs/docs/static/logo/favicon.ico +0 -0
- package/docs/docs/static/logo/logo_128x128.png +0 -0
- package/docs/docs/static/logo/logo_192x192.png +0 -0
- package/docs/docs/static/logo/logo_256x256.png +0 -0
- package/docs/docs/static/logo/logo_512x512.png +0 -0
- package/docs/docs/static/logo/logo_64x64.png +0 -0
- package/docs/docs/theme.md +0 -5
- /package/docs/{docs/Rechart → Rechart}/geo.md +0 -0
- /package/docs/{docs/Rechart → Rechart}/liquidfill.md +0 -0
- /package/docs/{docs/Rechart → Rechart}/polar.md +0 -0
- /package/docs/{docs/Rechart → Rechart}/sankey.md +0 -0
- /package/docs/{docs/Rechart/sunburst.md → Rechart/scatter.md} +0 -0
- /package/docs/{docs/Rechart/tree.md → Rechart/sunburst.md} +0 -0
- /package/docs/{docs/Rechart/wordcloud.md → Rechart/tree.md} +0 -0
- /package/docs/{docs/components/markdown.md → Rechart/wordcloud.md} +0 -0
- /package/docs/{docs/static → static}/_images/deploy-github-pages.png +0 -0
@@ -1,281 +1,281 @@
|
|
1
|
-
import React, { useEffect, useState } from 'react';
|
2
|
-
import simplefetch from '../fetch/fetch';
|
3
|
-
import { useAppContext } from '../appContext';
|
4
|
-
|
5
|
-
const generateNodes = (data, split_pattern) => {
|
6
|
-
return data.reduce((groups, item) => {
|
7
|
-
const parts = item.split(split_pattern);
|
8
|
-
const main = parts[0];
|
9
|
-
const sub = parts.slice(1).join(split_pattern);
|
10
|
-
|
11
|
-
if (sub) {
|
12
|
-
if (!groups[main]) {
|
13
|
-
groups[main] = [];
|
14
|
-
}
|
15
|
-
groups[main].push(sub);
|
16
|
-
} else {
|
17
|
-
groups[main] = null;
|
18
|
-
}
|
19
|
-
|
20
|
-
return groups;
|
21
|
-
}, {});
|
22
|
-
};
|
23
|
-
|
24
|
-
function Timeline({ props, style }) {
|
25
|
-
const { debug } = props;
|
26
|
-
|
27
|
-
const { style: _style_parsed = {} } = props;
|
28
|
-
const { class: className, ...customStyle } = _style_parsed;
|
29
|
-
|
30
|
-
// if debug is true, then border is red, else no border
|
31
|
-
style = {
|
32
|
-
...style,
|
33
|
-
border: debug ? '1px solid red' : 'none',
|
34
|
-
maxHeight: '500px',
|
35
|
-
overflowY: 'auto',
|
36
|
-
overflowX: 'hidden',
|
37
|
-
...customStyle,
|
38
|
-
position: 'relative',
|
39
|
-
};
|
40
|
-
|
41
|
-
const { id, val, config = {}, title } = props;
|
42
|
-
|
43
|
-
const {
|
44
|
-
split_pattern = '_',
|
45
|
-
node_width = '50%',
|
46
|
-
sort_pattern = new RegExp(/E(\d+)/),
|
47
|
-
distance_pattern = undefined,
|
48
|
-
basicGap = 1,
|
49
|
-
} = config;
|
50
|
-
// Render title if it exists
|
51
|
-
const renderTitle = () => {
|
52
|
-
return title && <h3>{title}</h3>;
|
53
|
-
};
|
54
|
-
|
55
|
-
const [nodes, setNodes] = useState([]);
|
56
|
-
|
57
|
-
useEffect(() => {
|
58
|
-
const { selection, urlval, rm_suffix } = props;
|
59
|
-
|
60
|
-
const fetchData = async () => {
|
61
|
-
try {
|
62
|
-
const response = await simplefetch(selection, { key: urlval });
|
63
|
-
// remove the suffix "_metadata" from the options
|
64
|
-
try {
|
65
|
-
const removed_suffix = response.map((item) =>
|
66
|
-
item.replace(rm_suffix, ''),
|
67
|
-
);
|
68
|
-
//console.log('Removed suffix:', removed_suffix);
|
69
|
-
const groupedNodes = generateNodes(
|
70
|
-
removed_suffix,
|
71
|
-
split_pattern,
|
72
|
-
);
|
73
|
-
setNodes(groupedNodes);
|
74
|
-
} catch (error) {
|
75
|
-
setNodes(response);
|
76
|
-
}
|
77
|
-
} catch (error) {
|
78
|
-
console.error('Error fetching options:', error);
|
79
|
-
}
|
80
|
-
};
|
81
|
-
|
82
|
-
fetchData();
|
83
|
-
}, [props, split_pattern, debug]);
|
84
|
-
|
85
|
-
const { setSharedData } = useAppContext();
|
86
|
-
|
87
|
-
const handleNodeClick = (node) => {
|
88
|
-
if (debug) console.log(`Node [${node}] clicked!`);
|
89
|
-
if (val) {
|
90
|
-
setSharedData((prevSharedData) => {
|
91
|
-
return { ...prevSharedData, [val]: [node] };
|
92
|
-
});
|
93
|
-
alert(`Clicked: ${node}`);
|
94
|
-
}
|
95
|
-
};
|
96
|
-
|
97
|
-
const _sort_pattern =
|
98
|
-
typeof sort_pattern === 'string'
|
99
|
-
? new RegExp(sort_pattern)
|
100
|
-
: sort_pattern;
|
101
|
-
|
102
|
-
const sortedNodes = Object.keys(nodes)
|
103
|
-
.sort((a, b) => {
|
104
|
-
//console.log('a:', a, 'b:', b, 'sort_pattern:', _sort_pattern);
|
105
|
-
const numA = parseInt(a.match(_sort_pattern)[1]);
|
106
|
-
const numB = parseInt(b.match(_sort_pattern)[1]);
|
107
|
-
return numA - numB;
|
108
|
-
})
|
109
|
-
.reduce((acc, key) => {
|
110
|
-
acc[key] = nodes[key];
|
111
|
-
return acc;
|
112
|
-
}, {});
|
113
|
-
|
114
|
-
const extractNumber = (str) => {
|
115
|
-
const matchE = str.match(/E(\d+)/);
|
116
|
-
|
117
|
-
if (distance_pattern && distance_pattern.regex) {
|
118
|
-
const dis_regex =
|
119
|
-
typeof distance_pattern?.regex === 'string'
|
120
|
-
? new RegExp(distance_pattern.regex)
|
121
|
-
: distance_pattern.regex;
|
122
|
-
|
123
|
-
const match = str.match(dis_regex);
|
124
|
-
|
125
|
-
//console.log('str', str, 'match:', match, 'distance_pattern:', dis_regex);
|
126
|
-
if (match) {
|
127
|
-
for (let i = distance_pattern.pos; i >= 1; i--) {
|
128
|
-
if (match[i]) {
|
129
|
-
return parseInt(match[i]);
|
130
|
-
}
|
131
|
-
}
|
132
|
-
}
|
133
|
-
} else if (matchE) {
|
134
|
-
return parseInt(matchE[1]);
|
135
|
-
}
|
136
|
-
return 0;
|
137
|
-
};
|
138
|
-
|
139
|
-
const calculateDistance = (main, previousMain) => {
|
140
|
-
if (!previousMain) return 0;
|
141
|
-
|
142
|
-
const numA = extractNumber(main);
|
143
|
-
const numB = extractNumber(previousMain);
|
144
|
-
|
145
|
-
//console.log('numA:', numA, 'numB:', numB, 'diff:', Math.abs(numA - numB));
|
146
|
-
|
147
|
-
return Math.abs(numA - numB) * basicGap; // Distance based on the basic gap value
|
148
|
-
};
|
149
|
-
|
150
|
-
let previousMain = null;
|
151
|
-
|
152
|
-
return (
|
153
|
-
<div
|
154
|
-
key={id}
|
155
|
-
style={{ ...style }}
|
156
|
-
className={className}>
|
157
|
-
{renderTitle()}
|
158
|
-
<div
|
159
|
-
key={id + '.timeline'}
|
160
|
-
style={{
|
161
|
-
display: 'flex',
|
162
|
-
flexDirection: 'column',
|
163
|
-
alignItems: 'flex-start',
|
164
|
-
position: 'relative',
|
165
|
-
}}>
|
166
|
-
<div
|
167
|
-
style={{
|
168
|
-
borderLeft: '10px solid black',
|
169
|
-
//minHeight: '350px',
|
170
|
-
height: '100%',
|
171
|
-
position: 'absolute',
|
172
|
-
left: '0px',
|
173
|
-
top: '0px',
|
174
|
-
}}
|
175
|
-
/>
|
176
|
-
<div
|
177
|
-
style={{ ...style }}
|
178
|
-
className={className}>
|
179
|
-
<div
|
180
|
-
style={{
|
181
|
-
maxHeight: '500px',
|
182
|
-
overflowY: 'auto',
|
183
|
-
overflowX: 'hidden',
|
184
|
-
}}>
|
185
|
-
{Object.keys(sortedNodes).map((main, index) => {
|
186
|
-
const distance = calculateDistance(
|
187
|
-
main,
|
188
|
-
previousMain,
|
189
|
-
);
|
190
|
-
previousMain = main; // Update previousMain for the next iteration
|
191
|
-
return (
|
192
|
-
<div
|
193
|
-
key={index}
|
194
|
-
style={{
|
195
|
-
display: 'flex',
|
196
|
-
alignItems: 'center',
|
197
|
-
marginTop: distance + 'px', // Apply distance here
|
198
|
-
position: 'relative',
|
199
|
-
flexDirection: 'column',
|
200
|
-
}}>
|
201
|
-
<div
|
202
|
-
style={{
|
203
|
-
position: 'absolute',
|
204
|
-
left: '0%',
|
205
|
-
top: '10px',
|
206
|
-
width: node_width ?? '50%',
|
207
|
-
height: '2px',
|
208
|
-
background: 'black',
|
209
|
-
}}
|
210
|
-
/>
|
211
|
-
<div
|
212
|
-
id='Timeline.Dot'
|
213
|
-
style={{
|
214
|
-
position: 'absolute',
|
215
|
-
left: '0%',
|
216
|
-
top: '15px',
|
217
|
-
width: '10px',
|
218
|
-
height: '10px',
|
219
|
-
borderRadius: '50%',
|
220
|
-
background: 'black',
|
221
|
-
}}
|
222
|
-
/>
|
223
|
-
{nodes[main] ? (
|
224
|
-
<>
|
225
|
-
<div style={{ marginLeft: '15%' }}>
|
226
|
-
{main}
|
227
|
-
</div>
|
228
|
-
<div
|
229
|
-
style={{
|
230
|
-
marginLeft: '15%',
|
231
|
-
display: 'flex',
|
232
|
-
flexWrap: 'wrap',
|
233
|
-
}}>
|
234
|
-
{nodes[main].map(
|
235
|
-
(sub, subIndex) => (
|
236
|
-
<button
|
237
|
-
key={subIndex}
|
238
|
-
style={{
|
239
|
-
padding:
|
240
|
-
'5px 3px',
|
241
|
-
marginLeft:
|
242
|
-
'2px',
|
243
|
-
border: '1px solid black',
|
244
|
-
cursor: 'pointer',
|
245
|
-
}}
|
246
|
-
onClick={() =>
|
247
|
-
handleNodeClick(
|
248
|
-
`${main}_${sub}`,
|
249
|
-
)
|
250
|
-
}>
|
251
|
-
{sub}
|
252
|
-
</button>
|
253
|
-
),
|
254
|
-
)}
|
255
|
-
</div>
|
256
|
-
</>
|
257
|
-
) : (
|
258
|
-
<div
|
259
|
-
style={{
|
260
|
-
marginLeft: '15%',
|
261
|
-
padding: '5px 3px',
|
262
|
-
border: '1px solid black',
|
263
|
-
cursor: 'pointer',
|
264
|
-
}}
|
265
|
-
onClick={() =>
|
266
|
-
handleNodeClick(main)
|
267
|
-
}>
|
268
|
-
{main}
|
269
|
-
</div>
|
270
|
-
)}
|
271
|
-
</div>
|
272
|
-
);
|
273
|
-
})}
|
274
|
-
</div>
|
275
|
-
</div>
|
276
|
-
</div>
|
277
|
-
</div>
|
278
|
-
);
|
279
|
-
}
|
280
|
-
|
281
|
-
export default Timeline;
|
1
|
+
import React, { useEffect, useState } from 'react';
|
2
|
+
import simplefetch from '../fetch/fetch';
|
3
|
+
import { useAppContext } from '../appContext';
|
4
|
+
|
5
|
+
const generateNodes = (data, split_pattern) => {
|
6
|
+
return data.reduce((groups, item) => {
|
7
|
+
const parts = item.split(split_pattern);
|
8
|
+
const main = parts[0];
|
9
|
+
const sub = parts.slice(1).join(split_pattern);
|
10
|
+
|
11
|
+
if (sub) {
|
12
|
+
if (!groups[main]) {
|
13
|
+
groups[main] = [];
|
14
|
+
}
|
15
|
+
groups[main].push(sub);
|
16
|
+
} else {
|
17
|
+
groups[main] = null;
|
18
|
+
}
|
19
|
+
|
20
|
+
return groups;
|
21
|
+
}, {});
|
22
|
+
};
|
23
|
+
|
24
|
+
function Timeline({ props, style }) {
|
25
|
+
const { debug } = props;
|
26
|
+
|
27
|
+
const { style: _style_parsed = {} } = props;
|
28
|
+
const { class: className, ...customStyle } = _style_parsed;
|
29
|
+
|
30
|
+
// if debug is true, then border is red, else no border
|
31
|
+
style = {
|
32
|
+
...style,
|
33
|
+
border: debug ? '1px solid red' : 'none',
|
34
|
+
maxHeight: '500px',
|
35
|
+
overflowY: 'auto',
|
36
|
+
overflowX: 'hidden',
|
37
|
+
...customStyle,
|
38
|
+
position: 'relative',
|
39
|
+
};
|
40
|
+
|
41
|
+
const { id, val, config = {}, title } = props;
|
42
|
+
|
43
|
+
const {
|
44
|
+
split_pattern = '_',
|
45
|
+
node_width = '50%',
|
46
|
+
sort_pattern = new RegExp(/E(\d+)/),
|
47
|
+
distance_pattern = undefined,
|
48
|
+
basicGap = 1,
|
49
|
+
} = config;
|
50
|
+
// Render title if it exists
|
51
|
+
const renderTitle = () => {
|
52
|
+
return title && <h3>{title}</h3>;
|
53
|
+
};
|
54
|
+
|
55
|
+
const [nodes, setNodes] = useState([]);
|
56
|
+
|
57
|
+
useEffect(() => {
|
58
|
+
const { selection, urlval, rm_suffix } = props;
|
59
|
+
|
60
|
+
const fetchData = async () => {
|
61
|
+
try {
|
62
|
+
const response = await simplefetch(selection, { key: urlval });
|
63
|
+
// remove the suffix "_metadata" from the options
|
64
|
+
try {
|
65
|
+
const removed_suffix = response.map((item) =>
|
66
|
+
item.replace(rm_suffix, ''),
|
67
|
+
);
|
68
|
+
//console.log('Removed suffix:', removed_suffix);
|
69
|
+
const groupedNodes = generateNodes(
|
70
|
+
removed_suffix,
|
71
|
+
split_pattern,
|
72
|
+
);
|
73
|
+
setNodes(groupedNodes);
|
74
|
+
} catch (error) {
|
75
|
+
setNodes(response);
|
76
|
+
}
|
77
|
+
} catch (error) {
|
78
|
+
console.error('Error fetching options:', error);
|
79
|
+
}
|
80
|
+
};
|
81
|
+
|
82
|
+
fetchData();
|
83
|
+
}, [props, split_pattern, debug]);
|
84
|
+
|
85
|
+
const { setSharedData } = useAppContext();
|
86
|
+
|
87
|
+
const handleNodeClick = (node) => {
|
88
|
+
if (debug) console.log(`Node [${node}] clicked!`);
|
89
|
+
if (val) {
|
90
|
+
setSharedData((prevSharedData) => {
|
91
|
+
return { ...prevSharedData, [val]: [node] };
|
92
|
+
});
|
93
|
+
alert(`Clicked: ${node}`);
|
94
|
+
}
|
95
|
+
};
|
96
|
+
|
97
|
+
const _sort_pattern =
|
98
|
+
typeof sort_pattern === 'string'
|
99
|
+
? new RegExp(sort_pattern)
|
100
|
+
: sort_pattern;
|
101
|
+
|
102
|
+
const sortedNodes = Object.keys(nodes)
|
103
|
+
.sort((a, b) => {
|
104
|
+
//console.log('a:', a, 'b:', b, 'sort_pattern:', _sort_pattern);
|
105
|
+
const numA = parseInt(a.match(_sort_pattern)[1]);
|
106
|
+
const numB = parseInt(b.match(_sort_pattern)[1]);
|
107
|
+
return numA - numB;
|
108
|
+
})
|
109
|
+
.reduce((acc, key) => {
|
110
|
+
acc[key] = nodes[key];
|
111
|
+
return acc;
|
112
|
+
}, {});
|
113
|
+
|
114
|
+
const extractNumber = (str) => {
|
115
|
+
const matchE = str.match(/E(\d+)/);
|
116
|
+
|
117
|
+
if (distance_pattern && distance_pattern.regex) {
|
118
|
+
const dis_regex =
|
119
|
+
typeof distance_pattern?.regex === 'string'
|
120
|
+
? new RegExp(distance_pattern.regex)
|
121
|
+
: distance_pattern.regex;
|
122
|
+
|
123
|
+
const match = str.match(dis_regex);
|
124
|
+
|
125
|
+
//console.log('str', str, 'match:', match, 'distance_pattern:', dis_regex);
|
126
|
+
if (match) {
|
127
|
+
for (let i = distance_pattern.pos; i >= 1; i--) {
|
128
|
+
if (match[i]) {
|
129
|
+
return parseInt(match[i]);
|
130
|
+
}
|
131
|
+
}
|
132
|
+
}
|
133
|
+
} else if (matchE) {
|
134
|
+
return parseInt(matchE[1]);
|
135
|
+
}
|
136
|
+
return 0;
|
137
|
+
};
|
138
|
+
|
139
|
+
const calculateDistance = (main, previousMain) => {
|
140
|
+
if (!previousMain) return 0;
|
141
|
+
|
142
|
+
const numA = extractNumber(main);
|
143
|
+
const numB = extractNumber(previousMain);
|
144
|
+
|
145
|
+
//console.log('numA:', numA, 'numB:', numB, 'diff:', Math.abs(numA - numB));
|
146
|
+
|
147
|
+
return Math.abs(numA - numB) * basicGap; // Distance based on the basic gap value
|
148
|
+
};
|
149
|
+
|
150
|
+
let previousMain = null;
|
151
|
+
|
152
|
+
return (
|
153
|
+
<div
|
154
|
+
key={id}
|
155
|
+
style={{ ...style }}
|
156
|
+
className={className}>
|
157
|
+
{renderTitle()}
|
158
|
+
<div
|
159
|
+
key={id + '.timeline'}
|
160
|
+
style={{
|
161
|
+
display: 'flex',
|
162
|
+
flexDirection: 'column',
|
163
|
+
alignItems: 'flex-start',
|
164
|
+
position: 'relative',
|
165
|
+
}}>
|
166
|
+
<div
|
167
|
+
style={{
|
168
|
+
borderLeft: '10px solid black',
|
169
|
+
//minHeight: '350px',
|
170
|
+
height: '100%',
|
171
|
+
position: 'absolute',
|
172
|
+
left: '0px',
|
173
|
+
top: '0px',
|
174
|
+
}}
|
175
|
+
/>
|
176
|
+
<div
|
177
|
+
style={{ ...style }}
|
178
|
+
className={className}>
|
179
|
+
<div
|
180
|
+
style={{
|
181
|
+
maxHeight: '500px',
|
182
|
+
overflowY: 'auto',
|
183
|
+
overflowX: 'hidden',
|
184
|
+
}}>
|
185
|
+
{Object.keys(sortedNodes).map((main, index) => {
|
186
|
+
const distance = calculateDistance(
|
187
|
+
main,
|
188
|
+
previousMain,
|
189
|
+
);
|
190
|
+
previousMain = main; // Update previousMain for the next iteration
|
191
|
+
return (
|
192
|
+
<div
|
193
|
+
key={index}
|
194
|
+
style={{
|
195
|
+
display: 'flex',
|
196
|
+
alignItems: 'center',
|
197
|
+
marginTop: distance + 'px', // Apply distance here
|
198
|
+
position: 'relative',
|
199
|
+
flexDirection: 'column',
|
200
|
+
}}>
|
201
|
+
<div
|
202
|
+
style={{
|
203
|
+
position: 'absolute',
|
204
|
+
left: '0%',
|
205
|
+
top: '10px',
|
206
|
+
width: node_width ?? '50%',
|
207
|
+
height: '2px',
|
208
|
+
background: 'black',
|
209
|
+
}}
|
210
|
+
/>
|
211
|
+
<div
|
212
|
+
id='Timeline.Dot'
|
213
|
+
style={{
|
214
|
+
position: 'absolute',
|
215
|
+
left: '0%',
|
216
|
+
top: '15px',
|
217
|
+
width: '10px',
|
218
|
+
height: '10px',
|
219
|
+
borderRadius: '50%',
|
220
|
+
background: 'black',
|
221
|
+
}}
|
222
|
+
/>
|
223
|
+
{nodes[main] ? (
|
224
|
+
<>
|
225
|
+
<div style={{ marginLeft: '15%' }}>
|
226
|
+
{main}
|
227
|
+
</div>
|
228
|
+
<div
|
229
|
+
style={{
|
230
|
+
marginLeft: '15%',
|
231
|
+
display: 'flex',
|
232
|
+
flexWrap: 'wrap',
|
233
|
+
}}>
|
234
|
+
{nodes[main].map(
|
235
|
+
(sub, subIndex) => (
|
236
|
+
<button
|
237
|
+
key={subIndex}
|
238
|
+
style={{
|
239
|
+
padding:
|
240
|
+
'5px 3px',
|
241
|
+
marginLeft:
|
242
|
+
'2px',
|
243
|
+
border: '1px solid black',
|
244
|
+
cursor: 'pointer',
|
245
|
+
}}
|
246
|
+
onClick={() =>
|
247
|
+
handleNodeClick(
|
248
|
+
`${main}_${sub}`,
|
249
|
+
)
|
250
|
+
}>
|
251
|
+
{sub}
|
252
|
+
</button>
|
253
|
+
),
|
254
|
+
)}
|
255
|
+
</div>
|
256
|
+
</>
|
257
|
+
) : (
|
258
|
+
<div
|
259
|
+
style={{
|
260
|
+
marginLeft: '15%',
|
261
|
+
padding: '5px 3px',
|
262
|
+
border: '1px solid black',
|
263
|
+
cursor: 'pointer',
|
264
|
+
}}
|
265
|
+
onClick={() =>
|
266
|
+
handleNodeClick(main)
|
267
|
+
}>
|
268
|
+
{main}
|
269
|
+
</div>
|
270
|
+
)}
|
271
|
+
</div>
|
272
|
+
);
|
273
|
+
})}
|
274
|
+
</div>
|
275
|
+
</div>
|
276
|
+
</div>
|
277
|
+
</div>
|
278
|
+
);
|
279
|
+
}
|
280
|
+
|
281
|
+
export default Timeline;
|