[{"data":1,"prerenderedAt":7},["ShallowReactive",2],{"example-markdown-content:en:show-single-nodes":3},{"markdown":4,"isPaidExample":5,"isTruncated":5,"charLimit":6},"# Keeping Isolated Nodes Visible in a Circle Layout\n\n## What This Example Builds\n\nThis example builds a full-height relation-graph viewer that arranges a sparse set of circular nodes into one orbit-like circle. Several nodes appear to have no visible relationships, but they still stay in the layout because the dataset is augmented with hidden structural edges before loading. Users can inspect the graph and click nodes or lines, although those clicks only write the clicked objects to the console.\n\n## How the Data Is Organized\n\nThe graph data is created inline inside `initializeGraph()` as one `RGJsonData` object with 19 nodes and 5 explicit lines. Before the data is loaded, the code derives `rootId` from the first node (`a`) and appends one extra root-to-node line for every other node with `opacity: 0`. In a real application, the same structure can represent people, devices, services, accounts, or records where some items have no visible relationship but still need stable placement inside one shared layout.\n\n## How relation-graph Is Used\n\n`index.tsx` wraps the example in `RGProvider`, and `MyGraph.tsx` retrieves the provider-scoped instance with `RGHooks.useGraphInstance()`. The graph options enable relation-graph's built-in `circle` layout, use border junction points, render nodes as 60 by 60 circles, and keep the default line width at 2. A mount-time `useEffect()` runs the initialization sequence: assemble the data, inject hidden helper edges, call `setJsonData()`, then `moveToCenter()` and `zoomToFit()`.\n\nThe example does not use custom slots, viewport tools, editor features, or extra graph subcomponents beyond `RGProvider` and `RelationGraph`. The reviewed SCSS file is only a shell of empty selectors, so the visible result is essentially relation-graph defaults plus the chosen layout and the inline wrapper height.\n\n## Key Interactions\n\n- The graph loads automatically when the component mounts, then immediately centers and fits itself to the viewport.\n- Clicking a node triggers `onNodeClick`, but the handler only logs the node object.\n- Clicking a line triggers `onLineClick`, but the handler only logs the line object.\n- There is no toolbar, expand/collapse flow, edit mode, or selection workflow in this example.\n\n## Key Code Fragments\n\nThis options block shows that the example relies on relation-graph's built-in circle layout and circular node defaults.\n\n```tsx\nconst graphOptions: RGOptions = {\n    debug: false,\n    defaultJunctionPoint: RGJunctionPoint.border,\n    defaultNodeShape: RGNodeShape.circle,\n    defaultNodeWidth: 60,\n    defaultNodeHeight: 60,\n    defaultLineWidth: 2,\n    layout: {\n        layoutName: 'circle'\n    }\n};\n```\n\nThis preprocessing pass is the core workaround: it derives a root and appends hidden helper lines before the graph is loaded.\n\n```tsx\nconst rootId = myJsonData.nodes[0].id;\nmyJsonData.rootId = rootId;\nlet lineIndex = myJsonData.lines.length + 1;\nmyJsonData.nodes.forEach(n => {\n    if (n.id !== rootId) {\n        myJsonData.lines.push({\n            id: `l${lineIndex++}`,\n            from: rootId,\n            to: n.id,\n            opacity: 0\n        });\n    }\n});\n```\n\nThis mount-time sequence proves that the augmented dataset is loaded and framed automatically instead of waiting for a manual action.\n\n```tsx\nuseEffect(() => {\n    initializeGraph();\n}, []);\n\n// ...\n\nawait graphInstance.setJsonData(myJsonData);\ngraphInstance.moveToCenter();\ngraphInstance.zoomToFit();\n```\n\nThis handler pair shows that user interaction is limited to inspection-oriented logging.\n\n```tsx\nconst onNodeClick = (nodeObject: RGNode, $event: RGUserEvent) => {\n    console.log('onNodeClick:', nodeObject);\n};\n\nconst onLineClick = (lineObject: RGLine, linkObject: RGLink, $event: RGUserEvent) => {\n    console.log('onLineClick:', lineObject);\n};\n```\n\n## What Makes This Example Distinct\n\nAccording to the prepared comparison data, this example is a plain baseline reference for one specific workaround: keep isolated-looking nodes inside a `circle` layout by manufacturing an invisible connected backbone before `setJsonData()`. That combination of inline static data, load-time augmentation, log-only click handlers, and a mostly default full-height canvas is the part that is rare, not the use of `RGProvider` or the standard load-center-fit API sequence by itself.\n\nCompared with `show-single-nodes3`, this version stays intentionally plain and does not turn visible line styling into part of the lesson. Compared with `show-single-nodes2`, it uses the same hidden-helper idea but keeps the placement strictly circle-based instead of switching to a force layout. Compared with `multi-group-2`, it does not render disconnected groups as-is; it rewrites the payload so nodes can still look isolated while participating in one chosen layout.\n\n## Where Else This Pattern Applies\n\nThis pattern transfers well to import-review and monitoring screens where some entities arrive without visible relationships but still need to stay on the canvas: unassigned employees in an org dataset, services without declared dependencies, partially matched customer records, or knowledge-graph entities that are waiting for links to be confirmed. It is also useful when a team wants the visual message of \"these items are currently isolated\" without giving up the stability of one built-in layout algorithm.\n",false,500,1782615417817]