reflex-gravityui-graph 0.1.0__py3-none-any.whl

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.
@@ -0,0 +1,93 @@
1
+ """reflex-gravityui-graph: a Reflex wrapper for @gravity-ui/graph.
2
+
3
+ Public API::
4
+
5
+ from reflex_gravityui_graph import graph_canvas, GravityGraph
6
+
7
+ # DDD value objects for building graph data:
8
+ from reflex_gravityui_graph import Block, Connection, Anchor, EAnchorType, GraphData
9
+
10
+ # Example/recipe helpers (reproduce the upstream Storybook stories):
11
+ from reflex_gravityui_graph import (
12
+ one_block, two_connected_blocks, colored_connections, block_with_anchors,
13
+ generate_layered_blocks, grouped_graph, default_settings, THEMES,
14
+ )
15
+ """
16
+
17
+ from typing import TYPE_CHECKING, Any
18
+
19
+ from .domain import (
20
+ DEFAULT_BLOCK_HEIGHT,
21
+ DEFAULT_BLOCK_IS,
22
+ DEFAULT_BLOCK_WIDTH,
23
+ Anchor,
24
+ Block,
25
+ Connection,
26
+ EAnchorType,
27
+ GraphData,
28
+ )
29
+ from .recipes import (
30
+ DARK_THEME,
31
+ LIGHT_THEME,
32
+ THEMES,
33
+ block_with_anchors,
34
+ colored_connections,
35
+ default_settings,
36
+ generate_layered_blocks,
37
+ grouped_graph,
38
+ one_block,
39
+ two_connected_blocks,
40
+ )
41
+
42
+ # The component layer (``graph.py``) imports Reflex. We expose it lazily via
43
+ # PEP 562 ``__getattr__`` so the pure-Python domain/recipe API stays importable
44
+ # and unit-testable without Reflex installed (NFR5). Reflex is only imported
45
+ # when one of these symbols is actually accessed.
46
+ _LAZY_COMPONENT_EXPORTS = {"GravityGraph", "graph_canvas", "GRAVITY_GRAPH_VERSION"}
47
+
48
+ if TYPE_CHECKING: # pragma: no cover - typing/IDE only
49
+ from .graph import ( # noqa: F401
50
+ GRAVITY_GRAPH_VERSION,
51
+ GravityGraph,
52
+ graph_canvas,
53
+ )
54
+
55
+
56
+ def __getattr__(name: str) -> Any:
57
+ """Lazily resolve the Reflex-dependent component exports (PEP 562)."""
58
+ if name in _LAZY_COMPONENT_EXPORTS:
59
+ from . import graph
60
+
61
+ return getattr(graph, name)
62
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
63
+
64
+
65
+ __version__ = "0.1.0"
66
+
67
+ __all__ = [
68
+ # Component
69
+ "GravityGraph",
70
+ "graph_canvas",
71
+ "GRAVITY_GRAPH_VERSION",
72
+ # Domain
73
+ "Anchor",
74
+ "Block",
75
+ "Connection",
76
+ "EAnchorType",
77
+ "GraphData",
78
+ "DEFAULT_BLOCK_IS",
79
+ "DEFAULT_BLOCK_WIDTH",
80
+ "DEFAULT_BLOCK_HEIGHT",
81
+ # Recipes
82
+ "default_settings",
83
+ "one_block",
84
+ "two_connected_blocks",
85
+ "colored_connections",
86
+ "block_with_anchors",
87
+ "generate_layered_blocks",
88
+ "grouped_graph",
89
+ "THEMES",
90
+ "LIGHT_THEME",
91
+ "DARK_THEME",
92
+ "__version__",
93
+ ]
@@ -0,0 +1,210 @@
1
+ """Domain value objects for @gravity-ui/graph entities (DDD).
2
+
3
+ These are framework-agnostic, immutable Python value objects that capture the
4
+ upstream entity shapes (``TBlock``, ``TConnection``, ``TAnchor``) and validate
5
+ their invariants in Python, so a misconfigured graph fails fast with a clear
6
+ message instead of silently rendering broken on Canvas. Each value object knows
7
+ how to serialize itself to the exact camelCase dict the library expects.
8
+
9
+ Typical use::
10
+
11
+ from reflex_gravityui_graph import Block, Connection, Anchor, EAnchorType
12
+
13
+ a = Block(id="a", x=0, y=0, name="A",
14
+ anchors=[Anchor(id="out", block_id="a", type=EAnchorType.OUT)])
15
+ b = Block(id="b", x=300, y=200, name="B",
16
+ anchors=[Anchor(id="in", block_id="b", type=EAnchorType.IN)])
17
+ edge = Connection(source_block_id="a", source_anchor_id="out",
18
+ target_block_id="b", target_anchor_id="in")
19
+
20
+ blocks = [a.to_dict(), b.to_dict()]
21
+ connections = [edge.to_dict()]
22
+ """
23
+
24
+ from __future__ import annotations
25
+
26
+ from dataclasses import dataclass, field
27
+ from enum import Enum
28
+ from typing import Any, Union
29
+
30
+ BlockId = Union[str, int]
31
+
32
+ # Default block discriminator. @gravity-ui/graph renders blocks whose ``is`` is
33
+ # not registered in ``settings.blockComponents`` with its built-in canvas block,
34
+ # so this default "just works" without registering a custom component.
35
+ DEFAULT_BLOCK_IS = "block-action"
36
+
37
+ # Library defaults for block geometry (constants.block.WIDTH / HEIGHT).
38
+ DEFAULT_BLOCK_WIDTH = 200
39
+ DEFAULT_BLOCK_HEIGHT = 160
40
+
41
+
42
+ class EAnchorType(str, Enum):
43
+ """Anchor direction, mirroring the upstream ``EAnchorType`` enum."""
44
+
45
+ IN = "IN"
46
+ OUT = "OUT"
47
+
48
+
49
+ @dataclass(frozen=True)
50
+ class Anchor:
51
+ """A connection point on a block (``TAnchor``).
52
+
53
+ ``index`` orders multiple anchors of the same ``type`` on a block (the
54
+ library auto-positions IN anchors on the left, OUT anchors on the right).
55
+ """
56
+
57
+ id: str
58
+ block_id: BlockId
59
+ type: Union[EAnchorType, str] = EAnchorType.OUT
60
+ index: int = 0
61
+
62
+ def __post_init__(self) -> None:
63
+ if not self.id:
64
+ raise ValueError("Anchor.id must be a non-empty string")
65
+ if self.index < 0:
66
+ raise ValueError(f"Anchor.index must be >= 0, got {self.index}")
67
+
68
+ def to_dict(self) -> dict[str, Any]:
69
+ anchor_type = (
70
+ self.type.value if isinstance(self.type, EAnchorType) else self.type
71
+ )
72
+ return {
73
+ "id": self.id,
74
+ "blockId": self.block_id,
75
+ "type": anchor_type,
76
+ "index": self.index,
77
+ }
78
+
79
+
80
+ @dataclass(frozen=True)
81
+ class Block:
82
+ """A graph node (``TBlock``).
83
+
84
+ The library requires ``id``, ``is``, ``x``, ``y``, ``width``, ``height`` and
85
+ ``name``; everything else is optional. ``is_`` maps to the upstream ``is``
86
+ discriminator (``is`` is a Python keyword, hence the trailing underscore).
87
+ """
88
+
89
+ id: BlockId
90
+ x: int = 0
91
+ y: int = 0
92
+ name: str = ""
93
+ is_: str = DEFAULT_BLOCK_IS
94
+ width: int = DEFAULT_BLOCK_WIDTH
95
+ height: int = DEFAULT_BLOCK_HEIGHT
96
+ selected: bool = False
97
+ group: str | None = None
98
+ anchors: list[Anchor] = field(default_factory=list)
99
+ meta: dict[str, Any] | None = None
100
+
101
+ def __post_init__(self) -> None:
102
+ if self.id is None or self.id == "":
103
+ raise ValueError("Block.id must be a non-empty id")
104
+ if self.width <= 0 or self.height <= 0:
105
+ raise ValueError(
106
+ f"Block {self.id!r} must have positive width/height, "
107
+ f"got {self.width}x{self.height}"
108
+ )
109
+
110
+ def to_dict(self) -> dict[str, Any]:
111
+ data: dict[str, Any] = {
112
+ "id": self.id,
113
+ "is": self.is_,
114
+ "x": self.x,
115
+ "y": self.y,
116
+ "width": self.width,
117
+ "height": self.height,
118
+ "name": self.name or str(self.id),
119
+ "selected": self.selected,
120
+ "anchors": [a.to_dict() for a in self.anchors],
121
+ }
122
+ if self.group is not None:
123
+ data["group"] = self.group
124
+ if self.meta is not None:
125
+ data["meta"] = self.meta
126
+ return data
127
+
128
+
129
+ @dataclass(frozen=True)
130
+ class Connection:
131
+ """A graph edge (``TConnection``).
132
+
133
+ Connect blocks directly (``source_block_id`` -> ``target_block_id``) or via
134
+ named anchors (``source_anchor_id`` / ``target_anchor_id``). Optional
135
+ ``label``, ``dashed`` and ``styles`` (e.g. ``{"selectedBackground": ...,
136
+ "dashes": [6, 4]}``) customize the rendered edge.
137
+ """
138
+
139
+ source_block_id: BlockId
140
+ target_block_id: BlockId
141
+ source_anchor_id: str | None = None
142
+ target_anchor_id: str | None = None
143
+ id: Union[str, int, None] = None
144
+ label: str | None = None
145
+ dashed: bool = False
146
+ selected: bool = False
147
+ styles: dict[str, Any] | None = None
148
+
149
+ def __post_init__(self) -> None:
150
+ if self.source_block_id is None or self.target_block_id is None:
151
+ raise ValueError(
152
+ "Connection requires both source_block_id and target_block_id"
153
+ )
154
+
155
+ def to_dict(self) -> dict[str, Any]:
156
+ data: dict[str, Any] = {
157
+ "sourceBlockId": self.source_block_id,
158
+ "targetBlockId": self.target_block_id,
159
+ }
160
+ if self.source_anchor_id is not None:
161
+ data["sourceAnchorId"] = self.source_anchor_id
162
+ if self.target_anchor_id is not None:
163
+ data["targetAnchorId"] = self.target_anchor_id
164
+ if self.id is not None:
165
+ data["id"] = self.id
166
+ if self.label is not None:
167
+ data["label"] = self.label
168
+ if self.dashed:
169
+ data["dashed"] = True
170
+ if self.selected:
171
+ data["selected"] = True
172
+ if self.styles is not None:
173
+ data["styles"] = self.styles
174
+ return data
175
+
176
+
177
+ @dataclass(frozen=True)
178
+ class GraphData:
179
+ """An aggregate of blocks + connections with validated referential integrity.
180
+
181
+ Use it to build a whole graph and emit the two props in one step::
182
+
183
+ data = GraphData(blocks=[...], connections=[...])
184
+ graph_canvas(blocks=data.blocks_payload(), connections=data.connections_payload())
185
+ """
186
+
187
+ blocks: list[Block] = field(default_factory=list)
188
+ connections: list[Connection] = field(default_factory=list)
189
+
190
+ def __post_init__(self) -> None:
191
+ ids = [b.id for b in self.blocks]
192
+ duplicates = {i for i in ids if ids.count(i) > 1}
193
+ if duplicates:
194
+ raise ValueError(f"Duplicate block ids: {sorted(map(str, duplicates))}")
195
+ known = set(ids)
196
+ for c in self.connections:
197
+ if c.source_block_id not in known:
198
+ raise ValueError(
199
+ f"Connection source {c.source_block_id!r} is not a known block"
200
+ )
201
+ if c.target_block_id not in known:
202
+ raise ValueError(
203
+ f"Connection target {c.target_block_id!r} is not a known block"
204
+ )
205
+
206
+ def blocks_payload(self) -> list[dict[str, Any]]:
207
+ return [b.to_dict() for b in self.blocks]
208
+
209
+ def connections_payload(self) -> list[dict[str, Any]]:
210
+ return [c.to_dict() for c in self.connections]
@@ -0,0 +1,146 @@
1
+ """A Reflex wrapper around @gravity-ui/graph.
2
+
3
+ `@gravity-ui/graph` (https://github.com/gravity-ui/graph) is a high-performance
4
+ graph / flowchart / node-editor visualization library. It renders the whole
5
+ graph on Canvas when zoomed out (fast for thousands of nodes) and swaps to
6
+ HTML/React for rich interactions when zoomed in.
7
+
8
+ The upstream React API is hook + imperative driven (``useGraph`` creates a
9
+ ``Graph`` instance, ``setEntities`` pushes nodes/edges, ``start`` runs the render
10
+ loop once attached). Reflex components cannot call React hooks directly, so this
11
+ package ships a small local JSX bridge (``graph_canvas.jsx``) that encapsulates
12
+ that lifecycle and exposes a flat, declarative prop surface. This module is the
13
+ Python side of that bridge.
14
+
15
+ Public API::
16
+
17
+ from reflex_gravityui_graph import graph_canvas
18
+
19
+ graph_canvas(
20
+ blocks=[{"id": "a", "is": "block-action", "x": 0, "y": 0,
21
+ "width": 120, "height": 120, "name": "A"}],
22
+ connections=[],
23
+ )
24
+ """
25
+
26
+ from __future__ import annotations
27
+
28
+ from typing import Any
29
+
30
+ import reflex as rx
31
+ from reflex.components.component import NoSSRComponent
32
+
33
+ # Pinned npm version for reproducible builds. Bump deliberately.
34
+ GRAVITY_GRAPH_VERSION = "@gravity-ui/graph@1.11.0"
35
+
36
+ # Copy the local JSX bridge into the compiled frontend's public dir, then import
37
+ # the bridge from there (same mechanism used for other JSX-bridge components).
38
+ _BRIDGE_PATH = rx.asset("./graph_canvas.jsx", shared=True)
39
+
40
+
41
+ def _payload_event_spec(payload: rx.Var[dict]) -> tuple[rx.Var[dict]]:
42
+ """Forward a single serializable payload dict to the event handler."""
43
+ return (payload,)
44
+
45
+
46
+ class GravityGraph(NoSSRComponent):
47
+ """A @gravity-ui/graph canvas, driven declaratively from Reflex.
48
+
49
+ The component is client-only: the engine touches ``window``/Canvas, so it is
50
+ a ``NoSSRComponent`` (Reflex emits a dynamic, SSR-disabled import). See
51
+ ``docs/sdd/02-architecture.md``.
52
+
53
+ Sizing: ``GraphCanvas`` fills its container, so give the component an
54
+ explicit height (e.g. ``height="600px"``) or pass ``style``.
55
+ """
56
+
57
+ # Import the local JSX bridge from the frontend public dir.
58
+ library = f"$/public{_BRIDGE_PATH}"
59
+
60
+ # Named export from the bridge.
61
+ tag = "GravityGraph"
62
+ is_default = False
63
+
64
+ # Ensure the real npm package lands in package.json with a pinned version.
65
+ lib_dependencies: list[str] = [GRAVITY_GRAPH_VERSION]
66
+
67
+ # ------------------------------------------------------------------ #
68
+ # Data props (plain, JSON-serializable)
69
+ # ------------------------------------------------------------------ #
70
+
71
+ # Blocks (nodes). Each dict uses upstream camelCase keys:
72
+ # ``id``, ``is``, ``x``, ``y``, ``width``, ``height``, ``name`` and the
73
+ # optional ``anchors``, ``selected``, ``group``, ``meta``.
74
+ blocks: rx.Var[list[dict[str, Any]]]
75
+
76
+ # Connections (edges). Each dict: ``sourceBlockId`` / ``targetBlockId`` and
77
+ # optional ``sourceAnchorId`` / ``targetAnchorId`` / ``id`` / ``label`` /
78
+ # ``styles`` / ``dashed`` / ``selected``.
79
+ connections: rx.Var[list[dict[str, Any]]]
80
+
81
+ # Graph settings (``TGraphSettingsConfig``): ``canDragCamera``,
82
+ # ``canZoomCamera``, ``canCreateNewConnections``, ``useBezierConnections``,
83
+ # ``bezierConnectionDirection``, ``showConnectionArrows``,
84
+ # ``showConnectionLabels``, ``useBlocksAnchors``, ``scaleFontSize``, ...
85
+ settings: rx.Var[dict[str, Any]]
86
+
87
+ # View colors (``RecursivePartial<TGraphColors>``): ``canvas``, ``block``,
88
+ # ``anchor``, ``connection``, ``selection``, ...
89
+ colors: rx.Var[dict[str, Any]]
90
+
91
+ # View constants (``RecursivePartial<TGraphConstants>``): ``system``,
92
+ # ``camera``, ``block``, ``connection``, ``text``.
93
+ constants: rx.Var[dict[str, Any]]
94
+
95
+ # Configuration name passed to the underlying graph instance.
96
+ config_name: rx.Var[str] # -> configName
97
+
98
+ # ------------------------------------------------------------------ #
99
+ # Lifecycle / camera props
100
+ # ------------------------------------------------------------------ #
101
+
102
+ # Start the render loop automatically once the canvas is attached.
103
+ auto_start: rx.Var[bool] # -> autoStart
104
+
105
+ # Fit the camera to the graph once attached.
106
+ zoom_on_start: rx.Var[bool] # -> zoomOnStart
107
+
108
+ # Zoom target: ``"center"``, a rect, or a list of block ids.
109
+ zoom_target: rx.Var[Any] # -> zoomTarget
110
+
111
+ # Padding (px) used when fitting the camera on start.
112
+ zoom_padding: rx.Var[int] # -> zoomPadding
113
+
114
+ # Render rich HTML/React block bodies at detailed zoom (default canvas-only).
115
+ render_html_blocks: rx.Var[bool] # -> renderHtmlBlocks
116
+
117
+ # ------------------------------------------------------------------ #
118
+ # Events (each forwards one serializable payload dict)
119
+ # ------------------------------------------------------------------ #
120
+
121
+ # ``{"added": [ids], "removed": [ids]}`` when the block selection changes.
122
+ on_block_selection_change: rx.EventHandler[_payload_event_spec]
123
+
124
+ # ``{"sourceBlockId", "targetBlockId", "sourceAnchorId", "targetAnchorId"}``
125
+ # when a new connection is drawn (requires ``canCreateNewConnections``).
126
+ on_connection_created: rx.EventHandler[_payload_event_spec]
127
+
128
+ # ``{"added": [ids], "removed": [ids]}`` when the connection selection changes.
129
+ on_connection_selection_change: rx.EventHandler[_payload_event_spec]
130
+
131
+ # ``{"x", "y", "scale"}`` whenever the camera pans/zooms.
132
+ on_camera_change: rx.EventHandler[_payload_event_spec]
133
+
134
+ # ``{"blockId", "x", "y"}`` when a block drag finishes.
135
+ on_block_drag_end: rx.EventHandler[_payload_event_spec]
136
+
137
+ # ``{"state"}`` on graph state transitions (e.g. ``"ATTACHED"``).
138
+ on_state_change: rx.EventHandler[_payload_event_spec]
139
+
140
+ # Reflex auto-converts snake_case prop names to camelCase, covering every
141
+ # prop above. Add entries only for names the heuristic would get wrong.
142
+ _rename_props: dict[str, str] = {}
143
+
144
+
145
+ # Convenience factory: ``graph_canvas(blocks=[...], connections=[...])``.
146
+ graph_canvas = GravityGraph.create
@@ -0,0 +1,123 @@
1
+ """Stub file for custom_components/reflex_gravityui_graph/graph.py"""
2
+
3
+ # ------------------- DO NOT EDIT ----------------------
4
+ # This file was generated by `reflex/utils/pyi_generator.py`!
5
+ # ------------------------------------------------------
6
+ from collections.abc import Mapping, Sequence
7
+ from typing import Any, Optional
8
+ from reflex_components_core.core.breakpoints import Breakpoints
9
+ from reflex_base.event import (
10
+ EventType,
11
+ PointerEventInfo,
12
+ )
13
+ from reflex_base.vars.base import Var
14
+ import reflex as rx
15
+ from reflex.components.component import NoSSRComponent
16
+
17
+ GRAVITY_GRAPH_VERSION = "@gravity-ui/graph@1.11.0"
18
+ _BRIDGE_PATH = rx.asset("./graph_canvas.jsx", shared=True)
19
+
20
+ class GravityGraph(NoSSRComponent):
21
+ @classmethod
22
+ def create(
23
+ cls,
24
+ *children,
25
+ blocks: Var[list[dict[str, Any]]] | list[dict[str, Any]] | None = None,
26
+ connections: Var[list[dict[str, Any]]] | list[dict[str, Any]] | None = None,
27
+ settings: Var[dict[str, Any]] | dict[str, Any] | None = None,
28
+ colors: Var[dict[str, Any]] | dict[str, Any] | None = None,
29
+ constants: Var[dict[str, Any]] | dict[str, Any] | None = None,
30
+ config_name: Var[str] | str | None = None,
31
+ auto_start: Var[bool] | bool | None = None,
32
+ zoom_on_start: Var[bool] | bool | None = None,
33
+ zoom_target: Any | Var[Any] | None = None,
34
+ zoom_padding: Var[int] | int | None = None,
35
+ render_html_blocks: Var[bool] | bool | None = None,
36
+ style: Sequence[Mapping[str, Any]]
37
+ | Mapping[str, Any]
38
+ | Var[Mapping[str, Any]]
39
+ | Breakpoints
40
+ | None = None,
41
+ key: Any | None = None,
42
+ id: Any | None = None,
43
+ ref: Var | None = None,
44
+ class_name: Any | None = None,
45
+ custom_attrs: dict[str, Any | Var] | None = None,
46
+ on_block_drag_end: Optional[EventType[()] | EventType[rx.Var[dict]]] = None,
47
+ on_block_selection_change: Optional[
48
+ EventType[()] | EventType[rx.Var[dict]]
49
+ ] = None,
50
+ on_blur: Optional[EventType[()]] = None,
51
+ on_camera_change: Optional[EventType[()] | EventType[rx.Var[dict]]] = None,
52
+ on_click: Optional[EventType[()] | EventType[PointerEventInfo]] = None,
53
+ on_connection_created: Optional[EventType[()] | EventType[rx.Var[dict]]] = None,
54
+ on_connection_selection_change: Optional[
55
+ EventType[()] | EventType[rx.Var[dict]]
56
+ ] = None,
57
+ on_context_menu: Optional[EventType[()] | EventType[PointerEventInfo]] = None,
58
+ on_double_click: Optional[EventType[()] | EventType[PointerEventInfo]] = None,
59
+ on_focus: Optional[EventType[()]] = None,
60
+ on_mount: Optional[EventType[()]] = None,
61
+ on_mouse_down: Optional[EventType[()]] = None,
62
+ on_mouse_enter: Optional[EventType[()]] = None,
63
+ on_mouse_leave: Optional[EventType[()]] = None,
64
+ on_mouse_move: Optional[EventType[()]] = None,
65
+ on_mouse_out: Optional[EventType[()]] = None,
66
+ on_mouse_over: Optional[EventType[()]] = None,
67
+ on_mouse_up: Optional[EventType[()]] = None,
68
+ on_scroll: Optional[EventType[()]] = None,
69
+ on_scroll_end: Optional[EventType[()]] = None,
70
+ on_state_change: Optional[EventType[()] | EventType[rx.Var[dict]]] = None,
71
+ on_unmount: Optional[EventType[()]] = None,
72
+ **props,
73
+ ) -> "GravityGraph":
74
+ """Create the component.
75
+
76
+ Args:
77
+ *children: The children of the component.
78
+ blocks: Blocks (nodes). Each dict uses upstream camelCase keys: ``id``, ``is``, ``x``, ``y``, ``width``, ``height``, ``name`` and the optional ``anchors``, ``selected``, ``group``, ``meta``.
79
+ connections: Connections (edges). Each dict: ``sourceBlockId`` / ``targetBlockId`` and optional ``sourceAnchorId`` / ``targetAnchorId`` / ``id`` / ``label`` / ``styles`` / ``dashed`` / ``selected``.
80
+ settings: Graph settings (``TGraphSettingsConfig``): ``canDragCamera``, ``canZoomCamera``, ``canCreateNewConnections``, ``useBezierConnections``, ``bezierConnectionDirection``, ``showConnectionArrows``, ``showConnectionLabels``, ``useBlocksAnchors``, ``scaleFontSize``, ...
81
+ colors: View colors (``RecursivePartial<TGraphColors>``): ``canvas``, ``block``, ``anchor``, ``connection``, ``selection``, ...
82
+ constants: View constants (``RecursivePartial<TGraphConstants>``): ``system``, ``camera``, ``block``, ``connection``, ``text``.
83
+ config_name: Configuration name passed to the underlying graph instance.
84
+ auto_start: Start the render loop automatically once the canvas is attached.
85
+ zoom_on_start: Fit the camera to the graph once attached.
86
+ zoom_target: Zoom target: ``"center"``, a rect, or a list of block ids.
87
+ zoom_padding: Padding (px) used when fitting the camera on start.
88
+ render_html_blocks: Render rich HTML/React block bodies at detailed zoom (default canvas-only).
89
+ style: The style of the component.
90
+ key: A unique key for the component.
91
+ id: The id for the component.
92
+ ref: The Var to pass as the ref to the component.
93
+ class_name: The class name for the component.
94
+ custom_attrs: Attributes passed directly to the component.
95
+ on_focus: Fired when the element (or some element inside of it) receives focus. For example, it is called when the user clicks on a text input.
96
+ on_blur: Fired when focus has left the element (or left some element inside of it). For example, it is called when the user clicks outside of a focused text input.
97
+ on_click: Fired when the user clicks on an element. For example, it's called when the user clicks on a button.
98
+ on_context_menu: Fired when the user right-clicks on an element.
99
+ on_double_click: Fired when the user double-clicks on an element.
100
+ on_mouse_down: Fired when the user presses a mouse button on an element.
101
+ on_mouse_enter: Fired when the mouse pointer enters the element.
102
+ on_mouse_leave: Fired when the mouse pointer leaves the element.
103
+ on_mouse_move: Fired when the mouse pointer moves over the element.
104
+ on_mouse_out: Fired when the mouse pointer moves out of the element.
105
+ on_mouse_over: Fired when the mouse pointer moves onto the element.
106
+ on_mouse_up: Fired when the user releases a mouse button on an element.
107
+ on_scroll: Fired when the user scrolls the element.
108
+ on_scroll_end: Fired when scrolling ends on the element.
109
+ on_mount: Fired when the component is mounted to the page.
110
+ on_unmount: Fired when the component is removed from the page. Only called during navigation, not on page refresh.
111
+ on_block_selection_change: ``{"added": [ids], "removed": [ids]}`` when the block selection changes.
112
+ on_connection_created: ``{"sourceBlockId", "targetBlockId", "sourceAnchorId", "targetAnchorId"}`` when a new connection is drawn (requires ``canCreateNewConnections``).
113
+ on_connection_selection_change: ``{"added": [ids], "removed": [ids]}`` when the connection selection changes.
114
+ on_camera_change: ``{"x", "y", "scale"}`` whenever the camera pans/zooms.
115
+ on_block_drag_end: ``{"blockId", "x", "y"}`` when a block drag finishes.
116
+ on_state_change: ``{"state"}`` on graph state transitions (e.g. ``"ATTACHED"``).
117
+ **props: The props of the component.
118
+
119
+ Returns:
120
+ The component."""
121
+ ...
122
+
123
+ graph_canvas = GravityGraph.create