panel-reactflow 0.3.0rc0__tar.gz → 0.3.1__tar.gz
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.
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/.github/workflows/build.yml +4 -4
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/.github/workflows/docs.yml +21 -5
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/.github/workflows/test.yml +6 -6
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/PKG-INFO +1 -1
- panel_reactflow-0.3.1/docs/assets/screenshots/examples/advanced.png +0 -0
- panel_reactflow-0.3.1/docs/assets/screenshots/examples/custom_editor.png +0 -0
- panel_reactflow-0.3.1/docs/assets/screenshots/examples/edge_editors.png +0 -0
- panel_reactflow-0.3.1/docs/assets/screenshots/examples/node_edge_instances.png +0 -0
- panel_reactflow-0.3.1/docs/assets/screenshots/examples/schema_types.png +0 -0
- panel_reactflow-0.3.1/docs/assets/screenshots/examples/simple.png +0 -0
- panel_reactflow-0.3.1/docs/assets/screenshots/examples/threejs_viewer.png +0 -0
- panel_reactflow-0.3.1/docs/assets/screenshots/examples/threejs_viewer_instances.png +0 -0
- panel_reactflow-0.3.1/docs/examples/advanced.md +12 -0
- panel_reactflow-0.3.1/docs/examples/custom-editor.md +12 -0
- panel_reactflow-0.3.1/docs/examples/edge-editors.md +12 -0
- panel_reactflow-0.3.1/docs/examples/index.md +64 -0
- panel_reactflow-0.3.1/docs/examples/node-edge-instances.md +12 -0
- panel_reactflow-0.3.1/docs/examples/schema-types.md +12 -0
- panel_reactflow-0.3.1/docs/examples/simple.md +11 -0
- panel_reactflow-0.3.1/docs/examples/threejs-viewer-instances.md +12 -0
- panel_reactflow-0.3.1/docs/examples/threejs-viewer.md +12 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/docs/how-to/define-nodes-edges.md +110 -3
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/docs/how-to/react-to-events.md +54 -2
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/docs/index.md +4 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/docs/releases.md +29 -0
- panel_reactflow-0.3.1/examples/node_edge_instances.py +138 -0
- panel_reactflow-0.3.1/examples/threejs_viewer_instances.py +335 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/pixi.lock +306 -305
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/src/panel_reactflow/__init__.py +4 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/src/panel_reactflow/base.py +756 -94
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/tests/test_api.py +341 -1
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/tests/test_core.py +40 -1
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/zensical.toml +11 -1
- panel_reactflow-0.3.0rc0/docs/examples.md +0 -13
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/.copier-answers.yml +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/.gitattributes +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/.github/CODEOWNERS +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/.github/dependabot.yml +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/.gitignore +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/.pre-commit-config.yaml +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/.prettierrc +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/LICENSE.txt +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/MANIFEST.in +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/README.md +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/docs/assets/logo.svg +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/docs/assets/screenshots/declare-types.png +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/docs/assets/screenshots/define-editors-edge.png +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/docs/assets/screenshots/define-editors-node.png +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/docs/assets/screenshots/define-nodes-edges.png +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/docs/assets/screenshots/embed-views-in-nodes.png +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/docs/assets/screenshots/quickstart.png +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/docs/assets/screenshots/react-to-events.png +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/docs/assets/screenshots/style-nodes-edges.png +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/docs/how-to/declare-types.md +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/docs/how-to/define-editors.md +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/docs/how-to/embed-views-in-nodes.md +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/docs/how-to/style-nodes-edges.md +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/docs/quickstart.md +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/docs/reference/panel_reactflow.md +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/examples/advanced.py +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/examples/custom_editor.py +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/examples/edge_editors.py +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/examples/schema_types.py +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/examples/simple.py +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/examples/threejs_viewer.py +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/hatch_build.py +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/pixi.toml +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/pyproject.toml +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/src/panel_reactflow/__version.py +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/src/panel_reactflow/dist/css/reactflow.css +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/src/panel_reactflow/dist/icons/gear.svg +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/src/panel_reactflow/dist/panel-reactflow.bundle.css +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/src/panel_reactflow/dist/panel-reactflow.bundle.js +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/src/panel_reactflow/models/reactflow.jsx +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/src/panel_reactflow/py.typed +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/src/panel_reactflow/schema.py +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/tests/__init__.py +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/tests/conftest.py +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/tests/ui/__init__.py +0 -0
- {panel_reactflow-0.3.0rc0 → panel_reactflow-0.3.1}/tests/ui/test_ui.py +0 -0
|
@@ -11,11 +11,11 @@ jobs:
|
|
|
11
11
|
build:
|
|
12
12
|
runs-on: ubuntu-latest
|
|
13
13
|
steps:
|
|
14
|
-
- uses: actions/checkout@
|
|
14
|
+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
15
15
|
with:
|
|
16
16
|
fetch-depth: 0
|
|
17
17
|
- name: Set up pixi
|
|
18
|
-
uses: prefix-dev/setup-pixi@
|
|
18
|
+
uses: prefix-dev/setup-pixi@a0af7a228712d6121d37aba47adf55c1332c9c2e # v0.9.4
|
|
19
19
|
with:
|
|
20
20
|
environments: build
|
|
21
21
|
- name: Build project
|
|
@@ -23,7 +23,7 @@ jobs:
|
|
|
23
23
|
- name: Check package
|
|
24
24
|
run: pixi run -e build check-wheel
|
|
25
25
|
- name: Upload package
|
|
26
|
-
uses: actions/upload-artifact@
|
|
26
|
+
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
|
27
27
|
with:
|
|
28
28
|
name: artifact
|
|
29
29
|
path: dist/*
|
|
@@ -37,7 +37,7 @@ jobs:
|
|
|
37
37
|
id-token: write
|
|
38
38
|
environment: pypi
|
|
39
39
|
steps:
|
|
40
|
-
- uses: actions/download-artifact@
|
|
40
|
+
- uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
|
|
41
41
|
with:
|
|
42
42
|
name: artifact
|
|
43
43
|
path: dist
|
|
@@ -43,23 +43,23 @@ jobs:
|
|
|
43
43
|
runs-on: ubuntu-latest
|
|
44
44
|
|
|
45
45
|
steps:
|
|
46
|
-
- uses: actions/checkout@
|
|
46
|
+
- uses: actions/checkout@v6
|
|
47
47
|
with:
|
|
48
48
|
fetch-depth: 0
|
|
49
49
|
- name: Set up Pixi
|
|
50
|
-
uses: prefix-dev/setup-pixi@
|
|
50
|
+
uses: prefix-dev/setup-pixi@a0af7a228712d6121d37aba47adf55c1332c9c2e # v0.9.4
|
|
51
51
|
with:
|
|
52
52
|
environments: docs
|
|
53
53
|
- name: Build documentation
|
|
54
54
|
run: pixi run -e docs docs-build
|
|
55
|
-
- uses: actions/upload-artifact@
|
|
55
|
+
- uses: actions/upload-artifact@v7
|
|
56
56
|
if: always()
|
|
57
57
|
with:
|
|
58
58
|
name: docs
|
|
59
59
|
if-no-files-found: error
|
|
60
60
|
path: builtdocs
|
|
61
61
|
- name: Upload artifact
|
|
62
|
-
uses: actions/upload-pages-artifact@
|
|
62
|
+
uses: actions/upload-pages-artifact@v4
|
|
63
63
|
with:
|
|
64
64
|
path: ./builtdocs
|
|
65
65
|
|
|
@@ -70,6 +70,22 @@ jobs:
|
|
|
70
70
|
runs-on: ubuntu-latest
|
|
71
71
|
needs: build
|
|
72
72
|
steps:
|
|
73
|
-
- name: Deploy
|
|
73
|
+
- name: Deploy dev
|
|
74
|
+
uses: peaceiris/actions-gh-pages@v4
|
|
75
|
+
# Dev site built on PRs
|
|
76
|
+
if: |
|
|
77
|
+
(github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository) ||
|
|
78
|
+
(github.event_name == 'workflow_dispatch' && github.event.inputs.target == 'dev') ||
|
|
79
|
+
(github.event_name == 'push' && (contains(steps.vars.outputs.tag, 'a') || contains(steps.vars.outputs.tag, 'b') || contains(steps.vars.outputs.tag, 'rc')))
|
|
80
|
+
with:
|
|
81
|
+
personal_token: ${{ secrets.HOLOVIZ_ACCESS_TOKEN }}
|
|
82
|
+
external_repository: holoviz-dev/panel-reactflow
|
|
83
|
+
publish_dir: ./builtdocs
|
|
84
|
+
force_orphan: true
|
|
85
|
+
- name: Deploy main
|
|
86
|
+
if: |
|
|
87
|
+
(github.event_name != 'pull_request') &&
|
|
88
|
+
((github.event_name == 'workflow_dispatch' && github.event.inputs.target == 'main') ||
|
|
89
|
+
(github.event_name == 'push' && !(contains(steps.vars.outputs.tag, 'a') || contains(steps.vars.outputs.tag, 'b') || contains(steps.vars.outputs.tag, 'rc'))))
|
|
74
90
|
id: deployment
|
|
75
91
|
uses: actions/deploy-pages@v4
|
|
@@ -20,7 +20,7 @@ jobs:
|
|
|
20
20
|
code_change: ${{ steps.filter.outputs.code }}
|
|
21
21
|
matrix: ${{ env.MATRIX }}
|
|
22
22
|
steps:
|
|
23
|
-
- uses: actions/checkout@
|
|
23
|
+
- uses: actions/checkout@v6
|
|
24
24
|
if: github.event_name != 'pull_request'
|
|
25
25
|
- name: Check for code changes
|
|
26
26
|
uses: dorny/paths-filter@v3
|
|
@@ -80,9 +80,9 @@ jobs:
|
|
|
80
80
|
needs: [setup, pixi_lock]
|
|
81
81
|
runs-on: "ubuntu-latest"
|
|
82
82
|
steps:
|
|
83
|
-
- uses: actions/checkout@
|
|
83
|
+
- uses: actions/checkout@v6
|
|
84
84
|
- name: Set up pixi
|
|
85
|
-
uses: prefix-dev/setup-pixi@v0.9.
|
|
85
|
+
uses: prefix-dev/setup-pixi@v0.9.4
|
|
86
86
|
- uses: holoviz-dev/holoviz_tasks/pre-commit@v0
|
|
87
87
|
- uses: pre-commit/action@v3.0.1
|
|
88
88
|
if: needs.setup.outputs.img_change == 'true'
|
|
@@ -111,11 +111,11 @@ jobs:
|
|
|
111
111
|
- windows-latest
|
|
112
112
|
steps:
|
|
113
113
|
- name: Checkout branch
|
|
114
|
-
uses: actions/checkout@
|
|
114
|
+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
115
115
|
with:
|
|
116
116
|
fetch-depth: 0
|
|
117
117
|
- name: Set up pixi
|
|
118
|
-
uses: prefix-dev/setup-pixi@
|
|
118
|
+
uses: prefix-dev/setup-pixi@a0af7a228712d6121d37aba47adf55c1332c9c2e # v0.9.4
|
|
119
119
|
with:
|
|
120
120
|
environments: ${{ matrix.environment }}
|
|
121
121
|
- name: Install repository
|
|
@@ -151,7 +151,7 @@ jobs:
|
|
|
151
151
|
echo "[run]\nconcurrency = greenlet" > .uicoveragerc
|
|
152
152
|
pixi run -e ${{ matrix.environment }} test-ui $COV --cov-config=.uicoveragerc $FAIL
|
|
153
153
|
- name: Upload UI Screenshots
|
|
154
|
-
uses: actions/upload-artifact@
|
|
154
|
+
uses: actions/upload-artifact@v7
|
|
155
155
|
if: always()
|
|
156
156
|
with:
|
|
157
157
|
name: ui_screenshots_${{ runner.os }}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: panel-reactflow
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: A Panel wrapper for the Reactflow JS library.
|
|
5
5
|
Project-URL: Homepage, https://github.com/panel-extensions/panel-reactflow
|
|
6
6
|
Project-URL: Source, https://github.com/panel-extensions/panel-reactflow
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Advanced
|
|
2
|
+
|
|
3
|
+
Schema-driven editor workflow with a custom node type, type stylesheets,
|
|
4
|
+
and top-panel event feedback.
|
|
5
|
+
|
|
6
|
+

|
|
7
|
+
|
|
8
|
+
## Source
|
|
9
|
+
|
|
10
|
+
```python
|
|
11
|
+
--8<-- "examples/advanced.py"
|
|
12
|
+
```
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Custom Editor
|
|
2
|
+
|
|
3
|
+
Registers a callable editor for `metric` nodes and pushes incremental updates
|
|
4
|
+
using `on_patch`.
|
|
5
|
+
|
|
6
|
+

|
|
7
|
+
|
|
8
|
+
## Source
|
|
9
|
+
|
|
10
|
+
```python
|
|
11
|
+
--8<-- "examples/custom_editor.py"
|
|
12
|
+
```
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Edge Editors
|
|
2
|
+
|
|
3
|
+
Shows schema-backed edge editing plus a custom callable edge editor for
|
|
4
|
+
specialized edge types.
|
|
5
|
+
|
|
6
|
+

|
|
7
|
+
|
|
8
|
+
## Source
|
|
9
|
+
|
|
10
|
+
```python
|
|
11
|
+
--8<-- "examples/edge_editors.py"
|
|
12
|
+
```
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Examples Gallery
|
|
2
|
+
|
|
3
|
+
Browse runnable examples from `examples/`. Each card links to a dedicated page
|
|
4
|
+
with a screenshot and full source code.
|
|
5
|
+
|
|
6
|
+
<div class="grid cards" markdown>
|
|
7
|
+
|
|
8
|
+
- 
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
**[Advanced](advanced.md)**
|
|
13
|
+
Schema-driven task nodes with event tracking.
|
|
14
|
+
|
|
15
|
+
- 
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
**[Custom Editor](custom-editor.md)**
|
|
20
|
+
Callable node editor with custom widgets.
|
|
21
|
+
|
|
22
|
+
- 
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
**[Edge Editors](edge-editors.md)**
|
|
27
|
+
Schema-backed and callable edge editors.
|
|
28
|
+
|
|
29
|
+
- 
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
**[Node/Edge Instances](node-edge-instances.md)**
|
|
34
|
+
Class-based nodes and edges with hooks.
|
|
35
|
+
|
|
36
|
+
- 
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
**[Schema Types](schema-types.md)**
|
|
41
|
+
Multiple node types, each with its own schema.
|
|
42
|
+
|
|
43
|
+
- 
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
**[Simple](simple.md)**
|
|
48
|
+
Minimal graph setup with top panel.
|
|
49
|
+
|
|
50
|
+
- 
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
**[ThreeJS Viewer](threejs-viewer.md)**
|
|
55
|
+
Graph-driven 3D cube viewer controls.
|
|
56
|
+
|
|
57
|
+
- 
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
**[ThreeJS Viewer (Instances)](threejs-viewer-instances.md)**
|
|
62
|
+
ThreeJS viewer with Node and Edge instances.
|
|
63
|
+
|
|
64
|
+
</div>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Node/Edge Instances
|
|
2
|
+
|
|
3
|
+
Uses `Node` and `Edge` subclasses for rich behavior, custom editors, and event
|
|
4
|
+
hooks while still rendering in a standard ReactFlow canvas.
|
|
5
|
+
|
|
6
|
+

|
|
7
|
+
|
|
8
|
+
## Source
|
|
9
|
+
|
|
10
|
+
```python
|
|
11
|
+
--8<-- "examples/node_edge_instances.py"
|
|
12
|
+
```
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Schema Types
|
|
2
|
+
|
|
3
|
+
Demonstrates multiple node types where each type contributes its own schema,
|
|
4
|
+
including both Param-derived and raw JSON Schema definitions.
|
|
5
|
+
|
|
6
|
+

|
|
7
|
+
|
|
8
|
+
## Source
|
|
9
|
+
|
|
10
|
+
```python
|
|
11
|
+
--8<-- "examples/schema_types.py"
|
|
12
|
+
```
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# ThreeJS Viewer (Instances)
|
|
2
|
+
|
|
3
|
+
The ThreeJS viewer example implemented with `Node` and `Edge` subclass
|
|
4
|
+
instances for object-oriented graph behavior.
|
|
5
|
+
|
|
6
|
+

|
|
7
|
+
|
|
8
|
+
## Source
|
|
9
|
+
|
|
10
|
+
```python
|
|
11
|
+
--8<-- "examples/threejs_viewer_instances.py"
|
|
12
|
+
```
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# ThreeJS Viewer
|
|
2
|
+
|
|
3
|
+
Interactive 3D cube rendering controlled through graph-connected parameter
|
|
4
|
+
nodes.
|
|
5
|
+
|
|
6
|
+

|
|
7
|
+
|
|
8
|
+
## Source
|
|
9
|
+
|
|
10
|
+
```python
|
|
11
|
+
--8<-- "examples/threejs_viewer.py"
|
|
12
|
+
```
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
Every graph in Panel-ReactFlow is built from two lists: **nodes** and
|
|
4
4
|
**edges**. Nodes represent entities on the canvas; edges represent
|
|
5
|
-
connections between them.
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
connections between them. Nodes can be plain dictionaries, `NodeSpec`
|
|
6
|
+
objects, or `Node` instances, so you can choose between lightweight payloads
|
|
7
|
+
and object-oriented node classes.
|
|
8
8
|
|
|
9
9
|
This guide covers how to create nodes and edges, use the helper dataclasses,
|
|
10
10
|
and update data after the graph is live.
|
|
@@ -104,6 +104,40 @@ nodes = [
|
|
|
104
104
|
|
|
105
105
|
---
|
|
106
106
|
|
|
107
|
+
## Define nodes as classes
|
|
108
|
+
|
|
109
|
+
Use `Node` when you want per-node Python state, event hooks, and optional
|
|
110
|
+
custom view/editor methods.
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
import panel as pn
|
|
114
|
+
from panel_reactflow import Node, ReactFlow
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
class JobNode(Node):
|
|
118
|
+
def __init__(self, **params):
|
|
119
|
+
super().__init__(type="job", data={"status": "idle"}, **params)
|
|
120
|
+
|
|
121
|
+
def __panel__(self):
|
|
122
|
+
return pn.pane.Markdown(f"**{self.label}**: {self.data.get('status')}")
|
|
123
|
+
|
|
124
|
+
def on_move(self, payload, flow):
|
|
125
|
+
print(f"{self.id} moved to {payload['position']}")
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
nodes = [
|
|
129
|
+
JobNode(id="j1", label="Fetch", position={"x": 0, "y": 0}),
|
|
130
|
+
JobNode(id="j2", label="Process", position={"x": 260, "y": 60}),
|
|
131
|
+
]
|
|
132
|
+
|
|
133
|
+
flow = ReactFlow(nodes=nodes)
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
`Node` instances stay as Python objects in `flow.nodes`; they are serialized
|
|
137
|
+
to dicts only when syncing to the frontend.
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
107
141
|
## Define edges
|
|
108
142
|
|
|
109
143
|
Edges link two nodes by their `id`. Use the top-level `label` for the
|
|
@@ -128,6 +162,79 @@ edges = [
|
|
|
128
162
|
|
|
129
163
|
---
|
|
130
164
|
|
|
165
|
+
## Define edges as classes
|
|
166
|
+
|
|
167
|
+
Use `Edge` when you want object-oriented edge state and edge-specific hooks or
|
|
168
|
+
editor logic.
|
|
169
|
+
|
|
170
|
+
```python
|
|
171
|
+
from panel_reactflow import Edge, ReactFlow
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
class FlowEdge(Edge):
|
|
175
|
+
def __init__(self, **params):
|
|
176
|
+
super().__init__(type="flow", data={"weight": 1.0}, **params)
|
|
177
|
+
|
|
178
|
+
def on_data_change(self, payload, flow):
|
|
179
|
+
print(f"{self.id} updated:", payload["patch"])
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
flow = ReactFlow(
|
|
183
|
+
nodes=[
|
|
184
|
+
{"id": "n1", "position": {"x": 0, "y": 0}, "data": {}},
|
|
185
|
+
{"id": "n2", "position": {"x": 260, "y": 60}, "data": {}},
|
|
186
|
+
],
|
|
187
|
+
edges=[FlowEdge(id="e1", source="n1", target="n2")],
|
|
188
|
+
)
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
`Edge` instances stay as Python objects in `flow.edges`; they are serialized
|
|
192
|
+
to dicts only when syncing to the frontend.
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## Data <-> parameter sync on `Node` and `Edge`
|
|
197
|
+
|
|
198
|
+
For class-based nodes/edges, Panel-ReactFlow supports two-way synchronization
|
|
199
|
+
between `data` and declared parameters.
|
|
200
|
+
|
|
201
|
+
### Which parameters are included?
|
|
202
|
+
|
|
203
|
+
Only subclass parameters with **explicit non-negative precedence**
|
|
204
|
+
(`precedence >= 0`) are treated as data fields.
|
|
205
|
+
|
|
206
|
+
```python
|
|
207
|
+
import param
|
|
208
|
+
from panel_reactflow import Node
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
class TaskNode(Node):
|
|
212
|
+
status = param.Selector(default="idle", objects=["idle", "running", "done"], precedence=0)
|
|
213
|
+
retries = param.Integer(default=0, precedence=0)
|
|
214
|
+
_internal_state = param.String(default="x", precedence=-1)
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
In this example:
|
|
218
|
+
|
|
219
|
+
- `status` and `retries` are included in `data`
|
|
220
|
+
- `_internal_state` is not included
|
|
221
|
+
|
|
222
|
+
### Sync behavior
|
|
223
|
+
|
|
224
|
+
- **Parameter -> data**: updating `node.status` or `edge.weight` triggers an
|
|
225
|
+
automatic data patch to the graph and frontend.
|
|
226
|
+
- **Data -> parameter**: incoming graph patches/sync updates write values back
|
|
227
|
+
onto matching parameters.
|
|
228
|
+
- **Schema generation**: if no explicit type schema is provided, these
|
|
229
|
+
included parameters are used to generate a JSON schema for editors.
|
|
230
|
+
|
|
231
|
+
### Editor implication
|
|
232
|
+
|
|
233
|
+
If your editor widgets are bound with `from_param(...)`, you usually do not
|
|
234
|
+
need manual `on_patch` watchers for those data parameters.
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
131
238
|
## Use the NodeSpec / EdgeSpec helpers
|
|
132
239
|
|
|
133
240
|
If you prefer a typed API, use the dataclass helpers. They validate fields
|
|
@@ -23,10 +23,10 @@ the `ReactFlow` instance as a second argument. You can also listen for
|
|
|
23
23
|
| `node_deleted` | A node is removed. | `node_id` |
|
|
24
24
|
| `node_moved` | A node is dragged to a new position. | `node_id`, `position` |
|
|
25
25
|
| `node_clicked` | A node is clicked (single click). | `node_id` |
|
|
26
|
-
| `node_data_changed` |
|
|
26
|
+
| `node_data_changed` | Node data is patched (via API, editor patch, or parameter-driven sync). | `node_id`, `patch` |
|
|
27
27
|
| `edge_added` | An edge is created (UI connect or API). | `edge` |
|
|
28
28
|
| `edge_deleted` | An edge is removed. | `edge_id` |
|
|
29
|
-
| `edge_data_changed` |
|
|
29
|
+
| `edge_data_changed` | Edge data is patched (via API, editor patch, or parameter-driven sync). | `edge_id`, `patch` |
|
|
30
30
|
| `selection_changed` | The active selection changes. | `nodes`, `edges` |
|
|
31
31
|
| `sync` | A batch sync from the frontend. | *(varies)* |
|
|
32
32
|
|
|
@@ -57,6 +57,58 @@ pn.Column(log, flow).servable()
|
|
|
57
57
|
|
|
58
58
|
---
|
|
59
59
|
|
|
60
|
+
## Handle events on `Node` classes
|
|
61
|
+
|
|
62
|
+
If you define nodes as `Node` subclasses, you can implement hooks directly on
|
|
63
|
+
the node instance:
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
from panel_reactflow import Node, ReactFlow
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class TaskNode(Node):
|
|
70
|
+
def on_event(self, payload, flow):
|
|
71
|
+
print("any node event:", payload["type"])
|
|
72
|
+
|
|
73
|
+
def on_delete(self, payload, flow):
|
|
74
|
+
print("deleted:", self.id)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
flow = ReactFlow(nodes=[TaskNode(id="t1", position={"x": 0, "y": 0}, data={})])
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Common hooks include `on_event` (wildcard), `on_add`, `on_move`, `on_click`,
|
|
81
|
+
`on_data_change`, and `on_delete`.
|
|
82
|
+
|
|
83
|
+
When a `Node` subclass parameter with `precedence >= 0` changes, it
|
|
84
|
+
automatically patches node data and will trigger `on_data_change`.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Handle events on `Edge` classes
|
|
89
|
+
|
|
90
|
+
`Edge` subclasses can handle edge lifecycle and patch events directly:
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
from panel_reactflow import Edge, ReactFlow
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class WeightedEdge(Edge):
|
|
97
|
+
def on_data_change(self, payload, flow):
|
|
98
|
+
print("edge patch:", payload["patch"])
|
|
99
|
+
|
|
100
|
+
def on_delete(self, payload, flow):
|
|
101
|
+
print("edge deleted:", self.id)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Common edge hooks include `on_event`, `on_add`, `on_data_change`,
|
|
105
|
+
`on_selection_changed`, and `on_delete`.
|
|
106
|
+
|
|
107
|
+
Likewise, changing an `Edge` subclass data parameter (`precedence >= 0`)
|
|
108
|
+
triggers `on_data_change` through the same data patch pipeline.
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
60
112
|
## Listen for all events
|
|
61
113
|
|
|
62
114
|
Use the wildcard `"*"` to receive every event. This is useful for
|
|
@@ -66,6 +66,10 @@ flow.servable()
|
|
|
66
66
|
- [Style Nodes & Edges](how-to/style-nodes-edges.md)
|
|
67
67
|
- [React to Events](how-to/react-to-events.md)
|
|
68
68
|
|
|
69
|
+
## Examples
|
|
70
|
+
|
|
71
|
+
- [Examples gallery](examples/index.md)
|
|
72
|
+
|
|
69
73
|
## Reference
|
|
70
74
|
|
|
71
75
|
- [API reference](reference/panel_reactflow.md)
|
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
# Release Notes
|
|
2
2
|
|
|
3
|
+
## Version 0.3.0
|
|
4
|
+
|
|
5
|
+
This release focuses on core graph-model capabilities, callback ergonomics,
|
|
6
|
+
rendering/styling improvements, and major documentation expansion.
|
|
7
|
+
|
|
8
|
+
### Highlights
|
|
9
|
+
|
|
10
|
+
- **Parameterized `Node`/`Edge` instances as first-class graph elements** —
|
|
11
|
+
`ReactFlow` now supports instance-based graph authoring with richer Python
|
|
12
|
+
object workflows, including improved serialization/sync behavior and expanded
|
|
13
|
+
API/core test coverage.
|
|
14
|
+
- **Event callback improvements** — `.on(...)` callbacks can now accept the
|
|
15
|
+
`ReactFlow` instance as a second argument and support async callbacks, making
|
|
16
|
+
app-level event handling significantly more flexible.
|
|
17
|
+
- **Rendering fixes for embedded views** — improved scaling and interaction
|
|
18
|
+
behavior when rendering figures inside nodes, including better handling of
|
|
19
|
+
drag/pan/scroll conflicts within embedded content.
|
|
20
|
+
- **Editor rendering robustness** — fixed node and edge editor rendering paths
|
|
21
|
+
so editors can render reliably even when no node `view` is defined.
|
|
22
|
+
- **Color mode and default node styling support** — added color-mode-aware
|
|
23
|
+
styling capabilities and refined baseline node CSS for better defaults out of
|
|
24
|
+
the box.
|
|
25
|
+
- **Expanded how-to documentation** — substantial updates to guides for
|
|
26
|
+
declaring types, defining nodes/edges, editors, embedding views, reacting to
|
|
27
|
+
events, and styling, with refreshed screenshots across the docs.
|
|
28
|
+
- **Examples overhaul in docs** — added an examples gallery with grid cards and
|
|
29
|
+
dedicated pages/screenshots for each example app, plus docs navigation
|
|
30
|
+
updates for easier discovery.
|
|
31
|
+
|
|
3
32
|
## Version 0.2.0
|
|
4
33
|
|
|
5
34
|
This release focuses on stronger typed graph specs, better node-view handling,
|