Skip to content

Commit 68f4fad

Browse files
authored
Merge pull request #287 from neo4j/add-more-buttons
Add more buttons + circular layout support
2 parents a721d01 + 86d6d75 commit 68f4fad

File tree

11 files changed

+8819
-8780
lines changed

11 files changed

+8819
-8780
lines changed

changelog.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
## New features
66

77
- Add convenience method `add_data` and `remove_data` to `GraphWidget`.
8+
- Added a selection button to the toolbar.
9+
- Added a layout button to the toolbar if `VG.render_widget` is used.
10+
- Support the new circular layout.
811

912
## Bug fixes
1013

@@ -13,5 +16,6 @@
1316
## Improvements
1417

1518
- Allow setting the theme manually in `VG.render(theme="light")` and `VG.render_widget(theme="dark")`.
19+
- `render` now allows to pass `layout` as a string as well. Previously expected to be a typed `neo4j_viz.Layout`.
1620

1721
## Other changes

js-applet/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@
3030
"@neo4j-ndl/base": "^4.7.1",
3131
"@neo4j-ndl/react": "^4.7.3",
3232
"@neo4j-ndl/react-graph": "^1.2.8",
33-
"@neo4j-nvl/base": "^1.0.0",
34-
"@neo4j-nvl/interaction-handlers": "^1.0.0",
35-
"@neo4j-nvl/react": "^1.0.0",
33+
"@neo4j-nvl/base": "^1.1.0",
34+
"@neo4j-nvl/interaction-handlers": "^1.1.0",
35+
"@neo4j-nvl/react": "^1.1.0",
3636
"@tanstack/react-table": "^8.20.5",
3737
"react": "^19.2.4",
3838
"react-dom": "^19.2.4"

