[{"data":1,"prerenderedAt":7},["ShallowReactive",2],{"example-markdown-content:en:enterprise-quadrant-fixed-layout":3},{"markdown":4,"isPaidExample":5,"isTruncated":5,"charLimit":6},"# Build a Four-Quadrant Enterprise Graph with Fixed Coordinates\n\n## What This Example Builds\n\nThis example renders one company at the center of the canvas and places four relationship categories around it: investors, persons, outbound investments, and branch offices. Each category gets its own group node, its own color, and its own line treatment, so the result reads as a quadrant-style enterprise relationship map instead of a generic tree.\n\nThe user does not edit graph structure here. The main interaction is live retuning of a manual layout: a floating panel lets the user change line length and node spacing, and the graph is repositioned immediately. The key point is that relation-graph is used as a fixed-position rendering surface while custom code decides every node coordinate.\n\n## How the Data Is Organized\n\nThe data starts as inline arrays inside `initializeGraph()`: one root company plus four category lists. `generateGraphData(...)` converts those lists into `RGJsonData` by creating the center node, four group nodes, and all leaf nodes and lines before the graph is loaded.\n\nThe important preprocessing step is that the initial JSON does not contain final coordinates. Instead, the generator adds metadata such as `type`, `quadrantKey`, and `index`, and `applyLayout(...)` uses that metadata later to compute x and y positions. In a real system, the same structure could represent shareholders, executives, subsidiaries, offices, suppliers, distributors, or any category-based network around one primary entity.\n\n## How relation-graph Is Used\n\nThe graph runs in `fixed` layout mode, so relation-graph does not choose node positions. `RelationGraph` is configured with rectangular nodes, zero default borders, left-right junction points, and a straight-line default, while the generated line data overrides individual routes to mix curved center links with orthogonal leaf links.\n\n`RGProvider` supplies graph context, and `RGHooks.useGraphInstance()` is the main integration point. The example uses it to load JSON data with `setJsonData(...)`, read the live node list with `getNodes()`, write coordinates back with `updateNode(...)`, and then recenter and fit the viewport with `moveToCenter()` and `zoomToFit()`. The shared `CanvasSettingsPanel` also uses the graph instance to change `wheelEventAction` and `dragEventAction` at runtime and to export the canvas as an image.\n\nThere are no graph slots and no structural editing tools in this example. The extra UI comes from shared subcomponents: `DraggableWindow` provides the floating shell, and `CanvasSettingsPanel` provides canvas-mode toggles and image export. Styling is customized through generated class names such as `my-nodes-invs` and SCSS overrides for node colors, line-label backgrounds, expand holders, and checked-state line styling.\n\n## Key Interactions\n\nTwo range inputs drive the example-specific behavior. Changing `leafLineLength` or `leafNodeGap` updates React state, and a follow-up effect reruns the custom coordinate pass over the current graph nodes.\n\nThe helper window itself can be dragged, minimized, and switched into a settings view. Inside that settings view, the user can change wheel behavior between scroll, zoom, and none; change drag behavior between selection, move, and none; and export the current graph as an image.\n\nNode and line click handlers are present, but they only log the clicked object. They do not control selection, highlighting, or editing.\n\n## Key Code Fragments\n\nThis option block shows that the graph is intentionally put into fixed mode and given rectangular, left-right defaults.\n\n```tsx\nconst userGraphOptions: RGOptions = {\n    layout: {\n        layoutName: 'fixed'\n    },\n    defaultNodeBorderWidth: 0,\n    defaultNodeShape: RGNodeShape.rect,\n    defaultJunctionPoint: RGJunctionPoint.lr,\n    defaultLineShape: RGLineShape.StandardStraight\n};\n```\n\nThis fragment shows that structural graph JSON is assembled first, while each leaf keeps quadrant metadata for the later layout pass.\n\n```ts\nnodes.push({\n    ...item,\n    className: `my-nodes-${rule.nodeClassSuffix}`,\n    data: { type: 'leaf', quadrantKey: rule.key, index: index }\n});\n\nlines.push(createLine(rule.rootId, item.id, {\n    text: item.desc || '',\n    color: rule.color,\n    showEndArrow: false,\n    lineShape: RGLineShape.SimpleOrthogonal\n}));\n```\n\nThis coordinate fragment is the core manual-layout logic: it grows leaves upward or downward by category and places them to the left or right of the group node.\n\n```ts\nif (rule.isTop) {\n    leafY = groupOriginY - (index * (LEAF_NODE_H + leafNodeGap)) + 30;\n} else {\n    leafY = groupOriginY + (index * (LEAF_NODE_H + leafNodeGap));\n}\n\nconst leafX = rule.isLeft\n    ? groupOriginX - leafLineLength - node.el_W\n    : (groupOriginX + 140) + leafLineLength;\n\nnodesPosition.push({ nodeId: node.id, x: leafX, y: leafY });\n```\n\nThis runtime pass shows how the custom coordinates are pushed back into the live relation-graph instance.\n\n```tsx\nconst nodes = graphInstance.getNodes();\nconst nodesPosition = applyLayout(\n    nodes,\n    leafNodeInitialWidth,\n    leafLineLength,\n    leafNodeGap\n);\nfor (const nodePos of nodesPosition) {\n    graphInstance.updateNode(nodePos.nodeId, {\n        x: nodePos.x,\n        y: nodePos.y\n    });\n}\n```\n\n## What Makes This Example Distinct\n\nBased on the prepared comparison data, this example is distinct because it is a direct reference for deterministic manual coordinate assignment, not a showcase of relation-graph's built-in layout presets. Compared with `layout-center`, it is the stronger starting point when the placement rules come from application logic and must be written back as explicit x and y values. Compared with `bothway-tree` and `bothway-tree2`, it is not teaching tree orientation or branch restyling; it is teaching category-based quadrant placement in fixed mode. Compared with `deep-each`, the meaningful live interaction is parameterized relayout rather than click-driven focus highlighting.\n\nIts rare combination is also important: a corporate relationship scene, four color-coded rectangular quadrants around one company node, curved center links plus orthogonal labeled leaf links, and a floating white helper window with runtime canvas utilities. That combination makes it a practical bridge example for teams that need a predictable layout region for each category instead of a layout chosen by the library.\n\n## Where Else This Pattern Applies\n\nThis pattern transfers well to shareholder maps, corporate control diagrams, vendor or customer relationship summaries, branch or region maps, and compliance dashboards where each category needs a stable visual region. The same separation between `generateGraphData(...)` and `applyLayout(...)` can also be used when positions come from an external service or an in-house algorithm rather than from hand-written quadrant rules.\n\nIt is also a useful migration pattern for teams bringing existing layout math into relation-graph. You can generate `RGJsonData` once, compute positions in a separate pass, and then push those coordinates into the live graph instance without rewriting the rendering layer.\n",false,500,1782615388618]