1- import { Group , Rect , Vector } from '@shopify/react-native-skia' ;
1+ import { Group , Rect } from '@shopify/react-native-skia' ;
22import { useCallback , useEffect , useMemo , useRef , useState } from 'react' ;
33import { useAnimatedReaction , useDerivedValue } from 'react-native-reanimated' ;
44
5- import { DEFAULT_ANIMATION_SETTINGS } from '@/constants/animations' ;
6- import {
7- ARROW_COMPONENT_SETTINGS ,
8- CURVED_EDGE_COMPONENT_SETTINGS ,
9- LABEL_COMPONENT_SETTINGS ,
10- STRAIGHT_EDGE_COMPONENT_SETTINGS ,
11- VERTEX_COMPONENT_SETTINGS
12- } from '@/constants/components' ;
13- import { RANDOM_PLACEMENT_SETTING } from '@/constants/placement' ;
145import { GraphEventsContextType } from '@/context/graphEvents' ;
156import { useGraphObserver } from '@/hooks' ;
167import {
17- AnimationSettingsWithDefaults ,
18- AnimationsSettings
19- } from '@/types/animations' ;
20- import { EdgeComponentProps } from '@/types/components' ;
21- import { Edge , Graph , Vertex } from '@/types/graphs' ;
8+ EdgeComponentProps ,
9+ GraphData ,
10+ GraphEdgeData ,
11+ GraphVertexData
12+ } from '@/types/components' ;
13+ import { Graph } from '@/types/graphs' ;
2214import {
2315 AnimatedBoundingRect ,
2416 AnimatedVector ,
2517 AnimatedVectorCoordinates ,
2618 BoundingRect
2719} from '@/types/layout' ;
2820import { GraphRenderers } from '@/types/renderer' ;
29- import {
30- DirectedEdgeSettings ,
31- GraphLayout ,
32- GraphSettings ,
33- GraphSettingsWithDefaults ,
34- RandomPlacementSettings
35- } from '@/types/settings' ;
36- import { GraphAnimationsSettingsWithDefaults } from '@/types/settings/animations' ;
21+ import { GraphSettings , GraphSettingsWithDefaults } from '@/types/settings' ;
3722import { animateVerticesToFinalPositions } from '@/utils/animations' ;
38- import { placeVertices } from '@/utils/placement' ;
23+ import {
24+ updateGraphEdgesData ,
25+ updateGraphRenderersWithDefaults ,
26+ updateGraphSettingsWithDefaults ,
27+ updateGraphVerticesData
28+ } from '@/utils/components' ;
29+ import { calcContainerBoundingRect , placeVertices } from '@/utils/placement' ;
3930
40- import DefaultEdgeArrowRenderer from './arrows/renderers/DefaultEdgeArrowRenderer' ;
41- import DefaultCurvedEdgeRenderer from './edges/curved/renderers/DefaultCurvedEdgeRenderer' ;
4231import EdgeComponent from './edges/EdgeComponent' ;
43- import DefaultStraightEdgeRenderer from './edges/straight/renderers/DefaultStraightEdgeRenderer' ;
44- import DefaultVertexRenderer from './vertices/renderers/DefaultVertexRenderer' ;
4532import VertexComponent from './vertices/VertexComponent' ;
4633
4734export type GraphComponentPrivateProps < V , E > = {
@@ -84,28 +71,11 @@ export default function GraphComponent<
8471 // GRAPH STATE
8572 // Vertices
8673 const [ verticesData , setVerticesData ] = useState <
87- Record <
88- string ,
89- {
90- vertex : Vertex < V , E > ;
91- targetPlacementPosition : Vector ;
92- animationSettings : AnimationSettingsWithDefaults ;
93- removed : boolean ;
94- }
95- >
74+ Record < string , GraphVertexData < V , E > >
9675 > ( { } ) ;
9776 // Edges
9877 const [ edgesData , setEdgesData ] = useState <
99- Record <
100- string ,
101- {
102- edge : Edge < E , V > ;
103- order : number ;
104- edgesCount : number ;
105- animationSettings : AnimationSettingsWithDefaults ;
106- removed : boolean ;
107- }
108- >
78+ Record < string , GraphEdgeData < E , V > >
10979 > ( { } ) ;
11080
11181 // ANIMATED VALUES
@@ -119,81 +89,25 @@ export default function GraphComponent<
11989 ) ;
12090
12191 const memoSettings = useMemo ( ( ) => {
122- const newSettings : GraphSettingsWithDefaults < V , E > = {
123- ...settings ,
124- placement : {
125- ...( RANDOM_PLACEMENT_SETTING as RandomPlacementSettings ) ,
126- ...settings ?. placement
127- } ,
128- components : {
129- ...settings ?. components ,
130- vertex : {
131- ...VERTEX_COMPONENT_SETTINGS ,
132- ...settings ?. components ?. vertex
133- } ,
134- edge : {
135- ...( settings ?. components ?. edge ?. type === 'curved'
136- ? CURVED_EDGE_COMPONENT_SETTINGS
137- : STRAIGHT_EDGE_COMPONENT_SETTINGS ) ,
138- ...settings ?. components ?. edge ,
139- ...( graph . isDirected ( )
140- ? {
141- arrow : {
142- ...ARROW_COMPONENT_SETTINGS ,
143- ...( settings ?. components ?. edge as DirectedEdgeSettings ) ?. arrow
144- }
145- }
146- : { } ) ,
147-
148- label : {
149- ...LABEL_COMPONENT_SETTINGS ,
150- ...settings ?. components ?. edge ?. label
151- }
152- }
153- } ,
154- animations : {
155- layout : {
156- ...DEFAULT_ANIMATION_SETTINGS ,
157- ...settings ?. animations ?. layout
158- } ,
159- vertices : {
160- ...DEFAULT_ANIMATION_SETTINGS ,
161- ...settings ?. animations ?. vertices
162- } ,
163- edges : {
164- ...DEFAULT_ANIMATION_SETTINGS ,
165- ...settings ?. animations ?. edges
166- }
167- }
168- } ;
92+ const newSettings : GraphSettingsWithDefaults < V , E > =
93+ updateGraphSettingsWithDefaults ( graph . isDirected ( ) , settings ) ;
16994
17095 graphEventsContext . setGraphSettings ( newSettings ) ;
17196
17297 return newSettings ;
17398 } , [ settings ] ) ;
17499
175100 const memoRenderers = useMemo (
176- ( ) => ( {
177- vertex : DefaultVertexRenderer ,
178- edge : {
179- arrow : graph . isDirected ( ) ? DefaultEdgeArrowRenderer : undefined ,
180- edge :
181- renderers ?. edge || settings ?. components ?. edge ?. type === 'curved'
182- ? DefaultCurvedEdgeRenderer
183- : DefaultStraightEdgeRenderer ,
184- label : renderers ?. label
185- }
186- } ) ,
187- [ graph , settings , renderers ]
101+ ( ) =>
102+ updateGraphRenderersWithDefaults (
103+ graph . isDirected ( ) ,
104+ memoSettings . components . edge . type ,
105+ renderers
106+ ) ,
107+ [ graph , memoSettings , renderers ]
188108 ) ;
189109
190- const memoGraphData = useMemo < {
191- vertices : Array < Vertex < V , E > > ;
192- edges : Array < Edge < E , V > > ;
193- layout : GraphLayout ;
194- animations : AnimationsSettings ;
195- defaultAnimations : GraphAnimationsSettingsWithDefaults ;
196- } > (
110+ const memoGraphData = useMemo < GraphData < V , E > > (
197111 ( ) => ( {
198112 ...graphData ,
199113 layout : placeVertices (
@@ -213,42 +127,12 @@ export default function GraphComponent<
213127
214128 useEffect ( ( ) => {
215129 // UPDATE VERTICES DATA
216- const newVerticesData = { ...verticesData } ;
217- // Add new vertices to vertex data
218- graphData . vertices . forEach ( vertex => {
219- const targetPlacementPosition =
220- memoGraphData . layout . verticesPositions [ vertex . key ] ;
221- if (
222- targetPlacementPosition &&
223- ( ! newVerticesData [ vertex . key ] || newVerticesData [ vertex . key ] ?. removed )
224- ) {
225- newVerticesData [ vertex . key ] = {
226- vertex,
227- animationSettings : {
228- ...memoGraphData . defaultAnimations . vertices ,
229- ...memoGraphData . animations . vertices [ vertex . key ]
230- } ,
231- targetPlacementPosition,
232- removed : false
233- } ;
234- }
235- } ) ;
236- // Mark vertices as removed if there were removed from the graph model
237- Object . keys ( newVerticesData ) . forEach ( key => {
238- if ( ! graph . hasVertex ( key ) ) {
239- newVerticesData [ key ] = {
240- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
241- ...newVerticesData [ key ] ! ,
242- removed : true ,
243- animationSettings : {
244- ...memoGraphData . defaultAnimations . vertices ,
245- ...memoGraphData . animations . vertices [ key ]
246- }
247- } ;
248- }
249- } ) ;
130+ const updatedVerticesData = updateGraphVerticesData (
131+ verticesData ,
132+ memoGraphData
133+ ) ;
250134 // Set new vertices graphData
251- setVerticesData ( newVerticesData ) ;
135+ setVerticesData ( updatedVerticesData ) ;
252136
253137 // Call onRender callback on the first render
254138 if ( isFirstRenderRef . current ) {
@@ -259,42 +143,9 @@ export default function GraphComponent<
259143
260144 useEffect ( ( ) => {
261145 // UPDATE EDGES DATA
262- // Add new edges to edges data
263- const newEdgesData = { ...edgesData } ;
264- graphData . orderedEdges . forEach ( ( { edge, order, edgesCount } ) => {
265- if (
266- ! newEdgesData [ edge . key ] ||
267- newEdgesData [ edge . key ] ?. removed ||
268- newEdgesData [ edge . key ] ?. edgesCount !== edgesCount
269- ) {
270- newEdgesData [ edge . key ] = {
271- edge,
272- order,
273- edgesCount,
274- removed : false ,
275- animationSettings : {
276- ...memoGraphData . defaultAnimations . edges ,
277- ...memoGraphData . animations . edges [ edge . key ]
278- }
279- } ;
280- }
281- } ) ;
282- // Mark edges as removed if there were removed from the graph model
283- Object . keys ( newEdgesData ) . forEach ( key => {
284- if ( ! graph . hasEdge ( key ) ) {
285- newEdgesData [ key ] = {
286- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
287- ...newEdgesData [ key ] ! ,
288- removed : true ,
289- animationSettings : {
290- ...memoGraphData . defaultAnimations . edges ,
291- ...memoGraphData . animations . edges [ key ]
292- }
293- } ;
294- }
295- } ) ;
146+ const updatedEdgesData = updateGraphEdgesData ( edgesData , memoGraphData ) ;
296147 // Set the new edges graphData
297- setEdgesData ( newEdgesData ) ;
148+ setEdgesData ( updatedEdgesData ) ;
298149 } , [ memoGraphData ] ) ;
299150
300151 useEffect ( ( ) => {
@@ -308,34 +159,29 @@ export default function GraphComponent<
308159 } , [ animatedEdgeLabelsPositions ] ) ;
309160
310161 useAnimatedReaction (
311- ( ) => ( { positions : animatedVerticesPositions } ) ,
162+ ( ) => ( {
163+ positions : Object . fromEntries (
164+ Object . entries ( animatedVerticesPositions ) . map ( ( [ key , coordinates ] ) => [
165+ key ,
166+ {
167+ x : coordinates . x . value ,
168+ y : coordinates . y . value
169+ }
170+ ] )
171+ )
172+ } ) ,
312173 ( { positions } ) => {
313- // Update the bounding rect on every vertex position change
314- let top = Infinity ;
315- let bottom = - Infinity ;
316- let left = Infinity ;
317- let right = - Infinity ;
318-
319- Object . values ( positions ) . forEach ( ( { x, y } ) => {
320- if ( x . value < left ) {
321- left = x . value ;
322- }
323- if ( x . value > right ) {
324- right = x . value ;
325- }
326- if ( y . value < top ) {
327- top = y . value ;
328- }
329- if ( y . value > bottom ) {
330- bottom = y . value ;
331- }
332- } ) ;
333-
334- const vertexRadius = memoSettings . components . vertex . radius ;
335- boundingRect . top . value = top - vertexRadius ;
336- boundingRect . bottom . value = bottom + vertexRadius ;
337- boundingRect . left . value = left - vertexRadius ;
338- boundingRect . right . value = right + vertexRadius ;
174+ Object . entries (
175+ calcContainerBoundingRect (
176+ positions ,
177+ // Padding near the edges of the container
178+ memoSettings . components . vertex . radius ,
179+ memoSettings . components . vertex . radius
180+ )
181+ ) . forEach (
182+ ( [ key , value ] ) =>
183+ ( boundingRect [ key as keyof AnimatedBoundingRect ] . value = value )
184+ ) ;
339185 }
340186 ) ;
341187
@@ -418,7 +264,9 @@ export default function GraphComponent<
418264 order,
419265 edgesCount,
420266 vertexRadius : memoSettings . components . vertex . radius ,
421- renderers : memoRenderers . edge ,
267+ edgeRenderer : memoRenderers . edge ,
268+ arrowRenderer : memoRenderers . arrow ,
269+ labelRenderer : memoRenderers . label ,
422270 settings : memoSettings . components . edge ,
423271 onRemove : handleEdgeRemove ,
424272 onLabelRender : handleEdgeLabelRender ,
0 commit comments