[{"data":1,"prerenderedAt":7},["ShallowReactive",2],{"example-markdown-content:en:system-architecture-diagram":3},{"markdown":4,"isPaidExample":5,"isTruncated":5,"charLimit":6},"# System Architecture Diagram with Custom Post-Layout Packing\n\n## What This Example Builds\n\nThis example turns one hierarchical platform description into a layered system architecture board. The finished view is not a conventional node-link diagram. Instead, it reads as stacked architecture sections, with large colored group containers for higher levels and white bordered cards for leaves.\n\nUsers can expand or collapse groups, switch the visible depth preset, toggle the minimap, show or hide expand tabs, change the level color palette, double-click any node to select its full descendant subtree, and open a floating settings panel to change canvas behavior or export an image.\n\nThe main implementation highlight is the two-step layout strategy. RelationGraph first builds fixed-layout hierarchy metadata, then the example runs its own packing pass to rearrange children inside each container and resize the parent box around the measured result. Combined with hidden links, that makes the graph look like a technical architecture board instead of a visible relationship network.\n\n## How the Data Is Organized\n\nThe shipped demo starts from an embedded nested tree in `ai-json-data.ts`. Each item contains `text`, approximate `x` and `y` coordinates, and optional `children`. At runtime, `parseJsonDataByAI()` flattens that tree into `RGJsonData`, generates node ids, preserves the source coordinates, stores depth metadata in `node.data`, and creates one parent-child line for every non-root relationship.\n\nThere are two important preprocessing steps before the final view is shown. First, every generated line is marked as hidden before `setJsonData()` runs, and the later style pass hides them again after the graph is loaded. Second, after loading, the example recolors nodes by level, expands the hierarchy to an initial threshold, and then performs its own post-layout packing pass before centering and fitting the viewport.\n\nIn a real system, the same structure could represent capability maps, product modules, technical stacks, platform layers, business domains, or any other hierarchy where approximate initial coordinates already exist and visible connectors would add more noise than value.\n\n## How relation-graph Is Used\n\nThe entry component wraps the demo in `RGProvider`, then `MyGraph` uses `RGHooks.useGraphInstance()` as the main control surface. Initialization uses `loading()`, `setJsonData()`, `moveToCenter()`, `zoomToFit()`, and `clearLoading()` to load and present the prepared graph. Later runtime behavior depends on instance methods such as `getNodes()`, `updateNodeData()`, `updateNode()`, `getNodesRectBox()`, `updateNodesVisibleProperty()`, `doLayout()`, `getDescendantNodes()`, `setEditingNodes()`, and `clearChecked()`.\n\nThe graph options deliberately start from a fixed base. The example enables `layoutName: 'fixed'`, rectangular nodes, curved lines, border junction points, left-side expand holders, relayout on expand or collapse, wheel scrolling, canvas dragging, and debug mode. That fixed layout is not the final visual arrangement. It is the intermediate stage that gives the code access to `node.lot.level` and `node.lot.childs`, which the custom layout pass then uses to repack children and resize each group container.\n\nSlots carry most of the visual transformation. `RGSlotOnNode` replaces default nodes with two branches: leaf nodes become white cards, while non-leaf nodes become framed containers with a title region. `RGSlotOnView` adds an optional `RGMiniView` and an always-on `RGEditingReferenceLine`. The shared floating helper window also uses `RGHooks.useGraphStore()` so its wheel and drag controls reflect the live graph options, and it uses `prepareForImageGeneration()` plus `restoreAfterImageGeneration()` to export the current canvas.\n\nStyling is as important as the layout code. The SCSS moves expand holders to the left edge, styles them as colored tabs through `var(--rg-node-color)`, renders level 0 and level 1 titles vertically on the left rail, and keeps leaf cards visually separate from group boxes. Because the example also hides every line, those slot and style overrides become the primary presentation layer.\n\n## Key Interactions\n\n- The depth selector shows labels `2` through `6`, maps them to thresholds `1` through `5`, reruns expansion, reapplies the custom layout, and fits the viewport again.\n- Double-clicking either a leaf card or a group container selects the clicked node together with all of its descendants through `getDescendantNodes()` and `setEditingNodes()`.\n- A minimap checkbox conditionally mounts or removes `RGMiniView`.\n- A second checkbox updates `defaultExpandHolderPosition` at runtime so expand or collapse tabs can stay visible on the left edge or disappear completely.\n- The palette editor can apply preset color schemes or change individual level colors, and each update recolors the graph by `node.lot.level`.\n- The floating settings overlay can switch wheel behavior, switch canvas drag behavior, and export the current graph as an image.\n- Clicking the canvas clears checked state and clears the current editing-node selection.\n\n## Key Code Fragments\n\nThis recursive branch shows how the nested source tree becomes graph lines and keeps flattening deeper levels.\n\n```ts\nif (parentNode) {\n    links_collect.push({\n        id: `${parentNode.id}-to-${nodeJson.id}`,\n        from: parentNode.id,\n        to: nodeJson.id\n    });\n}\nif (hasChildren) {\n    flatTreeData(_childs, nodeJson, nodes_collect, links_collect, deep + 1);\n}\n```\n\nThis initialization sequence hides connectors, loads the generated graph data, applies expansion and the custom layout, then centers and fits the result.\n\n```ts\nconst initializeGraph = async () => {\n    const myJsonData: RGJsonData = await parseJsonDataByAI();\n    myJsonData.lines.forEach(line => {\n        line.hidden = true;\n    });\n    graphInstance.loading();\n    await graphInstance.setJsonData(myJsonData);\n    updateGraphStyles();\n    await openByLevel(8);\n    await doMyLayout();\n    graphInstance.moveToCenter();\n    graphInstance.zoomToFit();\n    graphInstance.clearLoading();\n};\n```\n\nThis part of the post-layout pass measures each child cluster and resizes the parent group around the packed children.\n\n```ts\nconst childrenNodesSize = graphInstance.getNodesRectBox(childrenNodes);\nconst padding = 10;\nconst leftTitleWidth = node.lot.level \u003C= 1 ? 150 : 0;\nconst titleHeight = leftTitleWidth > 0 ? 0 : 30;\nconst groupMinWidth = 160;\ngraphInstance.updateNode(node, {\n    x: childrenNodesSize.minX - padding - leftTitleWidth,\n    y: childrenNodesSize.minY - padding - titleHeight,\n    width: Math.max(groupMinWidth, childrenNodesSize.width + padding * 2) + leftTitleWidth,\n    height: childrenNodesSize.height + padding * 2 + titleHeight\n});\n```\n\nThis slot renderer switches between leaf cards and group containers, and both branches attach the subtree-selection double-click behavior.\n\n```tsx\n\u003CRGSlotOnNode>\n    {({ node }: RGNodeSlotProps) => {\n        const level = node.lot?.level || 0;\n        const isLeaf = node.rgChildrenSize === 0;\n\n        return (\n            isLeaf ?\u003Cdiv\n                className={`my-leaf-node min-w-[150px] px-4 py-1 bg-white text-sm`}\n                onDoubleClick={() => {selectAllDescendantNodes(node);}}\n            >\n                    {node.text}\n            \u003C/div>\n```\n\nThis view slot adds viewer-oriented utilities without turning the example into a full editing workbench.\n\n```tsx\n\u003CRGSlotOnView>\n    {showMiniView && \u003CRGMiniView />}\n    \u003CRGEditingReferenceLine adsorption={true} />\n\u003C/RGSlotOnView>\n```\n\n## What Makes This Example Distinct\n\nCompared with `system-architecture-diagram-designer`, this example keeps the same architecture-board foundation but stays on the presentation side of the pattern. It does not add inline text editing, resize handles, or runtime node creation, so it is the cleaner reference when the goal is to render an architecture board rather than author one.\n\nCompared with `use-d3-layout`, the main lesson is not external algorithm swapping. The distinctive technique here is to let RelationGraph produce fixed hierarchy metadata, then use that metadata to run a shelf-style child packing pass, resize group containers around descendant bounds, and keep every connector hidden.\n\nCompared with slot-oriented viewer examples such as `node-slot-list` and `node`, the slots and styles here are not a general styling gallery. They all serve one narrow visual outcome: a layered architecture board with left-rail titles, depth-based colors, grouped containers, and level-based reveal controls.\n\nThe rare combination is the important part: embedded hierarchical JSON flattening, hidden parent-child lines, depth-coded groups, vertical section titles, runtime palette tuning, preset expansion levels, and a custom relayout pass on the same loaded diagram. That combination makes this example a strong starting point for architecture viewers where grouping matters more than visible edges.\n\n## Where Else This Pattern Applies\n\nThis pattern transfers well to technical capability maps, platform architecture overviews, layered product or service inventories, AI pipeline breakdowns, and enterprise system landscape summaries. It is especially useful when a hierarchy should stay visually grouped, when level-based reveal is helpful, and when explicit links would make the screen harder to read.\n\nIt can also be adapted to compliance control maps, operating model diagrams, responsibility stacks, or module dependency summaries where the underlying relationships still matter structurally but do not need to stay visible all the time. The reusable idea is to load a real hierarchy into relation-graph, keep the structural links for logic, and present the result as nested panels with custom packing and slot rendering.\n",false,500,1782616037889]