diff --git a/docs/releases.md b/docs/releases.md index 061a1a8..0b76a57 100644 --- a/docs/releases.md +++ b/docs/releases.md @@ -1,5 +1,16 @@ # Release Notes +## Version 0.4.1 + +A small enhancement release adding viewport zoom controls. + +### Enhancements + +- **Zoom limits** — new `min_zoom` (default `0.5`) and `max_zoom` + (default `2`) parameters constrain how far the canvas can be zoomed + out and in, and can be updated at runtime + ([#69](https://github.com/panel-extensions/panel-reactflow/pull/69)). + ## Version 0.4.0 This release adds new interaction features, edge routing options, and diff --git a/pixi.toml b/pixi.toml index f402e4c..9c2b31e 100644 --- a/pixi.toml +++ b/pixi.toml @@ -5,8 +5,8 @@ platforms = ["osx-arm64", "osx-64", "linux-64", "win-64"] [tasks] postinstall = "pip install --no-build-isolation --no-deps --disable-pip-version-check -e ." -compile = { cmd = "panel compile panel_splitjs", env = { PYTHONPATH = "./src:$PYTHONPATH" } } -compile-dev = { cmd = "panel compile panel_splitjs --build-dir build --watch", env = { PYTHONPATH = "./src:$PYTHONPATH" } } +compile = { cmd = "panel compile panel_reactflow", env = { PYTHONPATH = "./src:$PYTHONPATH" } } +compile-dev = { cmd = "panel compile panel_reactflow --build-dir build --watch", env = { PYTHONPATH = "./src:$PYTHONPATH" } } pre-commit-install = "pre-commit install" pre-commit-run = "pre-commit run -a" diff --git a/src/panel_reactflow/base.py b/src/panel_reactflow/base.py index da3cc10..4cb7a01 100644 --- a/src/panel_reactflow/base.py +++ b/src/panel_reactflow/base.py @@ -1279,6 +1279,10 @@ class ReactFlow(ReactComponent): Allow users to delete selected nodes or edges using keyboard shortcuts. enable_multiselect : bool, default True Allow selecting multiple nodes/edges with modifier keys (Shift/Ctrl). + max_zoom : float, default 2 + Maximum zoom level the viewport can be zoomed in to. + min_zoom : float, default 0.5 + Minimum zoom level the viewport can be zoomed out to. selection : dict, default {"nodes": [], "edges": []} Current selection state with lists of selected node and edge IDs. Read-only; updated automatically when selection changes. @@ -1446,6 +1450,10 @@ class ReactFlow(ReactComponent): enable_multiselect = param.Boolean(default=True, doc="Allow multiselect with modifier key.") + max_zoom = param.Number(default=2, bounds=(0, None), inclusive_bounds=(False, True), doc="Maximum zoom level of the viewport.") + + min_zoom = param.Number(default=0.5, bounds=(0, None), inclusive_bounds=(False, True), doc="Minimum zoom level of the viewport.") + selection = param.Dict(default={"nodes": [], "edges": []}, doc="Derived selection state for node and edge ids.") show_minimap = param.Boolean(default=False, doc="Show the minimap overlay.") diff --git a/src/panel_reactflow/models/reactflow.jsx b/src/panel_reactflow/models/reactflow.jsx index 90d1dcf..0d292c8 100644 --- a/src/panel_reactflow/models/reactflow.jsx +++ b/src/panel_reactflow/models/reactflow.jsx @@ -266,6 +266,8 @@ function FlowInner({ enableConnect, enableDelete, enableMultiselect, + maxZoom, + minZoom, showMinimap, syncMode, debounceMs, @@ -530,6 +532,8 @@ function FlowInner({ elementsSelectable={editable} deleteKeyCode={enableDelete ? ["Backspace", "Delete"] : null} multiSelectionKeyCode={enableMultiselect ? "Shift" : null} + minZoom={minZoom} + maxZoom={maxZoom} fitView > @@ -556,6 +560,8 @@ export function render({ model, view }) { const [enableConnect] = model.useState("enable_connect"); const [enableDelete] = model.useState("enable_delete"); const [enableMultiselect] = model.useState("enable_multiselect"); + const [maxZoom] = model.useState("max_zoom"); + const [minZoom] = model.useState("min_zoom"); const [showMinimap] = model.useState("show_minimap"); const [viewport, setViewport] = model.useState("viewport"); const [contextMenuPosition] = model.useState("_context_menu_position"); @@ -743,6 +749,8 @@ export function render({ model, view }) { enableConnect={enableConnect} enableDelete={enableDelete} enableMultiselect={enableMultiselect} + maxZoom={maxZoom} + minZoom={minZoom} showMinimap={showMinimap} syncMode={syncMode} debounceMs={debounceMs}