[{"data":1,"prerenderedAt":7},["ShallowReactive",2],{"example-markdown-content:en:corporate-group-relationship-map":3},{"markdown":4,"isPaidExample":5,"isTruncated":5,"charLimit":6},"# Corporate Group Relationship Map with Live Node Skin Switching\n\n## What This Example Builds\nThis example builds a read-focused corporate relationship viewer on a single centered canvas. It loads a prebuilt graph of 111 nodes and 209 labeled relationships, mixes controller-like people nodes with company nodes, and presents them as a dense network instead of a hierarchy. Users can switch the same loaded graph between circle and rect node presentations, turn custom slot rendering on or off, open a floating utility panel, change wheel and drag behavior, and export the current canvas as an image. The most useful technical point is that the presentation changes happen on the live graph instance instead of rebuilding the dataset.\n\n## How the Data Is Organized\nThe data lives in `my-data.ts` as a static inline `RGJsonData` object returned by the async `getMyJsonData()` helper. The object contains a `rootId`, a `nodes` array, and a `lines` array. Each node carries display fields such as `id`, `text`, `color`, and `borderColor`, and most nodes also include `data.nodetype` so the renderer can distinguish `ctrler` entities from `ent` entities; the dataset also contains one `main` node type. Each line contains `from`, `to`, `text`, and `fontColor`, and those labels mix percentages with executive-role text such as director or manager titles, so the graph represents a broader relationship board rather than a pure equity tree.\n\nThere is no real preprocessing before `setJsonData(...)`. `initializeGraph()` simply awaits `getMyJsonData()` and passes the object directly to relation-graph. In a production system, the same structure could come from shareholder analysis, board-control data, affiliate networks, partner ownership data, or compliance review outputs.\n\n## How relation-graph Is Used\nThe entry file wraps the demo in `RGProvider`, which allows hooks to resolve the active graph instance. Inside `MyGraph.tsx`, `RGHooks.useGraphInstance()` drives the main workflow: loading the static dataset, centering the viewport, fitting the graph to the canvas, changing runtime options, and updating already rendered nodes. The graph starts with `layoutName: 'center'`, `RGLineShape.StandardCurve`, `RGJunctionPoint.border`, no default node border, and a default node size of `60 x 60`.\n\nThe key implementation detail is the shape switch. `defaultNodeShape` is bound to React state, but the code also calls `getNodes()` and `updateNode(...)` after load because changing defaults alone does not restyle nodes that already exist in the graph. When the user switches to rectangular nodes, the example also changes the junction point from `border` to `ltrb` so connectors attach in a way that suits the new geometry.\n\n`RGSlotOnNode` is optional rather than mandatory. When enabled, the same data renders through custom business-oriented markup: circle mode shows an icon centered inside the node with a detached label below it, while rect mode shows a white chip with icon, text, and a border that reuses `var(--rg-node-color)`. The icon choice depends on `node.data.nodetype`, so controller nodes and enterprise nodes remain visually distinct.\n\nThe floating helper window comes from the shared `DraggableWindow` component. Its settings overlay uses `RGHooks.useGraphStore()` to read the current interaction options and uses graph instance APIs to switch `wheelEventAction` and `dragEventAction`. The same shared panel also runs the export flow through `prepareForImageGeneration()`, `modern-screenshot`, and `restoreAfterImageGeneration()`. Local SCSS overrides keep the canvas background white and style the detached node text, especially in the checked state.\n\n## Key Interactions\nThe Rect and Circle selector changes live node geometry and connector attachment behavior on already loaded nodes.\n\nThe checkbox mounts or unmounts `RGSlotOnNode`, so users can compare custom business-oriented node skins against built-in node rendering without changing the underlying data.\n\nThe floating description window can be dragged, minimized, and switched into a settings overlay from the gear button.\n\nInside the settings overlay, wheel handling can switch between `scroll`, `zoom`, and `none`, while canvas drag handling can switch between `selection`, `move`, and `none`.\n\nThe Download Image action captures the current graph canvas through the shared screenshot helper and downloads the result as a file.\n\n## Key Code Fragments\nThis fragment shows that the graph loads one prepared dataset, then recenters and fits the viewport instead of incrementally expanding branches.\n\n```tsx\nconst initializeGraph = async () => {\n    const myJsonData = await getMyJsonData();\n    await graphInstance.setJsonData(myJsonData);\n    graphInstance.moveToCenter(); // Center on canvas slot content\n    graphInstance.zoomToFit(); // Zoom to fit canvas slot content\n};\n```\n\nThis fragment proves that shape switching is applied to the live graph, not just to future nodes.\n\n```tsx\ngraphInstance.getNodes().forEach(node => {\n    graphInstance.updateNode(node, {\n        nodeShape: nodeShape,\n        width: nodeShape === RGNodeShape.circle ? 60 : 0,\n        height: nodeShape === RGNodeShape.circle ? 60 : 0\n    })\n});\n```\n\nThis fragment shows that custom slot rendering is optional and can be turned on or off from the example UI.\n\n```tsx\n\u003CSimpleUIBoolean\n    label=\"Use Node Slot to Render Node Content\"\n    currentValue={enableNodeSlot}\n    onChange={setEnableNodeSlot}\n/>\n\u003C/div>\n\u003C/DraggableWindow>\n\u003CRelationGraph options={graphOptions}>\n    {enableNodeSlot && \u003CRGSlotOnNode>\n```\n\nThis fragment shows how the slot renderer changes node content by shape and by business entity type.\n\n```tsx\nnodeShape === RGNodeShape.circle ? (\n    \u003Cdiv className=\"w-full h-full flex place-items-center justify-center\">\n        \u003Cdiv className=\"text-white w-full h-full flex place-items-center justify-center\">\n            {node.data.nodetype === 'ctrler' ? \u003CUserCircleIcon size={32} /> : \u003CBuilding2Icon size={32} />}\n        \u003C/div>\n        \u003Cdiv className=\"my-node-text absolute transform translate-y-[45px]\">{node.text}\u003C/div>\n    \u003C/div>\n) : (\n```\n\nThis fragment comes from the shared helper and shows how the example exposes export without rebuilding the graph.\n\n```tsx\nconst canvasDom = await graphInstance.prepareForImageGeneration();\nlet graphBackgroundColor = graphInstance.getOptions().backgroundColor;\nif (!graphBackgroundColor || graphBackgroundColor === 'transparent') {\n    graphBackgroundColor = '#ffffff';\n}\nconst imageBlob = await domToImageByModernScreenshot(canvasDom, {\n    backgroundColor: graphBackgroundColor\n});\nif (imageBlob) {\n    downloadBlob(imageBlob, 'my-image-name');\n}\n```\n\n## What Makes This Example Distinct\nCompared with nearby business examples such as `scene-org`, `investment-penetration`, and `investment`, this example stays on one preloaded centered network canvas instead of turning the scene into a tree, an org chart, or a lazy expansion flow. That matters when the requirement is to inspect many cross-links and mixed relationship labels at once.\n\nCompared with runtime-style neighbors such as `css-theme` and `drag-and-wheel-event`, the controls here are tied to business-scene readability. The main lesson is not generic theming or canvas testing. It is how to keep one dense corporate graph loaded and let users switch between built-in nodes and custom slot-rendered business skins while also changing node geometry on the already rendered graph.\n\nThe comparison data also marks the combination itself as unusual: center layout, dense labeled lines, role-colored people-versus-company entities, runtime node-shape switching, optional `RGSlotOnNode`, and a shared floating settings or export shell on the same page. That combination makes this example a stronger starting point for compact business-network viewers than for editors or hierarchy-first charts.\n\n## Where Else This Pattern Applies\nThis pattern transfers well to shareholder-control review screens, affiliate-network analysis, board-and-executive relationship viewers, and due-diligence dashboards that need one dense relationship board instead of a directional tree.\n\nIt also fits cases where product teams want two presentation modes over the same graph data, such as a compact icon-first overview and a more readable label-first card view.\n\nThe live `updateNode(...)` restyling approach is especially useful in any graph product where users can change visual encoding after load, for example switching between risk views, entity categories, or audience-specific display modes without re-fetching the dataset.\n",false,500,1782615399132]