visualifyjs 2.5.3-2.dev

Sign up to get free protection for your applications and to get access to all the features.
Files changed (147) hide show
  1. package/.github/workflows/static.yml.bak +51 -0
  2. package/LICENSE +674 -0
  3. package/README.md +59 -0
  4. package/config-overrides.js +31 -0
  5. package/dist/visualify.js +188 -0
  6. package/docs/.nojekyll +0 -0
  7. package/docs/docs/CLI.md +34 -0
  8. package/docs/docs/README.md +65 -0
  9. package/docs/docs/Rechart/bar.md +190 -0
  10. package/docs/docs/Rechart/funnel.md +241 -0
  11. package/docs/docs/Rechart/geo.md +0 -0
  12. package/docs/docs/Rechart/line.md +355 -0
  13. package/docs/docs/Rechart/liquidfill.md +0 -0
  14. package/docs/docs/Rechart/pie.md +225 -0
  15. package/docs/docs/Rechart/polar.md +0 -0
  16. package/docs/docs/Rechart/radar.md +253 -0
  17. package/docs/docs/Rechart/sankey.md +0 -0
  18. package/docs/docs/Rechart/scatter.md +298 -0
  19. package/docs/docs/Rechart/sunburst.md +0 -0
  20. package/docs/docs/Rechart/tree.md +0 -0
  21. package/docs/docs/Rechart/wordcloud.md +0 -0
  22. package/docs/docs/_404.md +52 -0
  23. package/docs/docs/_coverpage.md +11 -0
  24. package/docs/docs/_sidebar.md +44 -0
  25. package/docs/docs/components/dotBio.md +34 -0
  26. package/docs/docs/components/echart.md +82 -0
  27. package/docs/docs/components/html.md +34 -0
  28. package/docs/docs/components/macaron.md +145 -0
  29. package/docs/docs/components/markdown.md +0 -0
  30. package/docs/docs/components/more.md +142 -0
  31. package/docs/docs/components/plotly.md +62 -0
  32. package/docs/docs/components/scatterL.md +70 -0
  33. package/docs/docs/components/visium.md +57 -0
  34. package/docs/docs/configuration.md +121 -0
  35. package/docs/docs/deploy.md +31 -0
  36. package/docs/docs/log.md +9 -0
  37. package/docs/docs/more-pages.md +23 -0
  38. package/docs/docs/quickstart.md +124 -0
  39. package/docs/docs/rechart-attributes.md +74 -0
  40. package/docs/docs/rechart-basic-usage.md +162 -0
  41. package/docs/docs/static/_images/deploy-github-pages.png +0 -0
  42. package/docs/docs/static/logo/favicon.ico +0 -0
  43. package/docs/docs/static/logo/logo_128x128.png +0 -0
  44. package/docs/docs/static/logo/logo_192x192.png +0 -0
  45. package/docs/docs/static/logo/logo_256x256.png +0 -0
  46. package/docs/docs/static/logo/logo_512x512.png +0 -0
  47. package/docs/docs/static/logo/logo_64x64.png +0 -0
  48. package/docs/docs/theme.md +5 -0
  49. package/docs/index.html +71 -0
  50. package/docs/manifest.json +24 -0
  51. package/docs/static/css/fluff-stuff.css +170 -0
  52. package/docs/static/css/font-awesome.min.css +4 -0
  53. package/docs/static/css/visualify.css +25 -0
  54. package/docs/static/fonts/fontawesome-webfont.woff2 +0 -0
  55. package/docs/static/images/star.png +0 -0
  56. package/docs/static/js/configuration.js +448 -0
  57. package/docs/static/js/fluff.js +1 -0
  58. package/docs/static/js/visualify.js +188 -0
  59. package/docs/static/logo/favicon.ico +0 -0
  60. package/docs/static/logo/logo_128x128.png +0 -0
  61. package/docs/static/logo/logo_192x192.png +0 -0
  62. package/docs/static/logo/logo_256x256.png +0 -0
  63. package/docs/static/logo/logo_512x512.png +0 -0
  64. package/docs/static/logo/logo_64x64.png +0 -0
  65. package/package.json +84 -0
  66. package/rollup.config.mjs +76 -0
  67. package/src/_css/404.css +116 -0
  68. package/src/_css/App.css +38 -0
  69. package/src/_css/autoSuggestion.css +27 -0
  70. package/src/_css/circular-progress.css +33 -0
  71. package/src/_css/index.css +37 -0
  72. package/src/_css/modern.css +25 -0
  73. package/src/_media/404.png +0 -0
  74. package/src/_media/corner.svg +8 -0
  75. package/src/_media/download.svg +3 -0
  76. package/src/_media/icon.svg +1 -0
  77. package/src/_media/logo.svg +14 -0
  78. package/src/_test/App.test.js +15 -0
  79. package/src/_utils/reportWebVitals.js +13 -0
  80. package/src/core/appContext.js +27 -0
  81. package/src/core/components/Scatter.js +188 -0
  82. package/src/core/components/ScatterBio.js +572 -0
  83. package/src/core/components/VisiumPlot.js +165 -0
  84. package/src/core/components/browser.js +42 -0
  85. package/src/core/components/dotplot.js +413 -0
  86. package/src/core/components/html.js +29 -0
  87. package/src/core/components/list.js +178 -0
  88. package/src/core/components/macaron.js +201 -0
  89. package/src/core/components/markdown.js +56 -0
  90. package/src/core/components/parser.scatterBio.js +587 -0
  91. package/src/core/components/ratio.js +80 -0
  92. package/src/core/components/scatterL.js +173 -0
  93. package/src/core/components/searchbar.js +131 -0
  94. package/src/core/components/selection.js +193 -0
  95. package/src/core/components/timeline.js +281 -0
  96. package/src/core/components/visium.js +97 -0
  97. package/src/core/fetch/condfetch.js +82 -0
  98. package/src/core/fetch/fetch.js +92 -0
  99. package/src/core/fetch/json.js +29 -0
  100. package/src/core/fetch/vfetch.js +42 -0
  101. package/src/core/liveEditor.js +44 -0
  102. package/src/core/modules/codeEditorWithPreview.js +104 -0
  103. package/src/core/modules/echarts/common.js +20 -0
  104. package/src/core/modules/echarts/presetHandler.js +41 -0
  105. package/src/core/modules/echarts/presets/esodev.chromium.js +172 -0
  106. package/src/core/modules/echarts/presets/esodev.codex.js +130 -0
  107. package/src/core/modules/echarts/presets/esodev.visium.js +123 -0
  108. package/src/core/modules/echarts/presets/mmtrbc.js +186 -0
  109. package/src/core/modules/echarts.js +71 -0
  110. package/src/core/modules/echartsUtils.js +43 -0
  111. package/src/core/modules/echartswitcher.js +152 -0
  112. package/src/core/modules/replotly/presetHandler.js +24 -0
  113. package/src/core/modules/replotly/presets/minimum.js +18 -0
  114. package/src/core/modules/replotly/presets/mmtrbc.dot.js +114 -0
  115. package/src/core/modules/replotly/presets/mmtrbc.violin.js +100 -0
  116. package/src/core/modules/replotly.js +71 -0
  117. package/src/core/pages/404.js +50 -0
  118. package/src/core/pages/error.js +27 -0
  119. package/src/core/pages/jsonPage.js +62 -0
  120. package/src/core/pages/loading.js +44 -0
  121. package/src/core/parser/echart.data.js +183 -0
  122. package/src/core/parser/echart.features.js +125 -0
  123. package/src/core/parser/echart.general.js +147 -0
  124. package/src/core/parser/echart.hilbert.js +57 -0
  125. package/src/core/parser/echart.parser.js +210 -0
  126. package/src/core/parser/echart.series.js +67 -0
  127. package/src/core/parser/echart.types.js +76 -0
  128. package/src/core/parser/plotly.config.js +10 -0
  129. package/src/core/parser/plotly.data.js +132 -0
  130. package/src/core/parser/plotly.layout.js +10 -0
  131. package/src/core/parser/plotly.violin.js +18 -0
  132. package/src/core/recharts.js +62 -0
  133. package/src/core/router/alias.js +49 -0
  134. package/src/core/router/jsonRouter.js +31 -0
  135. package/src/core/themes/modern.js +32 -0
  136. package/src/core/themes/themeSelector.js +33 -0
  137. package/src/core/visualify.js +47 -0
  138. package/src/core/widgets/circularProgress.js +24 -0
  139. package/src/core/widgets/controller.js +83 -0
  140. package/src/core/widgets/errorBoundary.js +36 -0
  141. package/src/core/widgets/footer.js +177 -0
  142. package/src/core/widgets/header.js +234 -0
  143. package/src/core/widgets/layout/Grid.js +31 -0
  144. package/src/core/widgets/layout.js +36 -0
  145. package/src/core/widgets/mapping.js +42 -0
  146. package/src/index.js +62 -0
  147. package/src/setupTests.js +5 -0
