[{"data":1,"prerenderedAt":7},["ShallowReactive",2],{"example-markdown-content:en:circle-layout-isolated-nodes-with-green-straight-links":3},{"markdown":4,"isPaidExample":5,"isTruncated":5,"charLimit":6},"# Keeping Isolated Nodes Visible in a Styled Circle Layout\n\n## What This Example Builds\n\nThis example builds a full-height relation-graph viewer that places a sparse dataset into one circular arrangement. The visible result is a ring of 60 by 60 circular nodes, a small number of straight green links, and many nodes that look disconnected even though they still participate in the loaded graph. The main point is the combination of two small techniques: inject hidden structural lines before loading, then use graph options to make the visible links look deliberate without adding custom rendering.\n\n## How the Data Is Organized\n\nThe graph data is declared inline inside `initializeGraph()` as one `RGJsonData` object with 19 nodes and 5 visible lines. Before `setJsonData()` runs, the code derives `rootId` from the first node (`a`), writes that value back to `myJsonData.rootId`, and appends one invisible root-to-node helper line for every other node by generating sequential `l6`, `l7`, and later ids with `opacity: 0`.\n\nThat means the loaded graph is structurally more connected than the visible graph. In a real application, the same pattern can represent people, accounts, devices, products, or knowledge-graph entities that still need placement in one layout even when explicit visible relationships are missing or incomplete.\n\n## How relation-graph Is Used\n\n`index.tsx` wraps the example in `RGProvider`, and `MyGraph.tsx` retrieves the mounted graph instance through `RGHooks.useGraphInstance()`. The graph options define almost all of the visible behavior: `layoutName: 'circle'`, `RGNodeShape.circle`, `RGLineShape.StandardStraight`, border junction points, 60 by 60 default node size, 2-pixel lines, and a green default line color.\n\nThe runtime flow is minimal and explicit. A mount-only `useEffect()` calls `initializeGraph()`, the inline dataset is augmented in memory, and then the graph instance runs `setJsonData()`, `moveToCenter()`, and `zoomToFit()`. The example does not use slots, editor features, viewport tools, or extra graph subcomponents beyond `RGProvider` and `RelationGraph`. It imports a local SCSS file and wraps the canvas in `.my-graph`, but the reviewed stylesheet is mostly empty selector scaffolding, so the visual result comes primarily from the graph options and the `height: '100vh'` wrapper.\n\n## Key Interactions\n\n- The graph loads automatically on mount, then centers and fits itself to the viewport.\n- Clicking a node triggers `onNodeClick`, but the handler only logs the clicked node object.\n- Clicking a line triggers `onLineClick`, but the handler only logs the clicked line object.\n- There is no editing flow, no expand or collapse behavior, no selection workflow, and no toolbar interaction in this example.\n\n## Key Code Fragments\n\nThis options block shows that the example teaches a circle layout plus explicit visible line styling through `RGOptions`.\n\n```tsx\nconst graphOptions: RGOptions = {\n    debug: false,\n    defaultJunctionPoint: RGJunctionPoint.border,\n    defaultNodeShape: RGNodeShape.circle,\n    defaultLineShape: RGLineShape.StandardStraight,\n    defaultNodeWidth: 60,\n    defaultNodeHeight: 60,\n    defaultLineWidth: 2,\n    defaultLineColor: 'green',\n    layout: {\n        layoutName: 'circle'\n    }\n};\n```\n\nThis inline dataset is small and static before preprocessing, which makes the later augmentation step easy to see.\n\n```tsx\nconst myJsonData: RGJsonData = {\n    rootId: '',\n    nodes: [\n        { id: 'a', text: 'a' },\n        { id: 'b', text: 'b' },\n        { id: 'b1', text: 'b1' },\n        // ...\n        { id: 'e2', text: 'e2' }\n    ],\n    lines: [\n        { id: 'l1', from: 'b', to: 'b1' },\n        { id: 'l2', from: 'c2', to: 'b5' }\n        // ...\n    ]\n};\n```\n\nThis preprocessing pass is the core workaround: it derives a root and appends invisible helper edges before the graph is loaded.\n\n```tsx\nconst rootId = myJsonData.nodes[0].id;\nmyJsonData.rootId = rootId;\n\nlet lineCounter = myJsonData.lines.length + 1;\nmyJsonData.nodes.forEach(n => {\n    if (n.id !== rootId) {\n        myJsonData.lines.push({\n            id: `l${lineCounter++}`,\n            from: rootId,\n            to: n.id,\n            opacity: 0\n        });\n    }\n});\n```\n\nThis bootstrap sequence proves that the augmented data is loaded and framed automatically, and that user interaction stays inspection-only.\n\n```tsx\nuseEffect(() => {\n    initializeGraph();\n}, []);\n\nawait graphInstance.setJsonData(myJsonData);\ngraphInstance.moveToCenter();\ngraphInstance.zoomToFit();\n\nconst onNodeClick = (nodeObject: RGNode, $event: RGUserEvent) => {\n    console.log('onNodeClick:', nodeObject);\n};\n```\n\n## What Makes This Example Distinct\n\nThe prepared comparison data positions this example as the style-explicit sibling of the isolated-node workaround demos. Like `show-single-nodes` and `show-single-nodes2`, it derives a root from the first node and injects hidden helper edges so isolated-looking nodes still participate in layout. What makes this version stand out is that it also turns visible line styling into part of the lesson by using global options for straight 2-pixel green links in a `circle` layout.\n\nCompared with `show-single-nodes`, this version is less of a plain baseline and more of a compact reference for option-level line styling on top of the same workaround. Compared with `show-single-nodes2`, it keeps orbit-like circle placement instead of switching to a force layout with repulsion tuning. Compared with `advanced-line-usage`, its line configuration supports a disconnected-data layout workaround rather than serving as a broader visible line-behavior reference board.\n\n## Where Else This Pattern Applies\n\nThis pattern transfers well to graph views that must keep incomplete or currently unlinked records visible without inventing visible business relationships: unassigned employees in org data, devices with partial topology imports, customer or product records waiting for link resolution, or knowledge-graph entities that still need stable placement during review.\n\nIt is also a practical starting point when a team wants a small example that combines structural preprocessing with readable default edge styling. The hidden helper lines can remain an internal loading tactic while labels, panels, filters, or richer interactions are added later.\n",false,500,1782615419227]