wip
This commit is contained in:
168
tp-flow-node.js
Normal file
168
tp-flow-node.js
Normal file
@@ -0,0 +1,168 @@
|
||||
/**
|
||||
@license
|
||||
Copyright (c) 2024 trading_peter
|
||||
This program is available under Apache License Version 2.0
|
||||
*/
|
||||
|
||||
import { LitElement, html, css } from 'lit';
|
||||
|
||||
// tp-flow-node.js
|
||||
export class TpFlowNode extends LitElement {
|
||||
static get styles() {
|
||||
return [
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
position: absolute;
|
||||
background: #2b2b2b;
|
||||
border-radius: 4px;
|
||||
color: #fff;
|
||||
min-width: 150px;
|
||||
}
|
||||
|
||||
.node-header {
|
||||
padding: 8px;
|
||||
background: #3b3b3b;
|
||||
border-bottom: 1px solid #4b4b4b;
|
||||
border-radius: 4px 4px 0 0;
|
||||
}
|
||||
|
||||
.node-body {
|
||||
display: grid;
|
||||
grid-template-columns: 20px 1fr 20px;
|
||||
}
|
||||
|
||||
.node-content {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.node-ports {
|
||||
justify-content: space-between;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.input-ports, .output-ports {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
align-items: flex-start;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
.output-ports {
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.port {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
background: #666;
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.port:hover {
|
||||
background: #888;
|
||||
}
|
||||
`
|
||||
];
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<div class="node-header">
|
||||
<slot name="title">${this.flowNodeType}</slot>
|
||||
</div>
|
||||
<div class="node-body">
|
||||
<div class="input-ports">
|
||||
${this.inputs.map((input, idx) => html`
|
||||
<div class="port"
|
||||
data-port-type="input"
|
||||
data-port-id="${idx}"
|
||||
data-port-name="${input.name}"
|
||||
@mousedown="${this._handlePortClick}">
|
||||
</div>
|
||||
`)}
|
||||
</div>
|
||||
|
||||
<div class="node-content">
|
||||
${this.renderNodeContent()}
|
||||
</div>
|
||||
|
||||
<div class="output-ports">
|
||||
${this.outputs.map((output, idx) => html`
|
||||
<div class="port"
|
||||
data-port-type="output"
|
||||
data-port-id="${idx}"
|
||||
data-port-name="${output.name}"
|
||||
@mousedown="${this._handlePortClick}">
|
||||
</div>
|
||||
`)}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
renderNodeContent() {
|
||||
console.warn('Your node should override the renderNodeContent method.');
|
||||
return null;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
flowNodeType: { type: String },
|
||||
inputs: { type: Array },
|
||||
outputs: { type: Array },
|
||||
x: { type: Number },
|
||||
y: { type: Number },
|
||||
data: { type: Object }
|
||||
};
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.flowNodeType = 'BaseNode';
|
||||
this.inputs = [];
|
||||
this.outputs = [];
|
||||
this.x = 0;
|
||||
this.y = 0;
|
||||
this.data = {};
|
||||
}
|
||||
|
||||
_handlePortClick(e) {
|
||||
e.stopPropagation(); // Prevents the event from getting caught by the panning action.
|
||||
|
||||
const portEl = e.target;
|
||||
const detail = {
|
||||
nodeId: this.id,
|
||||
portType: portEl.dataset.portType,
|
||||
portId: portEl.dataset.portId,
|
||||
portName: portEl.dataset.portName
|
||||
};
|
||||
|
||||
this.dispatchEvent(new CustomEvent('port-click', {
|
||||
detail,
|
||||
bubbles: true,
|
||||
composed: true
|
||||
}));
|
||||
}
|
||||
|
||||
// Method to export node data
|
||||
exportData() {
|
||||
return {
|
||||
id: this.id,
|
||||
type: this.flowNodeType,
|
||||
x: this.x,
|
||||
y: this.y,
|
||||
data: this.data
|
||||
};
|
||||
}
|
||||
|
||||
// Method to import node data
|
||||
importData(data) {
|
||||
this.id = data.id;
|
||||
this.x = data.x;
|
||||
this.y = data.y;
|
||||
this.data = data.data;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user