@elicdavis/node-flow 0.1.15 → 0.1.17
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/.mocharc.json +5 -0
- package/dist/index.d.mts +139 -4
- package/dist/index.d.ts +139 -4
- package/dist/index.js +3754 -3352
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +3741 -3352
- package/dist/index.mjs.map +1 -1
- package/index.html +0 -30
- package/package.json +4 -2
- package/src/graph.ts +234 -41
- package/src/index.ts +82 -40
- package/src/input.ts +22 -14
- package/src/markdown/entry.ts +26 -3
- package/src/markdown/lexicalParser.ts +22 -32
- package/src/markdown/syntaxParser.ts +93 -68
- package/src/minimap.ts +178 -0
- package/src/node.ts +114 -0
- package/src/nodes/factory.ts +9 -5
- package/src/nodes/publisher.ts +39 -4
- package/src/nodes/subsystem.ts +218 -8
- package/src/notes/subsystem.ts +3 -0
- package/src/organize.ts +276 -181
- package/src/port.ts +143 -7
- package/src/render_scheduler.ts +49 -0
- package/src/styles/text.ts +8 -0
- package/src/theme.ts +8 -0
- package/src/types/text.ts +8 -4
- package/src/utils/string.ts +7 -1
- package/src/widgets/color.ts +5 -6
- package/src/widgets/factory.ts +1 -1
- package/src/widgets/image.ts +2 -0
- package/src/widgets/number.ts +2 -2
- package/src/widgets/slider.ts +2 -2
- package/src/widgets/string.ts +2 -2
- package/src/widgets/toggle.ts +2 -2
- package/src/widgets/widget.ts +22 -0
- package/test/markdown.test.ts +165 -0
- package/test/minimap.test.ts +103 -0
- package/test/node_menu_filter.test.ts +119 -0
- package/test/organize.test.ts +156 -0
- package/test/port.test.ts +125 -0
- package/test/render_scheduler.test.ts +119 -0
- package/tsconfig.json +6 -2
package/.mocharc.json
ADDED
package/dist/index.d.mts
CHANGED
|
@@ -72,6 +72,7 @@ interface ConnectionRendererParams {
|
|
|
72
72
|
outPort: Port | null;
|
|
73
73
|
}
|
|
74
74
|
type ConnectionRenderer = (params: ConnectionRendererParams) => void;
|
|
75
|
+
declare function DefaultConnectionRenderer(connectionSize: number, connectionColor: string | undefined, mouseOverSize: number, mouseOverColor: string | undefined): ConnectionRenderer;
|
|
75
76
|
declare class Connection {
|
|
76
77
|
#private;
|
|
77
78
|
constructor(inNode: FlowNode | null, inNodePortIndex: number, outNode: FlowNode | null, outNodePortIndex: number, renderer: ConnectionRenderer);
|
|
@@ -170,14 +171,45 @@ interface PortConfig {
|
|
|
170
171
|
type?: string;
|
|
171
172
|
description?: string;
|
|
172
173
|
array?: boolean;
|
|
174
|
+
/**
|
|
175
|
+
* Lets this port connect to a port of any type, instead of only to one
|
|
176
|
+
* declaring the same `type` string. For a port whose type is decided by
|
|
177
|
+
* whatever gets wired into it, where `type` is a placeholder shown to
|
|
178
|
+
* the user rather than a promise about the values passing through.
|
|
179
|
+
*/
|
|
180
|
+
anyType?: boolean;
|
|
181
|
+
/**
|
|
182
|
+
* Every type this port takes, when it takes more than one. For a port
|
|
183
|
+
* that works on a single value or an array of them, where `type` is
|
|
184
|
+
* only the one it happens to be showing.
|
|
185
|
+
*
|
|
186
|
+
* An empty or absent list means the port takes exactly its `type`,
|
|
187
|
+
* unless `anyType` says otherwise.
|
|
188
|
+
*/
|
|
189
|
+
acceptedTypes?: Array<string>;
|
|
173
190
|
emptyStyle?: PortStyle;
|
|
174
191
|
filledStyle?: PortStyle;
|
|
175
192
|
onConnectionAdded?: ConnectionChangeCallback;
|
|
176
193
|
onConnectionRemoved?: ConnectionChangeCallback;
|
|
177
194
|
}
|
|
195
|
+
/**
|
|
196
|
+
* Whether two ports may be connected, going by their types alone. Each port
|
|
197
|
+
* offers the set of types it takes - one entry for an ordinary port, several
|
|
198
|
+
* for a port that takes more than one, and none at all for a port that takes
|
|
199
|
+
* anything. They connect when those sets overlap.
|
|
200
|
+
*/
|
|
201
|
+
declare function portsCompatible(a: Port | undefined | null, b: Port | undefined | null): boolean;
|
|
202
|
+
declare function typeSetsCompatible(a: Array<string>, b: Array<string>): boolean;
|
|
203
|
+
declare function portConfigTypes(config: PortConfig): Array<string>;
|
|
178
204
|
declare class Port {
|
|
179
205
|
#private;
|
|
180
206
|
constructor(node: FlowNode, portType: PortType, config?: PortConfig);
|
|
207
|
+
setDataType(type: string): void;
|
|
208
|
+
setAnyType(anyType: boolean): void;
|
|
209
|
+
/**
|
|
210
|
+
* Scope accepted types to singular type
|
|
211
|
+
*/
|
|
212
|
+
settleOn(type: string): void;
|
|
181
213
|
addConnection(connection: Connection): void;
|
|
182
214
|
replaceConnection(connection: Connection, index: number): void;
|
|
183
215
|
addConnectionAddedListener(callback: ConnectionChangeCallback): void;
|
|
@@ -185,6 +217,12 @@ declare class Port {
|
|
|
185
217
|
addConnectionRemovedListener(callback: ConnectionChangeCallback): void;
|
|
186
218
|
clearConnection(connection: Connection): void;
|
|
187
219
|
getDataType(): string;
|
|
220
|
+
acceptsAnyType(): boolean;
|
|
221
|
+
/**
|
|
222
|
+
* Every type this port takes. Empty means it takes anything.
|
|
223
|
+
*/
|
|
224
|
+
acceptedTypes(): Array<string>;
|
|
225
|
+
setAcceptedTypes(types: Array<string>): void;
|
|
188
226
|
getPortType(): PortType;
|
|
189
227
|
getDisplayName(): string;
|
|
190
228
|
filledStyleColor(): string;
|
|
@@ -313,8 +351,14 @@ declare class FlowNode {
|
|
|
313
351
|
addInput(config: PortConfig): Port;
|
|
314
352
|
addOutput(config: PortConfig): Port;
|
|
315
353
|
addWidget(widget: Widget): void;
|
|
354
|
+
insertWidget(index: number, widget: Widget): void;
|
|
316
355
|
removeWidget(widget: Widget): void;
|
|
356
|
+
removeWidgetAt(index: number): Widget | undefined;
|
|
357
|
+
moveWidget(from: number, to: number): void;
|
|
358
|
+
clearWidgets(): void;
|
|
317
359
|
getWidget(index: number): Widget;
|
|
360
|
+
widgets(): ReadonlyArray<Widget>;
|
|
361
|
+
indexOfWidget(widget: Widget): number;
|
|
318
362
|
widgetCount(): number;
|
|
319
363
|
translate(delta: Vector2): void;
|
|
320
364
|
inBounds(ctx: CanvasRenderingContext2D, camera: Camera, position: Vector2): NodeIntersection;
|
|
@@ -331,11 +375,36 @@ declare class FlowNode {
|
|
|
331
375
|
outputs(): number;
|
|
332
376
|
addMessage(message: NodeMessageConfig): void;
|
|
333
377
|
clearMessages(): void;
|
|
378
|
+
hasBeenLaidOut(): boolean;
|
|
334
379
|
render(ctx: CanvasRenderingContext2D, camera: Camera, state: NodeState, mousePosition: Vector2 | undefined, postProcess: PassSubsystem): void;
|
|
380
|
+
layoutPortsWithoutDrawing(bounds: Box, zoom: number): boolean;
|
|
335
381
|
}
|
|
336
382
|
|
|
337
383
|
type NodeAddedCallback = (node: FlowNode) => void;
|
|
338
384
|
type NodeRemovedCallback = (node: FlowNode) => void;
|
|
385
|
+
/**
|
|
386
|
+
* A connection between two nodes of a copied set, by their position in that
|
|
387
|
+
* set rather than by node, so it can be rebuilt against the copies.
|
|
388
|
+
*/
|
|
389
|
+
interface InternalConnection {
|
|
390
|
+
fromNode: number;
|
|
391
|
+
fromPort: number;
|
|
392
|
+
toNode: number;
|
|
393
|
+
toPort: number;
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* A connection that was dragged out and dropped on empty canvas. Describes
|
|
397
|
+
* what a node would have to offer to finish it, and joins the two up once
|
|
398
|
+
* one has been made.
|
|
399
|
+
*/
|
|
400
|
+
interface DanglingConnection {
|
|
401
|
+
/** The side the new node has to offer. */
|
|
402
|
+
needs: PortType;
|
|
403
|
+
/** The types that side has to accept. Empty takes anything. */
|
|
404
|
+
types: Array<string>;
|
|
405
|
+
/** Wires the new node to the port the drag started from. */
|
|
406
|
+
connectTo: (node: FlowNode) => void;
|
|
407
|
+
}
|
|
339
408
|
interface ConnectionRendererConfiguration {
|
|
340
409
|
size?: number;
|
|
341
410
|
color?: string;
|
|
@@ -358,6 +427,8 @@ declare class NodeSubsystem {
|
|
|
358
427
|
clickStart(mousePosition: Vector2, camera: Camera, ctrlKey: boolean): boolean;
|
|
359
428
|
mouseDragEvent(delta: Vector2, scale: number): boolean;
|
|
360
429
|
clearNodeInputConnection(node: FlowNode, index: number): void;
|
|
430
|
+
connectionsWithin(nodes: Array<FlowNode>): Array<InternalConnection>;
|
|
431
|
+
setConnectionReleasedHandler(handler: (dangling: DanglingConnection) => void): void;
|
|
361
432
|
clickEnd(): void;
|
|
362
433
|
connectNodes(nodeOut: FlowNode, outPort: number, nodeIn: FlowNode, inPort: number): Connection | undefined;
|
|
363
434
|
getNodes(): Array<FlowNode>;
|
|
@@ -380,9 +451,26 @@ declare class NodeSubsystem {
|
|
|
380
451
|
removeNode(node: FlowNode): void;
|
|
381
452
|
organize(ctx: CanvasRenderingContext2D): void;
|
|
382
453
|
openContextMenu(ctx: CanvasRenderingContext2D, position: Vector2): ContextMenuConfig | null;
|
|
454
|
+
/** Drops the selection entirely. */
|
|
455
|
+
unselectAllNodes(): void;
|
|
456
|
+
/**
|
|
457
|
+
* Removes every selected node, and the connections that touched them.
|
|
458
|
+
*/
|
|
459
|
+
removeSelectedNodes(): Array<FlowNode>;
|
|
383
460
|
render(ctx: CanvasRenderingContext2D, camera: Camera, mousePosition: Vector2 | undefined): RenderResults | undefined;
|
|
384
461
|
}
|
|
385
462
|
|
|
463
|
+
/**
|
|
464
|
+
* Narrows a "new node" menu to the nodes that could actually be wired to a
|
|
465
|
+
* particular port.
|
|
466
|
+
*/
|
|
467
|
+
interface NodeMenuFilter {
|
|
468
|
+
/** Which side the new node has to offer. */
|
|
469
|
+
needs: PortType;
|
|
470
|
+
/** Types that side has to accept. An empty list takes anything. */
|
|
471
|
+
types: Array<string>;
|
|
472
|
+
onCreated?: (node: FlowNode) => void;
|
|
473
|
+
}
|
|
386
474
|
interface PublisherNodes {
|
|
387
475
|
[name: string]: FlowNodeConfig;
|
|
388
476
|
}
|
|
@@ -398,7 +486,7 @@ declare class Publisher {
|
|
|
398
486
|
nodes(): Map<string, FlowNodeConfig>;
|
|
399
487
|
register(nodeType: string, config: FlowNodeConfig): void;
|
|
400
488
|
unregister(nodeType: string): boolean;
|
|
401
|
-
contextMenu(graph: NodeSubsystem, position: Vector2): ContextMenuConfig;
|
|
489
|
+
contextMenu(graph: NodeSubsystem, position: Vector2, filter?: NodeMenuFilter): ContextMenuConfig;
|
|
402
490
|
create(nodeType: string): FlowNode;
|
|
403
491
|
}
|
|
404
492
|
|
|
@@ -416,8 +504,8 @@ declare class NodeFactory {
|
|
|
416
504
|
addOnNodeCreatedListener(callback: NodeCreatedCallback): void;
|
|
417
505
|
addPublisher(identifier: string, publisher: Publisher): void;
|
|
418
506
|
create(publisher: string, nodeType: string): FlowNode;
|
|
419
|
-
newNodeSubmenus(graph: NodeSubsystem, position: Vector2): Array<ContextMenuConfig>;
|
|
420
|
-
openMenu(graph: NodeSubsystem, position: Vector2): ContextMenuConfig;
|
|
507
|
+
newNodeSubmenus(graph: NodeSubsystem, position: Vector2, filter?: NodeMenuFilter): Array<ContextMenuConfig>;
|
|
508
|
+
openMenu(graph: NodeSubsystem, position: Vector2, filter?: NodeMenuFilter): ContextMenuConfig;
|
|
421
509
|
}
|
|
422
510
|
|
|
423
511
|
type NoteContentChangeCallback = (node: FlowNote, newContents: string) => void;
|
|
@@ -476,7 +564,33 @@ interface NoteSubsystemConfig {
|
|
|
476
564
|
notes?: Array<FlowNoteConfig>;
|
|
477
565
|
}
|
|
478
566
|
|
|
567
|
+
interface MinimapConfig {
|
|
568
|
+
enabled?: boolean;
|
|
569
|
+
width?: number;
|
|
570
|
+
height?: number;
|
|
571
|
+
margin?: number;
|
|
572
|
+
/** Overrides Theme.Minimap.BackgroundColor for this minimap alone. */
|
|
573
|
+
backgroundColor?: string;
|
|
574
|
+
/** Overrides Theme.Minimap.BorderColor for this minimap alone. */
|
|
575
|
+
borderColor?: string;
|
|
576
|
+
/** Overrides Theme.Minimap.NodeColor for this minimap alone. */
|
|
577
|
+
nodeColor?: string;
|
|
578
|
+
/** Overrides Theme.Minimap.ViewportColor for this minimap alone. */
|
|
579
|
+
viewportColor?: string;
|
|
580
|
+
}
|
|
581
|
+
declare class Minimap {
|
|
582
|
+
#private;
|
|
583
|
+
constructor(config?: MinimapConfig);
|
|
584
|
+
enabled(): boolean;
|
|
585
|
+
setEnabled(enabled: boolean): void;
|
|
586
|
+
contains(position: Vector2): boolean;
|
|
587
|
+
graphPositionOf(position: Vector2, out: Vector2): void;
|
|
588
|
+
render(ctx: CanvasRenderingContext2D, canvas: HTMLCanvasElement, camera: Camera, nodes: Array<FlowNode>): void;
|
|
589
|
+
}
|
|
590
|
+
|
|
479
591
|
type GraphRenderer = (canvas: HTMLCanvasElement, ctx: CanvasRenderingContext2D, position: Vector2, scale: number) => void;
|
|
592
|
+
type CopyCallback = (nodes: Array<FlowNode>, connections: Array<InternalConnection>) => void;
|
|
593
|
+
type PasteCallback = (position: Vector2) => void;
|
|
480
594
|
interface FlowNodeGraphConfiguration {
|
|
481
595
|
backgroundRenderer?: GraphRenderer;
|
|
482
596
|
backgroundColor?: string;
|
|
@@ -484,6 +598,7 @@ interface FlowNodeGraphConfiguration {
|
|
|
484
598
|
contextMenu?: ContextMenuConfig;
|
|
485
599
|
nodes?: NodeFactoryConfig;
|
|
486
600
|
board?: NoteSubsystemConfig;
|
|
601
|
+
minimap?: MinimapConfig;
|
|
487
602
|
}
|
|
488
603
|
declare class GraphView {
|
|
489
604
|
#private;
|
|
@@ -498,11 +613,15 @@ declare class GraphView {
|
|
|
498
613
|
declare class NodeFlowGraph {
|
|
499
614
|
#private;
|
|
500
615
|
constructor(canvas: HTMLCanvasElement, config?: FlowNodeGraphConfiguration);
|
|
616
|
+
addCopyListener(callback: CopyCallback): void;
|
|
617
|
+
addPasteListener(callback: PasteCallback): void;
|
|
501
618
|
addNoteAddedListener(callback: NoteAddedCallback): void;
|
|
502
619
|
addNoteRemovedListener(callback: NoteRemovedCallback): void;
|
|
503
620
|
addNoteDragStartListener(callback: NoteDragStartCallback): void;
|
|
504
621
|
addNoteDragStopListener(callback: NoteDragStopCallback): void;
|
|
505
622
|
zoom(amount: number, anchor?: Vector2): void;
|
|
623
|
+
/** The minimap, so it can be turned on and sized by the host. */
|
|
624
|
+
minimap(): Minimap;
|
|
506
625
|
currentView(): GraphView;
|
|
507
626
|
organize(): void;
|
|
508
627
|
addPublisher(identifier: string, publisher: Publisher): void;
|
|
@@ -512,6 +631,8 @@ declare class NodeFlowGraph {
|
|
|
512
631
|
* state used by Ctrl+click and box-select styling via FlowNode.selected()).
|
|
513
632
|
*/
|
|
514
633
|
getSelectedNodes(): Array<FlowNode>;
|
|
634
|
+
unselectAllNodes(): void;
|
|
635
|
+
removeSelectedNodes(): Array<FlowNode>;
|
|
515
636
|
/**
|
|
516
637
|
* Returns a copy of the current camera orientation (screen-space pan + zoom).
|
|
517
638
|
*/
|
|
@@ -541,6 +662,9 @@ declare class NodeFlowGraph {
|
|
|
541
662
|
addOnNodeCreatedListener(callback: NodeCreatedCallback): void;
|
|
542
663
|
addOnNodeAddedListener(callback: NodeAddedCallback): void;
|
|
543
664
|
addOnNodeRemovedListener(callback: NodeRemovedCallback): void;
|
|
665
|
+
requestRender(): void;
|
|
666
|
+
renderContinuously(): () => void;
|
|
667
|
+
dispose(): void;
|
|
544
668
|
}
|
|
545
669
|
|
|
546
670
|
declare const Theme: {
|
|
@@ -604,6 +728,14 @@ declare const Theme: {
|
|
|
604
728
|
FontColor: string;
|
|
605
729
|
DisabledFontColor: string;
|
|
606
730
|
};
|
|
731
|
+
Minimap: {
|
|
732
|
+
BackgroundColor: string;
|
|
733
|
+
BorderColor: string;
|
|
734
|
+
BorderRadius: number;
|
|
735
|
+
Padding: number;
|
|
736
|
+
NodeColor: string;
|
|
737
|
+
ViewportColor: string;
|
|
738
|
+
};
|
|
607
739
|
Note: {
|
|
608
740
|
FontColor: string;
|
|
609
741
|
FontSize: number;
|
|
@@ -628,6 +760,9 @@ declare const Theme: {
|
|
|
628
760
|
};
|
|
629
761
|
};
|
|
630
762
|
|
|
763
|
+
declare function requestRender(): void;
|
|
764
|
+
declare function renderContinuously(): () => void;
|
|
765
|
+
|
|
631
766
|
interface TextBoxStyleConfig {
|
|
632
767
|
box?: BoxStyleConfig;
|
|
633
768
|
text?: TextStyleConfig;
|
|
@@ -847,4 +982,4 @@ declare class WidgetFactory {
|
|
|
847
982
|
}
|
|
848
983
|
declare const GlobalWidgetFactory: WidgetFactory;
|
|
849
984
|
|
|
850
|
-
export { ButtonWidget, type CameraOrientation, ColorWidget, type ContextMenuConfig, type ContextMenuItemConfig, ContextMenuItemState, FlowNode, type FlowNodeConfig, type FlowNodeGraphConfiguration, type FlowNodeStyle, type FlowNodeTitleConfig, FlowNote, type FlowNoteConfig, GlobalWidgetFactory, type GraphRenderer, ImageWidget, MessageType, NodeFlowGraph, type NodeIntersection, type NodeMessageConfig, NodeState, type NoteAddedCallback, type NoteContentChangeCallback, type NoteDragStartCallback, type NoteDragStopCallback, type NoteRemovedCallback, type NoteSubsystemConfig, type NoteWidthChangeCallback, NumberWidget, Publisher, type PublisherConfig, SliderWidget, StringWidget, TextWidget, Theme, ToggleWidget, type WidgetConfig };
|
|
985
|
+
export { type Box, ButtonWidget, type ButtonWidgetConfig, type CameraOrientation, ColorWidget, type ColorWidgetConfig, Connection, type ConnectionRenderer, type ConnectionRendererParams, type ContextMenuConfig, type ContextMenuItemConfig, ContextMenuItemState, type CopyCallback, type DanglingConnection, DefaultConnectionRenderer, FlowNode, type FlowNodeConfig, type FlowNodeGraphConfiguration, type FlowNodeStyle, type FlowNodeTitleConfig, FlowNote, type FlowNoteConfig, GlobalWidgetFactory, type GraphRenderer, ImageWidget, type ImageWidgetConfig, type InternalConnection, MessageType, Minimap, type MinimapConfig, type NodeCreatedCallback, NodeFactory, type NodeFactoryConfig, NodeFlowGraph, type NodeIntersection, type NodeMenuFilter, type NodeMessageConfig, NodeState, type NoteAddedCallback, type NoteContentChangeCallback, type NoteDragStartCallback, type NoteDragStopCallback, type NoteRemovedCallback, type NoteSubsystemConfig, type NoteWidthChangeCallback, NumberWidget, type NumberWidgetConfig, type PasteCallback, Port, type PortConfig, type PortStyle, PortType, Publisher, type PublisherConfig, SliderWidget, type SliderWidgetConfig, StringWidget, type StringWidgetConfig, TextWidget, type TextWidgetConfig, Theme, type ToggleStyleConfig, ToggleWidget, type ToggleWidgetConfig, type Vector2, type Widget, type WidgetBuilder, type WidgetConfig, WidgetFactory, portConfigTypes, portsCompatible, renderContinuously, requestRender, typeSetsCompatible };
|
package/dist/index.d.ts
CHANGED
|
@@ -72,6 +72,7 @@ interface ConnectionRendererParams {
|
|
|
72
72
|
outPort: Port | null;
|
|
73
73
|
}
|
|
74
74
|
type ConnectionRenderer = (params: ConnectionRendererParams) => void;
|
|
75
|
+
declare function DefaultConnectionRenderer(connectionSize: number, connectionColor: string | undefined, mouseOverSize: number, mouseOverColor: string | undefined): ConnectionRenderer;
|
|
75
76
|
declare class Connection {
|
|
76
77
|
#private;
|
|
77
78
|
constructor(inNode: FlowNode | null, inNodePortIndex: number, outNode: FlowNode | null, outNodePortIndex: number, renderer: ConnectionRenderer);
|
|
@@ -170,14 +171,45 @@ interface PortConfig {
|
|
|
170
171
|
type?: string;
|
|
171
172
|
description?: string;
|
|
172
173
|
array?: boolean;
|
|
174
|
+
/**
|
|
175
|
+
* Lets this port connect to a port of any type, instead of only to one
|
|
176
|
+
* declaring the same `type` string. For a port whose type is decided by
|
|
177
|
+
* whatever gets wired into it, where `type` is a placeholder shown to
|
|
178
|
+
* the user rather than a promise about the values passing through.
|
|
179
|
+
*/
|
|
180
|
+
anyType?: boolean;
|
|
181
|
+
/**
|
|
182
|
+
* Every type this port takes, when it takes more than one. For a port
|
|
183
|
+
* that works on a single value or an array of them, where `type` is
|
|
184
|
+
* only the one it happens to be showing.
|
|
185
|
+
*
|
|
186
|
+
* An empty or absent list means the port takes exactly its `type`,
|
|
187
|
+
* unless `anyType` says otherwise.
|
|
188
|
+
*/
|
|
189
|
+
acceptedTypes?: Array<string>;
|
|
173
190
|
emptyStyle?: PortStyle;
|
|
174
191
|
filledStyle?: PortStyle;
|
|
175
192
|
onConnectionAdded?: ConnectionChangeCallback;
|
|
176
193
|
onConnectionRemoved?: ConnectionChangeCallback;
|
|
177
194
|
}
|
|
195
|
+
/**
|
|
196
|
+
* Whether two ports may be connected, going by their types alone. Each port
|
|
197
|
+
* offers the set of types it takes - one entry for an ordinary port, several
|
|
198
|
+
* for a port that takes more than one, and none at all for a port that takes
|
|
199
|
+
* anything. They connect when those sets overlap.
|
|
200
|
+
*/
|
|
201
|
+
declare function portsCompatible(a: Port | undefined | null, b: Port | undefined | null): boolean;
|
|
202
|
+
declare function typeSetsCompatible(a: Array<string>, b: Array<string>): boolean;
|
|
203
|
+
declare function portConfigTypes(config: PortConfig): Array<string>;
|
|
178
204
|
declare class Port {
|
|
179
205
|
#private;
|
|
180
206
|
constructor(node: FlowNode, portType: PortType, config?: PortConfig);
|
|
207
|
+
setDataType(type: string): void;
|
|
208
|
+
setAnyType(anyType: boolean): void;
|
|
209
|
+
/**
|
|
210
|
+
* Scope accepted types to singular type
|
|
211
|
+
*/
|
|
212
|
+
settleOn(type: string): void;
|
|
181
213
|
addConnection(connection: Connection): void;
|
|
182
214
|
replaceConnection(connection: Connection, index: number): void;
|
|
183
215
|
addConnectionAddedListener(callback: ConnectionChangeCallback): void;
|
|
@@ -185,6 +217,12 @@ declare class Port {
|
|
|
185
217
|
addConnectionRemovedListener(callback: ConnectionChangeCallback): void;
|
|
186
218
|
clearConnection(connection: Connection): void;
|
|
187
219
|
getDataType(): string;
|
|
220
|
+
acceptsAnyType(): boolean;
|
|
221
|
+
/**
|
|
222
|
+
* Every type this port takes. Empty means it takes anything.
|
|
223
|
+
*/
|
|
224
|
+
acceptedTypes(): Array<string>;
|
|
225
|
+
setAcceptedTypes(types: Array<string>): void;
|
|
188
226
|
getPortType(): PortType;
|
|
189
227
|
getDisplayName(): string;
|
|
190
228
|
filledStyleColor(): string;
|
|
@@ -313,8 +351,14 @@ declare class FlowNode {
|
|
|
313
351
|
addInput(config: PortConfig): Port;
|
|
314
352
|
addOutput(config: PortConfig): Port;
|
|
315
353
|
addWidget(widget: Widget): void;
|
|
354
|
+
insertWidget(index: number, widget: Widget): void;
|
|
316
355
|
removeWidget(widget: Widget): void;
|
|
356
|
+
removeWidgetAt(index: number): Widget | undefined;
|
|
357
|
+
moveWidget(from: number, to: number): void;
|
|
358
|
+
clearWidgets(): void;
|
|
317
359
|
getWidget(index: number): Widget;
|
|
360
|
+
widgets(): ReadonlyArray<Widget>;
|
|
361
|
+
indexOfWidget(widget: Widget): number;
|
|
318
362
|
widgetCount(): number;
|
|
319
363
|
translate(delta: Vector2): void;
|
|
320
364
|
inBounds(ctx: CanvasRenderingContext2D, camera: Camera, position: Vector2): NodeIntersection;
|
|
@@ -331,11 +375,36 @@ declare class FlowNode {
|
|
|
331
375
|
outputs(): number;
|
|
332
376
|
addMessage(message: NodeMessageConfig): void;
|
|
333
377
|
clearMessages(): void;
|
|
378
|
+
hasBeenLaidOut(): boolean;
|
|
334
379
|
render(ctx: CanvasRenderingContext2D, camera: Camera, state: NodeState, mousePosition: Vector2 | undefined, postProcess: PassSubsystem): void;
|
|
380
|
+
layoutPortsWithoutDrawing(bounds: Box, zoom: number): boolean;
|
|
335
381
|
}
|
|
336
382
|
|
|
337
383
|
type NodeAddedCallback = (node: FlowNode) => void;
|
|
338
384
|
type NodeRemovedCallback = (node: FlowNode) => void;
|
|
385
|
+
/**
|
|
386
|
+
* A connection between two nodes of a copied set, by their position in that
|
|
387
|
+
* set rather than by node, so it can be rebuilt against the copies.
|
|
388
|
+
*/
|
|
389
|
+
interface InternalConnection {
|
|
390
|
+
fromNode: number;
|
|
391
|
+
fromPort: number;
|
|
392
|
+
toNode: number;
|
|
393
|
+
toPort: number;
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* A connection that was dragged out and dropped on empty canvas. Describes
|
|
397
|
+
* what a node would have to offer to finish it, and joins the two up once
|
|
398
|
+
* one has been made.
|
|
399
|
+
*/
|
|
400
|
+
interface DanglingConnection {
|
|
401
|
+
/** The side the new node has to offer. */
|
|
402
|
+
needs: PortType;
|
|
403
|
+
/** The types that side has to accept. Empty takes anything. */
|
|
404
|
+
types: Array<string>;
|
|
405
|
+
/** Wires the new node to the port the drag started from. */
|
|
406
|
+
connectTo: (node: FlowNode) => void;
|
|
407
|
+
}
|
|
339
408
|
interface ConnectionRendererConfiguration {
|
|
340
409
|
size?: number;
|
|
341
410
|
color?: string;
|
|
@@ -358,6 +427,8 @@ declare class NodeSubsystem {
|
|
|
358
427
|
clickStart(mousePosition: Vector2, camera: Camera, ctrlKey: boolean): boolean;
|
|
359
428
|
mouseDragEvent(delta: Vector2, scale: number): boolean;
|
|
360
429
|
clearNodeInputConnection(node: FlowNode, index: number): void;
|
|
430
|
+
connectionsWithin(nodes: Array<FlowNode>): Array<InternalConnection>;
|
|
431
|
+
setConnectionReleasedHandler(handler: (dangling: DanglingConnection) => void): void;
|
|
361
432
|
clickEnd(): void;
|
|
362
433
|
connectNodes(nodeOut: FlowNode, outPort: number, nodeIn: FlowNode, inPort: number): Connection | undefined;
|
|
363
434
|
getNodes(): Array<FlowNode>;
|
|
@@ -380,9 +451,26 @@ declare class NodeSubsystem {
|
|
|
380
451
|
removeNode(node: FlowNode): void;
|
|
381
452
|
organize(ctx: CanvasRenderingContext2D): void;
|
|
382
453
|
openContextMenu(ctx: CanvasRenderingContext2D, position: Vector2): ContextMenuConfig | null;
|
|
454
|
+
/** Drops the selection entirely. */
|
|
455
|
+
unselectAllNodes(): void;
|
|
456
|
+
/**
|
|
457
|
+
* Removes every selected node, and the connections that touched them.
|
|
458
|
+
*/
|
|
459
|
+
removeSelectedNodes(): Array<FlowNode>;
|
|
383
460
|
render(ctx: CanvasRenderingContext2D, camera: Camera, mousePosition: Vector2 | undefined): RenderResults | undefined;
|
|
384
461
|
}
|
|
385
462
|
|
|
463
|
+
/**
|
|
464
|
+
* Narrows a "new node" menu to the nodes that could actually be wired to a
|
|
465
|
+
* particular port.
|
|
466
|
+
*/
|
|
467
|
+
interface NodeMenuFilter {
|
|
468
|
+
/** Which side the new node has to offer. */
|
|
469
|
+
needs: PortType;
|
|
470
|
+
/** Types that side has to accept. An empty list takes anything. */
|
|
471
|
+
types: Array<string>;
|
|
472
|
+
onCreated?: (node: FlowNode) => void;
|
|
473
|
+
}
|
|
386
474
|
interface PublisherNodes {
|
|
387
475
|
[name: string]: FlowNodeConfig;
|
|
388
476
|
}
|
|
@@ -398,7 +486,7 @@ declare class Publisher {
|
|
|
398
486
|
nodes(): Map<string, FlowNodeConfig>;
|
|
399
487
|
register(nodeType: string, config: FlowNodeConfig): void;
|
|
400
488
|
unregister(nodeType: string): boolean;
|
|
401
|
-
contextMenu(graph: NodeSubsystem, position: Vector2): ContextMenuConfig;
|
|
489
|
+
contextMenu(graph: NodeSubsystem, position: Vector2, filter?: NodeMenuFilter): ContextMenuConfig;
|
|
402
490
|
create(nodeType: string): FlowNode;
|
|
403
491
|
}
|
|
404
492
|
|
|
@@ -416,8 +504,8 @@ declare class NodeFactory {
|
|
|
416
504
|
addOnNodeCreatedListener(callback: NodeCreatedCallback): void;
|
|
417
505
|
addPublisher(identifier: string, publisher: Publisher): void;
|
|
418
506
|
create(publisher: string, nodeType: string): FlowNode;
|
|
419
|
-
newNodeSubmenus(graph: NodeSubsystem, position: Vector2): Array<ContextMenuConfig>;
|
|
420
|
-
openMenu(graph: NodeSubsystem, position: Vector2): ContextMenuConfig;
|
|
507
|
+
newNodeSubmenus(graph: NodeSubsystem, position: Vector2, filter?: NodeMenuFilter): Array<ContextMenuConfig>;
|
|
508
|
+
openMenu(graph: NodeSubsystem, position: Vector2, filter?: NodeMenuFilter): ContextMenuConfig;
|
|
421
509
|
}
|
|
422
510
|
|
|
423
511
|
type NoteContentChangeCallback = (node: FlowNote, newContents: string) => void;
|
|
@@ -476,7 +564,33 @@ interface NoteSubsystemConfig {
|
|
|
476
564
|
notes?: Array<FlowNoteConfig>;
|
|
477
565
|
}
|
|
478
566
|
|
|
567
|
+
interface MinimapConfig {
|
|
568
|
+
enabled?: boolean;
|
|
569
|
+
width?: number;
|
|
570
|
+
height?: number;
|
|
571
|
+
margin?: number;
|
|
572
|
+
/** Overrides Theme.Minimap.BackgroundColor for this minimap alone. */
|
|
573
|
+
backgroundColor?: string;
|
|
574
|
+
/** Overrides Theme.Minimap.BorderColor for this minimap alone. */
|
|
575
|
+
borderColor?: string;
|
|
576
|
+
/** Overrides Theme.Minimap.NodeColor for this minimap alone. */
|
|
577
|
+
nodeColor?: string;
|
|
578
|
+
/** Overrides Theme.Minimap.ViewportColor for this minimap alone. */
|
|
579
|
+
viewportColor?: string;
|
|
580
|
+
}
|
|
581
|
+
declare class Minimap {
|
|
582
|
+
#private;
|
|
583
|
+
constructor(config?: MinimapConfig);
|
|
584
|
+
enabled(): boolean;
|
|
585
|
+
setEnabled(enabled: boolean): void;
|
|
586
|
+
contains(position: Vector2): boolean;
|
|
587
|
+
graphPositionOf(position: Vector2, out: Vector2): void;
|
|
588
|
+
render(ctx: CanvasRenderingContext2D, canvas: HTMLCanvasElement, camera: Camera, nodes: Array<FlowNode>): void;
|
|
589
|
+
}
|
|
590
|
+
|
|
479
591
|
type GraphRenderer = (canvas: HTMLCanvasElement, ctx: CanvasRenderingContext2D, position: Vector2, scale: number) => void;
|
|
592
|
+
type CopyCallback = (nodes: Array<FlowNode>, connections: Array<InternalConnection>) => void;
|
|
593
|
+
type PasteCallback = (position: Vector2) => void;
|
|
480
594
|
interface FlowNodeGraphConfiguration {
|
|
481
595
|
backgroundRenderer?: GraphRenderer;
|
|
482
596
|
backgroundColor?: string;
|
|
@@ -484,6 +598,7 @@ interface FlowNodeGraphConfiguration {
|
|
|
484
598
|
contextMenu?: ContextMenuConfig;
|
|
485
599
|
nodes?: NodeFactoryConfig;
|
|
486
600
|
board?: NoteSubsystemConfig;
|
|
601
|
+
minimap?: MinimapConfig;
|
|
487
602
|
}
|
|
488
603
|
declare class GraphView {
|
|
489
604
|
#private;
|
|
@@ -498,11 +613,15 @@ declare class GraphView {
|
|
|
498
613
|
declare class NodeFlowGraph {
|
|
499
614
|
#private;
|
|
500
615
|
constructor(canvas: HTMLCanvasElement, config?: FlowNodeGraphConfiguration);
|
|
616
|
+
addCopyListener(callback: CopyCallback): void;
|
|
617
|
+
addPasteListener(callback: PasteCallback): void;
|
|
501
618
|
addNoteAddedListener(callback: NoteAddedCallback): void;
|
|
502
619
|
addNoteRemovedListener(callback: NoteRemovedCallback): void;
|
|
503
620
|
addNoteDragStartListener(callback: NoteDragStartCallback): void;
|
|
504
621
|
addNoteDragStopListener(callback: NoteDragStopCallback): void;
|
|
505
622
|
zoom(amount: number, anchor?: Vector2): void;
|
|
623
|
+
/** The minimap, so it can be turned on and sized by the host. */
|
|
624
|
+
minimap(): Minimap;
|
|
506
625
|
currentView(): GraphView;
|
|
507
626
|
organize(): void;
|
|
508
627
|
addPublisher(identifier: string, publisher: Publisher): void;
|
|
@@ -512,6 +631,8 @@ declare class NodeFlowGraph {
|
|
|
512
631
|
* state used by Ctrl+click and box-select styling via FlowNode.selected()).
|
|
513
632
|
*/
|
|
514
633
|
getSelectedNodes(): Array<FlowNode>;
|
|
634
|
+
unselectAllNodes(): void;
|
|
635
|
+
removeSelectedNodes(): Array<FlowNode>;
|
|
515
636
|
/**
|
|
516
637
|
* Returns a copy of the current camera orientation (screen-space pan + zoom).
|
|
517
638
|
*/
|
|
@@ -541,6 +662,9 @@ declare class NodeFlowGraph {
|
|
|
541
662
|
addOnNodeCreatedListener(callback: NodeCreatedCallback): void;
|
|
542
663
|
addOnNodeAddedListener(callback: NodeAddedCallback): void;
|
|
543
664
|
addOnNodeRemovedListener(callback: NodeRemovedCallback): void;
|
|
665
|
+
requestRender(): void;
|
|
666
|
+
renderContinuously(): () => void;
|
|
667
|
+
dispose(): void;
|
|
544
668
|
}
|
|
545
669
|
|
|
546
670
|
declare const Theme: {
|
|
@@ -604,6 +728,14 @@ declare const Theme: {
|
|
|
604
728
|
FontColor: string;
|
|
605
729
|
DisabledFontColor: string;
|
|
606
730
|
};
|
|
731
|
+
Minimap: {
|
|
732
|
+
BackgroundColor: string;
|
|
733
|
+
BorderColor: string;
|
|
734
|
+
BorderRadius: number;
|
|
735
|
+
Padding: number;
|
|
736
|
+
NodeColor: string;
|
|
737
|
+
ViewportColor: string;
|
|
738
|
+
};
|
|
607
739
|
Note: {
|
|
608
740
|
FontColor: string;
|
|
609
741
|
FontSize: number;
|
|
@@ -628,6 +760,9 @@ declare const Theme: {
|
|
|
628
760
|
};
|
|
629
761
|
};
|
|
630
762
|
|
|
763
|
+
declare function requestRender(): void;
|
|
764
|
+
declare function renderContinuously(): () => void;
|
|
765
|
+
|
|
631
766
|
interface TextBoxStyleConfig {
|
|
632
767
|
box?: BoxStyleConfig;
|
|
633
768
|
text?: TextStyleConfig;
|
|
@@ -847,4 +982,4 @@ declare class WidgetFactory {
|
|
|
847
982
|
}
|
|
848
983
|
declare const GlobalWidgetFactory: WidgetFactory;
|
|
849
984
|
|
|
850
|
-
export { ButtonWidget, type CameraOrientation, ColorWidget, type ContextMenuConfig, type ContextMenuItemConfig, ContextMenuItemState, FlowNode, type FlowNodeConfig, type FlowNodeGraphConfiguration, type FlowNodeStyle, type FlowNodeTitleConfig, FlowNote, type FlowNoteConfig, GlobalWidgetFactory, type GraphRenderer, ImageWidget, MessageType, NodeFlowGraph, type NodeIntersection, type NodeMessageConfig, NodeState, type NoteAddedCallback, type NoteContentChangeCallback, type NoteDragStartCallback, type NoteDragStopCallback, type NoteRemovedCallback, type NoteSubsystemConfig, type NoteWidthChangeCallback, NumberWidget, Publisher, type PublisherConfig, SliderWidget, StringWidget, TextWidget, Theme, ToggleWidget, type WidgetConfig };
|
|
985
|
+
export { type Box, ButtonWidget, type ButtonWidgetConfig, type CameraOrientation, ColorWidget, type ColorWidgetConfig, Connection, type ConnectionRenderer, type ConnectionRendererParams, type ContextMenuConfig, type ContextMenuItemConfig, ContextMenuItemState, type CopyCallback, type DanglingConnection, DefaultConnectionRenderer, FlowNode, type FlowNodeConfig, type FlowNodeGraphConfiguration, type FlowNodeStyle, type FlowNodeTitleConfig, FlowNote, type FlowNoteConfig, GlobalWidgetFactory, type GraphRenderer, ImageWidget, type ImageWidgetConfig, type InternalConnection, MessageType, Minimap, type MinimapConfig, type NodeCreatedCallback, NodeFactory, type NodeFactoryConfig, NodeFlowGraph, type NodeIntersection, type NodeMenuFilter, type NodeMessageConfig, NodeState, type NoteAddedCallback, type NoteContentChangeCallback, type NoteDragStartCallback, type NoteDragStopCallback, type NoteRemovedCallback, type NoteSubsystemConfig, type NoteWidthChangeCallback, NumberWidget, type NumberWidgetConfig, type PasteCallback, Port, type PortConfig, type PortStyle, PortType, Publisher, type PublisherConfig, SliderWidget, type SliderWidgetConfig, StringWidget, type StringWidgetConfig, TextWidget, type TextWidgetConfig, Theme, type ToggleStyleConfig, ToggleWidget, type ToggleWidgetConfig, type Vector2, type Widget, type WidgetBuilder, type WidgetConfig, WidgetFactory, portConfigTypes, portsCompatible, renderContinuously, requestRender, typeSetsCompatible };
|