@xyo-network/react-node-renderer 7.5.7 → 7.5.11
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.
- package/dist/browser/Cytoscape/CytoscapeElements.d.ts +2 -6
- package/dist/browser/Cytoscape/CytoscapeElements.d.ts.map +1 -1
- package/dist/browser/components/module/graph/Popper.d.ts +3 -2
- package/dist/browser/components/module/graph/Popper.d.ts.map +1 -1
- package/dist/browser/components/module/graph/node/hooks/useNodeElement.d.ts +8 -5
- package/dist/browser/components/module/graph/node/hooks/useNodeElement.d.ts.map +1 -1
- package/dist/browser/components/relational/graph/Graph.d.ts.map +1 -1
- package/dist/browser/hooks/cytoscape/elements/useRenderNewElements.d.ts +1 -1
- package/dist/browser/hooks/cytoscape/elements/useRenderNewElements.d.ts.map +1 -1
- package/dist/browser/index.mjs +362 -423
- package/dist/browser/index.mjs.map +1 -1
- package/package.json +188 -59
- package/src/Cytoscape/CytoscapeElements.ts +0 -96
- package/src/Cytoscape/CytoscapeIcons.tsx +0 -23
- package/src/Cytoscape/CytoscapeStyles.ts +0 -46
- package/src/Cytoscape/index.ts +0 -4
- package/src/Cytoscape/lib/CyNodeModuleTypes.ts +0 -1
- package/src/Cytoscape/lib/encodeSvg.ts +0 -19
- package/src/Cytoscape/lib/iconMap.ts +0 -12
- package/src/Cytoscape/lib/index.ts +0 -5
- package/src/Cytoscape/lib/layout/ColaLayout.ts +0 -5
- package/src/Cytoscape/lib/layout/ConcentricLayout.ts +0 -12
- package/src/Cytoscape/lib/layout/index.ts +0 -2
- package/src/Cytoscape/lib/parseModuleType.ts +0 -29
- package/src/components/cytoscape-extensions/WithExtensions.tsx +0 -16
- package/src/components/cytoscape-extensions/index.ts +0 -1
- package/src/components/index.ts +0 -3
- package/src/components/lib/RelationalGraphProps.ts +0 -16
- package/src/components/lib/index.ts +0 -1
- package/src/components/module/CardParser.stories.tsx +0 -36
- package/src/components/module/CardParser.tsx +0 -24
- package/src/components/module/graph/DetailsFlexbox.tsx +0 -22
- package/src/components/module/graph/GraphFlexBox.stories.tsx +0 -118
- package/src/components/module/graph/GraphFlexBox.tsx +0 -84
- package/src/components/module/graph/Popper.tsx +0 -77
- package/src/components/module/graph/index.ts +0 -1
- package/src/components/module/graph/node/Hover.tsx +0 -38
- package/src/components/module/graph/node/hooks/index.ts +0 -1
- package/src/components/module/graph/node/hooks/useNodeElement.tsx +0 -41
- package/src/components/module/graph/node/index.ts +0 -1
- package/src/components/module/index.ts +0 -2
- package/src/components/relational/graph/Graph.stories.tsx +0 -201
- package/src/components/relational/graph/Graph.tsx +0 -200
- package/src/components/relational/graph/GraphCola.stories.tsx +0 -187
- package/src/components/relational/graph/GraphCoseBilkent.stories.tsx +0 -186
- package/src/components/relational/graph/GraphDagre.stories.tsx +0 -186
- package/src/components/relational/graph/GraphEuler.stories.tsx +0 -187
- package/src/components/relational/graph/GraphEvents.stories.tsx +0 -82
- package/src/components/relational/graph/ProvidedNodeRenderer.tsx +0 -23
- package/src/components/relational/graph/index.ts +0 -2
- package/src/components/relational/graph/story/TestData.tsx +0 -51
- package/src/components/relational/graph/story/index.ts +0 -1
- package/src/components/relational/index.ts +0 -1
- package/src/contexts/CytoscapeInstance/Context.ts +0 -5
- package/src/contexts/CytoscapeInstance/Provider.tsx +0 -24
- package/src/contexts/CytoscapeInstance/State.ts +0 -8
- package/src/contexts/CytoscapeInstance/index.ts +0 -4
- package/src/contexts/CytoscapeInstance/use.ts +0 -5
- package/src/contexts/index.ts +0 -1
- package/src/hooks/cytoscape/elements/index.ts +0 -2
- package/src/hooks/cytoscape/elements/useCytoscapeElements.ts +0 -47
- package/src/hooks/cytoscape/elements/useElements.tsx +0 -15
- package/src/hooks/cytoscape/elements/useHoveredNode.tsx +0 -34
- package/src/hooks/cytoscape/elements/useNewElements.tsx +0 -17
- package/src/hooks/cytoscape/elements/useRenderNewElements.tsx +0 -17
- package/src/hooks/cytoscape/elements/useSelectedElement.tsx +0 -25
- package/src/hooks/cytoscape/index.ts +0 -4
- package/src/hooks/cytoscape/useCytoscapeOptions.ts +0 -29
- package/src/hooks/cytoscape/useCytoscapeStyle.tsx +0 -34
- package/src/hooks/cytoscape/useIcons.tsx +0 -22
- package/src/hooks/cytoscape/useModuleDetails.tsx +0 -83
- package/src/hooks/cytoscape/useRelationalGraphOptions.tsx +0 -23
- package/src/hooks/index.ts +0 -1
- package/src/index.ts +0 -4
- package/src/types/global.d.ts +0 -19
- package/src/types/images.d.ts +0 -5
- package/src/types/theme.d.ts +0 -1
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import { CancelRounded } from '@mui/icons-material'
|
|
2
|
-
import type { PopperProps } from '@mui/material'
|
|
3
|
-
import {
|
|
4
|
-
Button, Card, CardActions, CardHeader, IconButton, Paper, Popper, styled,
|
|
5
|
-
} from '@mui/material'
|
|
6
|
-
import { Identicon } from '@xylabs/react-identicon'
|
|
7
|
-
import type { NodeSingular } from 'cytoscape'
|
|
8
|
-
import React from 'react'
|
|
9
|
-
|
|
10
|
-
export interface ModuleHoverPopperProps extends PopperProps {
|
|
11
|
-
node?: NodeSingular
|
|
12
|
-
onClose?: () => void
|
|
13
|
-
onModuleDetails?: (address?: string) => void
|
|
14
|
-
onModuleExplore?: (address?: string) => void
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export const ModuleHoverPopper: React.FC<ModuleHoverPopperProps> = ({
|
|
18
|
-
anchorEl, onClose, onModuleDetails, onModuleExplore, node, ...props
|
|
19
|
-
}) => {
|
|
20
|
-
const { address, name } = node?.data() ?? {}
|
|
21
|
-
return (
|
|
22
|
-
<>
|
|
23
|
-
{anchorEl
|
|
24
|
-
? (
|
|
25
|
-
<Popper anchorEl={anchorEl} {...props}>
|
|
26
|
-
<Card elevation={3}>
|
|
27
|
-
<CardHeader
|
|
28
|
-
action={
|
|
29
|
-
onClose
|
|
30
|
-
? (
|
|
31
|
-
<IconButton size="small" onClick={onClose}>
|
|
32
|
-
<CancelRounded />
|
|
33
|
-
</IconButton>
|
|
34
|
-
)
|
|
35
|
-
: null
|
|
36
|
-
}
|
|
37
|
-
avatar={(
|
|
38
|
-
<Paper
|
|
39
|
-
elevation={6}
|
|
40
|
-
sx={{ bgcolor: '#fff', p: 1 }}
|
|
41
|
-
>
|
|
42
|
-
<Identicon value={address} size={24} />
|
|
43
|
-
</Paper>
|
|
44
|
-
)}
|
|
45
|
-
title={name}
|
|
46
|
-
subheader={address}
|
|
47
|
-
/>
|
|
48
|
-
<StyledCardActions>
|
|
49
|
-
{onModuleDetails
|
|
50
|
-
? (
|
|
51
|
-
<Button onClick={() => onModuleDetails?.(address)} size="small" variant="contained">
|
|
52
|
-
Details
|
|
53
|
-
</Button>
|
|
54
|
-
)
|
|
55
|
-
: null}
|
|
56
|
-
{onModuleExplore
|
|
57
|
-
? (
|
|
58
|
-
<Button onClick={() => onModuleExplore?.(address)} size="small" variant="contained">
|
|
59
|
-
Explore
|
|
60
|
-
</Button>
|
|
61
|
-
)
|
|
62
|
-
: null}
|
|
63
|
-
</StyledCardActions>
|
|
64
|
-
</Card>
|
|
65
|
-
</Popper>
|
|
66
|
-
)
|
|
67
|
-
: null}
|
|
68
|
-
</>
|
|
69
|
-
)
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export const StyledModuleHoverPopper = styled(ModuleHoverPopper, { name: 'StyledComponents' })(() => ({ zIndex: 2 }))
|
|
73
|
-
|
|
74
|
-
export const StyledCardActions = styled(CardActions, { name: 'StyledCardActions' })(() => ({
|
|
75
|
-
display: 'flex',
|
|
76
|
-
justifyContent: 'center',
|
|
77
|
-
}))
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './GraphFlexBox.tsx'
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import type { PopperProps } from '@mui/material'
|
|
2
|
-
import { styled } from '@mui/material'
|
|
3
|
-
import { FlexCol } from '@xylabs/react-flexbox'
|
|
4
|
-
import type { NodeSingular } from 'cytoscape'
|
|
5
|
-
import type { ReactElement } from 'react'
|
|
6
|
-
import React from 'react'
|
|
7
|
-
|
|
8
|
-
import { useNodeElement } from './hooks/index.ts'
|
|
9
|
-
|
|
10
|
-
export interface ModuleHoverProps {
|
|
11
|
-
children?: (anchorElement?: PopperProps['anchorEl'], container?: PopperProps['container']) => ReactElement
|
|
12
|
-
node?: NodeSingular
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export const ModuleGraphNodeHover: React.FC<ModuleHoverProps> = ({ children, node }) => {
|
|
16
|
-
const {
|
|
17
|
-
boundingBox, ref, currentElement,
|
|
18
|
-
} = useNodeElement(node)
|
|
19
|
-
|
|
20
|
-
return (
|
|
21
|
-
<>
|
|
22
|
-
<StyledNodeGhostElementFlexCol ref={ref} left={boundingBox?.x1} height={boundingBox?.h} top={boundingBox?.y1} width={boundingBox?.w} />
|
|
23
|
-
{node
|
|
24
|
-
? <>{children?.(currentElement)}</>
|
|
25
|
-
: null}
|
|
26
|
-
</>
|
|
27
|
-
)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const StyledNodeGhostElementFlexCol = styled(FlexCol, { name: 'StyledNodeGhostElementFlexCol' })(() => ({
|
|
31
|
-
// For easier debugging of the 'ghost' element that matches the hovered cytoscape node
|
|
32
|
-
// backgroundColor: '#fff',
|
|
33
|
-
// opacity: 0.25,
|
|
34
|
-
|
|
35
|
-
cursor: 'pointer',
|
|
36
|
-
pointerEvents: 'none',
|
|
37
|
-
position: 'absolute',
|
|
38
|
-
}))
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './useNodeElement.tsx'
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import type { PopperProps } from '@mui/material'
|
|
2
|
-
import type { NodeSingular } from 'cytoscape'
|
|
3
|
-
import {
|
|
4
|
-
useEffect, useRef, useState,
|
|
5
|
-
} from 'react'
|
|
6
|
-
|
|
7
|
-
export const useNodeElement = (node?: NodeSingular) => {
|
|
8
|
-
const ref = useRef<HTMLDivElement>(null)
|
|
9
|
-
const [currentElement, setCurrentElement] = useState<PopperProps['anchorEl'] | null>(null)
|
|
10
|
-
const [boundingBox, setBoundingBox] = useState(node?.renderedBoundingBox())
|
|
11
|
-
|
|
12
|
-
// Ensure first render clears the previous element when node changes to avoid flicker
|
|
13
|
-
useEffect(() => {
|
|
14
|
-
setCurrentElement(null)
|
|
15
|
-
}, [node])
|
|
16
|
-
|
|
17
|
-
useEffect(() => {
|
|
18
|
-
setBoundingBox(node?.renderedBoundingBox())
|
|
19
|
-
}, [node])
|
|
20
|
-
|
|
21
|
-
useEffect(() => {
|
|
22
|
-
const listener = () => {
|
|
23
|
-
setBoundingBox(node?.renderedBoundingBox())
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
node?.on('position', listener)
|
|
27
|
-
|
|
28
|
-
return () => {
|
|
29
|
-
node?.off('position', undefined, listener)
|
|
30
|
-
}
|
|
31
|
-
}, [node])
|
|
32
|
-
|
|
33
|
-
// Once boundingBox state is set and applied to the layout, update the ref
|
|
34
|
-
useEffect(() => {
|
|
35
|
-
setCurrentElement(ref.current)
|
|
36
|
-
}, [boundingBox])
|
|
37
|
-
|
|
38
|
-
return {
|
|
39
|
-
boundingBox, currentElement, ref,
|
|
40
|
-
}
|
|
41
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './Hover.tsx'
|
|
@@ -1,201 +0,0 @@
|
|
|
1
|
-
import { Button, ButtonGroup } from '@mui/material'
|
|
2
|
-
import type {
|
|
3
|
-
Decorator, Meta, StoryFn,
|
|
4
|
-
} from '@storybook/react-vite'
|
|
5
|
-
import { useAsyncEffect } from '@xylabs/react-async-effect'
|
|
6
|
-
import { MemoryArchivist, MemoryArchivistConfigSchema } from '@xyo-network/archivist-memory'
|
|
7
|
-
import { HttpBridge, HttpBridgeConfigSchema } from '@xyo-network/bridge-http'
|
|
8
|
-
import { IdWitness, IdWitnessConfigSchema } from '@xyo-network/id-plugin'
|
|
9
|
-
import type { AttachableModuleInstance } from '@xyo-network/module-model'
|
|
10
|
-
import { MemoryNode } from '@xyo-network/node-memory'
|
|
11
|
-
import { NodeConfigSchema } from '@xyo-network/node-model'
|
|
12
|
-
import {
|
|
13
|
-
NodeProvider, useWeakNodeFromNode, useWeakProvidedNode,
|
|
14
|
-
} from '@xyo-network/react-node'
|
|
15
|
-
import { DefaultSeedPhrase } from '@xyo-network/react-storybook'
|
|
16
|
-
import { useWallet, WalletProvider } from '@xyo-network/react-wallet'
|
|
17
|
-
import { SentinelConfigSchema } from '@xyo-network/sentinel'
|
|
18
|
-
import { MemorySentinel } from '@xyo-network/sentinel-memory'
|
|
19
|
-
import React, { useState } from 'react'
|
|
20
|
-
|
|
21
|
-
import { CytoscapeInstanceProvider } from '../../../contexts/index.ts'
|
|
22
|
-
import { useCytoscapeElements, useCytoscapeOptions } from '../../../hooks/index.ts'
|
|
23
|
-
import { NodeRelationalGraphFlexBox } from './Graph.tsx'
|
|
24
|
-
import { ProvidedNodeRenderer } from './ProvidedNodeRenderer.tsx'
|
|
25
|
-
import { options } from './story/index.ts'
|
|
26
|
-
|
|
27
|
-
const client = { url: 'http://localhost:8080/node' }
|
|
28
|
-
|
|
29
|
-
const MemoryNodeDecorator: Decorator = (Story, args) => {
|
|
30
|
-
const [node, setNode] = useState<MemoryNode>()
|
|
31
|
-
|
|
32
|
-
useAsyncEffect(
|
|
33
|
-
async () => {
|
|
34
|
-
try {
|
|
35
|
-
const node = await MemoryNode.create({ config: { name: 'GlobalNode', schema: NodeConfigSchema } })
|
|
36
|
-
const node1 = await MemoryNode.create({ config: { name: 'ChildNode', schema: NodeConfigSchema } })
|
|
37
|
-
const bridge = await HttpBridge.create({
|
|
38
|
-
config: {
|
|
39
|
-
name: 'Bridge', client, schema: HttpBridgeConfigSchema, security: { allowAnonymous: true },
|
|
40
|
-
},
|
|
41
|
-
})
|
|
42
|
-
await node.register(bridge)
|
|
43
|
-
await node.attach(bridge.address, true)
|
|
44
|
-
|
|
45
|
-
const archivist = await MemoryArchivist.create({ config: { name: 'RootStorageArchivist', schema: MemoryArchivistConfigSchema } })
|
|
46
|
-
await node.register(archivist)
|
|
47
|
-
await node.attach(archivist.address, true)
|
|
48
|
-
|
|
49
|
-
const sentinel = await MemorySentinel.create({
|
|
50
|
-
config: {
|
|
51
|
-
name: 'MemorySentinel', schema: SentinelConfigSchema, synchronous: true, tasks: [],
|
|
52
|
-
},
|
|
53
|
-
})
|
|
54
|
-
await node.register(sentinel)
|
|
55
|
-
await node.attach(sentinel.address, true)
|
|
56
|
-
|
|
57
|
-
const archivist1 = await MemoryArchivist.create({ config: { name: 'RootStorageArchivist1', schema: MemoryArchivistConfigSchema } })
|
|
58
|
-
await node1.register(archivist1)
|
|
59
|
-
await node1.attach(archivist1.address, true)
|
|
60
|
-
|
|
61
|
-
await node.register(node1)
|
|
62
|
-
await node.attach(node1.address, true)
|
|
63
|
-
|
|
64
|
-
setNode(node)
|
|
65
|
-
} catch (e) {
|
|
66
|
-
console.error('Error Creating MemoryNode', e)
|
|
67
|
-
}
|
|
68
|
-
},
|
|
69
|
-
[],
|
|
70
|
-
)
|
|
71
|
-
|
|
72
|
-
const [wallet] = useWallet({ mnemonic: DefaultSeedPhrase })
|
|
73
|
-
|
|
74
|
-
return (
|
|
75
|
-
<WalletProvider rootWallet={wallet}>
|
|
76
|
-
<NodeProvider node={node}>
|
|
77
|
-
<CytoscapeInstanceProvider>
|
|
78
|
-
<Story {...args} />
|
|
79
|
-
</CytoscapeInstanceProvider>
|
|
80
|
-
</NodeProvider>
|
|
81
|
-
</WalletProvider>
|
|
82
|
-
)
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export default {
|
|
86
|
-
component: NodeRelationalGraphFlexBox,
|
|
87
|
-
parameters: { layout: 'fullscreen' },
|
|
88
|
-
title: 'node/renderer/NodeRelationalGraph',
|
|
89
|
-
} as Meta
|
|
90
|
-
|
|
91
|
-
const Template: StoryFn<typeof NodeRelationalGraphFlexBox> = props => <NodeRelationalGraphFlexBox {...props} />
|
|
92
|
-
|
|
93
|
-
const TemplateDescribe: StoryFn<typeof NodeRelationalGraphFlexBox> = (props) => {
|
|
94
|
-
const [node] = useWeakProvidedNode()
|
|
95
|
-
const elements = useCytoscapeElements(node)
|
|
96
|
-
const options = useCytoscapeOptions(elements)
|
|
97
|
-
return <NodeRelationalGraphFlexBox options={options} {...props} />
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const TemplateCustomAddress: StoryFn<typeof NodeRelationalGraphFlexBox> = (props) => {
|
|
101
|
-
const [node] = useWeakNodeFromNode('ChildNode')
|
|
102
|
-
const elements = useCytoscapeElements(node)
|
|
103
|
-
const options = useCytoscapeOptions(elements)
|
|
104
|
-
|
|
105
|
-
return <NodeRelationalGraphFlexBox options={options} {...props} />
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
const TemplateProvidedNodeRenderer: StoryFn<typeof ProvidedNodeRenderer> = (props) => {
|
|
109
|
-
const [layout, setLayout] = useState<'dagre' | 'euler' | 'cose-bilkent' | 'cola'>('euler')
|
|
110
|
-
return (
|
|
111
|
-
<div style={{
|
|
112
|
-
height: '100vh', width: '100vw', position: 'relative',
|
|
113
|
-
}}
|
|
114
|
-
>
|
|
115
|
-
<ButtonGroup>
|
|
116
|
-
<Button variant={layout === 'dagre' ? 'contained' : 'outlined'} onClick={() => setLayout('dagre')}>Dagre</Button>
|
|
117
|
-
<Button variant={layout === 'euler' ? 'contained' : 'outlined'} onClick={() => setLayout('euler')}>Euler</Button>
|
|
118
|
-
<Button variant={layout === 'cose-bilkent' ? 'contained' : 'outlined'} onClick={() => setLayout('cose-bilkent')}>CoseBilkent</Button>
|
|
119
|
-
<Button variant={layout === 'cola' ? 'contained' : 'outlined'} onClick={() => setLayout('cola')}>Cola</Button>
|
|
120
|
-
</ButtonGroup>
|
|
121
|
-
<ProvidedNodeRenderer {...props} layout={layout} />
|
|
122
|
-
</div>
|
|
123
|
-
)
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
const TemplateAttachDetach: StoryFn<typeof NodeRelationalGraphFlexBox> = (props) => {
|
|
127
|
-
const [node] = useWeakNodeFromNode('ChildNode')
|
|
128
|
-
const elements = useCytoscapeElements(node)
|
|
129
|
-
const options = useCytoscapeOptions(elements)
|
|
130
|
-
const [idWitness, setIdWitness] = useState<IdWitness>()
|
|
131
|
-
const [layout, setLayout] = useState<'dagre' | 'euler' | 'cose-bilkent' | 'cola'>('euler')
|
|
132
|
-
|
|
133
|
-
useAsyncEffect(
|
|
134
|
-
async () => {
|
|
135
|
-
const witnessModule = await IdWitness.create({
|
|
136
|
-
config: {
|
|
137
|
-
name: 'IdWitness', salt: 'test', schema: IdWitnessConfigSchema,
|
|
138
|
-
},
|
|
139
|
-
})
|
|
140
|
-
setIdWitness(witnessModule)
|
|
141
|
-
},
|
|
142
|
-
[],
|
|
143
|
-
)
|
|
144
|
-
|
|
145
|
-
const handleAddWitness = async () => {
|
|
146
|
-
if (node && idWitness) {
|
|
147
|
-
const memoryNode = node.deref() as MemoryNode | undefined
|
|
148
|
-
await memoryNode?.register(idWitness as unknown as AttachableModuleInstance)
|
|
149
|
-
await memoryNode?.attach(idWitness.address, true)
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
const handleRemoveWitness = async () => {
|
|
154
|
-
if (node && idWitness) {
|
|
155
|
-
const memoryNode = node.deref() as MemoryNode | undefined
|
|
156
|
-
if (((await memoryNode?.registered()) ?? []).includes(idWitness.address)) {
|
|
157
|
-
await memoryNode?.unregister(idWitness as unknown as AttachableModuleInstance)
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
return (
|
|
163
|
-
<>
|
|
164
|
-
<ButtonGroup>
|
|
165
|
-
<Button onClick={handleAddWitness}>Add Witness</Button>
|
|
166
|
-
<Button onClick={handleRemoveWitness}>Remove Witness</Button>
|
|
167
|
-
<Button onClick={() => setLayout('dagre')}>Dagre</Button>
|
|
168
|
-
<Button onClick={() => setLayout('euler')}>Euler</Button>
|
|
169
|
-
<Button onClick={() => setLayout('cose-bilkent')}>CoseBilkent</Button>
|
|
170
|
-
<Button onClick={() => setLayout('cola')}>Cola</Button>
|
|
171
|
-
</ButtonGroup>
|
|
172
|
-
<NodeRelationalGraphFlexBox layout={layout} options={options} {...props} />
|
|
173
|
-
</>
|
|
174
|
-
)
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
const Default = Template.bind({})
|
|
178
|
-
Default.args = {}
|
|
179
|
-
|
|
180
|
-
const WithData = Template.bind({})
|
|
181
|
-
WithData.args = { options }
|
|
182
|
-
|
|
183
|
-
const WithDescribe = TemplateDescribe.bind({})
|
|
184
|
-
WithDescribe.args = {}
|
|
185
|
-
WithDescribe.decorators = [MemoryNodeDecorator]
|
|
186
|
-
|
|
187
|
-
const WithCustomAddress = TemplateCustomAddress.bind({})
|
|
188
|
-
WithCustomAddress.args = {}
|
|
189
|
-
WithCustomAddress.decorators = [MemoryNodeDecorator]
|
|
190
|
-
|
|
191
|
-
const WithAttachDetach = TemplateAttachDetach.bind({})
|
|
192
|
-
WithAttachDetach.args = {}
|
|
193
|
-
WithAttachDetach.decorators = [MemoryNodeDecorator]
|
|
194
|
-
|
|
195
|
-
const WithProvidedNodeRenderer = TemplateProvidedNodeRenderer.bind({})
|
|
196
|
-
WithProvidedNodeRenderer.args = {}
|
|
197
|
-
WithProvidedNodeRenderer.decorators = [MemoryNodeDecorator]
|
|
198
|
-
|
|
199
|
-
export {
|
|
200
|
-
Default, WithAttachDetach, WithCustomAddress, WithData, WithDescribe, WithProvidedNodeRenderer,
|
|
201
|
-
}
|
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
import type { CardProps } from '@mui/material'
|
|
2
|
-
import {
|
|
3
|
-
Box, Button, ButtonGroup, Card, CardHeader, Paper, useTheme,
|
|
4
|
-
} from '@mui/material'
|
|
5
|
-
import {
|
|
6
|
-
FlexCol, FlexGrowRow, FlexRow,
|
|
7
|
-
} from '@xylabs/react-flexbox'
|
|
8
|
-
import { Identicon } from '@xylabs/react-identicon'
|
|
9
|
-
import type { Address } from '@xylabs/sdk-js'
|
|
10
|
-
import { asAddress, isDefined } from '@xylabs/sdk-js'
|
|
11
|
-
import { useWeakModuleFromNode } from '@xyo-network/react-node'
|
|
12
|
-
import type {
|
|
13
|
-
Core, EventHandler, NodeSingular,
|
|
14
|
-
} from 'cytoscape'
|
|
15
|
-
import cytoscape from 'cytoscape'
|
|
16
|
-
import cola from 'cytoscape-cola'
|
|
17
|
-
import coseBilkentLayout from 'cytoscape-cose-bilkent'
|
|
18
|
-
import dagre from 'cytoscape-dagre'
|
|
19
|
-
import euler from 'cytoscape-euler'
|
|
20
|
-
import React, {
|
|
21
|
-
useEffect, useRef, useState,
|
|
22
|
-
} from 'react'
|
|
23
|
-
|
|
24
|
-
import type { NodeRelationalGraphProps } from '../../lib/index.ts'
|
|
25
|
-
|
|
26
|
-
const applyLayout = (cy?: cytoscape.Core, name = 'cola', options?: object) => {
|
|
27
|
-
cy?.layout({ name, ...options }).run()
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const loadLayout = (layout = 'cola') => {
|
|
31
|
-
switch (layout) {
|
|
32
|
-
case 'cose-bilkent': {
|
|
33
|
-
cytoscape.use(coseBilkentLayout)
|
|
34
|
-
break
|
|
35
|
-
}
|
|
36
|
-
case 'cola': {
|
|
37
|
-
cytoscape.use(cola)
|
|
38
|
-
break
|
|
39
|
-
}
|
|
40
|
-
case 'euler': {
|
|
41
|
-
cytoscape.use(euler)
|
|
42
|
-
break
|
|
43
|
-
}
|
|
44
|
-
case 'dagre': {
|
|
45
|
-
cytoscape.use(dagre)
|
|
46
|
-
break
|
|
47
|
-
}
|
|
48
|
-
default: {
|
|
49
|
-
cytoscape.use(euler)
|
|
50
|
-
break
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
type ModuleHoverDetailsProps = CardProps & {
|
|
56
|
-
address: Address
|
|
57
|
-
name: string
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const ModuleHoverDetails: React.FC<ModuleHoverDetailsProps> = ({
|
|
61
|
-
name, address, ...props
|
|
62
|
-
}) => {
|
|
63
|
-
return (
|
|
64
|
-
<Card elevation={3} {...props}>
|
|
65
|
-
<CardHeader
|
|
66
|
-
avatar={(
|
|
67
|
-
<Paper
|
|
68
|
-
elevation={6}
|
|
69
|
-
sx={{ bgcolor: '#fff', p: 1 }}
|
|
70
|
-
>
|
|
71
|
-
<Identicon value={address} size={24} />
|
|
72
|
-
</Paper>
|
|
73
|
-
)}
|
|
74
|
-
title={name}
|
|
75
|
-
subheader={address}
|
|
76
|
-
/>
|
|
77
|
-
</Card>
|
|
78
|
-
)
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export const NodeRelationalGraphFlexBox: React.FC<NodeRelationalGraphProps> = ({
|
|
82
|
-
actions, children, node, layout, layoutOptions, showDetails, detail, options, onHover, ...props
|
|
83
|
-
}) => {
|
|
84
|
-
const theme = useTheme()
|
|
85
|
-
const [cy, setCy] = useState<Core>()
|
|
86
|
-
const cytoscapeRef = useRef<HTMLDivElement>(null)
|
|
87
|
-
const [hoverBoundingBox, setHoverBoundingBox] = useState<{ x1: number; x2: number; y1: number; y2: number }>()
|
|
88
|
-
const [hoverAddress, setHoverAddress] = useState<Address>()
|
|
89
|
-
|
|
90
|
-
const [moduleInstance] = useWeakModuleFromNode(hoverAddress, { node })
|
|
91
|
-
|
|
92
|
-
useEffect(() => {
|
|
93
|
-
const listener: EventHandler = ({ target }) => {
|
|
94
|
-
const cyNode = target as NodeSingular
|
|
95
|
-
const bb = cyNode?.renderedBoundingBox?.()
|
|
96
|
-
setHoverBoundingBox(bb)
|
|
97
|
-
const id = cyNode.id?.()
|
|
98
|
-
if (isDefined(id)) {
|
|
99
|
-
if (id.includes('/')) {
|
|
100
|
-
setHoverAddress(undefined)
|
|
101
|
-
onHover?.()
|
|
102
|
-
} else {
|
|
103
|
-
setHoverAddress(asAddress(id))
|
|
104
|
-
onHover?.(asAddress(id))
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
cy?.on('mouseover tap', listener)
|
|
109
|
-
|
|
110
|
-
return () => {
|
|
111
|
-
cy?.off('mouseover tap', listener)
|
|
112
|
-
}
|
|
113
|
-
}, [onHover, cy])
|
|
114
|
-
|
|
115
|
-
const handleReset = () => {
|
|
116
|
-
cy?.reset()
|
|
117
|
-
applyLayout(cy, layout ?? 'euler', layoutOptions)
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
useEffect(() => {
|
|
121
|
-
let newCy: Core | undefined
|
|
122
|
-
const container = cytoscapeRef.current
|
|
123
|
-
if (container) {
|
|
124
|
-
newCy = cytoscape({
|
|
125
|
-
container,
|
|
126
|
-
...options,
|
|
127
|
-
})
|
|
128
|
-
setCy(newCy)
|
|
129
|
-
} else {
|
|
130
|
-
newCy?.destroy()
|
|
131
|
-
setCy(undefined)
|
|
132
|
-
}
|
|
133
|
-
return () => {
|
|
134
|
-
newCy?.destroy()
|
|
135
|
-
setCy(undefined)
|
|
136
|
-
}
|
|
137
|
-
}, [options, cytoscapeRef, layoutOptions])
|
|
138
|
-
|
|
139
|
-
useEffect(() => {
|
|
140
|
-
if (cy) {
|
|
141
|
-
loadLayout(layout)
|
|
142
|
-
applyLayout(cy, layout ?? 'cola', layoutOptions)
|
|
143
|
-
}
|
|
144
|
-
}, [cy, layoutOptions, layout])
|
|
145
|
-
|
|
146
|
-
return (
|
|
147
|
-
<FlexCol id="relational-graph-wrapper" {...props}>
|
|
148
|
-
{hoverAddress && hoverBoundingBox
|
|
149
|
-
? (
|
|
150
|
-
<Box position="absolute" top={hoverBoundingBox.y1} left={hoverBoundingBox.x1} zIndex={100}>
|
|
151
|
-
<ModuleHoverDetails address={hoverAddress} name={moduleInstance?.deref()?.id ?? 'Unknown'} />
|
|
152
|
-
</Box>
|
|
153
|
-
)
|
|
154
|
-
: null}
|
|
155
|
-
<FlexRow justifyContent="start" width="100%">
|
|
156
|
-
{actions === null
|
|
157
|
-
? null
|
|
158
|
-
: isDefined(actions)
|
|
159
|
-
? (
|
|
160
|
-
<ButtonGroup>
|
|
161
|
-
{actions}
|
|
162
|
-
<Button size="small" variant="contained" onClick={handleReset}>
|
|
163
|
-
Reset View
|
|
164
|
-
</Button>
|
|
165
|
-
</ButtonGroup>
|
|
166
|
-
)
|
|
167
|
-
: (
|
|
168
|
-
<Button size="small" variant="contained" onClick={handleReset}>
|
|
169
|
-
Reset
|
|
170
|
-
</Button>
|
|
171
|
-
)}
|
|
172
|
-
</FlexRow>
|
|
173
|
-
<FlexGrowRow width="100%" alignItems="start">
|
|
174
|
-
{showDetails
|
|
175
|
-
? (
|
|
176
|
-
<FlexCol height="100%" width="85%">
|
|
177
|
-
{detail}
|
|
178
|
-
</FlexCol>
|
|
179
|
-
)
|
|
180
|
-
: null}
|
|
181
|
-
<FlexCol
|
|
182
|
-
justifyContent="start"
|
|
183
|
-
classes="cytoscape-wrap"
|
|
184
|
-
width={showDetails ? '15%' : '100%'}
|
|
185
|
-
height={showDetails ? '50%' : '100%'}
|
|
186
|
-
border={showDetails ? `1px solid ${theme.vars.palette.divider}` : undefined}
|
|
187
|
-
>
|
|
188
|
-
{/* Cytoscape Element */}
|
|
189
|
-
<FlexCol alignItems="stretch" position="absolute" width="100%" height="100%" ref={cytoscapeRef} />
|
|
190
|
-
{children}
|
|
191
|
-
</FlexCol>
|
|
192
|
-
</FlexGrowRow>
|
|
193
|
-
</FlexCol>
|
|
194
|
-
)
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
NodeRelationalGraphFlexBox.displayName = 'NodeRelationalGraph'
|
|
198
|
-
|
|
199
|
-
/** @deprecated */
|
|
200
|
-
export const NodeRelationalGraph = NodeRelationalGraphFlexBox
|