import {type CSSResultGroup, html, type PropertyValues, unsafeCSS} from 'lit'; import {ifDefined} from 'lit/directives/if-defined.js'; import {property} from 'lit/decorators.js'; import ZincElement from '../../../../internal/zinc-element'; import ZnIcon from '../../../icon'; import {emptyDragImage, FLOW_TYPE_MIME} from '../../flow.types'; import styles from './flow-step.scss'; /** * @summary A draggable step in the ``, representing a registered node type. Drag * it onto the canvas (or a "+" slot) of a `` to add that step. * @documentation https://zinc.style/components/flow-step * @status experimental * @since 1.0 * * @dependency zn-icon * * @event flow-step-drag - Emitted on dragstart with `detail.type`, so the builder can preview the drop. * @event flow-step-drag-end - Emitted on dragend. * * @slot - The step's label. May also hold `` declarations (never displayed) * that drive the flow builder's built-in branch conditions editor. * * @csspart base - The row. */ export default class ZnFlowStep extends ZincElement { static styles: CSSResultGroup = unsafeCSS(styles); static dependencies = {'zn-icon': ZnIcon}; /** The node type id this item creates when dropped. */ @property() type: string; /** Display label; falls back to the slotted text. Also used as the node's label. */ @property() label: string; @property() icon: string; @property({attribute: 'icon-library'}) iconLibrary: string; @property() color: string; @property() description: string; /** JSON array of input ports — `""` for a trigger (no input), omit for a single default input. */ @property() inputs: string; /** JSON array of outputs (`"a"` or `{"id","label"}`), e.g. `'[{"id":"true","label":"TRUE"}]'`. Omit for one default output. */ @property() outputs: string; connectedCallback() { super.connectedCallback(); this.draggable = true; this.addEventListener('dragstart', this._onDragStart); this.addEventListener('dragend', this._onDragEnd); } disconnectedCallback() { this.removeEventListener('dragstart', this._onDragStart); this.removeEventListener('dragend', this._onDragEnd); super.disconnectedCallback(); } protected updated(changed: PropertyValues) { super.updated(changed); this.style.setProperty('--node-accent', this.color ?? 'rgb(var(--zn-color-primary))'); } private _onDragStart = (e: DragEvent) => { if (!e.dataTransfer || !this.type) return; e.dataTransfer.setData(FLOW_TYPE_MIME, this.type); e.dataTransfer.effectAllowed = 'copyMove'; // Hide the native drag image — the builder shows an in-canvas preview instead. e.dataTransfer.setDragImage(emptyDragImage(), 0, 0); this.dispatchEvent(new CustomEvent('flow-step-drag', { bubbles: true, composed: true, detail: {type: this.type} })); }; private _onDragEnd = () => { this.dispatchEvent(new CustomEvent('flow-step-drag-end', {bubbles: true, composed: true})); }; render() { return html` ${this.label ?? ''} `; } }