@elicdavis/node-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 (68) hide show
  1. package/.github/workflows/deploy.yml +57 -0
  2. package/README.md +159 -0
  3. package/dev.tsconfig.json +18 -0
  4. package/docs/promotional-image.png +0 -0
  5. package/esbuild.ts +32 -0
  6. package/index.html +311 -0
  7. package/package.json +50 -0
  8. package/src/camera.ts +30 -0
  9. package/src/connection.ts +249 -0
  10. package/src/contextMenu.ts +367 -0
  11. package/src/draggable.ts +13 -0
  12. package/src/elements/base.ts +192 -0
  13. package/src/elements/container.ts +119 -0
  14. package/src/elements/interfaces.ts +50 -0
  15. package/src/elements/text.ts +86 -0
  16. package/src/graph.ts +535 -0
  17. package/src/graphSubsystem.ts +31 -0
  18. package/src/index.ts +28 -0
  19. package/src/input.ts +153 -0
  20. package/src/markdown/entry.ts +323 -0
  21. package/src/markdown/lexicalParser.ts +148 -0
  22. package/src/markdown/markdown.ts +14 -0
  23. package/src/markdown/syntaxParser.ts +344 -0
  24. package/src/markdown/token.ts +43 -0
  25. package/src/metadata.ts +3 -0
  26. package/src/node.ts +1130 -0
  27. package/src/nodes/factory.ts +87 -0
  28. package/src/nodes/publisher.ts +98 -0
  29. package/src/nodes/subsystem.ts +760 -0
  30. package/src/notes/note.ts +295 -0
  31. package/src/notes/subsystem.ts +262 -0
  32. package/src/organize.ts +181 -0
  33. package/src/pass/subsystem.ts +64 -0
  34. package/src/performance.ts +9 -0
  35. package/src/popup.ts +81 -0
  36. package/src/popups/form.ts +63 -0
  37. package/src/popups/string.ts +33 -0
  38. package/src/port.ts +223 -0
  39. package/src/quickMenu.ts +330 -0
  40. package/src/styles/box.ts +104 -0
  41. package/src/styles/canvasTextAlign.ts +8 -0
  42. package/src/styles/canvasTextBaseline.ts +9 -0
  43. package/src/styles/cursor.ts +18 -0
  44. package/src/styles/stroke.ts +39 -0
  45. package/src/styles/text.ts +90 -0
  46. package/src/styles/textBox.ts +82 -0
  47. package/src/theme.ts +78 -0
  48. package/src/types/box.ts +126 -0
  49. package/src/types/list.ts +41 -0
  50. package/src/types/pool.ts +66 -0
  51. package/src/types/text.ts +136 -0
  52. package/src/types/vector2.ts +34 -0
  53. package/src/utils/color.ts +136 -0
  54. package/src/utils/html.ts +21 -0
  55. package/src/utils/math.ts +8 -0
  56. package/src/utils/string.ts +98 -0
  57. package/src/widgets/button.ts +107 -0
  58. package/src/widgets/color.ts +151 -0
  59. package/src/widgets/factory.ts +46 -0
  60. package/src/widgets/image.ts +163 -0
  61. package/src/widgets/number.ts +153 -0
  62. package/src/widgets/slider.ts +216 -0
  63. package/src/widgets/string.ts +128 -0
  64. package/src/widgets/text.ts +92 -0
  65. package/src/widgets/toggle.ts +205 -0
  66. package/src/widgets/widget.ts +12 -0
  67. package/tsconfig.json +15 -0
  68. package/tsup.config.ts +10 -0
