[{"data":1,"prerenderedAt":7},["ShallowReactive",2],{"example-markdown-content:en:view-and-canvas-slots-overview":3},{"markdown":4,"isPaidExample":5,"isTruncated":5,"charLimit":6},"# Comparing Built-In View and Canvas Slots in One Graph\n\n## What This Example Builds\n\nThis example builds a full-height relation graph that doubles as a slot-surface comparison board. The graph itself is a small static network, but the visible teaching content is three large color-coded HTML panels rendered through `RGSlotOnView`, `RGSlotOnCanvasAbove`, and `RGSlotOnCanvas`.\n\nThe user can type into a text input in the view-layer panel, then watch that same text appear inside the two canvas-based panels. A `Show More Info` button in the canvas-above panel reveals an extra block, so the example demonstrates both shared state and a simple conditional overlay inside graph-owned layers.\n\nThe main point is not graph data editing or business semantics. The important result is a concrete side-by-side comparison of how built-in view and canvas slot surfaces can host ordinary interactive HTML.\n\n## How the Data Is Organized\n\nThe graph data is created inline inside `initializeGraph()` as one `RGJsonData` object with `rootId: '2'`, a flat `nodes` array, and a flat `lines` array. Each node carries `id`, `text`, and a `data.myicon` field. Each line already includes its own `id`, `from`, `to`, and `text`.\n\nThere is no separate preprocessing pass before `setJsonData()`. The object is assembled directly in the shape that relation-graph expects, then loaded into the instance as-is. In a real application, the same structure could represent organizations, systems, dependency links, ownership links, or any other small relationship set where the graph mainly serves as a host surface for layered UI.\n\n## How relation-graph Is Used\n\n`index.tsx` wraps the example in `RGProvider`, and `MyGraph.tsx` uses `RGHooks.useGraphInstance()` to get the active instance. A mount-only `useEffect()` calls `initializeGraph()`, which loads the inline dataset and immediately calls `moveToCenter()` and `zoomToFit()` so the demo starts in a normalized view.\n\nThe `RelationGraph` itself is configured lightly. The only explicit graph options are `defaultJunctionPoint: RGJunctionPoint.border` and `defaultLineColor: '#666'`. The reviewed source does not set an explicit `layout`, so the node arrangement comes from relation-graph defaults for this data.\n\nThe core implementation detail is that all three slot demonstrations are children of the same `RelationGraph` instance. `RGSlotOnView` hosts a fixed instructional panel with the text input. `RGSlotOnCanvasAbove` hosts a second panel with a toggle button and a conditional extra block. `RGSlotOnCanvas` hosts a third panel that continuously shows the mirrored text. Each panel uses `pointer-events-auto`, which allows ordinary HTML controls to remain interactive inside the graph scene.\n\nNo graph editing APIs, node events, or line events are used. The local SCSS file mostly provides empty selector scaffolding, so the visible teaching effect comes from inline absolute positioning, bright background colors, and the built-in slot surfaces themselves. The `Show More Info` control is a shared local `SimpleUIButton` component imported from `DraggableWindow.tsx`, not a special relation-graph widget.\n\n## Key Interactions\n\n- Typing in the `RGSlotOnView` input updates `searchText`.\n- The current `searchText` value is rendered again inside the `RGSlotOnCanvasAbove` reveal area and inside the `RGSlotOnCanvas` preview area.\n- Clicking `Show More Info` toggles the conditional block in the canvas-above slot.\n- The example is structured so users can compare a view-layer panel with two canvas-layer panels inside the same graph scene rather than opening a separate demo for each surface.\n\n## Key Code Fragments\n\nThis wrapper shows that the whole demo runs inside one relation-graph provider context.\n\n```tsx\nconst Demo = () => {\n    return (\n        \u003CRGProvider>\n            \u003CMyGraph />\n        \u003C/RGProvider>\n    );\n};\n```\n\nThis block shows that the example uses hook-based instance access and only minimal graph-level options.\n\n```tsx\nconst MyGraph = () => {\n  const [searchText, setSearchText] = useState('You can use this search box to search for nodes');\n  const [showBackgroundGraph, setShowBackgroundGraph] = useState(false);\n\n  const graphInstance = RGHooks.useGraphInstance();\n\n  const graphOptions: RGOptions = {\n    defaultJunctionPoint: RGJunctionPoint.border,\n    defaultLineColor: '#666'\n  };\n```\n\nThis fragment proves that the graph payload is assembled inline as flat `nodes` and `lines`.\n\n```tsx\nconst myJsonData: RGJsonData = {\n  rootId: '2',\n  nodes: [\n    { id: '1', text: 'Node-1', data: { myicon: 'el-icon-star-on' } },\n    { id: '2', text: 'Node-2', data: { myicon: 'el-icon-setting' } },\n    { id: '3', text: 'Node-3', data: { myicon: 'el-icon-setting' } },\n    // ... more nodes ...\n  ],\n  lines: [\n    { id: 'l1', from: '7', to: '71', text: 'Investment' },\n    { id: 'l2', from: '7', to: '72', text: 'Investment' },\n    // ... more lines ...\n  ]\n};\n```\n\nThis initialization sequence is the only graph-instance workflow: load the data, center it, then fit it.\n\n```tsx\nif (graphInstance) {\n  await graphInstance.setJsonData(myJsonData);\n  await graphInstance.moveToCenter();\n  await graphInstance.zoomToFit();\n}\n```\n\nThis slot fragment shows the view-layer panel and the input that drives shared React state.\n\n```tsx\n\u003CRGSlotOnView>\n  \u003Cdiv className=\"pointer-events-auto\" style={{ top: '0px', left: '0px', position: 'absolute', width: '600px', border: '#efefef solid 1px', zIndex: 22 }}>\n    \u003Cdiv style={{ backgroundColor: '#fa7b7e', padding: '10px', width: '100%', fontSize: '18px' }}>This is the view slot(RGSlotOnView)\u003C/div>\n    \u003Cdiv style={{ backgroundColor: '#7a9ef8', padding: '10px', width: '100%', fontSize: '12px' }}>\n      You can customize the content here, such as putting a search box:\n      \u003Cinput type=\"text\" defaultValue={searchText} onChange={(e) => { setSearchText(e.target.value); }} />\n    \u003C/div>\n  \u003C/div>\n\u003C/RGSlotOnView>\n```\n\nThis fragment shows the canvas-above slot using a local button to reveal extra content that reuses the same text state.\n\n```tsx\n\u003CRGSlotOnCanvasAbove>\n  \u003Cdiv className=\"pointer-events-auto\" style={{ top: '-300px', left: '-300px', position: 'absolute', width: '600px', border: '#efefef solid 1px' }}>\n    \u003Cdiv style={{ backgroundColor: '#f5df7a', padding: '10px', width: '100%', fontSize: '12px' }}>\n      You can put anything here, these contents will move and scale with the canvas.\n      \u003CSimpleUIButton onClick={toggleGraph}>Show More Info\u003C/SimpleUIButton>\n    \u003C/div>\n    {showBackgroundGraph && (\n      \u003Cdiv className=\"flex justify-center place-items-center text-2xl text-red-900\" style={{ backgroundColor: '#cb7ffd', width: '600px', height: '600px', overflow: 'hidden' }}>\n        \u003Cdiv>{searchText}\u003C/div>\n      \u003C/div>\n    )}\n  \u003C/div>\n\u003C/RGSlotOnCanvasAbove>\n```\n\nThis final slot keeps the mirrored text visible all the time in the canvas-layer panel.\n\n```tsx\n\u003CRGSlotOnCanvas>\n  \u003Cdiv className=\"pointer-events-auto\" style={{ top: '100px', left: '-100px', position: 'absolute', width: '600px', border: '#efefef solid 1px' }}>\n    \u003Cdiv style={{ backgroundColor: '#f5df7a', padding: '10px', width: '100%', fontSize: '12px' }}>\n      You can put anything here, even another graph, these contents will move and scale with the canvas.\n    \u003C/div>\n    \u003Cdiv className=\"flex justify-center place-items-center text-2xl text-red-900\" style={{ backgroundColor: 'rgba(127,201,253)', width: '600px', height: '400px', overflow: 'hidden' }}>\n      \u003Cdiv>{searchText}\u003C/div>\n    \u003C/div>\n  \u003C/div>\n\u003C/RGSlotOnCanvas>\n```\n\n## What Makes This Example Distinct\n\nThe comparison data makes the distinguishing point explicit: this example is unusual because it compares `RGSlotOnView`, `RGSlotOnCanvasAbove`, and `RGSlotOnCanvas` side by side inside one `RelationGraph`. Nearby examples such as `node-menu` and `node-menu-2` also use view-layer HTML, but they focus on node-triggered menus and transient overlays. This example keeps multiple teaching panels visible at once and does not depend on selecting a node, line, or canvas target.\n\nIt also differs from `scene-network-use-canvas-slot`, which uses a canvas slot as part of a finished dashboard-like composition. Here, the canvas slot is only one part of a three-surface comparison, and its content is intentionally simple so the layer behavior stays readable. Against `customize-fullscreen-action`, the main integration lesson moves inside the graph container rather than around it in a wrapper layout.\n\nThe most distinctive feature combination is a single shared React state flowing through three built-in slot surfaces: a view-slot input, a canvas-above reveal panel, and a canvas-slot readout. That makes this example a stronger starting point when the requirement is coordinated HTML overlays across graph layers rather than menus, fullscreen behavior, or graph editing.\n\n## Where Else This Pattern Applies\n\nThis pattern fits graph screens that need both fixed controls and graph-bound overlays at the same time. Examples include a search or filter box pinned to the viewport, annotation cards that should move with the canvas, and instructional panels that explain zoom or pan behavior directly inside the graph scene.\n\nIt also transfers well to monitoring boards, architecture diagrams, relationship inspection tools, and onboarding demos. In those cases, the underlying nodes and lines can come from real business data, while the slot composition pattern stays the same: one state source, ordinary HTML controls, and separate placement rules for view-level and canvas-level content.\n",false,500,1782615419944]