[{"data":1,"prerenderedAt":7},["ShallowReactive",2],{"example-markdown-content:en:animated-line-slot-detail-link":3},{"markdown":4,"isPaidExample":5,"isTruncated":5,"charLimit":6},"# Animating Custom Line Slots with Clickable Detail Labels\n\n## What This Example Builds\n\nThis example builds a left-to-right route tree on a dark canvas, then replaces the default edge renderer with a custom line slot. The result is a set of thick animated pipe-like lines, a magenta dot that travels along each computed path, and a white line label that can append a green `Detail` action.\n\nUsers can inspect the network visually, click lines without losing relation-graph's normal line event flow, trigger a line-specific detail action from the label, open the floating settings panel, and export the canvas as an image. The main point of the demo is that the line layer is fully customized while relation-graph still supplies the geometry, text positioning, and event pipeline.\n\n## How the Data Is Organized\n\nThe graph is loaded from an inline `RGJsonData` object with `rootId`, `nodes`, and `lines`. Each line stores `from`, `to`, `text`, and a `data` payload with route-style metadata such as `myIcon`, `myCapacity`, `myWeight`, and `mySpeed`. Before loading the data, the demo iterates over every line and sets `showEndArrow = false`, which keeps the pipe animation visually clean and avoids mixing the custom stroke with default arrowheads.\n\nThat structure can map directly to shipment routes, service dependencies, machine-to-machine transfers, or any directional network where the edge carries operational metrics. The dataset is static in this demo, but the same shape would work with API-driven line metadata as long as each connection can still be expressed as a `from` and `to` pair plus per-line details.\n\n## How relation-graph Is Used\n\n`RGProvider` wraps the whole demo so hooks resolve against the active graph instance. Inside `MyGraph`, `RelationGraph` is configured with a tree layout that grows from the left, `levelGaps` of `[500, 400]`, `RGJunctionPoint.lr`, and `RGLineShape.StandardCurve`. That gives the custom renderer a predictable curved route shape to decorate.\n\nThe main customization point is `RGSlotOnLine`. Instead of accepting relation-graph's default line output, the example passes each line's runtime slot props into `MyLineContent`. That component calls `generateLinePath` to get the real SVG path, calls `generateLineTextStyle` to reuse relation-graph's computed label positioning, forwards custom clicks back into `graphInstance.onLineClick`, renders the path through `RGLinePath`, and conditionally renders the non-SVG label branch through `RGLineText`.\n\nThe graph instance API is also used outside the slot. `setJsonData`, `moveToCenter`, and `zoomToFit` initialize the view on mount. The shared settings panel uses `setOptions` to switch wheel and drag behavior, and it uses `prepareForImageGeneration` plus `restoreAfterImageGeneration` to export a clean canvas image. The visual finish comes from `my-relation-graph.scss`, which overrides the map background, removes node chrome, adds a selected-node glow, animates the line stroke with `stroke-dasharray`, and drives the moving dot with `offset-path`.\n\n## Key Interactions\n\n- Clicking the SVG line path still enters relation-graph's `onLineClick` pipeline even though the line visuals come from a custom slot.\n- When the non-SVG label branch is active, clicking the label also forwards to the same line click handler.\n- The appended `Detail` link calls parent logic with the current `RGLine` and opens an alert for that line.\n- The floating `DraggableWindow` can be dragged, minimized, and switched into a canvas settings panel.\n- The settings panel changes wheel behavior, changes canvas drag behavior, and downloads an exported image of the current graph.\n\n## Key Code Fragments\n\nThis block shows the layout and default line settings that the custom renderer builds on.\n\n```tsx\nconst graphOptions: RGOptions = {\n    defaultJunctionPoint: RGJunctionPoint.lr,\n    defaultLineShape: RGLineShape.StandardCurve,\n    layout: {\n        layoutName: 'tree',\n        from: 'left',\n        levelGaps: [500, 400]\n    }\n};\n```\n\nThis block shows the inline route dataset and the preprocessing step that disables default end arrows before loading.\n\n```tsx\nconst myJsonData: RGJsonData = {\n    rootId: 'base',\n    nodes: [\n        { id: 'base', text: '🏢 Base', },\n        // ...\n    ],\n    lines: [\n        { from: 'base', to: '1', text: 'Line X01', data: { myIcon: '🚢', myCapacity: 1.2, myWeight: 1, mySpeed: 1 } },\n        // ...\n    ]\n};\nmyJsonData.lines.forEach((line) => {\n    line.showEndArrow = false;\n});\nawait graphInstance.setJsonData(myJsonData);\n```\n\nThis block shows how the example replaces relation-graph's default line renderer with `MyLineContent`.\n\n```tsx\n\u003CRelationGraph\n    options={graphOptions}\n    onLineClick={onLineClick}\n>\n    \u003CRGSlotOnLine>\n        {(lineSlotProps: RGLineSlotProps) => {\n            return (\n                \u003CMyLineContent\n                    {...lineSlotProps}\n                    onMyLineDetailClick={onMyLineDetailClick}\n                />\n            );\n        }}\n    \u003C/RGSlotOnLine>\n\u003C/RelationGraph>\n```\n\nThis block shows the custom slot computing real path geometry once and exposing it to both relation-graph helpers and CSS animation.\n\n```tsx\nconst linePathInfo = useMemo\u003CRGLinePathInfo>(() => graphInstance.generateLinePath(lineConfig), [lineConfig]);\nconst onLineClick = (e: React.MouseEvent | React.TouchEvent) => {\n    graphInstance.onLineClick(lineConfig.line, e.nativeEvent);\n};\nconst textStyle = graphInstance.generateLineTextStyle(lineConfig, linePathInfo);\nconst pathEl = document.createElementNS('http://www.w3.org/2000/svg', 'path');\npathEl.setAttribute('d', linePathInfo.pathData);\nreturn (\u003Cg\n    style={{\n        '--my-line-path': `path('${linePathInfo.pathData}')`,\n        '--my-line-path-length': pathEl.getTotalLength()\n    }}>\n```\n\nThis block shows the slot keeping relation-graph's native line primitive while adding a moving dot.\n\n```tsx\n\u003CRGLinePath\n    lineConfig={lineConfig}\n    linePathInfo={linePathInfo}\n    useTextOnPath={useSvgTextPath}\n    checked={checked}\n    graphInstanceId={graphInstanceId}\n    onLineClick={onLineClick}\n>\n    \u003Ccircle className=\"my-dot\" r=\"5\">\u003C/circle>\n\u003C/RGLinePath>\n```\n\nThis block shows the non-SVG label branch adding a separate `Detail` action after the computed line text.\n\n```tsx\n\u003Cdiv\n    className={`rg-line-label ${useTextOnPath ? 'rg-line-label-on-path' : ''}`}\n    style={{\n        ...textStyle.cssStyles\n    }}\n    onTouchStart={onLineClick}\n    onClick={onLineClick}\n>\n    {textStyle.text}\n    \u003Ca\n        className=\"text-green-300 cursor-pointer hover:underline\"\n        onClick={() => { onMyLineDetailClick(lineConfig.line); }}\n    >\n        Detail\n    \u003C/a>\n\u003C/div>\n```\n\nThis block shows the CSS that converts the computed geometry into pipe animation and path-following motion.\n\n```scss\n.rg-line {\n    stroke: rgb(67, 102, 241);\n    stroke-width: 10px;\n    animation: draw-line 5s linear infinite;\n    stroke-dasharray: var(--my-line-path-length);\n    stroke-dashoffset: var(--my-line-path-length);\n}\n\n.my-dot {\n    offset-path: var(--my-line-path);\n    offset-distance: 0%;\n    animation: ride-path 5s linear infinite;\n}\n```\n\n## What Makes This Example Distinct\n\nThe comparison data positions this example as a focused animated line-slot reference rather than a general line-style sample. Its clearest distinguishing trait is that it keeps `RGLinePath` and `RGLineText` in the loop, but still uses `generateLinePath`, `generateLineTextStyle`, and relation-graph's normal `onLineClick` flow inside a fully replaced line renderer. That combination is already rare on its own.\n\nCompared with `adv-line-slot`, this example puts more emphasis on measured pipeline animation than on endpoint annotation. It uses the actual SVG path length to drive both the stroke draw-in effect and the moving dot, while `adv-line-slot` is described as the more general annotated line-slot sibling. Compared with `adv-line-slot-2`, this is the leaner reference: it stays focused on animated line rendering and a simple detail action instead of adding custom node slots, progress-position markers, or checked-only metric panels. Compared with `adv-line-slot2`, it stays closer to relation-graph's native line primitives instead of transforming each edge into ribbon-like filled geometry.\n\nThe result is a compact viewer-oriented pattern that combines a dark route-monitoring look, hybrid SVG and HTML labels, and line-level actions without turning into a broader editing demo.\n\n## Where Else This Pattern Applies\n\nThis pattern can be adapted to logistics dashboards, network traffic views, service dependency maps, manufacturing transfer flows, energy distribution routes, or security path analysis. It is especially useful when the edge needs to carry the story: animated flow, line-specific metrics, direct line actions, and exportable presentation output, while relation-graph continues to handle the underlying path geometry and event routing.\n",false,500,1782615379075]