@ghchinoy/litflow 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +163 -0
- package/dist/index.d.ts +8 -0
- package/dist/lit-controls.d.ts +12 -0
- package/dist/lit-edge.d.ts +15 -0
- package/dist/lit-flow.d.ts +43 -0
- package/dist/lit-handle.d.ts +14 -0
- package/dist/lit-minimap.d.ts +17 -0
- package/dist/lit-node.d.ts +12 -0
- package/dist/litflow.js +1000 -0
- package/dist/litflow.js.map +1 -0
- package/dist/store.d.ts +22 -0
- package/dist/theme.d.ts +1 -0
- package/dist/theme.js +64 -0
- package/dist/theme.js.map +1 -0
- package/package.json +52 -0
- package/src/index.ts +8 -0
- package/src/lit-controls.ts +83 -0
- package/src/lit-edge.ts +48 -0
- package/src/lit-flow.ts +784 -0
- package/src/lit-handle.ts +71 -0
- package/src/lit-minimap.ts +161 -0
- package/src/lit-node.ts +40 -0
- package/src/store.ts +55 -0
- package/src/theme.ts +61 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 G. Hussain Chinoy
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# LitFlow: xyflow + Lit WebComponents
|
|
2
|
+
|
|
3
|
+
LitFlow is a demonstration and starter kit for using the [xyflow](https://xyflow.com/) core system with [Lit](https://lit.dev/) WebComponents. It provides a lightweight, framework-agnostic way to build node-based UIs.
|
|
4
|
+
|
|
5
|
+
## 🚀 Quick Start
|
|
6
|
+
|
|
7
|
+
### Prerequisites
|
|
8
|
+
- Node.js (v18+)
|
|
9
|
+
- npm or pnpm
|
|
10
|
+
|
|
11
|
+
### Installation
|
|
12
|
+
```bash
|
|
13
|
+
pnpm install
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
### Development
|
|
17
|
+
```bash
|
|
18
|
+
./start-server.sh
|
|
19
|
+
```
|
|
20
|
+
This will start the Vite development server and open the examples runner.
|
|
21
|
+
|
|
22
|
+
## 📖 Usage Guide
|
|
23
|
+
|
|
24
|
+
### 1. Installation
|
|
25
|
+
```bash
|
|
26
|
+
pnpm add @ghchinoy/litflow
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### 2. Basic Usage
|
|
30
|
+
Import the library in your main entry point to register the custom elements:
|
|
31
|
+
|
|
32
|
+
```javascript
|
|
33
|
+
import '@ghchinoy/litflow';
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Then use the `<lit-flow>` component in your HTML or framework template:
|
|
37
|
+
|
|
38
|
+
```html
|
|
39
|
+
<lit-flow id="my-flow" show-controls show-minimap show-grid="false"></lit-flow>
|
|
40
|
+
|
|
41
|
+
<script>
|
|
42
|
+
const flow = document.getElementById('my-flow');
|
|
43
|
+
|
|
44
|
+
// Interactivity controls
|
|
45
|
+
flow.nodesDraggable = false;
|
|
46
|
+
flow.panOnDrag = false;
|
|
47
|
+
flow.showGrid = false;
|
|
48
|
+
|
|
49
|
+
flow.nodes = [
|
|
50
|
+
{ id: '1', position: { x: 100, y: 100 }, data: { label: 'Hello' } },
|
|
51
|
+
{ id: '2', position: { x: 300, y: 100 }, data: { label: 'World' } }
|
|
52
|
+
];
|
|
53
|
+
|
|
54
|
+
flow.edges = [
|
|
55
|
+
{ id: 'e1-2', source: '1', target: '2' }
|
|
56
|
+
];
|
|
57
|
+
</script>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### 3. Interactivity & Display
|
|
61
|
+
You can control the flow's behavior using attributes or properties:
|
|
62
|
+
|
|
63
|
+
| Attribute | Property | Default | Description |
|
|
64
|
+
|-----------|----------|---------|-------------|
|
|
65
|
+
| `show-controls` | `showControls` | `false` | Show zoom/fit controls |
|
|
66
|
+
| `show-minimap` | `showMinimap` | `false` | Show the minimap |
|
|
67
|
+
| `show-grid` | `showGrid` | `true` | Show the background grid |
|
|
68
|
+
| `nodes-draggable` | `nodesDraggable` | `true` | Allow dragging nodes |
|
|
69
|
+
| `nodes-connectable` | `nodesConnectable` | `true` | Allow creating new edges |
|
|
70
|
+
| `pan-on-drag` | `panOnDrag` | `true` | Allow panning the canvas |
|
|
71
|
+
| `zoom-on-scroll` | `zoomOnScroll` | `true` | Allow zooming with mouse wheel |
|
|
72
|
+
|
|
73
|
+
### 4. Custom Nodes
|
|
74
|
+
To create a custom node, define a Lit component using **Light DOM** and register it with the flow:
|
|
75
|
+
|
|
76
|
+
```javascript
|
|
77
|
+
import { LitElement, html } from 'lit';
|
|
78
|
+
import { customElement } from 'lit/decorators.js';
|
|
79
|
+
|
|
80
|
+
@customElement('my-custom-node')
|
|
81
|
+
class MyNode extends LitElement {
|
|
82
|
+
createRenderRoot() { return this; } // Required for xyflow compatibility
|
|
83
|
+
render() {
|
|
84
|
+
return html`<div>${this.data.label}</div>`;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Register the type
|
|
89
|
+
const flow = document.querySelector('lit-flow');
|
|
90
|
+
flow.nodeTypes = {
|
|
91
|
+
...flow.nodeTypes,
|
|
92
|
+
'special': 'my-custom-node'
|
|
93
|
+
};
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### 4. Styling (Material 3)
|
|
97
|
+
LitFlow comes with a built-in Material 3 theme. You can import the design tokens and apply them to your flow:
|
|
98
|
+
|
|
99
|
+
```javascript
|
|
100
|
+
import { m3Tokens } from '@ghchinoy/litflow/theme';
|
|
101
|
+
|
|
102
|
+
// These tokens are automatically applied to <lit-flow>
|
|
103
|
+
// but you can also use them in your own custom nodes.
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## 🏗️ Architecture
|
|
107
|
+
|
|
108
|
+
LitFlow leverages `@xyflow/system`, the same headless core that powers React Flow and Svelte Flow.
|
|
109
|
+
|
|
110
|
+
- **`examples/`**: Contains various implementation examples.
|
|
111
|
+
- `examples/index.html`: The main entry point to browse examples.
|
|
112
|
+
- `examples/basic/`: A simple graph implementation.
|
|
113
|
+
- `examples/multiple-handles/`: Nodes with multiple input/output ports.
|
|
114
|
+
- `examples/dynamic-interactivity/`: Adding/removing nodes and edges at runtime.
|
|
115
|
+
- `examples/subflows/`: Nested nodes and parent-child relationships.
|
|
116
|
+
- **`<lit-flow>`**: The root component. It initializes the `XYPanZoom` instance for the viewport and manages the collection of nodes and edges.
|
|
117
|
+
- **`<lit-node>`**: A reactive Lit component for individual nodes. Uses **Light DOM** to ensure compatibility with xyflow's system utilities (like hit-testing).
|
|
118
|
+
- **`<lit-handle>`**: A connection port component. Also uses **Light DOM** to ensure discoverability during connection dragging.
|
|
119
|
+
- **`<lit-controls>`**: A UI overlay providing zoom and fit-view controls.
|
|
120
|
+
- **`<lit-minimap>`**: A live overview of the flow with viewport tracking.
|
|
121
|
+
- **`store.ts`**: A state container using `@lit-labs/signals` for fine-grained, high-performance reactivity.
|
|
122
|
+
|
|
123
|
+
## 🛠️ Key Features
|
|
124
|
+
- **Panning & Zooming**: Full support for viewport manipulation via d3-zoom (via xyflow).
|
|
125
|
+
- **Node Dragging**: Individual nodes can be dragged, with positions synced back to the state.
|
|
126
|
+
- **Manual Connections**: Drag-to-connect functionality between handles with a live connection line.
|
|
127
|
+
- **Controls & MiniMap**: Built-in utility components for navigation and overview.
|
|
128
|
+
- **Reactive Updates**: Powered by `@lit-labs/signals` for efficient, targeted re-renders.
|
|
129
|
+
- **Light DOM Architecture**: Optimized for `@xyflow/system` compatibility while maintaining Lit's reactive benefits.
|
|
130
|
+
- **Custom Node Support**: Easily build complex nodes with internal state and custom Lit templates.
|
|
131
|
+
|
|
132
|
+
## 📖 Documentation
|
|
133
|
+
- [Lit vs React for xyflow](./LIT_VS_REACT.md): A comparison of using Lit WebComponents vs React for building flow-based UIs.
|
|
134
|
+
- [Creating Custom Nodes](./CUSTOM_NODES.md): A primer on building complex, data-driven nodes in LitFlow.
|
|
135
|
+
- [GEMINI.md](./GEMINI.md): Project conventions and technical insights for AI agents.
|
|
136
|
+
|
|
137
|
+
## 🛠️ Development & Publishing
|
|
138
|
+
|
|
139
|
+
### Build
|
|
140
|
+
To build the library and generate type definitions:
|
|
141
|
+
```bash
|
|
142
|
+
pnpm run build
|
|
143
|
+
```
|
|
144
|
+
This will output the compiled files and types to the `dist/` directory.
|
|
145
|
+
|
|
146
|
+
### Publishing to npm
|
|
147
|
+
The package is published under the `@ghchinoy` scope. To publish a new version:
|
|
148
|
+
|
|
149
|
+
1. **Update the version**:
|
|
150
|
+
```bash
|
|
151
|
+
pnpm version patch # or minor, major
|
|
152
|
+
```
|
|
153
|
+
2. **Build the project**:
|
|
154
|
+
```bash
|
|
155
|
+
pnpm run build
|
|
156
|
+
```
|
|
157
|
+
3. **Publish**:
|
|
158
|
+
```bash
|
|
159
|
+
pnpm publish --access public
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## 🤝 Contributing
|
|
163
|
+
This project is an exploration of xyflow's headless capabilities. Feel free to open issues or submit PRs to improve the Lit integration!
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { LitElement } from 'lit';
|
|
2
|
+
import { type PanZoomInstance } from '@xyflow/system';
|
|
3
|
+
declare const LitControls_base: typeof LitElement;
|
|
4
|
+
export declare class LitControls extends LitControls_base {
|
|
5
|
+
static styles: import("lit").CSSResult;
|
|
6
|
+
panZoom?: PanZoomInstance;
|
|
7
|
+
private _zoomIn;
|
|
8
|
+
private _zoomOut;
|
|
9
|
+
private _fitView;
|
|
10
|
+
render(): import("lit").TemplateResult<1>;
|
|
11
|
+
}
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { LitElement } from 'lit';
|
|
2
|
+
import { Position } from '@xyflow/system';
|
|
3
|
+
declare const LitEdge_base: typeof LitElement;
|
|
4
|
+
export declare class LitEdge extends LitEdge_base {
|
|
5
|
+
static styles: import("lit").CSSResult;
|
|
6
|
+
sourceX: number;
|
|
7
|
+
sourceY: number;
|
|
8
|
+
targetX: number;
|
|
9
|
+
targetY: number;
|
|
10
|
+
sourcePosition: Position;
|
|
11
|
+
targetPosition: Position;
|
|
12
|
+
selected: boolean;
|
|
13
|
+
render(): import("lit").TemplateResult<2>;
|
|
14
|
+
}
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { LitElement } from 'lit';
|
|
2
|
+
import { type Viewport, type NodeBase } from '@xyflow/system';
|
|
3
|
+
import './lit-node';
|
|
4
|
+
import './lit-edge';
|
|
5
|
+
declare const LitFlow_base: typeof LitElement;
|
|
6
|
+
export declare class LitFlow extends LitFlow_base {
|
|
7
|
+
static styles: import("lit").CSSResult[];
|
|
8
|
+
_renderer?: HTMLElement;
|
|
9
|
+
_viewport?: HTMLElement;
|
|
10
|
+
private _panZoom?;
|
|
11
|
+
private _drags;
|
|
12
|
+
private _resizeObserver?;
|
|
13
|
+
private _state;
|
|
14
|
+
nodeTypes: Record<string, string>;
|
|
15
|
+
showControls: boolean;
|
|
16
|
+
showMinimap: boolean;
|
|
17
|
+
showGrid: boolean;
|
|
18
|
+
nodesDraggable: boolean;
|
|
19
|
+
nodesConnectable: boolean;
|
|
20
|
+
panOnDrag: boolean;
|
|
21
|
+
zoomOnScroll: boolean;
|
|
22
|
+
zoomOnPinch: boolean;
|
|
23
|
+
zoomOnDoubleClick: boolean;
|
|
24
|
+
private _width;
|
|
25
|
+
private _height;
|
|
26
|
+
set nodes(nodes: NodeBase[]);
|
|
27
|
+
get nodes(): NodeBase[];
|
|
28
|
+
set edges(edges: any[]);
|
|
29
|
+
get edges(): any[];
|
|
30
|
+
viewport: Viewport;
|
|
31
|
+
connectedCallback(): void;
|
|
32
|
+
disconnectedCallback(): void;
|
|
33
|
+
private _updateNodeDimensions;
|
|
34
|
+
private _selectNode;
|
|
35
|
+
firstUpdated(): void;
|
|
36
|
+
updated(changedProperties: Map<string, any>): void;
|
|
37
|
+
private _setupDrags;
|
|
38
|
+
private _renderEdge;
|
|
39
|
+
private _onHandlePointerDown;
|
|
40
|
+
private _renderConnectionLine;
|
|
41
|
+
render(): import("lit").TemplateResult;
|
|
42
|
+
}
|
|
43
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { LitElement } from 'lit';
|
|
2
|
+
import { Position } from '@xyflow/system';
|
|
3
|
+
export declare class LitHandle extends LitElement {
|
|
4
|
+
createRenderRoot(): this;
|
|
5
|
+
type: 'source' | 'target';
|
|
6
|
+
position: Position;
|
|
7
|
+
handleId?: string;
|
|
8
|
+
nodeId?: string;
|
|
9
|
+
constructor();
|
|
10
|
+
private _onPointerDown;
|
|
11
|
+
connectedCallback(): void;
|
|
12
|
+
updated(changedProperties: Map<string, any>): void;
|
|
13
|
+
render(): import("lit").TemplateResult<1>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { LitElement } from 'lit';
|
|
2
|
+
import { type PanZoomInstance, type InternalNodeBase, type Transform } from '@xyflow/system';
|
|
3
|
+
declare const LitMinimap_base: typeof LitElement;
|
|
4
|
+
export declare class LitMinimap extends LitMinimap_base {
|
|
5
|
+
static styles: import("lit").CSSResult;
|
|
6
|
+
panZoom?: PanZoomInstance;
|
|
7
|
+
nodeLookup: Map<string, InternalNodeBase>;
|
|
8
|
+
transform: Transform;
|
|
9
|
+
translateExtent: [[number, number], [number, number]];
|
|
10
|
+
width: number;
|
|
11
|
+
height: number;
|
|
12
|
+
private _minimapInstance?;
|
|
13
|
+
updated(changedProperties: Map<string, any>): void;
|
|
14
|
+
private _getBoundingRect;
|
|
15
|
+
render(): import("lit").TemplateResult<1>;
|
|
16
|
+
}
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { LitElement } from 'lit';
|
|
2
|
+
declare const LitNode_base: typeof LitElement;
|
|
3
|
+
export declare class LitNode extends LitNode_base {
|
|
4
|
+
createRenderRoot(): this;
|
|
5
|
+
label: string;
|
|
6
|
+
type: string;
|
|
7
|
+
data: any;
|
|
8
|
+
selected: boolean;
|
|
9
|
+
nodeId: string;
|
|
10
|
+
render(): import("lit").TemplateResult<1>;
|
|
11
|
+
}
|
|
12
|
+
export {};
|