jerosoler / Drawflow

Simple flow library 🖥️🖱️
https://jerosoler.github.io/Drawflow/
MIT License
4.41k stars 713 forks source link

Can drawflow use svelte components? #524

Open Crystal701 opened 1 year ago

Crystal701 commented 1 year ago

Hi. Is there anyway to use svelte component as the node itself?

jerosoler commented 1 year ago

Hi @Crystal701

Default no.

But I've been experimenting a bit with svelte's REPL. It must be said that I have not touched svelte.

But I managed to load a svelte node by overriding the "addNode" function.

REPL-URL: https://svelte.dev/repl/hello-world?version=3.50.1

Name file: "App.svelte" Code:

<script>
  import { onMount } from 'svelte';
    import Drawflow from 'drawflow'
    import MyElement from './Component2.svelte';
    //import styleDrawflow from 'drawflow/dist/drawflow.min.css'

    onMount(() => {

        var id = document.getElementById("drawflow");
        const editor = new Drawflow(id);

        editor.addNode = function(name, num_in, num_out, ele_pos_x, ele_pos_y, classoverride, data, html, typenode = false) {
                        if (this.useuuid) {
                            var newNodeId = this.getUuid();
                        } else {
                            var newNodeId = this.nodeId;
                        }
                        const parent = document.createElement('div');
                        parent.classList.add("parent-node");

                        const node = document.createElement('div');
                        node.innerHTML = "";
                        node.setAttribute("id", "node-"+newNodeId);
                        node.classList.add("drawflow-node");
                        if(classoverride != '') {
                            node.classList.add(...classoverride.split(' '));
                        }

                        const inputs = document.createElement('div');
                        inputs.classList.add("inputs");

                        const outputs = document.createElement('div');
                        outputs.classList.add("outputs");

                        const json_inputs = {}
                        for(var x = 0; x < num_in; x++) {
                            const input = document.createElement('div');
                            input.classList.add("input");
                            input.classList.add("input_"+(x+1));
                            json_inputs["input_"+(x+1)] = { "connections": []};
                            inputs.appendChild(input);
                        }

                        const json_outputs = {}
                        for(var x = 0; x < num_out; x++) {
                            const output = document.createElement('div');
                            output.classList.add("output");
                            output.classList.add("output_"+(x+1));
                            json_outputs["output_"+(x+1)] = { "connections": []};
                            outputs.appendChild(output);
                        }

                        const content = document.createElement('div');
                        content.classList.add("drawflow_content_node");
                        if(typenode === false) {
                            content.innerHTML = html;
                        } else if (typenode === true) {
                            content.appendChild(this.noderegister[html].html.cloneNode(true));

                        } else {
                            // SVELTE CODE
                            const wrapper = new this.noderegister[html].html({
                                target: content,
                            });
                            // SVELTE CODE
                        }

                        Object.entries(data).forEach(function (key, value) {
                            if(typeof key[1] === "object") {
                                insertObjectkeys(null, key[0], key[0]);
                            } else {
                                var elems = content.querySelectorAll('[df-'+key[0]+']');
                                    for(var i = 0; i < elems.length; i++) {
                                        elems[i].value = key[1];
                                        if(elems[i].isContentEditable) {
                                            elems[i].innerText = key[1];
                                        }
                                    }
                            }
                        })

                        function insertObjectkeys(object, name, completname) {
                            if(object === null) {
                                var object = data[name];
                            } else {
                                var object = object[name]
                            }
                            if(object !== null) {
                                Object.entries(object).forEach(function (key, value) {
                                    if(typeof key[1] === "object") {
                                        insertObjectkeys(object, key[0], completname+'-'+key[0]);
                                    } else {
                                        var elems = content.querySelectorAll('[df-'+completname+'-'+key[0]+']');
                                            for(var i = 0; i < elems.length; i++) {
                                                elems[i].value = key[1];
                                                if(elems[i].isContentEditable) {
                                                    elems[i].innerText = key[1];
                                                }
                                            }
                                    }
                                });
                            }
                        }
                        node.appendChild(inputs);
                        node.appendChild(content);
                        node.appendChild(outputs);
                        node.style.top = ele_pos_y + "px";
                        node.style.left = ele_pos_x + "px";
                        parent.appendChild(node);
                        this.precanvas.appendChild(parent);
                        var json = {
                            id: newNodeId,
                            name: name,
                            data: data,
                            class: classoverride,
                            html: html,
                            typenode: typenode,
                            inputs: json_inputs,
                            outputs: json_outputs,
                            pos_x: ele_pos_x,
                            pos_y: ele_pos_y,
                        }
                        this.drawflow.drawflow[this.module].data[newNodeId] = json;
                        this.dispatch('nodeCreated', newNodeId);
                        if (!this.useuuid) {
                            this.nodeId++;
                        }
                        return newNodeId;
                    }

        editor.start();

        // Normal HTML Node
        editor.addNode('test', 0, 1, 150, 300, 'test', {}, 'test');

        // Register Node
        editor.registerNode('testComponent', MyElement);
        // Use
        editor.addNode('github', 0, 1, 150, 300, 'github', {}, 'testComponent', 'svelte');

    })
</script>

<div id="drawflow" class="parent-drawflow"></div>

<style>
    #drawflow {
        position:relative;
        width: 600px;
        height: 400px;
        border: 1px solid red;
    }
</style>

Name file: "Component2.svelte" Code component:

<script>
    export let name = 'world';
</script>

<h1>Hello {name}!</h1>

And load component correctly without style.

image

I think it's the right way to load a component, it's out of the documentation: https://svelte.dev/docs#run-time-client-side-component-api-creating-a-component

The only thing I haven't been able to load is the drawflow style 'styleDrawflow', surely the REPL has limitations.

The code that has been overwritten would also have to be overwritten by the addNodeImport function. It is currently documented with // SVELTE CODE

Having never worked with svelte I don't know if it's the right way. I think so.

Here is someone who has already imported svelte, although I don't know if the components.