@@ -0,0 +1,57 @@
1
+ name: Deployment
2
+
3
+ concurrency: production
4
+
5
+ on:
6
+ push:
7
+ branches:
8
+ - main
9
+
10
+ permissions:
11
+ contents: write
12
+
13
+ env:
14
+ NODE_VERSION: '18.x' # set this to the node version to use
15
+
16
+ jobs:
17
+ build:
18
+ runs-on: ubuntu-latest
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+
22
+ - name: Set up Node.js
23
+ uses: actions/setup-node@v4
24
+ with:
25
+ node-version: ${{ env.NODE_VERSION }}
26
+ cache: 'npm'
27
+
28
+ - name: npm install, build, and test
29
+ run: |
30
+ npm install
31
+ npm run build --
32
+ rm -rf node_modules/
33
+ - name: Upload artifact for deployment job
34
+ uses: actions/upload-artifact@v4
35
+ with:
36
+ name: node-app
37
+ path: .
38
+
39
+ deploy:
40
+ runs-on: ubuntu-latest
41
+ needs: build
42
+ environment:
43
+ name: 'production'
44
+
45
+ steps:
46
+ - name: Download artifact from build job
47
+ uses: actions/download-artifact@v4
48
+ with:
49
+ name: node-app
50
+
51
+ - name: Deploy to GitHub Pages
52
+ uses: crazy-max/ghaction-github-pages@v4
53
+ with:
54
+ target_branch: gh-pages
55
+ build_dir: .
56
+ env:
57
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
package/README.md ADDED
@@ -0,0 +1,159 @@
1
+ # Node Flow
2
+
3
+ Another Flow-based Node graph Library.
4
+
5
+ Check it out [here](https://elicdavis.github.io/node-flow/).
6
+
7
+ ![promotional image](./docs/promotional-image.png)
8
+
9
+ ## About
10
+
11
+ Node Flow is a javascript library that enables developers to build node based tools similar to Unreal Blueprints or Blender Nodes.
12
+
13
+ ## Features
14
+
15
+ * Nodes
16
+ * Markdown Notes
17
+ * More Nodes
18
+
19
+ ## Install
20
+
21
+ Download the latest build [here](https://raw.githubusercontent.com/EliCDavis/node-flow/gh-pages/dist/web/NodeFlow.js).
22
+
23
+ ## Building
24
+
25
+ If you want to build the library yourself, you can run
26
+
27
+ ```bash
28
+ npm run package
29
+ ```
30
+
31
+ ## API
32
+
33
+ ### Graph API
34
+
35
+ #### Creation
36
+
37
+ The only requirement for creating a graph is providing it an instance of a [canvas](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas).
38
+
39
+ ```javascript
40
+ // Create a canvas to render our graph to
41
+ var canvas = document.createElement("canvas");
42
+
43
+ // Create our Node Flow Graph
44
+ var graph = new NodeFlowGraph(canvas)
45
+ ```
46
+
47
+ There are a bunch of optional parameters you can provide the graph:
48
+
49
+ ```javascript
50
+ var graph = new NodeFlowGraph(canvas, {
51
+ // Background color of the graph.
52
+ backgroundColor: "#FF5500",
53
+
54
+ // You can add extra items to the context
55
+ // menu that pops up when you right click.
56
+ contextMenu: {
57
+ subMenus: [
58
+ {
59
+ // Text that shows up in the context
60
+ // menu
61
+ name: "Example Context Menu Item",
62
+
63
+ // This is recursive. We can nest as
64
+ // many submenus within eachother as
65
+ // we want. This field is optional.
66
+ subMenus: [],
67
+
68
+ items: [
69
+ {
70
+ name: "Sub menu Item!!!"
71
+ }
72
+ ]
73
+ }
74
+ ],
75
+
76
+ // Items that show up at the base of the
77
+ // context menu
78
+ items: [
79
+ {
80
+ // Text that shows up in the context
81
+ // menu
82
+ name: "Example Context Menu Item",
83
+
84
+ // Function that get's executed when
85
+ // Item is clicked.
86
+ callback: () => {
87
+ alert("Example Context Menu Item");
88
+ }
89
+ }
90
+ ]
91
+ },
92
+
93
+ // Notes we want rendered on the graph.
94
+ board: {
95
+ notes: [
96
+ {
97
+ // Where to render the note
98
+ position: { x: 20, y: 20 },
99
+
100
+ // Whether or not the note can be
101
+ // interacted with on the graph
102
+ locked: true,
103
+
104
+ // Markdown enabled text
105
+ text: `
106
+ # My First note!!!
107
+
108
+ Not sure what to write here
109
+ `
110
+ },
111
+ ]
112
+ },
113
+ });
114
+ ```
115
+
116
+ ### Node API
117
+
118
+ #### Creation
119
+
120
+ ```javascript
121
+ // All nodes require a title. That's about it.
122
+ var node = new FlowNode({
123
+ title: "My First Node!",
124
+ });
125
+
126
+ // Be sure to add it to the graph so it can be rendered.
127
+ graph.addNode(node);
128
+ ```
129
+
130
+ #### Inputs and Outputs
131
+
132
+ Create a Add node that takes two numbers and outputs a single number
133
+
134
+ ```javascript
135
+ var node = new FlowNode({
136
+ title: "Add",
137
+ inputs: [
138
+ { name: "a", type: "float32" },
139
+ { name: "b", type: "float32" }
140
+ ],
141
+ outputs: [
142
+ { name: "sum", type: "float32" }
143
+ ],
144
+ });
145
+ ```
146
+
147
+ You can also add additional inputs and outputs to the node after it's been created
148
+
149
+ ```javascript
150
+ node.addInput({ name: "c", type: "float32" })
151
+ node.addOutput({ name: "sum", type: "float32" })
152
+ ```
153
+
154
+ ## Library Development
155
+
156
+ Just run
157
+
158
+ ```bash
159
+ ```npm run watch
@@ -0,0 +1,18 @@
1
+ {
2
+ "compilerOptions": {
3
+ "declaration": true,
4
+ "outFile": "./dist/js/NodeFlow.js",
5
+ "sourceMap": true,
6
+ "strict": true,
7
+ "module": "AMD",
8
+ "target": "ESNext"
9
+ },
10
+
11
+ "include": [
12
+ "src/index.ts"
13
+ ],
14
+
15
+ "exclude": [
16
+ "node_modules"
17
+ ]
18
+ }
Binary file
package/esbuild.ts ADDED
@@ -0,0 +1,32 @@
1
+ import { build, serve, BuildOptions } from 'esbuild';
2
+
3
+ const buildOptsWeb: BuildOptions = {
4
+ entryPoints: ['./src/index.ts'],
5
+ outfile: './dist/web/NodeFlow.js',
6
+ platform: 'browser',
7
+ target: ['esNext'],
8
+ // format: 'cjs',
9
+ bundle: true,
10
+ sourcemap: true,
11
+ minify: true,
12
+ treeShaking: true,
13
+ };
14
+
15
+ const serveOpts = { servedir: './' };
16
+ const flags = process.argv.filter(arg => /--[^=].*/.test(arg));
17
+ const enableWatch = (flags.includes('--watch'));
18
+
19
+ if (enableWatch) {
20
+ buildOptsWeb.watch = {
21
+ onRebuild: (error, result) => {
22
+ if (error) { console.error('watch web development build failed:', error); }
23
+ else { console.log('watch web development build succeeded:', result); }
24
+ }
25
+ };
26
+
27
+ serve(serveOpts, {}).then((result) => {
28
+ console.log(`serving extension from "${serveOpts.servedir}" at "http://${result.host}:${result.port}"`);
29
+ });
30
+ }
31
+
32
+ build(buildOptsWeb).then(() => enableWatch ? console.log("watching web development build...") : null);
package/index.html ADDED
@@ -0,0 +1,311 @@
1
+ <html>
2
+
3
+ <head>
4
+ <meta http-equiv="content-type" content="text/html; charset=utf-8" />
5
+ <title>Node Flow Demo</title>
6
+ <link rel="shortcut icon" href="#" />
7
+ <link rel="preconnect" href="https://fonts.googleapis.com">
8
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9
+ <link href="https://fonts.googleapis.com/css2?family=Source+Code+Pro:ital,wght@0,200..900;1,200..900&display=swap"
10
+ rel="stylesheet">
11
+ <style>
12
+ * {
13
+ margin: 0;
14
+ padding: 0;
15
+ }
16
+
17
+ html,
18
+ body {
19
+ width: 100%;
20
+ height: 100%;
21
+ }
22
+
23
+ canvas {
24
+ width: 100%;
25
+ height: 100%;
26
+ display: block;
27
+ }
28
+ </style>
29
+
30
+ <script src="./dist/index.mjs" type="module"></script>
31
+ </head>
32
+
33
+ <body>
34
+ <canvas id="canvas"></canvas>
35
+ <script type="module">
36
+ import { Theme, FlowNode, NodeFlowGraph, FlowNote } from "./dist/index.mjs";
37
+
38
+ const canvas = document.getElementById("canvas");
39
+ Theme.FontFamily = "Source Code Pro";
40
+
41
+ const node3 = new FlowNode({
42
+ title: "Node 3",
43
+ position: { x: 850, y: 150 },
44
+ inputs: [
45
+ { name: "test input 1", type: "int" }
46
+ ],
47
+ outputs: [
48
+ { name: "float", type: "float32" }
49
+ ],
50
+ widgets: [
51
+ {
52
+ type: "slider",
53
+ config: {
54
+ min: 0,
55
+ max: 5,
56
+ value: 2.5,
57
+ snapIncrement: .25
58
+ }
59
+ }
60
+ ]
61
+ });
62
+
63
+ const graph = new NodeFlowGraph(canvas, {
64
+ nodes: {
65
+ publishers: {
66
+ "example": {
67
+ name: "Example",
68
+ description: "Bunch of example nodes",
69
+ version: "v1.0.0",
70
+ nodes: {
71
+ "empty": {
72
+ title: "Empty Node",
73
+ canEditTitle: true,
74
+ canEditPorts: true,
75
+ canEditInfo: true
76
+ },
77
+ "widgets/slider": {
78
+ title: "Slider Node",
79
+ widgets: [
80
+ {
81
+ type: "slider",
82
+ config: {
83
+ value: 0.5,
84
+ }
85
+ }
86
+ ],
87
+ outputs: [
88
+ {
89
+ name: "out",
90
+ type: "float32"
91
+ }
92
+ ]
93
+ },
94
+ "widgets/color": {
95
+ title: "Color Node",
96
+ widgets: [
97
+ {
98
+ type: "color",
99
+ config: {
100
+ }
101
+ }
102
+ ],
103
+ outputs: [
104
+ {
105
+ name: "out",
106
+ type: "color"
107
+ }
108
+ ]
109
+ },
110
+ "widgets/text": {
111
+ title: "Text Node",
112
+ widgets: [
113
+ {
114
+ type: "text",
115
+ config: {
116
+ value: "Arbitrary Text"
117
+ }
118
+ }
119
+ ],
120
+ outputs: [
121
+ {
122
+ name: "out",
123
+ type: "color"
124
+ }
125
+ ]
126
+ }
127
+ }
128
+ },
129
+ },
130
+ },
131
+ board: {
132
+ notes: [
133
+ {
134
+ text: `
135
+ # Notes
136
+
137
+ This is an example of a *note* written in **markdown**.
138
+
139
+ You can place notes around your graph to help explain your graph to other users.
140
+
141
+ ## Editting
142
+
143
+ *Right-click* on this note and select "Edit Note" to put your text here!
144
+
145
+ ## Support
146
+
147
+ This is a minimal implementation with graph-specific functionality. Currently implemented features are:
148
+
149
+ * H1, H2, and H3
150
+ * Bold and Italic
151
+ * Unordered Lists
152
+ * Code blocks
153
+ `,
154
+ position: {
155
+ x: 2300,
156
+ y: 20
157
+ },
158
+ locked: true,
159
+ },
160
+ {
161
+ position: {
162
+ x: 20,
163
+ y: 20
164
+ },
165
+ locked: true,
166
+ text: `
167
+ # Node Flow
168
+
169
+ Node Flow is a javascript library that enables developers to build node based tools similar to Unreal Blueprints or Blender Nodes.
170
+
171
+ ## Example
172
+
173
+ Scattered across this graph contains code snippets on how to accomplish different things within the library.
174
+
175
+ \`\`\`
176
+ // Create a canvas to render our graph to
177
+ let canvas = document.createElement("canvas");
178
+
179
+ // Create our Node Flow Graph
180
+ let graph = new NodeFlowGraph(canvas)
181
+ \`\`\`
182
+ `
183
+ },
184
+
185
+ ]
186
+ }
187
+ });
188
+
189
+ graph.addNote(new FlowNote({
190
+ position: { x: 800, y: 20 },
191
+ locked: true,
192
+ text: `
193
+ ## Inputs and Outputs
194
+
195
+ Create a Add node that takes two numbers and outputs a single number
196
+
197
+ \`\`\`
198
+ let node = new FlowNode({
199
+ title: "Add",
200
+ info: "I add two numbers",
201
+ inputs: [
202
+ { name: "a", type: "float32" },
203
+ { name: "b", type: "float32" }
204
+ ],
205
+ outputs: [
206
+ { name: "sum", type: "float32" }
207
+ ],
208
+ });
209
+ graph.addNode(node);
210
+ \`\`\`
211
+
212
+ You can also add additional inputs and outputs to the node after it's been created
213
+
214
+ \`\`\`
215
+ node.addInput({ name: "c", type: "float32" })
216
+ node.addOutput({ name: "sum", type: "float32" })
217
+ \`\`\`
218
+ ` }));
219
+
220
+
221
+
222
+ var sumNode = new FlowNode({
223
+ position: {
224
+ x: 850,
225
+ y: 600
226
+ },
227
+ title: "Add",
228
+ info: "I add two numbers",
229
+ inputs: [
230
+ { name: "a", type: "float32" },
231
+ { name: "b", type: "float32" }
232
+ ],
233
+ outputs: [
234
+ { name: "sum", type: "float32" }
235
+ ],
236
+ });
237
+
238
+
239
+ var aNode = new FlowNode({
240
+ position: {
241
+ x: 550,
242
+ y: 500
243
+ },
244
+ title: "Number",
245
+ info: "I'm a node with a number widget",
246
+ outputs: [
247
+ { name: "value", type: "float32" }
248
+ ],
249
+ widgets: [
250
+ {
251
+ type: "number",
252
+ config: { value: 1 }
253
+ }
254
+ ]
255
+ });
256
+
257
+ var bNode = new FlowNode({
258
+ position: {
259
+ x: 550,
260
+ y: 650
261
+ },
262
+ title: "Number",
263
+ info: "I'm a node with both a number and image widget on it",
264
+ outputs: [
265
+ { name: "value", type: "float32" }
266
+ ],
267
+ widgets: [
268
+ {
269
+ type: "number",
270
+ config: { value: 2 }
271
+ },
272
+ {
273
+ type: "image",
274
+ config: {
275
+ image: "https://i.imgur.com/qRZgWC0.jpeg"
276
+ }
277
+ }
278
+ ]
279
+ })
280
+
281
+ const arrNode = new FlowNode({
282
+ position: {
283
+ x: 1050,
284
+ y: 600
285
+ },
286
+ title: "Add",
287
+ subTitle: "Array Inputs",
288
+ info: "This node contains a port that can take multiple input nodes at once, which can be useful for operations that can operate on [0,n] data sizes",
289
+ inputs: [
290
+ { name: "numbers", type: "float32", array: true },
291
+ ],
292
+ outputs: [
293
+ { name: "sum", type: "float32" }
294
+ ],
295
+ });
296
+
297
+ graph.addNode(sumNode)
298
+ graph.addNode(aNode)
299
+ graph.addNode(bNode)
300
+ graph.addNode(arrNode)
301
+
302
+ graph.connectNodes(aNode, 0, sumNode, 0)
303
+ graph.connectNodes(bNode, 0, sumNode, 1)
304
+
305
+ graph.connectNodes(aNode, 0, arrNode, 0)
306
+ graph.connectNodes(bNode, 0, arrNode, 0)
307
+
308
+ </script>
309
+ </body>
310
+
311
+ </html>
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@elicdavis/node-flow",
3
+ "description": "build node graphs",
4
+ "author": "Eli C Davis",
5
+ "version": "0.1.0",
6
+ "license": "MIT",
7
+ "keywords": [
8
+ "nodes",
9
+ "node-flow",
10
+ "graph"
11
+ ],
12
+ "main": "./dist/index.js",
13
+ "module": "./dist/index.mjs",
14
+ "types": "./dist/index.d.ts",
15
+ "scripts": {
16
+ "build": "ts-node ./esbuild.ts",
17
+ "watch": "npm run build -- --watch",
18
+ "package": "tsup"
19
+ },
20
+ "homepage": "https://github.com/EliCDavis/node-flow",
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://github.com/EliCDavis/node-flow.git"
24
+ },
25
+ "bugs": {
26
+ "url": "https://github.com/EliCDavis/node-flow/issues"
27
+ },
28
+ "devDependencies": {
29
+ "@esbuild-plugins/node-globals-polyfill": "^0.1.1",
30
+ "@esbuild-plugins/node-modules-polyfill": "^0.1.4",
31
+ "@types/glob": "^7.2.0",
32
+ "@types/mocha": "^9.1.1",
33
+ "@types/node": "16.x",
34
+ "@typescript-eslint/eslint-plugin": "^5.31.0",
35
+ "@typescript-eslint/parser": "^5.31.0",
36
+ "abort-controller": "^3.0.0",
37
+ "esbuild": "^0.15.11",
38
+ "eslint": "^8.20.0",
39
+ "eslint-config-standard": "^17.0.0",
40
+ "eslint-plugin-import": "^2.25.2",
41
+ "eslint-plugin-n": "^15.0.0",
42
+ "eslint-plugin-promise": "^6.0.0",
43
+ "glob": "^8.0.3",
44
+ "mocha": "^10.0.0",
45
+ "stream-browserify": "^3.0.0",
46
+ "ts-node": "^10.9.1",
47
+ "tsup": "^8.4.0",
48
+ "typescript": "^4.7.4"
49
+ }
50
+ }
package/src/camera.ts ADDED
@@ -0,0 +1,30 @@
1
+ import { Vector2, Zero } from "./types/vector2";
2
+
3
+ export class Camera {
4
+
5
+ zoom: number;
6
+
7
+ position: Vector2;
8
+
9
+ constructor() {
10
+ this.zoom = 1;
11
+ this.position = Zero();
12
+ }
13
+
14
+ screenSpaceToGraphSpace(screenPosition: Vector2, out: Vector2): void {
15
+ const scale = this.zoom;
16
+ out.x = (screenPosition.x / scale) - (this.position.x / scale);
17
+ out.y = (screenPosition.y / scale) - (this.position.y / scale);
18
+ }
19
+
20
+ graphSpaceToScreenSpace(graphPosition: Vector2, out: Vector2): void {
21
+ out.x = this.position.x + (graphPosition.x * this.zoom);
22
+ out.y = this.position.y + (graphPosition.y * this.zoom);
23
+ }
24
+
25
+ reset(): void {
26
+ this.zoom = 1;
27
+ this.position.x = 0;
28
+ this.position.y = 0;
29
+ }
30
+ }