@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.
- package/.github/workflows/deploy.yml +57 -0
- package/README.md +159 -0
- package/dev.tsconfig.json +18 -0
- package/docs/promotional-image.png +0 -0
- package/esbuild.ts +32 -0
- package/index.html +311 -0
- package/package.json +50 -0
- package/src/camera.ts +30 -0
- package/src/connection.ts +249 -0
- package/src/contextMenu.ts +367 -0
- package/src/draggable.ts +13 -0
- package/src/elements/base.ts +192 -0
- package/src/elements/container.ts +119 -0
- package/src/elements/interfaces.ts +50 -0
- package/src/elements/text.ts +86 -0
- package/src/graph.ts +535 -0
- package/src/graphSubsystem.ts +31 -0
- package/src/index.ts +28 -0
- package/src/input.ts +153 -0
- package/src/markdown/entry.ts +323 -0
- package/src/markdown/lexicalParser.ts +148 -0
- package/src/markdown/markdown.ts +14 -0
- package/src/markdown/syntaxParser.ts +344 -0
- package/src/markdown/token.ts +43 -0
- package/src/metadata.ts +3 -0
- package/src/node.ts +1130 -0
- package/src/nodes/factory.ts +87 -0
- package/src/nodes/publisher.ts +98 -0
- package/src/nodes/subsystem.ts +760 -0
- package/src/notes/note.ts +295 -0
- package/src/notes/subsystem.ts +262 -0
- package/src/organize.ts +181 -0
- package/src/pass/subsystem.ts +64 -0
- package/src/performance.ts +9 -0
- package/src/popup.ts +81 -0
- package/src/popups/form.ts +63 -0
- package/src/popups/string.ts +33 -0
- package/src/port.ts +223 -0
- package/src/quickMenu.ts +330 -0
- package/src/styles/box.ts +104 -0
- package/src/styles/canvasTextAlign.ts +8 -0
- package/src/styles/canvasTextBaseline.ts +9 -0
- package/src/styles/cursor.ts +18 -0
- package/src/styles/stroke.ts +39 -0
- package/src/styles/text.ts +90 -0
- package/src/styles/textBox.ts +82 -0
- package/src/theme.ts +78 -0
- package/src/types/box.ts +126 -0
- package/src/types/list.ts +41 -0
- package/src/types/pool.ts +66 -0
- package/src/types/text.ts +136 -0
- package/src/types/vector2.ts +34 -0
- package/src/utils/color.ts +136 -0
- package/src/utils/html.ts +21 -0
- package/src/utils/math.ts +8 -0
- package/src/utils/string.ts +98 -0
- package/src/widgets/button.ts +107 -0
- package/src/widgets/color.ts +151 -0
- package/src/widgets/factory.ts +46 -0
- package/src/widgets/image.ts +163 -0
- package/src/widgets/number.ts +153 -0
- package/src/widgets/slider.ts +216 -0
- package/src/widgets/string.ts +128 -0
- package/src/widgets/text.ts +92 -0
- package/src/widgets/toggle.ts +205 -0
- package/src/widgets/widget.ts +12 -0
- package/tsconfig.json +15 -0
- package/tsup.config.ts +10 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { FlowNode } from "../node";
|
|
2
|
+
import { Publisher, PublisherConfig } from "./publisher";
|
|
3
|
+
import { ContextMenuConfig } from "../contextMenu";
|
|
4
|
+
import { Vector2 } from "../types/vector2";
|
|
5
|
+
import { nodeFlowGroup as nodeFlowContextMenuGroup, NodeSubsystem } from "./subsystem";
|
|
6
|
+
|
|
7
|
+
export type NodeCreatedCallback = (publisher: string, nodeType: string, node: FlowNode) => void;
|
|
8
|
+
|
|
9
|
+
interface NodeFactoryPublishers {
|
|
10
|
+
[name: string]: PublisherConfig
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface NodeFactoryConfig {
|
|
14
|
+
publishers?: NodeFactoryPublishers
|
|
15
|
+
onNodeCreated?: NodeCreatedCallback;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export class NodeFactory {
|
|
19
|
+
#registeredPublishers: Map<string, Publisher>;
|
|
20
|
+
|
|
21
|
+
#registeredCallbacks: Array<NodeCreatedCallback>;
|
|
22
|
+
|
|
23
|
+
constructor(config?: NodeFactoryConfig) {
|
|
24
|
+
this.#registeredPublishers = new Map<string, Publisher>();
|
|
25
|
+
this.#registeredCallbacks = new Array<NodeCreatedCallback>();
|
|
26
|
+
|
|
27
|
+
if (config?.onNodeCreated) {
|
|
28
|
+
this.#registeredCallbacks.push(config?.onNodeCreated);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (config?.publishers !== undefined) {
|
|
32
|
+
for (let entry in config.publishers) {
|
|
33
|
+
this.addPublisher(entry, new Publisher(config.publishers[entry]));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
public addOnNodeCreatedListener(callback: NodeCreatedCallback): void {
|
|
39
|
+
this.#registeredCallbacks.push(callback);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public addPublisher(identifier: string, publisher: Publisher): void {
|
|
43
|
+
this.#registeredPublishers.set(identifier, publisher);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// I'm not even sure if I want this here? You can register on Publishers...
|
|
47
|
+
// So why not just make people register with the publisher.
|
|
48
|
+
// public register(publisher: string, nodeType: string, config: FlowNodeConfiguration): void {
|
|
49
|
+
// const foundPublisher = this.#registeredPublishers.get(publisher);
|
|
50
|
+
// if (foundPublisher === undefined) {
|
|
51
|
+
// console.error("no publisher registered with identifier:" + publisher);
|
|
52
|
+
// return;
|
|
53
|
+
// }
|
|
54
|
+
|
|
55
|
+
// foundPublisher.register(nodeType, config);
|
|
56
|
+
// }
|
|
57
|
+
|
|
58
|
+
public create(publisher: string, nodeType: string): FlowNode {
|
|
59
|
+
const publisherIdentifier = this.#registeredPublishers.get(publisher)
|
|
60
|
+
if (publisherIdentifier === undefined) {
|
|
61
|
+
throw new Error("no publisher registered with identifier: " + publisher);
|
|
62
|
+
}
|
|
63
|
+
const node = publisherIdentifier.create(nodeType);
|
|
64
|
+
|
|
65
|
+
for (let i = 0; i < this.#registeredCallbacks.length; i++) {
|
|
66
|
+
const callback = this.#registeredCallbacks[i];
|
|
67
|
+
callback(publisher, nodeType, node);
|
|
68
|
+
}
|
|
69
|
+
return node;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
public newNodeSubmenus(graph: NodeSubsystem, position: Vector2): Array<ContextMenuConfig> {
|
|
73
|
+
const menus: Array<ContextMenuConfig> = [];
|
|
74
|
+
for (let [_, publisher] of this.#registeredPublishers) {
|
|
75
|
+
menus.push(publisher.contextMenu(graph, position))
|
|
76
|
+
}
|
|
77
|
+
return menus;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
public openMenu(graph: NodeSubsystem, position: Vector2): ContextMenuConfig {
|
|
81
|
+
return {
|
|
82
|
+
name: "New Node",
|
|
83
|
+
group: nodeFlowContextMenuGroup,
|
|
84
|
+
subMenus: this.newNodeSubmenus(graph, position),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { ContextMenuConfig, ContextMenuItemConfig } from "../contextMenu";
|
|
2
|
+
import { FlowNode, FlowNodeConfig } from '../node';
|
|
3
|
+
import { Vector2 } from "../types/vector2";
|
|
4
|
+
import { NodeSubsystem } from "./subsystem";
|
|
5
|
+
|
|
6
|
+
interface PublisherNodes {
|
|
7
|
+
[name: string]: FlowNodeConfig
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface PublisherConfig {
|
|
11
|
+
name?: string;
|
|
12
|
+
description?: string;
|
|
13
|
+
version?: string;
|
|
14
|
+
nodes?: PublisherNodes
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export class Publisher {
|
|
18
|
+
|
|
19
|
+
#name: string;
|
|
20
|
+
|
|
21
|
+
#description: string;
|
|
22
|
+
|
|
23
|
+
#version: string;
|
|
24
|
+
|
|
25
|
+
#registeredNodes: Map<string, FlowNodeConfig>
|
|
26
|
+
|
|
27
|
+
constructor(config?: PublisherConfig) {
|
|
28
|
+
this.#name = config?.name === undefined ? "Unknown" : config.name;
|
|
29
|
+
this.#description = config?.description === undefined ? "" : config.description;
|
|
30
|
+
this.#version = config?.version === undefined ? "v0.0.0" : config.version;
|
|
31
|
+
|
|
32
|
+
this.#registeredNodes = new Map<string, FlowNodeConfig>();
|
|
33
|
+
|
|
34
|
+
if (config?.nodes !== undefined) {
|
|
35
|
+
for (const nodeKey in config.nodes) {
|
|
36
|
+
this.register(nodeKey, config.nodes[nodeKey]);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
nodes(): Map<string, FlowNodeConfig> {
|
|
42
|
+
return this.#registeredNodes;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
register(nodeType: string, config: FlowNodeConfig): void {
|
|
46
|
+
this.#registeredNodes.set(nodeType, config);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
#recurseBuildMenu(graph: NodeSubsystem, name: string, subMenu: Map<string, FlowNodeConfig>, position: Vector2): ContextMenuConfig {
|
|
50
|
+
const items: Array<ContextMenuItemConfig> = [];
|
|
51
|
+
const subMenus = new Map<string, Map<string, FlowNodeConfig>>();
|
|
52
|
+
|
|
53
|
+
for (let [key, nodeConfig] of subMenu) {
|
|
54
|
+
const elements = key.split("/");
|
|
55
|
+
if (elements.length === 1) {
|
|
56
|
+
items.push({
|
|
57
|
+
name: key,
|
|
58
|
+
callback: () => {
|
|
59
|
+
const node = new FlowNode(nodeConfig);
|
|
60
|
+
node.setPosition(position);
|
|
61
|
+
graph.addNode(node);
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
} else {
|
|
65
|
+
if (!subMenus.has(elements[0])) {
|
|
66
|
+
subMenus.set(elements[0], new Map<string, FlowNodeConfig>());
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const menu = subMenus.get(elements[0]);
|
|
70
|
+
elements.shift();
|
|
71
|
+
menu?.set(elements.join("/"), nodeConfig)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const menus: Array<ContextMenuConfig> = [];
|
|
76
|
+
for (let [key, nodes] of subMenus) {
|
|
77
|
+
menus.push(this.#recurseBuildMenu(graph, key, nodes, position))
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
name: name,
|
|
82
|
+
items: items,
|
|
83
|
+
subMenus: menus
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
contextMenu(graph: NodeSubsystem, position: Vector2): ContextMenuConfig {
|
|
88
|
+
return this.#recurseBuildMenu(graph, this.#name, this.#registeredNodes, position);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
create(nodeType: string): FlowNode {
|
|
92
|
+
const config = this.#registeredNodes.get(nodeType)
|
|
93
|
+
if (config === undefined) {
|
|
94
|
+
throw new Error("no builder registered for node: " + nodeType);
|
|
95
|
+
}
|
|
96
|
+
return new FlowNode(config);
|
|
97
|
+
}
|
|
98
|
+
}
|