({
nodes: [],
links: [],
})
const selectClick = (node: NodeObject, event: any) => {
window.open('org-protocol://roam-node?node=' + node.id, '_self')
if (event.timeStamp - doubleClick < 400) {
// getLocalGraphData(node)
}
// setDoubleClick(event.timeStamp)
if (node) {
return setSelectedNode(node)
}
}
return (
{
if (!physics.colorful) {
if (Object.keys(highlightedNodes).length === 0) {
return 'rgb(100, 100, 100, 1)'
}
return highlightedNodes[node.id!] ? '#a991f1' : 'rgb(50, 50, 50, 0.5)'
}
const palette = [
'#ff665c',
'#e69055',
'#7bc275',
'#4db5bd',
'#FCCE7B',
'#51afef',
'#1f5582',
'#C57BDB',
'#a991f1',
'#5cEfFF',
'#6A8FBF',
]
// random
return palette[0]
if (node.neighbors.length === 1 || node.neighbors.length === 2) {
return palette[node.neighbors[0].index % 11]
}
return palette[node.index % 11]
}}
linkColor={(link) => {
if (Object.keys(highlightedNodes).length === 0) {
return 'rgb(50, 50, 50, 0.8)'
}
const linkIsHighlighted =
(link.source as NodeObject).id! === centralHighlightedNode?.id! ||
(link.target as NodeObject).id! === centralHighlightedNode?.id!
return linkIsHighlighted ? '#a991f1' : 'rgb(50, 50, 50, 0.2)'
}}
linkDirectionalParticles={physics.particles}
linkDirectionalParticleWidth={physics.particleWidth}
nodeLabel={(node) => (node as OrgRoamNode).title}
linkWidth={(link) => {
const linkIsHighlighted =
(link.source as NodeObject).id! === centralHighlightedNode?.id! ||
(link.target as NodeObject).id! === centralHighlightedNode?.id!
return linkIsHighlighted ? 3 * physics.linkWidth : physics.linkWidth
}}
nodeRelSize={physics.nodeRel}
nodeVal={(node) => {
const links = props.linksByNodeId[node.id!] ?? []
const basicSize = 3 + links.length
const highlightSize = highlightedNodes[node.id!] ? 2 : 0
return basicSize + highlightSize
}}
nodeCanvasObject={(node, ctx, globalScale) => {
if (!physics.labels) {
return
}
if (globalScale <= physics.labelScale && !highlightedNodes[node.id!]) {
return
}
const nodeTitle = (node as OrgRoamNode).title
const label = nodeTitle.substring(0, Math.min(nodeTitle.length, 30))
// const label = 'label'
const fontSize = 12 / globalScale
const textWidth = ctx.measureText(label).width
const bckgDimensions = [textWidth * 1.1, fontSize].map((n) => n + fontSize * 0.5) as [
number,
number,
] // some padding
const fadeFactor = Math.min(
(3 * (globalScale - physics.labelScale)) / physics.labelScale,
1,
)
// draw label background
ctx.fillStyle =
'rgba(20, 20, 20, ' +
(highlightedNodes.length === 0
? 0.5 * fadeFactor
: highlightedNodes[node.id!]
? 0.5
: 0.15 * fadeFactor) +
')'
ctx.fillRect(
node.x! - bckgDimensions[0] / 2,
node.y! - bckgDimensions[1] / 2,
...bckgDimensions,
)
// draw label text
ctx.textAlign = 'center'
ctx.textBaseline = 'middle'
ctx.fillStyle =
'rgb(255, 255, 255, ' +
(highlightedNodes.length === 0
? fadeFactor
: highlightedNodes[node.id!]
? 1
: 0.3 * fadeFactor) +
')'
ctx.font = `${fontSize}px Sans-Serif`
ctx.fillText(label, node.x!, node.y!)
}}
nodeCanvasObjectMode={() => 'after'}
d3AlphaDecay={physics.alphaDecay}
d3AlphaMin={physics.alphaTarget}
d3VelocityDecay={physics.velocityDecay}
backgroundColor={'#242730'}
onNodeClick={selectClick}
onBackgroundClick={() => {
setSelectedNode(null)
}}
onNodeHover={(node) => {
if (!physics.hover) {
return
}
setHoverNode(node)
}}
/>
)
}