@linkdlab/funcnodes_react_flow 0.1.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 (67) hide show
  1. package/README.md +46 -0
  2. package/package copy.json +63 -0
  3. package/package.json +75 -0
  4. package/public/favicon.ico +0 -0
  5. package/public/index.html +43 -0
  6. package/public/logo192.png +0 -0
  7. package/public/logo512.png +0 -0
  8. package/public/manifest.json +25 -0
  9. package/public/robots.txt +3 -0
  10. package/public/worker_manager +1 -0
  11. package/src/App.css +38 -0
  12. package/src/App.test.tsx +9 -0
  13. package/src/App.tsx +22 -0
  14. package/src/frontend/datarenderer/images.tsx +28 -0
  15. package/src/frontend/datarenderer/index.tsx +53 -0
  16. package/src/frontend/datarenderer/plotly.tsx +82 -0
  17. package/src/frontend/dialog.scss +88 -0
  18. package/src/frontend/dialog.tsx +70 -0
  19. package/src/frontend/edge.scss +15 -0
  20. package/src/frontend/edge.tsx +31 -0
  21. package/src/frontend/funcnodesreactflow.scss +63 -0
  22. package/src/frontend/funcnodesreactflow.tsx +283 -0
  23. package/src/frontend/header/header.scss +48 -0
  24. package/src/frontend/header/index.tsx +268 -0
  25. package/src/frontend/index.tsx +4 -0
  26. package/src/frontend/layout/htmlelements.scss +63 -0
  27. package/src/frontend/lib.scss +157 -0
  28. package/src/frontend/lib.tsx +198 -0
  29. package/src/frontend/node/index.tsx +3 -0
  30. package/src/frontend/node/io/default_input_renderer.tsx +327 -0
  31. package/src/frontend/node/io/default_output_render.tsx +26 -0
  32. package/src/frontend/node/io/handle_renderer.tsx +89 -0
  33. package/src/frontend/node/io/index.tsx +4 -0
  34. package/src/frontend/node/io/io.scss +91 -0
  35. package/src/frontend/node/io/io.tsx +114 -0
  36. package/src/frontend/node/io/nodeinput.tsx +125 -0
  37. package/src/frontend/node/io/nodeoutput.tsx +37 -0
  38. package/src/frontend/node/node.scss +265 -0
  39. package/src/frontend/node/node.tsx +208 -0
  40. package/src/frontend/nodecontextmenu.scss +18 -0
  41. package/src/frontend/utils/colorpicker.scss +37 -0
  42. package/src/frontend/utils/colorpicker.tsx +342 -0
  43. package/src/frontend/utils/jsondata.tsx +19 -0
  44. package/src/frontend/utils/table.scss +22 -0
  45. package/src/frontend/utils/table.tsx +159 -0
  46. package/src/funcnodes/funcnodesworker.ts +455 -0
  47. package/src/funcnodes/index.ts +4 -0
  48. package/src/funcnodes/websocketworker.ts +153 -0
  49. package/src/funcnodes/workermanager.ts +229 -0
  50. package/src/index.css +13 -0
  51. package/src/index.tsx +19 -0
  52. package/src/logo.svg +1 -0
  53. package/src/react-app-env.d.ts +1 -0
  54. package/src/reportWebVitals.ts +15 -0
  55. package/src/setupTests.ts +5 -0
  56. package/src/state/edge.ts +35 -0
  57. package/src/state/fnrfzst.ts +440 -0
  58. package/src/state/index.ts +139 -0
  59. package/src/state/lib.ts +26 -0
  60. package/src/state/node.ts +118 -0
  61. package/src/state/nodespace.ts +151 -0
  62. package/src/state/reactflow.ts +65 -0
  63. package/src/types/lib.d.ts +16 -0
  64. package/src/types/node.d.ts +29 -0
  65. package/src/types/nodeio.d.ts +82 -0
  66. package/src/types/worker.d.ts +56 -0
  67. package/tsconfig.json +20 -0