@@ -0,0 +1,178 @@
1
+ import React, { useState } from 'react';
2
+ import { Button, InputGroup, FormControl, ListGroup } from 'react-bootstrap';
3
+ import { useAppContext } from '../appContext';
4
+ import SearchBar from './searchbar';
5
+
6
+ const List = ({ props, style }) => {
7
+ const { debug } = props;
8
+
9
+ const { style: _style_parsed = {} } = props;
10
+ const { class: className, ...customStyle } = _style_parsed;
11
+
12
+ // if debug is true, then border is red, else no border
13
+ style = {
14
+ ...style,
15
+ border: debug ? '1px solid red' : 'none',
16
+ margin: '0px auto',
17
+ width: '200px',
18
+ ...customStyle,
19
+ };
20
+
21
+ // Title & Subtitle--------------------------------------------------
22
+ const { id = 'genelist', title, subtitle } = props;
23
+ // Render title
24
+ const renderTitle = () => {
25
+ return title && <h3>{title}</h3>;
26
+ };
27
+
28
+ const renderSubtitle = () => {
29
+ return subtitle && <h5>{subtitle}</h5>;
30
+ };
31
+ // Search | Typing --------------------------------------------------
32
+ const { search } = props;
33
+ const renderSearch = () => {
34
+ return search && <SearchBar props={search} />;
35
+ };
36
+ // Input --------------------------------------------------
37
+ const { input } = props;
38
+
39
+ const [items, setItems] = useState([]);
40
+ const [inputValue, setInputValue] = useState('');
41
+
42
+ const handleInputChange = (event) => {
43
+ setInputValue(event.target.value);
44
+ };
45
+
46
+ const renderInput = () => {
47
+ return (
48
+ input && (
49
+ <FormControl
50
+ placeholder={input.placeholder}
51
+ aria-label={input.ariaLabel}
52
+ aria-describedby='basic-addon2'
53
+ value={inputValue}
54
+ onChange={handleInputChange}
55
+ />
56
+ )
57
+ );
58
+ };
59
+ // Button --------------------------------------------------
60
+ const { add, clear, remove } = props.btn;
61
+
62
+ const { sharedData, setSharedData } = useAppContext();
63
+ const { addfrom } = add;
64
+ const val_shared = sharedData[addfrom];
65
+
66
+ const handleAddItem = () => {
67
+ if (!input && !add.addfrom) {
68
+ alert('Please enable input first');
69
+ } else if (addfrom && val_shared) {
70
+ if (items.includes(val_shared)) {
71
+ alert('Item already exist');
72
+ } else {
73
+ setItems([...items, val_shared]);
74
+ setSharedData({ ...sharedData, [id]: [...items, val_shared] });
75
+ }
76
+ } else if (inputValue.trim() !== '') {
77
+ setItems([...items, inputValue]);
78
+ setInputValue('');
79
+ }
80
+ };
81
+
82
+ const handleRemoveItem = (itemIndex) => {
83
+ setItems(items.filter((_, index) => index !== itemIndex));
84
+
85
+ if (addfrom && val_shared) {
86
+ setSharedData({
87
+ ...sharedData,
88
+ [id]: items.filter((_, index) => index !== itemIndex),
89
+ });
90
+ }
91
+ };
92
+
93
+ const handleClearItems = () => {
94
+ setItems([]);
95
+
96
+ if (addfrom && val_shared) {
97
+ setSharedData({ ...sharedData, [id]: [] });
98
+ }
99
+
100
+ if (clear.msg) {
101
+ alert(clear.msg === true ? 'All items cleared' : clear.msg);
102
+ }
103
+ };
104
+
105
+ const renderAddbtn = () => {
106
+ return (
107
+ add &&
108
+ add.show && (
109
+ <Button
110
+ style={add.style}
111
+ variant='outline-secondary'
112
+ onClick={handleAddItem}>
113
+ {add.text}
114
+ </Button>
115
+ )
116
+ );
117
+ };
118
+
119
+ const renderClearbtn = () => {
120
+ return (
121
+ clear &&
122
+ clear.show && (
123
+ <Button
124
+ style={clear.style}
125
+ variant='outline-secondary'
126
+ onClick={handleClearItems}>
127
+ {clear.text}
128
+ </Button>
129
+ )
130
+ );
131
+ };
132
+
133
+ const renderRemovebtn = (index) => {
134
+ return (
135
+ remove &&
136
+ remove.show && (
137
+ <Button
138
+ variant='outline-danger'
139
+ size='sm'
140
+ style={{ ...remove.style, float: 'right' }}
141
+ onClick={() => handleRemoveItem(index)}>
142
+ {remove.text ?? 'X'}
143
+ </Button>
144
+ )
145
+ );
146
+ };
147
+
148
+ const { liststyle = { maxHeight: '380px', overflow: 'auto' } } = props;
149
+
150
+ return (
151
+ <div
152
+ key={id}
153
+ style={style}
154
+ className={className}>
155
+ {renderTitle()}
156
+ {renderSubtitle()}
157
+ {renderSearch()}
158
+ <InputGroup
159
+ className='mb-3'
160
+ style={{ justifyContent: 'center' }}>
161
+ {renderInput()}
162
+ {renderAddbtn()}
163
+ {renderClearbtn()}
164
+ </InputGroup>
165
+
166
+ <ListGroup style={liststyle}>
167
+ {items.map((item, index) => (
168
+ <ListGroup.Item key={index}>
169
+ {item}
170
+ {renderRemovebtn(index)}
171
+ </ListGroup.Item>
172
+ ))}
173
+ </ListGroup>
174
+ </div>
175
+ );
176
+ };
177
+
178
+ export default List;
@@ -0,0 +1,201 @@
1
+ import React, { useState, useEffect, useMemo } from 'react';
2
+ import { useAppContext } from '../appContext';
3
+ import ReCharts from '../modules/echarts';
4
+
5
+ function processData(
6
+ nodes,
7
+ selected,
8
+ _symbolSize,
9
+ maxValue,
10
+ inner_color,
11
+ unclickable,
12
+ ) {
13
+ const { nodes: selectedNodes, category: selectedCategory } = selected;
14
+
15
+ return nodes.nodes.map((node) => {
16
+ const symbolSize =
17
+ typeof _symbolSize === 'number'
18
+ ? _symbolSize
19
+ : typeof _symbolSize === 'string'
20
+ ? _symbolSize === 'default'
21
+ ? (6 - node.category) * 6
22
+ : 10 + (parseFloat(node[_symbolSize]) / maxValue) * 30 ||
23
+ (6 - node.category) * 6
24
+ : (6 - node.category) * 6; // Fallback to default
25
+
26
+ const isSelected = selectedNodes.includes(node.name);
27
+ const isSameCategory = node.category === selectedCategory;
28
+ const isOriginalState =
29
+ selectedCategory === null && selectedNodes.length === 0;
30
+ const isUnclickable =
31
+ unclickable.includes(node.name) ||
32
+ unclickable.includes(node.category);
33
+ const opacity = isUnclickable
34
+ ? 0.8
35
+ : isOriginalState
36
+ ? 1
37
+ : isSelected
38
+ ? 1
39
+ : isSameCategory
40
+ ? 1
41
+ : 0.2;
42
+ const color = isUnclickable
43
+ ? 'gray'
44
+ : isOriginalState
45
+ ? `hsl(${node.category * 110}, 50%, 50%)`
46
+ : isSelected
47
+ ? inner_color.selected ?? 'red'
48
+ : isSameCategory
49
+ ? `hsl(${node.category * 100}, 50%, 50%)`
50
+ : inner_color.unselectable ?? 'grey';
51
+
52
+ return {
53
+ ...node,
54
+ symbolSize,
55
+ itemStyle: {
56
+ color,
57
+ opacity,
58
+ },
59
+ emphasis: {
60
+ focus: 'self',
61
+ itemStyle: {
62
+ color,
63
+ opacity,
64
+ },
65
+ label: {
66
+ position: 'insideTop',
67
+ show: true, // Show label
68
+ },
69
+ },
70
+ };
71
+ });
72
+ }
73
+
74
+ function Macaron({ props, style }) {
75
+ const { debug, style: _style, className } = props;
76
+ const { id, title, data } = props;
77
+
78
+ const {
79
+ animation = false,
80
+ draggable = true,
81
+ repulsion = 100,
82
+ edgeLength = 40,
83
+ height: inner_height = '93%',
84
+ width: inner_width = '100%',
85
+ unclickable = [],
86
+ symbolSize: _symbolSize = 'default',
87
+ color: inner_color = {
88
+ selected: 'red',
89
+ unselectable: 'grey',
90
+ },
91
+ singleclick = true,
92
+ } = props.config;
93
+
94
+ const [selected, setSelected] = useState({ nodes: [], category: null });
95
+ const { val = 'vnode' } = props;
96
+
97
+ const inner_style = {
98
+ border: debug ? '1px solid black' : 'none',
99
+ height: inner_height,
100
+ width: inner_width,
101
+ };
102
+
103
+ const maxValue = useMemo(() => {
104
+ const values = data.nodes.map(
105
+ (node) => parseFloat(node[_symbolSize]) || 50,
106
+ );
107
+ return Math.max(...values);
108
+ }, [data, _symbolSize]);
109
+
110
+ const processedData = useMemo(
111
+ () =>
112
+ processData(
113
+ data,
114
+ selected,
115
+ _symbolSize,
116
+ maxValue,
117
+ inner_color,
118
+ unclickable,
119
+ ),
120
+ [data, selected, _symbolSize, maxValue, inner_color, unclickable],
121
+ );
122
+
123
+ const onChartClick = (params) => {
124
+ const category = params.data.category;
125
+ const name = params.data.name;
126
+ if (
127
+ params.dataType === 'node' &&
128
+ !unclickable.includes(category) &&
129
+ !unclickable.includes(name) &&
130
+ (selected.category === null || category === selected.category)
131
+ ) {
132
+ let updatedSelectedNodes = [...selected.nodes];
133
+ let updatedSelectedCategory = selected.category;
134
+ if (selected.nodes.includes(name)) {
135
+ updatedSelectedNodes = updatedSelectedNodes.filter(
136
+ (nodeName) => nodeName !== name,
137
+ );
138
+ if (updatedSelectedNodes.length === 0) {
139
+ updatedSelectedCategory = null;
140
+ }
141
+ } else {
142
+ if (singleclick) updatedSelectedNodes = [name];
143
+ else updatedSelectedNodes.push(name);
144
+ updatedSelectedCategory = category;
145
+ }
146
+ setSelected({
147
+ nodes: updatedSelectedNodes,
148
+ category: updatedSelectedCategory,
149
+ });
150
+ }
151
+ };
152
+
153
+ const { setSharedData } = useAppContext();
154
+
155
+ useEffect(() => {
156
+ if (
157
+ val &&
158
+ Array.isArray(selected.nodes) &&
159
+ selected.nodes.length >= 0
160
+ ) {
161
+ setSharedData((prevSharedData) => ({
162
+ ...prevSharedData,
163
+ [val]: selected.nodes,
164
+ }));
165
+ }
166
+ }, [selected, val, setSharedData]);
167
+
168
+ return (
169
+ <div
170
+ key={id}
171
+ style={{ ...style, ..._style }}
172
+ className={className}>
173
+ {title && <h3>{title}</h3>}
174
+ <ReCharts
175
+ options={{
176
+ series: [
177
+ {
178
+ type: 'graph',
179
+ layout: 'force',
180
+ animation,
181
+ draggable,
182
+ label: {
183
+ position: 'top',
184
+ formatter: '{b}',
185
+ show: true,
186
+ },
187
+ data: processedData,
188
+ categories: data.categories,
189
+ edges: data.edges,
190
+ force: { repulsion, edgeLength },
191
+ },
192
+ ],
193
+ }}
194
+ style={inner_style}
195
+ onEvents={{ click: onChartClick }}
196
+ />
197
+ </div>
198
+ );
199
+ }
200
+
201
+ export default Macaron;
@@ -0,0 +1,56 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import axios from 'axios';
3
+ import { unified } from 'unified';
4
+ import remarkParse from 'remark-parse';
5
+ import remarkHtml from 'remark-html';
6
+
7
+ function Markdown({ props, style }) {
8
+ const { path } = props;
9
+ const [markdownContent, setMarkdownContent] = useState('');
10
+ const [error, setError] = useState(null);
11
+
12
+ useEffect(() => {
13
+ // Fetch the Markdown content from the specified path or file
14
+ axios.get(path).then(
15
+ (response) => {
16
+ const markdown = response.data;
17
+
18
+ // Create a new unified processor and use remark-parse and remark-html plugins
19
+ unified()
20
+ .use(remarkParse)
21
+ .use(remarkHtml)
22
+ .process(markdown, (err, file) => {
23
+ if (err) {
24
+ console.error('Error processing Markdown:', err);
25
+ setError('Error processing Markdown');
26
+ } else {
27
+ // Set the HTML content to be rendered
28
+ setMarkdownContent(String(file));
29
+ }
30
+ });
31
+ },
32
+ (error) => {
33
+ console.error('Error fetching Markdown:', error);
34
+ setError('Error fetching Markdown');
35
+ }
36
+ );
37
+ }, [path]);
38
+
39
+ if (error) {
40
+ return (
41
+ <div className='markdown-error' style={{ ...style }}>
42
+ {error}
43
+ </div>
44
+ );
45
+ }
46
+
47
+ return (
48
+ <div
49
+ className='markdown-content'
50
+ style={{ ...style }}
51
+ dangerouslySetInnerHTML={{ __html: markdownContent }}
52
+ />
53
+ );
54
+ }
55
+
56
+ export default Markdown;