diff --git a/README.md b/README.md index dee738725..55b695fd2 100755 --- a/README.md +++ b/README.md @@ -2,10 +2,11 @@ This is the litegraph version used in [ComfyUI_frontend](https://github.com/Comfy-Org/ComfyUI_frontend). -This repo is litegraph with following modifications: +This repo is litegraph with the following modifications: - Accumulated comfyUI custom changes (2024-01 ~ 2024-05) (https://github.com/Comfy-Org/litegraph.js/pull/1) - Type schema change for ComfyUI_frontend TS migration (https://github.com/Comfy-Org/litegraph.js/pull/3) - Zoom fix (https://github.com/Comfy-Org/litegraph.js/pull/7) +- Emit search box triggering custom events () # Install `npm i @comfyorg/litegraph` diff --git a/package.json b/package.json index 7e91148e9..c0f593ce1 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@comfyorg/litegraph", - "version": "0.7.21", + "version": "0.7.22", "description": "A graph node editor similar to PD or UDK Blueprints. It works in an HTML5 Canvas and allows to export graphs to be included in applications.", "main": "src/litegraph.js", "types": "src/litegraph.d.ts", diff --git a/src/litegraph.d.ts b/src/litegraph.d.ts index 7f7cfc2d5..5c2960674 100755 --- a/src/litegraph.d.ts +++ b/src/litegraph.d.ts @@ -24,10 +24,10 @@ export interface INodeSlot { type: string | -1; label?: string; dir?: - | typeof LiteGraph.UP - | typeof LiteGraph.RIGHT - | typeof LiteGraph.DOWN - | typeof LiteGraph.LEFT; + | typeof LiteGraph.UP + | typeof LiteGraph.RIGHT + | typeof LiteGraph.DOWN + | typeof LiteGraph.LEFT; color_on?: string; color_off?: string; shape?: SlotShape; @@ -104,8 +104,8 @@ export interface IComboWidget string[], { values: - | string[] - | ((widget: IComboWidget, node: LGraphNode) => string[]); + | string[] + | ((widget: IComboWidget, node: LGraphNode) => string[]); } > { type: "combo"; @@ -146,6 +146,20 @@ export type ContextMenuEventListener = ( node: LGraphNode ) => boolean | void; +export type LinkReleaseContext = { + node_from: LGraphNode; + slot_from: INodeSlot; + type_filter_in: string; +}; + +export type LiteGraphCanvasEventType = "empty-release" | "empty-double-click"; + +export type LiteGraphCanvasEvent = CustomEvent<{ + subType: string; + originalEvent: Event, + linkReleaseContext?: LinkReleaseContext; +}>; + export const LiteGraph: { DEFAULT_GROUP_FONT_SIZE: any; overlapBounding(visible_area: any, _bounding: any): unknown; @@ -244,7 +258,7 @@ export const LiteGraph: { createNode(type: string): T; /** Register a node class so it can be listed when the user wants to create a new one */ - registerNodeType(type: string, base: { new (): LGraphNode }): void; + registerNodeType(type: string, base: { new(): LGraphNode }): void; /** removes a node type from the system */ unregisterNodeType(type: string): void; /** Removes all previously registered node's types. */ @@ -426,7 +440,7 @@ export declare class LGraph { /** * Positions every node in a more readable manner */ - arrange(margin?: number,layout?: string): void; + arrange(margin?: number, layout?: string): void; /** * Returns the amount of time the graph has been running in milliseconds * @return number of milliseconds the graph has been running @@ -602,10 +616,10 @@ export type SerializedLGraphNode = { /** https://github.com/jagenjo/litegraph.js/blob/master/guides/README.md#lgraphnode */ export declare class LGraphNode { - onResize?: Function; + onResize?: Function; // Used in group node - setInnerNodes(nodes: LGraphNode[]); + setInnerNodes(nodes: LGraphNode[]); static title_color: string; static title: string; @@ -1054,8 +1068,8 @@ export declare class LGraphNode { } export type LGraphNodeConstructor = { - nodeData: any; // Used by group node. - new (): T; + nodeData: any; // Used by group node. + new(): T; }; export type SerializedLGraphGroup = { @@ -1257,10 +1271,10 @@ export declare class LGraphCanvas { /** Called by `LGraphCanvas.showSearchBox` */ onSearchBox: | (( - helper: Element, - value: string, - graphCanvas: LGraphCanvas - ) => string[]) + helper: Element, + value: string, + graphCanvas: LGraphCanvas + ) => string[]) | null; onSearchBoxSelection: | ((name: string, event: MouseEvent, graphCanvas: LGraphCanvas) => void) diff --git a/src/litegraph.js b/src/litegraph.js index 61d3b8aad..04362d7ce 100755 --- a/src/litegraph.js +++ b/src/litegraph.js @@ -6186,10 +6186,22 @@ LGraphNode.prototype.executeAction = function(action) } } - if (is_double_click && !this.read_only && this.allow_searchbox) { - this.showSearchBox(e); - e.preventDefault(); - e.stopPropagation(); + if (is_double_click && !this.read_only) { + if (this.allow_searchbox) { + this.showSearchBox(e); + e.preventDefault(); + e.stopPropagation(); + } + this.canvas.dispatchEvent(new CustomEvent( + "litegraph:canvas", + { + bubbles: true, + detail: { + type: "empty-double-click", + originalEvent: e, + } + }, + )); } clicking_canvas_bg = true; @@ -6756,9 +6768,7 @@ LGraphNode.prototype.executeAction = function(action) // look for a good slot this.connecting_node.connectByType(this.connecting_slot,node,connType); } - - }else if (this.connecting_input){ - + } else if (this.connecting_input) { var slot = this.isOverNodeOutput( node, e.canvasX, @@ -6772,22 +6782,34 @@ LGraphNode.prototype.executeAction = function(action) // look for a good slot this.connecting_node.connectByTypeOutput(this.connecting_slot,node,connType); } - } - - - //} - - }else{ - + } else { + const linkReleaseContext = this.connecting_output ? { + node_from: this.connecting_node, + slot_from: this.connecting_output, + type_filter_in: this.connecting_output.type + } : { + node_to: this.connecting_node, + slot_from: this.connecting_input, + type_filter_out: this.connecting_input.type + }; + + this.canvas.dispatchEvent(new CustomEvent( + "litegraph:canvas", { + bubbles: true, + detail: { + subType: "empty-release", + originalEvent: e, + linkReleaseContext, + }, + } + )); // add menu when releasing link in empty space if (LiteGraph.release_link_on_empty_shows_menu){ - if (e.shiftKey && this.allow_searchbox){ - if(this.connecting_output){ - this.showSearchBox(e,{node_from: this.connecting_node, slot_from: this.connecting_output, type_filter_in: this.connecting_output.type}); - }else if(this.connecting_input){ - this.showSearchBox(e,{node_to: this.connecting_node, slot_from: this.connecting_input, type_filter_out: this.connecting_input.type}); - } + if (e.shiftKey){ + if (this.allow_searchbox) { + this.showSearchBox(e, linkReleaseContext); + } }else{ if(this.connecting_output){ this.showConnectionMenu({nodeFrom: this.connecting_node, slotFrom: this.connecting_output, e: e});