js-applet/src/graph-widget.tsx

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {createRender, useModelState} from "@anywidget/react";
22
import "@neo4j-ndl/base/lib/neo4j-ds-styles.css";
3-
import {GraphVisualization} from "@neo4j-ndl/react-graph";
3+
import {Gesture, GraphVisualization} from "@neo4j-ndl/react-graph";
44
import type {Layout, NvlOptions} from "@neo4j-nvl/base";
55
import {useEffect, useMemo, useState} from "react";
66
import {
@@ -10,15 +10,17 @@ import {
1010
transformRelationships,
1111
} from "./data-transforms";
1212
import {GraphErrorBoundary} from "./graph-error-boundary";
13+
import {Divider, IconButtonArray} from "@neo4j-ndl/react";
1314

1415
export type Theme = "dark" | "light" | "auto";
1516

1617
export type GraphOptions = {
17-
layout?: Layout;
18+
layout: Layout;
1819
nvlOptions?: Partial<NvlOptions>;
1920
zoom?: number;
2021
pan?: { x: number; y: number };
2122
layoutOptions?: Record<string, unknown>;
23+
showLayoutButton: boolean;
2224
};
2325

2426
export type WidgetData = {
@@ -69,14 +71,18 @@ function GraphWidget() {
6971
const [nodes] = useModelState<WidgetData["nodes"]>("nodes");
7072
const [relationships] =
7173
useModelState<WidgetData["relationships"]>("relationships");
72-
const [options] = useModelState<WidgetData["options"]>("options");
74+
const [options, setOptions] = useModelState<WidgetData["options"]>("options");
7375
const [height] = useModelState<WidgetData["height"]>("height");
7476
const [width] = useModelState<WidgetData["width"]>("width");
7577
const [theme] = useModelState<WidgetData["theme"]>("theme");
78+
const [gesture, setGesture] = useState<Gesture>('box');
79+
const {layout, nvlOptions, zoom, pan, layoutOptions, showLayoutButton} = options ?? {};
80+
const setLayout = (layout: Layout) => {
81+
setOptions({...options, layout});
82+
}
7683

7784
useTheme(theme ?? "auto");
7885

79-
const {layout, nvlOptions, zoom, pan, layoutOptions} = options ?? {};
8086
const [neoNodes, neoRelationships] = useMemo(
8187
() => [
8288
transformNodes(nodes ?? []),
@@ -102,7 +108,10 @@ function GraphWidget() {
102108
<GraphVisualization
103109
nodes={neoNodes}
104110
rels={neoRelationships}
111+
gesture={gesture}
112+
setGesture={setGesture}
105113
layout={layout}
114+
setLayout={setLayout}
106115
nvlOptions={nvlOptionsWithoutWorkers}
107116
zoom={zoom}
108117
pan={pan}
@@ -114,6 +123,21 @@ function GraphWidget() {
114123
sidePanelWidth,
115124
children: <GraphVisualization.SingleSelectionSidePanelContents/>,
116125
}}
126+
bottomRightIsland={
127+
<IconButtonArray size="medium">
128+
<GraphVisualization.GestureSelectButton menuPlacement="top-end-bottom-end"/>
129+
<Divider orientation="horizontal"/>
130+
<GraphVisualization.ZoomInButton/>
131+
<GraphVisualization.ZoomOutButton/>
132+
<GraphVisualization.ZoomToFitButton/>
133+
{showLayoutButton && (
134+
<>
135+
<Divider orientation="horizontal"/>
136+
<GraphVisualization.LayoutSelectButton menuPlacement="top-end-bottom-end"/>
137+
</>
138+
)}
139+
</IconButtonArray>
140+
}
117141
/>
118142
</div>
119143
);

js-applet/yarn.lock

Lines changed: 63 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -810,22 +810,23 @@
810810
chroma-js "2.4.2"
811811

812812
"@neo4j-ndl/base@^4.7.1":
813-
version "4.9.0"
814-
resolved "https://registry.yarnpkg.com/@neo4j-ndl/base/-/base-4.9.0.tgz#f76dfa4bce5a3a7b5612842b1b2ca7ffe3705e60"
815-
integrity sha512-e6LK0H7uQj56F7lbTLTdQDlKgvCs8XE3I7zMx8Itt+qzMq5QNcHQ7OU7RU9x7w7EzNwWjeMBry3AT0PtMaCHHA==
813+
version "4.9.2"
814+
resolved "https://registry.yarnpkg.com/@neo4j-ndl/base/-/base-4.9.2.tgz#ab39ba2c64363f706d059ce916391eda31fad0df"
815+
integrity sha512-V7g8qzuhDRy8ACZkd69fxlglV8UaLBBWPPIgrL9wfDg0UhIHfF8nkotw2/VVqXdL/CujqkMF/kbpveDfK4b2MA==
816816

817817
"@neo4j-ndl/react-graph@^1.2.8":
818-
version "1.2.20"
819-
resolved "https://registry.yarnpkg.com/@neo4j-ndl/react-graph/-/react-graph-1.2.20.tgz#d8454b6014c57c77d582a441dd92a912398f2476"
820-
integrity sha512-ptLMNaKHcFDXZECZcVfSoZ4Xc7+mjGEs66SHrsrr4UboHelMAU9/lBQZIXXQ7grNg6cesHRJ2ULdU0E/Vnu0PQ==
818+
version "1.2.26"
819+
resolved "https://registry.yarnpkg.com/@neo4j-ndl/react-graph/-/react-graph-1.2.26.tgz#049ae139b4393302d1d571300f014712900af7b5"
820+
integrity sha512-khx+yF7LKBMuAakjiCKyxlD7JGQRU7B1nxjLUpy60G5Hpdskh/PR/DG9BP/UiYiYoIakuv5gB2eapsvkrMaHcA==
821821
dependencies:
822822
classnames "2.5.1"
823823
re-resizable "6.11.2"
824+
zod "^4.3.6"
824825

825826
"@neo4j-ndl/react@^4.7.3":
826-
version "4.9.2"
827-
resolved "https://registry.yarnpkg.com/@neo4j-ndl/react/-/react-4.9.2.tgz#c8ac8c88c5d176162383eba36ea8d8b84b84f0e6"
828-
integrity sha512-fFJagmWp1zPDmVO+2mJhxvrFmTYxYk6HrOE1bo+gN8mLyCxgYFTEc/6z3k81u/8I+Krn0iEuBMDf5Zd6MUChoQ==
827+
version "4.9.8"
828+
resolved "https://registry.yarnpkg.com/@neo4j-ndl/react/-/react-4.9.8.tgz#0b7bd396a0ae9f5a0f52c154c9d96ad66371ccd6"
829+
integrity sha512-Z0Li/GKwCoJiRhfIBf1sOyxp5kY4k1yDeEwZ4l2Ln8Ud70zKK1vSv2UscPSJKbI3bNxNqK8OUDUjxA8/Jkm34g==
829830
dependencies:
830831
"@dnd-kit/core" "6.3.1"
831832
"@dnd-kit/sortable" "10.0.0"
@@ -851,7 +852,7 @@
851852
tinycolor2 "1.6.0"
852853
usehooks-ts "3.1.1"
853854

854-
"@neo4j-nvl/base@1.1.0", "@neo4j-nvl/base@^1.0.0":
855+
"@neo4j-nvl/base@1.1.0", "@neo4j-nvl/base@^1.1.0":
855856
version "1.1.0"
856857
resolved "https://registry.yarnpkg.com/@neo4j-nvl/base/-/base-1.1.0.tgz#2699e6c7705a5ff0ce67169940aa3d7f5bfec6ed"
857858
integrity sha512-33n4hLIZXz2okmmscE1woLZgi7XlQUxKaHdRbUiBofQ/00MgR6U73+WKVt2N3MaGEqwLS9w74z8srJiOvFx+WA==
@@ -870,7 +871,7 @@
870871
tinycolor2 "1.6.0"
871872
uuid "8.3.2"
872873

873-
"@neo4j-nvl/interaction-handlers@1.1.0", "@neo4j-nvl/interaction-handlers@^1.0.0":
874+
"@neo4j-nvl/interaction-handlers@1.1.0", "@neo4j-nvl/interaction-handlers@^1.1.0":
874875
version "1.1.0"
875876
resolved "https://registry.yarnpkg.com/@neo4j-nvl/interaction-handlers/-/interaction-handlers-1.1.0.tgz#a2caea03d34b6c2e7d9ea558b30b61f300c49139"
876877
integrity sha512-t9PaPujIa6q1+Bze0uLZ2FzICKiYdlLu7xIHCvg3rsKtOcVU9UK16luZbui+ofDoyaxDCqwZ7JsFXk9bzxrAVA==
@@ -890,7 +891,7 @@
890891
cytoscape-cose-bilkent "4.1.0"
891892
graphlib "2.1.8"
892893

893-
"@neo4j-nvl/react@^1.0.0":
894+
"@neo4j-nvl/react@^1.1.0":
894895
version "1.1.0"
895896
resolved "https://registry.yarnpkg.com/@neo4j-nvl/react/-/react-1.1.0.tgz#139bb6581df2749f447f745004b50a09428de7a7"
896897
integrity sha512-eYQajX0fpKl9sUbxBbFmMgDifR9EKm6XNLIB2d7NATOrETUQWv+68LUN87jqqvSixfwWot2uaPxDyUiTF3wLVA==
@@ -2220,51 +2221,51 @@
22202221
resolved "https://registry.yarnpkg.com/@segment/isodate/-/isodate-1.0.3.tgz#f44e8202d5edd277ce822785239474b2c9411d4a"
22212222
integrity sha512-BtanDuvJqnACFkeeYje7pWULVv8RgZaqKHWwGFnL/g/TH/CcZjkIVTfGDp/MAxmilYHUkrX70SqwnYSTNEaN7A==
22222223

2223-
"@shikijs/core@3.22.0":
2224-
version "3.22.0"
2225-
resolved "https://registry.yarnpkg.com/@shikijs/core/-/core-3.22.0.tgz#9e9e8bd6d65b61fa74205a30491b921079996cdd"
2226-
integrity sha512-iAlTtSDDbJiRpvgL5ugKEATDtHdUVkqgHDm/gbD2ZS9c88mx7G1zSYjjOxp5Qa0eaW0MAQosFRmJSk354PRoQA==
2224+
"@shikijs/core@3.23.0":
2225+
version "3.23.0"
2226+
resolved "https://registry.yarnpkg.com/@shikijs/core/-/core-3.23.0.tgz#79248ec4ad3de4fd5c12993f5c30cb071ec04812"
2227+
integrity sha512-NSWQz0riNb67xthdm5br6lAkvpDJRTgB36fxlo37ZzM2yq0PQFFzbd8psqC2XMPgCzo1fW6cVi18+ArJ44wqgA==
22272228
dependencies:
2228-
"@shikijs/types" "3.22.0"
2229+
"@shikijs/types" "3.23.0"
22292230
"@shikijs/vscode-textmate" "^10.0.2"
22302231
"@types/hast" "^3.0.4"
22312232
hast-util-to-html "^9.0.5"
22322233

2233-
"@shikijs/engine-javascript@3.22.0":
2234-
version "3.22.0"
2235-
resolved "https://registry.yarnpkg.com/@shikijs/engine-javascript/-/engine-javascript-3.22.0.tgz#507f5cbb3e565268a35ee8aed42ff73016899e6d"
2236-
integrity sha512-jdKhfgW9CRtj3Tor0L7+yPwdG3CgP7W+ZEqSsojrMzCjD1e0IxIbwUMDDpYlVBlC08TACg4puwFGkZfLS+56Tw==
2234+
"@shikijs/engine-javascript@3.23.0":
2235+
version "3.23.0"
2236+
resolved "https://registry.yarnpkg.com/@shikijs/engine-javascript/-/engine-javascript-3.23.0.tgz#eae89a47913f486e5a05130d13b965c424c33b21"
2237+
integrity sha512-aHt9eiGFobmWR5uqJUViySI1bHMqrAgamWE1TYSUoftkAeCCAiGawPMwM+VCadylQtF4V3VNOZ5LmfItH5f3yA==
22372238
dependencies:
2238-
"@shikijs/types" "3.22.0"
2239+
"@shikijs/types" "3.23.0"
22392240
"@shikijs/vscode-textmate" "^10.0.2"
22402241
oniguruma-to-es "^4.3.4"
22412242

2242-
"@shikijs/engine-oniguruma@3.22.0":
2243-
version "3.22.0"
2244-
resolved "https://registry.yarnpkg.com/@shikijs/engine-oniguruma/-/engine-oniguruma-3.22.0.tgz#d16b66ed18470bc99f5026ec9f635695a10cb7f5"
2245-
integrity sha512-DyXsOG0vGtNtl7ygvabHd7Mt5EY8gCNqR9Y7Lpbbd/PbJvgWrqaKzH1JW6H6qFkuUa8aCxoiYVv8/YfFljiQxA==
2243+
"@shikijs/engine-oniguruma@3.23.0":
2244+
version "3.23.0"
2245+
resolved "https://registry.yarnpkg.com/@shikijs/engine-oniguruma/-/engine-oniguruma-3.23.0.tgz#789421048d66ac1b33613169d6d18b9cc6e340ed"
2246+
integrity sha512-1nWINwKXxKKLqPibT5f4pAFLej9oZzQTsby8942OTlsJzOBZ0MWKiwzMsd+jhzu8YPCHAswGnnN1YtQfirL35g==
22462247
dependencies:
2247-
"@shikijs/types" "3.22.0"
2248+
"@shikijs/types" "3.23.0"
22482249
"@shikijs/vscode-textmate" "^10.0.2"
22492250

2250-
"@shikijs/langs@3.22.0":
2251-
version "3.22.0"
2252-
resolved "https://registry.yarnpkg.com/@shikijs/langs/-/langs-3.22.0.tgz#949338647714b89314efbd333070b0c0263b232a"
2253-
integrity sha512-x/42TfhWmp6H00T6uwVrdTJGKgNdFbrEdhaDwSR5fd5zhQ1Q46bHq9EO61SCEWJR0HY7z2HNDMaBZp8JRmKiIA==
2251+
"@shikijs/langs@3.23.0":
2252+
version "3.23.0"
2253+
resolved "https://registry.yarnpkg.com/@shikijs/langs/-/langs-3.23.0.tgz#00959d8b16c7f671221ae79b3ad8cde7e6a5c112"
2254+
integrity sha512-2Ep4W3Re5aB1/62RSYQInK9mM3HsLeB91cHqznAJMuylqjzNVAVCMnNWRHFtcNHXsoNRayP9z1qj4Sq3nMqYXg==
22542255
dependencies:
2255-
"@shikijs/types" "3.22.0"
2256+
"@shikijs/types" "3.23.0"
22562257

2257-
"@shikijs/themes@3.22.0":
2258-
version "3.22.0"
2259-
resolved "https://registry.yarnpkg.com/@shikijs/themes/-/themes-3.22.0.tgz#0a316f0b1bda2dea378dd0c9d7e0a703f36af2c3"
2260-
integrity sha512-o+tlOKqsr6FE4+mYJG08tfCFDS+3CG20HbldXeVoyP+cYSUxDhrFf3GPjE60U55iOkkjbpY2uC3It/eeja35/g==
2258+
"@shikijs/themes@3.23.0":
2259+
version "3.23.0"
2260+
resolved "https://registry.yarnpkg.com/@shikijs/themes/-/themes-3.23.0.tgz#fd96ca5ad52639057995bc2093682884e1846f27"
2261+
integrity sha512-5qySYa1ZgAT18HR/ypENL9cUSGOeI2x+4IvYJu4JgVJdizn6kG4ia5Q1jDEOi7gTbN4RbuYtmHh0W3eccOrjMA==
22612262
dependencies:
2262-
"@shikijs/types" "3.22.0"
2263+
"@shikijs/types" "3.23.0"
22632264

2264-
"@shikijs/types@3.22.0":
2265-
version "3.22.0"
2266-
resolved "https://registry.yarnpkg.com/@shikijs/types/-/types-3.22.0.tgz#43fe92d163742424e794894cb27ce6ce1b4ca8a8"
2267-
integrity sha512-491iAekgKDBFE67z70Ok5a8KBMsQ2IJwOWw3us/7ffQkIBCyOQfm/aNwVMBUriP02QshIfgHCBSIYAl3u2eWjg==
2265+
"@shikijs/types@3.23.0":
2266+
version "3.23.0"
2267+
resolved "https://registry.yarnpkg.com/@shikijs/types/-/types-3.23.0.tgz#d441571a058641926018ae3de99866f39e5bbdf2"
2268+
integrity sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ==
22682269
dependencies:
22692270
"@shikijs/vscode-textmate" "^10.0.2"
22702271
"@types/hast" "^3.0.4"
@@ -2608,9 +2609,9 @@
26082609
integrity sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==
26092610

26102611
"@types/node@^25.2.3":
2611-
version "25.3.0"
2612-
resolved "https://registry.yarnpkg.com/@types/node/-/node-25.3.0.tgz#749b1bd4058e51b72e22bd41e9eab6ebd0180470"
2613-
integrity sha512-4K3bqJpXpqfg2XKGK9bpDTc6xO/xoUP/RBWS7AtRMug6zZFaRekiLzjVtAoZMquxoAbzBvy5nxQ7veS5eYzf8A==
2612+
version "25.3.2"
2613+
resolved "https://registry.yarnpkg.com/@types/node/-/node-25.3.2.tgz#cbc4b963e1b3503eb2bcf7c55bf48c95204918d1"
2614+
integrity sha512-RpV6r/ij22zRRdyBPcxDeKAzH43phWVKEjL2iksqo1Vz3CuBUrgmPpPhALKiRfU7OMCmeeO9vECBMsV0hMTG8Q==
26142615
dependencies:
26152616
undici-types "~7.18.0"
26162617

@@ -4183,9 +4184,9 @@ json5@^2.2.3:
41834184
integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==
41844185

41854186
katex@^0.16.0, katex@^0.16.22:
4186-
version "0.16.32"
4187-
resolved "https://registry.yarnpkg.com/katex/-/katex-0.16.32.tgz#4f0cbfb68db20f2ea333173c35e8e45d729a65fa"
4188-
integrity sha512-ac0FzkRJlpw4WyH3Zu/OgU9LmPKqjHr6O2BxfSrBt8uJ1BhvH2YK3oJ4ut/K+O+6qQt2MGpdbn0MrffVEnnUDQ==
4187+
version "0.16.33"
4188+
resolved "https://registry.yarnpkg.com/katex/-/katex-0.16.33.tgz#5cd5af2ddc1132fe6a710ae6604ec1f19fca9e91"
4189+
integrity sha512-q3N5u+1sY9Bu7T4nlXoiRBXWfwSefNGoKeOwekV+gw0cAXQlz2Ww6BLcmBxVDeXBMUDQv6fK5bcNaJLxob3ZQA==
41894190
dependencies:
41904191
commander "^8.3.0"
41914192

@@ -5488,16 +5489,16 @@ shell-quote@1.8.3:
54885489
integrity sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==
54895490

54905491
shiki@^3.12.2:
5491-
version "3.22.0"
5492-
resolved "https://registry.yarnpkg.com/shiki/-/shiki-3.22.0.tgz#3d590efee11feb75769354b1f64240915c3af827"
5493-
integrity sha512-LBnhsoYEe0Eou4e1VgJACes+O6S6QC0w71fCSp5Oya79inkwkm15gQ1UF6VtQ8j/taMDh79hAB49WUk8ALQW3g==
5494-
dependencies:
5495-
"@shikijs/core" "3.22.0"
5496-
"@shikijs/engine-javascript" "3.22.0"
5497-
"@shikijs/engine-oniguruma" "3.22.0"
5498-
"@shikijs/langs" "3.22.0"
5499-
"@shikijs/themes" "3.22.0"
5500-
"@shikijs/types" "3.22.0"
5492+
version "3.23.0"
5493+
resolved "https://registry.yarnpkg.com/shiki/-/shiki-3.23.0.tgz#fca5332195e3afd6c94b384103ae9671a29c7fb9"
5494+
integrity sha512-55Dj73uq9ZXL5zyeRPzHQsK7Nbyt6Y10k5s7OjuFZGMhpp4r/rsLBH0o/0fstIzX1Lep9VxefWljK/SKCzygIA==
5495+
dependencies:
5496+
"@shikijs/core" "3.23.0"
5497+
"@shikijs/engine-javascript" "3.23.0"
5498+
"@shikijs/engine-oniguruma" "3.23.0"
5499+
"@shikijs/langs" "3.23.0"
5500+
"@shikijs/themes" "3.23.0"
5501+
"@shikijs/types" "3.23.0"
55015502
"@shikijs/vscode-textmate" "^10.0.2"
55025503
"@types/hast" "^3.0.4"
55035504

@@ -6079,6 +6080,11 @@ yargs@17.7.2:
60796080
y18n "^5.0.5"
60806081
yargs-parser "^21.1.1"
60816082

6083+
zod@^4.3.6:
6084+
version "4.3.6"
6085+
resolved "https://registry.yarnpkg.com/zod/-/zod-4.3.6.tgz#89c56e0aa7d2b05107d894412227087885ab112a"
6086+
integrity sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==
6087+
60826088
zwitch@^2.0.0, zwitch@^2.0.4:
60836089
version "2.0.4"
60846090
resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-2.0.4.tgz#c827d4b0acb76fc3e685a4c6ec2902d51070e9d7"

python-wrapper/src/neo4j_viz/options.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ class Layout(str, Enum):
3434
The coordinate layout sets the position of each node based on the `x` and `y` properties of the node.
3535
"""
3636
GRID = "grid"
37+
"""
38+
A basic circular layout.
39+
"""
40+
CIRCULAR = "circular"
3741

3842

3943
@enum_tools.documentation.document_enum
@@ -161,6 +165,8 @@ class RenderOptions(BaseModel, extra="allow"):
161165
min_zoom: Optional[float] = Field(None, serialization_alias="minZoom", description="The minimum zoom level allowed")
162166
allow_dynamic_min_zoom: Optional[bool] = Field(None, serialization_alias="allowDynamicMinZoom")
163167

168+
show_layout_button: bool = False
169+
164170
@model_validator(mode="after")
165171
def check_layout_options_match(self) -> RenderOptions:
166172
if self.layout_options is None:
@@ -172,9 +178,6 @@ def check_layout_options_match(self) -> RenderOptions:
172178
raise ValueError("layout_options must be of type ForceDirectedLayoutOptions for force-directed layout")
173179
return self
174180

175-
def to_dict(self) -> dict[str, Any]:
176-
return self.model_dump(exclude_none=True, by_alias=True)
177-
178181
def to_js_options(self) -> dict[str, Any]:
179182
"""Convert render options to the JS-compatible format for the GraphVisualization component.
180183
@@ -197,6 +200,8 @@ def to_js_options(self) -> dict[str, Any]:
197200
result["layout"] = "free"
198201
case Layout.GRID:
199202
result["layout"] = "grid"
203+
case Layout.CIRCULAR:
204+
result["layout"] = "circular"
200205

201206
if self.layout_options is not None:
202207
result["layoutOptions"] = self.layout_options.model_dump(exclude_none=True)
@@ -219,6 +224,8 @@ def to_js_options(self) -> dict[str, Any]:
219224
if self.pan_X is not None or self.pan_Y is not None:
220225
result["pan"] = {"x": self.pan_X or 0, "y": self.pan_Y or 0}
221226

227+
result["showLayoutButton"] = self.show_layout_button
228+
222229
return result
223230

224231

0 commit comments

Comments
 (0)