@@ -0,0 +1,63 @@
1
+ .styleelement {
2
+ &:hover {
3
+ background-color: var(--funcnodesbackground_light);
4
+ }
5
+
6
+ &:active {
7
+ background-color: var(--funheadercolor);
8
+ color: var(--funcnodesbackground1);
9
+ }
10
+
11
+ &:focus {
12
+ outline: 1px solid var(--funheadercolor);
13
+ }
14
+
15
+ height: 2rem;
16
+ background-color: var(--funcnodesbackground1);
17
+ color: var(--funcnodestextcolor1);
18
+ border-radius: 0.75rem;
19
+ border: 1px solid var(--funheadercolor);
20
+ padding-left: 0.5rem;
21
+ padding-right: 0.5rem;
22
+ }
23
+
24
+ .styleddropdown {
25
+ @extend .styleelement;
26
+ padding-right: 0.25rem;
27
+ }
28
+
29
+ .styledbtn {
30
+ @extend .styleelement;
31
+ cursor: pointer;
32
+ }
33
+
34
+ .styledinput {
35
+ @extend .styleelement;
36
+
37
+ :focus {
38
+ outline: none;
39
+ }
40
+ }
41
+
42
+ input[type="number"]::-webkit-inner-spin-button,
43
+ input[type="number"]::-webkit-outer-spin-button {
44
+ opacity: 0.5;
45
+ background-color: tr;
46
+ }
47
+
48
+ .styledcheckbox {
49
+ @extend .styleelement;
50
+ height: auto;
51
+ &:focus {
52
+ outline: none;
53
+ }
54
+ &:after {
55
+ content: "";
56
+ background-color: var(--funheadercolor);
57
+ }
58
+ &.checked {
59
+ background-color: var(--funheadercolor);
60
+ color: var(--funcnodesbackground1);
61
+ }
62
+ accent-color: var(--funheadercolor);
63
+ }
@@ -0,0 +1,157 @@
1
+ :root {
2
+ --expandtime: 0.3s;
3
+ --libnodebgcolor: #48465f;
4
+ --libnodebgcolor_hover: #6a6698;
5
+ }
6
+ .libcontainer {
7
+ top: 0;
8
+ left: 0;
9
+
10
+ height: 100%;
11
+ padding: 0.5rem;
12
+ box-sizing: border-box;
13
+ display: flex;
14
+ flex-direction: column;
15
+
16
+ border-radius: 0.5rem;
17
+ }
18
+
19
+ .library {
20
+ display: flex;
21
+ flex-direction: column;
22
+ flex-grow: 1;
23
+ overflow: hidden;
24
+ width: 15rem;
25
+ background-color: var(--funcnodesbackground2);
26
+ border-radius: var(--containerboarderradius);
27
+ padding: 0.5rem;
28
+
29
+ & .libtitle {
30
+ font-size: 1rem;
31
+ font-weight: bold;
32
+ color: var(--funheadercolor);
33
+ }
34
+
35
+ & hr {
36
+ &.hr_prominent {
37
+ border: 0.5px solid var(--funheadercolor);
38
+ }
39
+ width: 100%;
40
+ }
41
+ }
42
+
43
+ .addlib {
44
+ background-color: var(--funcnodesbackground2);
45
+ border-radius: var(--containerboarderradius);
46
+ padding: 0.5rem;
47
+
48
+ & button {
49
+ background-color: var(--funcnodesbackground1);
50
+ color: var(--funheadercolor);
51
+ border: 0;
52
+ border-radius: 0.5rem;
53
+ padding: 0.5rem;
54
+ cursor: pointer;
55
+ font-size: 1rem;
56
+ width: 100%;
57
+ &:hover {
58
+ background-color: var(--funheadercolor);
59
+ color: var(--funcnodesbackground1);
60
+ }
61
+ &:active {
62
+ background-color: var(--funcnodesbackground1);
63
+ color: var(--funcnodestextcolor1);
64
+ }
65
+ }
66
+ & button[disabled] {
67
+ background-color: var(--funcnodesbackground1);
68
+ color: var(--funcnodestextcolor1);
69
+ cursor: not-allowed;
70
+ }
71
+ }
72
+ .libfilter {
73
+ display: flex;
74
+ width: 100%;
75
+ flex-direction: row;
76
+ background-color: rgba(0, 0, 0, 0.1);
77
+ padding: 0.2rem;
78
+ &:focus-within {
79
+ border: 1px solid var(--funheadercolor);
80
+ }
81
+ & input {
82
+ flex-grow: 1;
83
+ background-color: transparent;
84
+ color: var(--funcnodestextcolor1);
85
+ border: 0;
86
+
87
+ &:focus {
88
+ outline: none;
89
+ }
90
+ }
91
+ }
92
+ .libnodecontainer {
93
+ display: grid;
94
+
95
+ transition: grid-template-rows var(--expandtime) ease-out;
96
+ &.close {
97
+ grid-template-rows: 0fr;
98
+ }
99
+ &.open {
100
+ grid-template-rows: 1fr;
101
+ }
102
+
103
+ &_inner {
104
+ transition: opacity var(--expandtime) ease-out;
105
+ overflow: hidden;
106
+ padding-left: 10px;
107
+ }
108
+ &.close &_inner {
109
+ opacity: 0.2;
110
+ }
111
+ &.open &_inner {
112
+ opacity: 1;
113
+ }
114
+ }
115
+ .shelfcontainer {
116
+ padding-top: 0.2rem;
117
+ padding-bottom: 0.2rem;
118
+ display: flex;
119
+ flex-direction: column;
120
+ & .shelftitle {
121
+ font-size: 0.8rem;
122
+
123
+ color: var(--funheadercolor);
124
+ opacity: 0.8;
125
+ display: flex;
126
+
127
+ &_text {
128
+ flex-grow: 1;
129
+ }
130
+ }
131
+ }
132
+
133
+ .libnodeentry {
134
+ border-radius: 10px;
135
+ box-sizing: border-box;
136
+ background-color: var(--libnodebgcolor);
137
+ margin-bottom: 0.2rem;
138
+ // border-radius: 0.2rem;
139
+ padding: 0.1rem;
140
+ cursor: pointer;
141
+ border: 1px solid var(--libnodebgcolor);
142
+ transition: border 0.2s ease-in-out;
143
+ font-size: 0.8rem;
144
+ box-shadow: -0.2rem 0px rgba(0, 76, 255);
145
+ &:hover {
146
+ background-color: var(--libnodebgcolor_hover);
147
+ border: 1px solid rgba(0, 76, 255);
148
+ }
149
+ }
150
+
151
+ .expandicon {
152
+ transform: rotate(0deg);
153
+ &.close {
154
+ transform: rotate(180deg);
155
+ }
156
+ transition: transform var(--expandtime) ease-out;
157
+ }
@@ -0,0 +1,198 @@
1
+ import React, { useState, useContext } from "react";
2
+ import "./lib.scss";
3
+
4
+ import { FuncNodesReactFlowZustandInterface } from "../state";
5
+ import { UseBoundStore } from "zustand";
6
+ import { MouseEvent } from "react";
7
+ import { FuncNodesContext } from "./index";
8
+ import SearchIcon from "@mui/icons-material/Search";
9
+ import CloseIcon from "@mui/icons-material/Close";
10
+ import ExpandLessIcon from "@mui/icons-material/ExpandLess";
11
+ import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
12
+ import CustomDialog from "./dialog";
13
+
14
+ const LibraryNode = ({ item }: { item: LibNode }) => {
15
+ const zustand: FuncNodesReactFlowZustandInterface =
16
+ useContext(FuncNodesContext);
17
+
18
+ const add_to_flow = () => {
19
+ zustand.worker?.add_node(item.node_id);
20
+ };
21
+
22
+ const nodeclick = (event: MouseEvent<HTMLDivElement>) => {
23
+ // if double click, add node to graph
24
+ if (event.detail === 2) {
25
+ add_to_flow();
26
+ }
27
+ };
28
+ return (
29
+ <div className="libnodeentry" onClick={nodeclick} title={item.description}>
30
+ {item.node_name || item.node_id}
31
+ </div>
32
+ );
33
+ };
34
+
35
+ const filterShelf = (shelf: Shelf, filter: string): boolean => {
36
+ const hasFilteredNodes =
37
+ shelf.nodes?.some((node) =>
38
+ node.node_id.toLowerCase().includes(filter.toLowerCase())
39
+ ) ?? false;
40
+
41
+ const hasFilteredSubShelves =
42
+ shelf.subshelves?.some((subShelf) => filterShelf(subShelf, filter)) ??
43
+ false;
44
+
45
+ return hasFilteredNodes || hasFilteredSubShelves;
46
+ };
47
+
48
+ const LibraryShelf = ({ item, filter }: { item: Shelf; filter: string }) => {
49
+ const [isOpen, setIsOpen] = useState(false);
50
+
51
+ const handleToggle = () => setIsOpen(!isOpen);
52
+
53
+ const filterednodes = item.nodes?.filter((node) =>
54
+ node.node_id.toLowerCase().includes(filter.toLowerCase())
55
+ );
56
+
57
+ const _isopen = isOpen || filter.length > 0;
58
+ if (!filterShelf(item, filter)) {
59
+ return <></>;
60
+ }
61
+
62
+ return (
63
+ <div className="shelfcontainer">
64
+ <div
65
+ className="shelftitle"
66
+ onClick={handleToggle}
67
+ style={{ cursor: "pointer" }}
68
+ title={item.description}
69
+ >
70
+ <div className="shelftitle_text">{item.name}</div>
71
+ <div className={"expandicon " + (_isopen ? "open" : "close")}>
72
+ <ExpandLessIcon />
73
+ </div>
74
+ </div>
75
+ <div className={"libnodecontainer " + (_isopen ? "open" : "close")}>
76
+ <div className="libnodecontainer_inner">
77
+ {filterednodes && (
78
+ <>
79
+ {filterednodes.map((subItem, idx) => (
80
+ <LibraryNode key={idx} item={subItem} />
81
+ ))}
82
+ </>
83
+ )}
84
+ {item.subshelves && (
85
+ <>
86
+ {item.subshelves.map((subItem, idx) => (
87
+ <LibraryShelf key={idx} item={subItem} filter={filter} />
88
+ ))}
89
+ </>
90
+ )}
91
+ </div>
92
+ </div>
93
+ <hr />
94
+ </div>
95
+ );
96
+ };
97
+
98
+ const LibFilter = ({
99
+ filter,
100
+ setFilter,
101
+ }: {
102
+ filter: string;
103
+ setFilter: (filter: string) => void;
104
+ }) => {
105
+ // input with left icon
106
+
107
+ return (
108
+ <div className="libfilter">
109
+ <SearchIcon fontSize="inherit" />
110
+ <input
111
+ type="text"
112
+ placeholder="Filter"
113
+ value={filter}
114
+ onChange={(e) => {
115
+ setFilter(e.target.value);
116
+ }}
117
+ />
118
+ {filter && (
119
+ <CloseIcon
120
+ fontSize="inherit"
121
+ onClick={() => {
122
+ setFilter("");
123
+ }}
124
+ />
125
+ )}
126
+ </div>
127
+ );
128
+ };
129
+
130
+ const AddLibraryOverLay = ({ children }: { children: React.ReactNode }) => {
131
+ const [newlib, setNewLib] = useState("");
132
+ const zustand: FuncNodesReactFlowZustandInterface =
133
+ useContext(FuncNodesContext);
134
+ if (!zustand.worker) {
135
+ return <></>;
136
+ }
137
+ const add_new_lib = () => {
138
+ if (zustand.worker === undefined) {
139
+ return;
140
+ }
141
+ zustand.worker.add_lib(newlib);
142
+ setNewLib("");
143
+ };
144
+ return (
145
+ <CustomDialog
146
+ title="Add Library"
147
+ trigger={children}
148
+ description="Add a new library to the current worker."
149
+ buttons={[
150
+ {
151
+ text: "add",
152
+ onClick: add_new_lib,
153
+ },
154
+ ]}
155
+ >
156
+ <input
157
+ className="styledinput"
158
+ type="text"
159
+ value={newlib}
160
+ onChange={(e) => {
161
+ setNewLib(e.target.value);
162
+ }}
163
+ />
164
+ </CustomDialog>
165
+ );
166
+ };
167
+
168
+ const Library = () => {
169
+ const zustand: FuncNodesReactFlowZustandInterface =
170
+ useContext(FuncNodesContext);
171
+ const libstate = zustand.lib.libstate((state) => state.state);
172
+
173
+ const [filter, setFilter] = useState("");
174
+
175
+ return (
176
+ <div className="libcontainer">
177
+ <div className="library">
178
+ <div className="libtitle">Lib</div>
179
+ <hr className="hr_prominent" />
180
+ <LibFilter filter={filter} setFilter={setFilter} />
181
+ <div className="vscrollcontainer">
182
+ {libstate.shelves.map((item, idx) => (
183
+ <LibraryShelf key={idx} item={item} filter={filter} />
184
+ ))}
185
+ </div>
186
+ <hr />
187
+ </div>
188
+ <div className="addlib">
189
+ <AddLibraryOverLay>
190
+ <button disabled={zustand.worker === undefined}>Add Library</button>
191
+ </AddLibraryOverLay>
192
+ </div>
193
+ </div>
194
+ );
195
+ };
196
+
197
+ export default Library;
198
+ export { LibraryShelf as LibraryItem };
@@ -0,0 +1,3 @@
1
+ import DefaultNode from "./node";
2
+
3
+ export default DefaultNode;