[{"data":1,"prerenderedAt":7},["ShallowReactive",2],{"example-markdown-content:en:node-descendant-subtree-highlight":3},{"markdown":4,"isPaidExample":5,"isTruncated":5,"charLimit":6},"# Highlighting a Node's Descendant Subtree\n\n## What This Example Builds\n\nThis example builds a full-viewport hierarchy viewer that starts from a preloaded tree of letter-labeled nodes and lets the user inspect one branch at a time. The graph is shown as a centered network of blue circular nodes with matching blue links, while a floating helper window explains the interaction and exposes shared demo utilities.\n\nThe main interaction is subtree focus. When the user clicks a non-leaf node, that node and all of its descendants stay fully visible and turn purple, while unrelated nodes fade into the background. Clicking the canvas clears that temporary focus state and restores the full graph.\n\nThe most important idea is that the graph data is not rebuilt after each click. The example keeps one loaded hierarchy in memory and changes node and line state in place through relation-graph instance APIs.\n\n## How the Data Is Organized\n\nThe dataset is declared inline as one `RGJsonData` object inside `initializeGraph`. It uses a flat structure with `rootId`, a `nodes` array of `{ id, text }` records, and a `lines` array of `{ id, from, to }` records. That shape is enough for relation-graph to reconstruct the hierarchy once `setJsonData()` runs.\n\nThere is no preprocessing step before `setJsonData()`. The only derived logic happens after the graph is already loaded: on node click, the code walks the runtime node object's `node.lot.childs` chain to collect descendant ids. That means the example teaches a runtime inspection pattern rather than a data-transformation pipeline.\n\nIn real applications, the same structure can represent category trees, organization units, folder hierarchies, product assemblies, or permissions inheritance. The letter labels here are only placeholder data for the interaction pattern.\n\n## How relation-graph Is Used\n\nThe demo is wrapped in `RGProvider` so hook-based graph access works inside `MyGraph`. The graph itself uses the `center` layout, circular nodes, and fixed 60 by 60 node sizing, with blue as the default node and line color. After the inline data is loaded, the instance recenters and fits the whole graph into view.\n\nThe example relies on `RGHooks.useGraphInstance()` rather than refs. That hook is used in two places: the main graph component uses it for `setJsonData()`, `moveToCenter()`, `zoomToFit()`, `getNodes()`, `getLines()`, `updateNode()`, `updateLine()`, and `dataUpdated()`, while the shared `DraggableWindow` settings panel uses the same graph context to change wheel and drag behavior and to export an image.\n\nNo relation-graph slots are rendered in the current source, and there is no editing workflow. This is a read-only viewer that demonstrates post-load graph mutation through instance APIs. The imported SCSS file is only a scaffold with empty rule blocks, so the visible styling comes from graph options and runtime state overrides rather than CSS skinning.\n\n## Key Interactions\n\nThe primary interaction is node click. A click on a non-leaf node recursively gathers the clicked node plus every descendant, then applies a focus-plus-context state: selected-branch nodes stay opaque and purple, unrelated nodes fade, and only internal lines inside the selected subtree are recolored.\n\nThe second important interaction is canvas click. Instead of reloading data, the canvas handler clears the temporary node and line overrides and commits the reset with `dataUpdated()`.\n\nThe floating helper window adds secondary utility interactions. It can be dragged, minimized, switched into a settings panel, used to change wheel and drag behavior through `setOptions()`, and used to export the graph as an image through `prepareForImageGeneration()` and `restoreAfterImageGeneration()`. Those controls are useful, but they come from shared demo scaffolding rather than from a subtree-specific implementation.\n\n## Key Code Fragments\n\nThis fragment shows that the demo is configured as a centered, circular, fixed-size hierarchy before any click logic is applied.\n\n```tsx\nconst graphInstance = RGHooks.useGraphInstance();\n\nconst graphOptions: RGOptions = {\n    layout: {\n        layoutName: 'center'\n    },\n    defaultNodeColor: 'rgb(29, 169, 245)',\n    defaultLineColor: 'rgb(29, 169, 245)',\n    defaultNodeShape: RGNodeShape.circle,\n    defaultNodeWidth: 60,\n    defaultNodeHeight: 60\n};\n```\n\nThis fragment shows the inline data-loading workflow that keeps the whole hierarchy in one graph instance from the start.\n\n```tsx\nconst initializeGraph = async () => {\n    const myJsonData: RGJsonData = {\n        rootId: 'a',\n        nodes: [\n            { id: 'a', text: 'a' }, { id: 'b', text: 'b' }, { id: 'b1', text: 'b1' },\n            // ...\n        ],\n        lines: [\n            { id: 'l1', from: 'a', to: 'b' }, { id: 'l2', from: 'b', to: 'b1' },\n            // ...\n        ]\n    };\n    await graphInstance.setJsonData(myJsonData);\n    graphInstance.moveToCenter();\n    graphInstance.zoomToFit();\n};\n```\n\nThis fragment proves that descendant collection happens from runtime node objects, not from a separate precomputed lookup table.\n\n```tsx\nconst deepGetAllChildIds = (node: RGNode, ids: string[] = []): string[] => {\n    if (ids.includes(node.id)) return ids;\n    ids.push(node.id);\n    for (const cNode of node.lot.childs) {\n        deepGetAllChildIds(cNode, ids);\n    }\n    return ids;\n};\n```\n\nThis fragment shows how the selected subtree stays visible while non-descendants are dimmed in one node-update pass.\n\n```tsx\nconst onNodeClick = (nodeObject: RGNode, $event: RGUserEvent) => {\n    const allChildIds = deepGetAllChildIds(nodeObject);\n    graphInstance.getNodes().forEach(node => {\n        if (allChildIds.includes(node.id)) {\n            graphInstance.updateNode(node, { opacity: 1, color: 'rgb(116,2,173)' });\n        } else {\n            graphInstance.updateNode(node, { opacity: 0.1, color: undefined });\n        }\n    });\n};\n```\n\nThis fragment shows that line emphasis is coordinated with node emphasis and then committed explicitly.\n\n```tsx\ngraphInstance.getLines().forEach(line => {\n    if (allChildIds.includes(line.from) && allChildIds.includes(line.to)) {\n        graphInstance.updateLine(line, { color: 'rgb(116,2,173)' });\n    } else {\n        graphInstance.updateLine(line, { color: '' });\n    }\n});\ngraphInstance.dataUpdated();\n```\n\nThis fragment shows the shared settings panel mutating live graph behavior and starting screenshot export through the active graph instance.\n\n```tsx\nconst graphInstance = RGHooks.useGraphInstance();\nconst { options } = RGHooks.useGraphStore();\n\n\u003CSettingRow\n    label=\"Wheel Event:\"\n    options={[\n        { label: 'Scroll', value: 'scroll' },\n        { label: 'Zoom', value: 'zoom' },\n        { label: 'None', value: 'none' },\n    ]}\n    value={options.wheelEventAction}\n    onChange={(newValue: string) => { graphInstance.setOptions({ wheelEventAction: newValue }); }}\n/>\n```\n\n## What Makes This Example Distinct\n\nCompared with nearby examples such as `line-hightlight-pro`, `bothway-tree2`, and `layout-tree`, this demo stays on one stable layout and uses its complexity budget on descendant-subtree inspection. Its distinguishing move is the recursive walk over `node.lot.childs`, followed by a graph-wide node and line update pass that changes interpretation without changing the loaded data.\n\nThat makes it different from examples that only mark one clicked object, switch tree orientations, or append new data fragments. The comparison records describe this combination as unusual: a plain centered blue hierarchy, runtime descendant traversal, focus-plus-context fading, and a canvas-reset affordance in one compact viewer.\n\nIt is also a stronger reference for branch-level emphasis than demos that highlight just a line or just the clicked node. Here, the entire selected branch stays legible, including internal links, while the rest of the graph remains visible as context instead of disappearing.\n\n## Where Else This Pattern Applies\n\nThe same pattern transfers well to any tree where users need to inspect one branch without losing the surrounding context. Examples include organization structures, navigation trees, permission inheritance, file-system browsers, product category trees, and bill-of-material hierarchies.\n\nIt also works as a starting point for analytic drill-down interactions. A production version could replace the placeholder letters with business records, combine the subtree highlight with side-panel details, or add filters that decide which descendants remain in focus, while keeping the same runtime strategy of walking child nodes and updating the already-loaded graph in place.\n",false,500,1782615426610]