diff --git a/packages/sdk/packages/node-renderer/package.json b/packages/sdk/packages/node-renderer/package.json index 516b333ced..1bfa1c00c4 100644 --- a/packages/sdk/packages/node-renderer/package.json +++ b/packages/sdk/packages/node-renderer/package.json @@ -12,6 +12,7 @@ "dependencies": { "@xylabs/react-async-effect": "^3.0.6", "@xylabs/react-flexbox": "^3.0.6", + "@xylabs/react-identicon": "^3.0.6", "@xylabs/react-shared": "^3.0.6", "@xyo-network/account-model": "^2.75.4", "@xyo-network/archivist-model": "^2.75.4", @@ -24,8 +25,7 @@ "@xyo-network/react-node": "workspace:~", "@xyo-network/react-shared": "workspace:~", "cytoscape": "^3.26.0", - "cytoscape-cola": "^2.5.1", - "cytoscape-popper": "^2.0.0" + "cytoscape-cola": "^2.5.1" }, "peerDependencies": { "@mui/icons-material": "^5", diff --git a/packages/sdk/packages/node-renderer/src/Cytoscape/lib/layout/ConcentricLayout.ts b/packages/sdk/packages/node-renderer/src/Cytoscape/lib/layout/ConcentricLayout.ts index 94f52deee4..5030708544 100644 --- a/packages/sdk/packages/node-renderer/src/Cytoscape/lib/layout/ConcentricLayout.ts +++ b/packages/sdk/packages/node-renderer/src/Cytoscape/lib/layout/ConcentricLayout.ts @@ -1,6 +1,6 @@ -import { CytoscapeOptions } from 'cytoscape' +import { LayoutOptions } from 'cytoscape' -export const ConcentricLayout: CytoscapeOptions['layout'] = { +export const ConcentricLayout: LayoutOptions = { concentric: function (node) { return node.degree() }, diff --git a/packages/sdk/packages/node-renderer/src/components/ModuleGraphFlexBox.tsx b/packages/sdk/packages/node-renderer/src/components/ModuleGraphFlexBox.tsx deleted file mode 100644 index 55c5227153..0000000000 --- a/packages/sdk/packages/node-renderer/src/components/ModuleGraphFlexBox.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import { Button } from '@mui/material' -import { FlexBoxProps } from '@xylabs/react-flexbox' -import { ModuleInstance } from '@xyo-network/module' -import { EventObject } from 'cytoscape' -import { useEffect } from 'react' - -import { useCytoscapeInstance } from '../contexts' -import { useAddNewElements, useNewElements, usePopperListener, useRelationalGraphOptions } from '../hooks' -import { WithExtensions } from './cytoscape-extensions' -import { NodeRelationalGraphFlexBox } from './RelationalGraph' - -export interface ModuleGraphFlexBoxProps extends FlexBoxProps { - rootModule?: ModuleInstance | null -} - -export const ModuleGraphFlexBox: React.FC = ({ rootModule, ...props }) => { - const { cy } = useCytoscapeInstance(true) - const popperListener = usePopperListener() - const { handleToggleLabels, hideLabels, options } = useRelationalGraphOptions(rootModule ?? undefined) - - const { newElements, setSelectedElement } = useNewElements() - - useAddNewElements(newElements, hideLabels) - - useEffect(() => { - const listener = (event: EventObject) => { - const element = event.target[0] - if (element.isNode()) setSelectedElement(element) - } - cy?.on('select', listener) - - return () => { - cy?.off('select', listener) - } - }, [cy, setSelectedElement]) - - useEffect(() => { - cy?.ready(() => { - cy.nodes().forEach((node) => popperListener(node, hideLabels, cy)) - }) - }, [cy, hideLabels, popperListener, setSelectedElement]) - - return ( - - - Toggle Labels - - } - options={options} - {...props} - /> - - ) -} diff --git a/packages/sdk/packages/node-renderer/src/components/RelationalGraph.tsx b/packages/sdk/packages/node-renderer/src/components/RelationalGraph.tsx index d82478f289..082719cf24 100644 --- a/packages/sdk/packages/node-renderer/src/components/RelationalGraph.tsx +++ b/packages/sdk/packages/node-renderer/src/components/RelationalGraph.tsx @@ -7,7 +7,7 @@ import { forwardRef, useEffect, useState } from 'react' import { useCytoscapeInstance } from '../contexts' import { NodeRelationalGraphProps } from './lib' -export const NodeRelationalGraphFlexBox = forwardRef(({ actions, options, ...props }, ref) => { +export const NodeRelationalGraphFlexBox = forwardRef(({ actions, children, options, ...props }, ref) => { const [cy, setCy] = useState() const { setCy: setCyContext } = useCytoscapeInstance() const sharedRef = useShareForwardedRef(ref) @@ -43,6 +43,7 @@ export const NodeRelationalGraphFlexBox = forwardRef {/* Cytoscape Element */} + {children} ) }) diff --git a/packages/sdk/packages/node-renderer/src/components/WithCola.tsx b/packages/sdk/packages/node-renderer/src/components/WithCola.tsx deleted file mode 100644 index 72689fcd5a..0000000000 --- a/packages/sdk/packages/node-renderer/src/components/WithCola.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { use } from 'cytoscape' -import cola from 'cytoscape-cola' -import { PropsWithChildren, useEffect, useState } from 'react' - -export const WithCola: React.FC = ({ children }) => { - const [initialized, setInitialized] = useState(false) - useEffect(() => { - use(cola) - setInitialized(true) - }, []) - - return <>{initialized ? children : undefined} -} diff --git a/packages/sdk/packages/node-renderer/src/components/cytoscape-extensions/WithExtensions.tsx b/packages/sdk/packages/node-renderer/src/components/cytoscape-extensions/WithExtensions.tsx index b3a6dbcef6..0d934da150 100644 --- a/packages/sdk/packages/node-renderer/src/components/cytoscape-extensions/WithExtensions.tsx +++ b/packages/sdk/packages/node-renderer/src/components/cytoscape-extensions/WithExtensions.tsx @@ -1,13 +1,11 @@ import { use } from 'cytoscape' import cola from 'cytoscape-cola' -import popper from 'cytoscape-popper' import { PropsWithChildren, useEffect, useState } from 'react' export const WithExtensions: React.FC = ({ children }) => { const [initialized, setInitialized] = useState(false) useEffect(() => { use(cola) - use(popper) setInitialized(true) }, []) diff --git a/packages/sdk/packages/node-renderer/src/components/index.ts b/packages/sdk/packages/node-renderer/src/components/index.ts index e38fc2961c..a54365d3c1 100644 --- a/packages/sdk/packages/node-renderer/src/components/index.ts +++ b/packages/sdk/packages/node-renderer/src/components/index.ts @@ -1,4 +1,4 @@ export * from './lib' -export * from './ModuleCardParser' +export * from './module' export * from './ProvidedNodeRenderer' export * from './RelationalGraph' diff --git a/packages/sdk/packages/node-renderer/src/components/lib/RelationalGraphProps.ts b/packages/sdk/packages/node-renderer/src/components/lib/RelationalGraphProps.ts index 183c08cf72..2a14212f87 100644 --- a/packages/sdk/packages/node-renderer/src/components/lib/RelationalGraphProps.ts +++ b/packages/sdk/packages/node-renderer/src/components/lib/RelationalGraphProps.ts @@ -1,8 +1,8 @@ import { FlexBoxProps } from '@xylabs/react-flexbox' import { CytoscapeOptions } from 'cytoscape' -import { ReactNode } from 'react' +import { PropsWithChildren, ReactNode } from 'react' -export interface NodeRelationalGraphProps extends FlexBoxProps { +export interface NodeRelationalGraphProps extends PropsWithChildren { actions?: ReactNode options?: CytoscapeOptions } diff --git a/packages/sdk/packages/node-renderer/src/components/ModuleCardParser.stories.tsx b/packages/sdk/packages/node-renderer/src/components/module/CardParser.stories.tsx similarity index 95% rename from packages/sdk/packages/node-renderer/src/components/ModuleCardParser.stories.tsx rename to packages/sdk/packages/node-renderer/src/components/module/CardParser.stories.tsx index 678d103493..de665a7d65 100644 --- a/packages/sdk/packages/node-renderer/src/components/ModuleCardParser.stories.tsx +++ b/packages/sdk/packages/node-renderer/src/components/module/CardParser.stories.tsx @@ -2,7 +2,7 @@ import { Meta, StoryObj } from '@storybook/react' import { MemoryArchivist, MemoryArchivistConfigSchema } from '@xyo-network/archivist' import { IdWitness, IdWitnessConfigSchema } from '@xyo-network/id-plugin' -import { ModuleCardParser } from './ModuleCardParser' +import { ModuleCardParser } from './CardParser' const meta: Meta = { component: ModuleCardParser, diff --git a/packages/sdk/packages/node-renderer/src/components/ModuleCardParser.tsx b/packages/sdk/packages/node-renderer/src/components/module/CardParser.tsx similarity index 69% rename from packages/sdk/packages/node-renderer/src/components/ModuleCardParser.tsx rename to packages/sdk/packages/node-renderer/src/components/module/CardParser.tsx index 47f1e7aa62..39e57ff94f 100644 --- a/packages/sdk/packages/node-renderer/src/components/ModuleCardParser.tsx +++ b/packages/sdk/packages/node-renderer/src/components/module/CardParser.tsx @@ -1,5 +1,5 @@ -import { asArchivistInstance } from '@xyo-network/archivist-model' -import { asDivinerInstance } from '@xyo-network/diviner-model' +import { asArchivistInstance, isArchivistInstance } from '@xyo-network/archivist-model' +import { asDivinerInstance, isDivinerInstance } from '@xyo-network/diviner-model' import { ModuleInstance } from '@xyo-network/module' import { ArchivistCard } from '@xyo-network/react-archivist' import { DivinerCard, ModuleCard } from '@xyo-network/react-module' @@ -10,9 +10,9 @@ export interface ModuleCardParserProps { export const ModuleCardParser: React.FC = ({ module }) => { switch (true) { - case module?.config.schema.includes('archivist'): + case isArchivistInstance(module): return - case module?.config.schema.includes('diviner'): + case isDivinerInstance(module): return default: return diff --git a/packages/sdk/packages/node-renderer/src/components/ModuleGraphFlexBox.stories.tsx b/packages/sdk/packages/node-renderer/src/components/module/graph/GraphFlexBox.stories.tsx similarity index 96% rename from packages/sdk/packages/node-renderer/src/components/ModuleGraphFlexBox.stories.tsx rename to packages/sdk/packages/node-renderer/src/components/module/graph/GraphFlexBox.stories.tsx index f3323f8914..8a22a92501 100644 --- a/packages/sdk/packages/node-renderer/src/components/ModuleGraphFlexBox.stories.tsx +++ b/packages/sdk/packages/node-renderer/src/components/module/graph/GraphFlexBox.stories.tsx @@ -10,8 +10,8 @@ import { useWallet, WalletProvider } from '@xyo-network/react-wallet' import { MemorySentinel, SentinelConfigSchema } from '@xyo-network/sentinel' import { useState } from 'react' -import { CytoscapeInstanceProvider } from '../contexts' -import { ModuleGraphFlexBox } from './ModuleGraphFlexBox' +import { CytoscapeInstanceProvider } from '../../../contexts' +import { ModuleGraphFlexBox } from './GraphFlexBox' const nodeUrl = 'http://localhost:8080/node' diff --git a/packages/sdk/packages/node-renderer/src/components/module/graph/GraphFlexBox.tsx b/packages/sdk/packages/node-renderer/src/components/module/graph/GraphFlexBox.tsx new file mode 100644 index 0000000000..42afcd5e40 --- /dev/null +++ b/packages/sdk/packages/node-renderer/src/components/module/graph/GraphFlexBox.tsx @@ -0,0 +1,36 @@ +import { Button } from '@mui/material' +import { FlexBoxProps } from '@xylabs/react-flexbox' +import { ModuleInstance } from '@xyo-network/module' + +import { useHoveredNode, useNewElements, useRelationalGraphOptions, useRenderNewElements, useSelectedElement } from '../../../hooks' +import { WithExtensions } from '../../cytoscape-extensions' +import { NodeRelationalGraphFlexBox } from '../../RelationalGraph' +import { ModuleGraphNodeHover } from './NodeHover' + +export interface ModuleGraphFlexBoxProps extends FlexBoxProps { + rootModule?: ModuleInstance | null +} + +export const ModuleGraphFlexBox: React.FC = ({ rootModule, ...props }) => { + const { handleToggleLabels, hideLabels, options } = useRelationalGraphOptions(rootModule ?? undefined) + const selectedElement = useSelectedElement() + const newElements = useNewElements(selectedElement) + const renderedElements = useRenderNewElements(newElements, hideLabels) + const hoveredNode = useHoveredNode(renderedElements) + + return ( + + + Toggle Labels + + } + options={options} + {...props} + > + + + + ) +} diff --git a/packages/sdk/packages/node-renderer/src/components/module/graph/NodeHover.tsx b/packages/sdk/packages/node-renderer/src/components/module/graph/NodeHover.tsx new file mode 100644 index 0000000000..738ff74aab --- /dev/null +++ b/packages/sdk/packages/node-renderer/src/components/module/graph/NodeHover.tsx @@ -0,0 +1,56 @@ +import { NodeSingular } from 'cytoscape' +import { useLayoutEffect, useRef, useState } from 'react' + +import { ModuleHoverPopper } from './Popper' + +export interface ModuleHoverProps { + node?: NodeSingular +} + +export const ModuleGraphNodeHover: React.FC = ({ node }) => { + const { address, name } = node?.data() ?? {} + const [boundingBox, setBoundingBox] = useState(node?.renderedBoundingBox()) + const ref = useRef(null) + const [currentEl, setCurrentEl] = useState(null) + + useLayoutEffect(() => { + if (node && ref.current) { + setBoundingBox(node.renderedBoundingBox()) + setCurrentEl(ref.current) + } + + const listener = () => { + setBoundingBox(node?.renderedBoundingBox()) + } + + node?.on('position', listener) + + return () => { + node?.off('position', undefined, listener) + } + }, [node]) + + return ( + <> + {node ? ( + <> +
+ + + ) : null} + + ) +} diff --git a/packages/sdk/packages/node-renderer/src/components/module/graph/Popper.tsx b/packages/sdk/packages/node-renderer/src/components/module/graph/Popper.tsx new file mode 100644 index 0000000000..059dc89ccb --- /dev/null +++ b/packages/sdk/packages/node-renderer/src/components/module/graph/Popper.tsx @@ -0,0 +1,23 @@ +import { alpha, Chip, Popper, PopperProps, Theme, Typography } from '@mui/material' +import { FlexCol, FlexRow } from '@xylabs/react-flexbox' +import { Identicon } from '@xylabs/react-identicon' + +export interface ModuleHoverPopperProps extends PopperProps { + address?: string + element?: HTMLElement | null + name?: string +} + +export const ModuleHoverPopper: React.FC = ({ address, element, name, ...props }) => { + return ( + + alpha(theme.palette.background.paper, 0.95) }}> + + + {name} + + + + + ) +} diff --git a/packages/sdk/packages/node-renderer/src/components/module/graph/index.ts b/packages/sdk/packages/node-renderer/src/components/module/graph/index.ts new file mode 100644 index 0000000000..164c92d04f --- /dev/null +++ b/packages/sdk/packages/node-renderer/src/components/module/graph/index.ts @@ -0,0 +1 @@ +export * from './GraphFlexBox' diff --git a/packages/sdk/packages/node-renderer/src/components/module/index.ts b/packages/sdk/packages/node-renderer/src/components/module/index.ts new file mode 100644 index 0000000000..9cb5435dc5 --- /dev/null +++ b/packages/sdk/packages/node-renderer/src/components/module/index.ts @@ -0,0 +1,2 @@ +export * from './CardParser' +export * from './graph' diff --git a/packages/sdk/packages/node-renderer/src/hooks/cytoscape/index.ts b/packages/sdk/packages/node-renderer/src/hooks/cytoscape/index.ts index 362777272e..ca0f84bc9a 100644 --- a/packages/sdk/packages/node-renderer/src/hooks/cytoscape/index.ts +++ b/packages/sdk/packages/node-renderer/src/hooks/cytoscape/index.ts @@ -1,6 +1,7 @@ -export * from './useAddNewElements' export * from './useCytoscapeElements' export * from './useCytoscapeOptions' +export * from './useHoveredNode' export * from './useNewElements' -export * from './usePopperListener' export * from './useRelationalGraphOptions' +export * from './useRenderNewElements' +export * from './useSelectedElement' diff --git a/packages/sdk/packages/node-renderer/src/hooks/cytoscape/useAddNewElements.tsx b/packages/sdk/packages/node-renderer/src/hooks/cytoscape/useAddNewElements.tsx deleted file mode 100644 index 71a4e9d0f9..0000000000 --- a/packages/sdk/packages/node-renderer/src/hooks/cytoscape/useAddNewElements.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { ElementDefinition } from 'cytoscape' -import { useEffect } from 'react' - -import { useCytoscapeInstance } from '../../contexts' -import { ColaLayout } from '../../Cytoscape' -import { usePopperListener } from './usePopperListener' - -export const useAddNewElements = (newElements: ElementDefinition[] = [], hideLabels?: boolean) => { - const { cy } = useCytoscapeInstance(true) - const popperListener = usePopperListener() - - useEffect(() => { - if (newElements.length > 1) { - const renderedElements = cy?.add(newElements) - renderedElements?.nodes().forEach((node) => popperListener(node, hideLabels, cy)) - cy?.layout(ColaLayout).run() - } - }, [cy, hideLabels, newElements, popperListener]) -} diff --git a/packages/sdk/packages/node-renderer/src/hooks/cytoscape/useHoveredNode.tsx b/packages/sdk/packages/node-renderer/src/hooks/cytoscape/useHoveredNode.tsx new file mode 100644 index 0000000000..3d860b894c --- /dev/null +++ b/packages/sdk/packages/node-renderer/src/hooks/cytoscape/useHoveredNode.tsx @@ -0,0 +1,32 @@ +import { NodeCollection, NodeSingular } from 'cytoscape' +import { useCallback, useEffect, useState } from 'react' + +import { useCytoscapeInstance } from '../../contexts' + +export const useHoveredNode = (renderedElements?: NodeCollection) => { + const { cy } = useCytoscapeInstance(true) + const [hoveredNode, setHoveredNode] = useState() + + const nodeListener = useCallback((node: NodeSingular) => { + node.on('mouseover tap', () => { + setHoveredNode(node) + }) + node.on('mouseout', () => { + setHoveredNode(undefined) + }) + }, []) + + useEffect(() => { + if (renderedElements) { + renderedElements.nodes().forEach(nodeListener) + } + }, [nodeListener, renderedElements]) + + useEffect(() => { + cy?.ready(() => { + cy.nodes().forEach(nodeListener) + }) + }, [cy, nodeListener]) + + return hoveredNode +} diff --git a/packages/sdk/packages/node-renderer/src/hooks/cytoscape/useNewElements.tsx b/packages/sdk/packages/node-renderer/src/hooks/cytoscape/useNewElements.tsx index d9ece9129c..52367a9c3e 100644 --- a/packages/sdk/packages/node-renderer/src/hooks/cytoscape/useNewElements.tsx +++ b/packages/sdk/packages/node-renderer/src/hooks/cytoscape/useNewElements.tsx @@ -1,13 +1,12 @@ import { useModuleFromNode } from '@xyo-network/react-node' -import { NodeDataDefinition } from 'cytoscape' -import { useEffect, useState } from 'react' +import { NodeSingular } from 'cytoscape' +import { useEffect } from 'react' import { useCytoscapeInstance } from '../../contexts' import { useCytoscapeElements } from './useCytoscapeElements' -export const useNewElements = () => { +export const useNewElements = (selectedElement?: NodeSingular) => { const { cy } = useCytoscapeInstance(true) - const [selectedElement, setSelectedElement] = useState() const { address: selectedAddress } = selectedElement?.data() ?? {} const [module] = useModuleFromNode(selectedAddress) const newElements = useCytoscapeElements(module) @@ -19,5 +18,5 @@ export const useNewElements = () => { } }, [cy, selectedAddress]) - return { newElements, setSelectedElement } + return newElements } diff --git a/packages/sdk/packages/node-renderer/src/hooks/cytoscape/usePopperListener.tsx b/packages/sdk/packages/node-renderer/src/hooks/cytoscape/usePopperListener.tsx deleted file mode 100644 index 6b84b78e3a..0000000000 --- a/packages/sdk/packages/node-renderer/src/hooks/cytoscape/usePopperListener.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { useTheme } from '@mui/material' -import { Core, NodeSingular } from 'cytoscape' -import { useCallback } from 'react' - -export const usePopperListener = () => { - const theme = useTheme() - - const popperListener = useCallback( - (node: NodeSingular, hideLabels?: boolean, cy?: Core) => { - const div = document.createElement('div') - const shadowColor = theme.palette.getContrastText(theme.palette.text.primary) - - const popper = node.popper({ - content: () => { - div.innerHTML = node.data().name - div.style.opacity = '0' - div.style.transition = 'opacity .25s' - div.style.textShadow = `0 0 3px ${shadowColor}` - - document.body.appendChild(div) - - return div - }, - }) - - const update = async () => { - await popper.update() - } - - node.on('position', update) - node.on('mouseover', () => (hideLabels ? (div.style.opacity = '1') : undefined)) - node.on('mouseout', () => (hideLabels ? (div.style.opacity = '0') : undefined)) - - cy?.on('pan zoom resize', update) - }, - [theme], - ) - - return popperListener -} diff --git a/packages/sdk/packages/node-renderer/src/hooks/cytoscape/useRelationalGraphOptions.tsx b/packages/sdk/packages/node-renderer/src/hooks/cytoscape/useRelationalGraphOptions.tsx index 078565b531..86a8ecc600 100644 --- a/packages/sdk/packages/node-renderer/src/hooks/cytoscape/useRelationalGraphOptions.tsx +++ b/packages/sdk/packages/node-renderer/src/hooks/cytoscape/useRelationalGraphOptions.tsx @@ -1,13 +1,13 @@ import { ModuleInstance } from '@xyo-network/module' import { useState } from 'react' -import { ColaLayout } from '../../Cytoscape' +import { ConcentricLayout } from '../../Cytoscape' import { useCytoscapeElements } from './useCytoscapeElements' import { useCytoscapeOptions } from './useCytoscapeOptions' import { useCytoscapeStyle } from './useCytoscapeStyle' export const useRelationalGraphOptions = (module?: ModuleInstance) => { - const [hideLabels, setHideLabels] = useState(false) + const [hideLabels, setHideLabels] = useState(true) const handleToggleLabels = () => { setHideLabels((oldValue) => !oldValue) @@ -15,7 +15,7 @@ export const useRelationalGraphOptions = (module?: ModuleInstance) => { const elements = useCytoscapeElements(module) const style = useCytoscapeStyle(hideLabels) - const options = useCytoscapeOptions(elements, style, ColaLayout) + const options = useCytoscapeOptions(elements, style, ConcentricLayout) return { handleToggleLabels, hideLabels, options } } diff --git a/packages/sdk/packages/node-renderer/src/hooks/cytoscape/useRenderNewElements.tsx b/packages/sdk/packages/node-renderer/src/hooks/cytoscape/useRenderNewElements.tsx new file mode 100644 index 0000000000..45f761aa66 --- /dev/null +++ b/packages/sdk/packages/node-renderer/src/hooks/cytoscape/useRenderNewElements.tsx @@ -0,0 +1,20 @@ +import { CollectionReturnValue, ElementDefinition } from 'cytoscape' +import { useEffect, useState } from 'react' + +import { useCytoscapeInstance } from '../../contexts' +import { ColaLayout } from '../../Cytoscape' + +export const useRenderNewElements = (newElements: ElementDefinition[] = [], hideLabels?: boolean) => { + const { cy } = useCytoscapeInstance(true) + const [renderedElements, setRenderedElements] = useState() + + useEffect(() => { + if (newElements.length > 1) { + const renderedElements = cy?.add(newElements) + setRenderedElements(renderedElements) + cy?.layout(ColaLayout).run() + } + }, [cy, hideLabels, newElements]) + + return renderedElements +} diff --git a/packages/sdk/packages/node-renderer/src/hooks/cytoscape/useSelectedElement.tsx b/packages/sdk/packages/node-renderer/src/hooks/cytoscape/useSelectedElement.tsx new file mode 100644 index 0000000000..3ab6fcfce8 --- /dev/null +++ b/packages/sdk/packages/node-renderer/src/hooks/cytoscape/useSelectedElement.tsx @@ -0,0 +1,23 @@ +import { EventObject, NodeSingular } from 'cytoscape' +import { useEffect, useState } from 'react' + +import { useCytoscapeInstance } from '../../contexts' + +export const useSelectedElement = () => { + const { cy } = useCytoscapeInstance(true) + const [selectedElement, setSelectedElement] = useState() + + useEffect(() => { + const listener = (event: EventObject) => { + const element = event.target[0] + if (element.isNode()) setSelectedElement(element) + } + cy?.on('select', listener) + + return () => { + cy?.off('select', listener) + } + }, [cy, setSelectedElement]) + + return selectedElement +} diff --git a/packages/sdk/packages/node-renderer/src/types/global.d.ts b/packages/sdk/packages/node-renderer/src/types/global.d.ts index c09b24e89c..4174b06e48 100644 --- a/packages/sdk/packages/node-renderer/src/types/global.d.ts +++ b/packages/sdk/packages/node-renderer/src/types/global.d.ts @@ -2,8 +2,3 @@ declare module 'cytoscape-cola' { const ext: cytoscape.Ext export = ext } - -declare module 'cytoscape-popper' { - const ext: cytoscape.Ext - export = ext -} diff --git a/yarn.lock b/yarn.lock index ae2196a0a1..902afed07b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9717,6 +9717,7 @@ __metadata: "@types/react-dom": ^18.2.8 "@xylabs/react-async-effect": ^3.0.6 "@xylabs/react-flexbox": ^3.0.6 + "@xylabs/react-identicon": ^3.0.6 "@xylabs/react-shared": ^3.0.6 "@xylabs/ts-scripts-yarn3": ^3.0.79 "@xylabs/tsconfig-react": ^3.0.79 @@ -9739,7 +9740,6 @@ __metadata: "@xyo-network/sentinel": ^2.75.4 cytoscape: ^3.26.0 cytoscape-cola: ^2.5.1 - cytoscape-popper: ^2.0.0 typescript: ^5.2.2 peerDependencies: "@mui/icons-material": ^5 @@ -13218,17 +13218,6 @@ __metadata: languageName: node linkType: hard -"cytoscape-popper@npm:^2.0.0": - version: 2.0.0 - resolution: "cytoscape-popper@npm:2.0.0" - dependencies: - "@popperjs/core": ^2.0.0 - peerDependencies: - cytoscape: ^3.2.0 - checksum: 857ea88e4d32e359c255785696fb68b993a1122db8ff492fe6977ea6908e82b1c63a4c73f8c04f2bdc3cbcf562f91f71a615d09e4985054dd709ba34b2739b04 - languageName: node - linkType: hard - "cytoscape@npm:^3.26.0": version: 3.26.0 resolution: "cytoscape@npm:3.26.0"