tp-flow-nodes/tp-flow-node.js

168 lines
3.6 KiB
JavaScript
Raw Normal View History

2024-12-18 21:27:29 +01:00
/**
@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;
}
}