[{"data":1,"prerenderedAt":7},["ShallowReactive",2],{"example-markdown-content:en:edit-node-text":3},{"markdown":4,"isPaidExample":5,"isTruncated":5,"charLimit":6},"# Inline Node Text Editing in a Fixed Layout Graph\n\n## What This Example Builds\n\nThis example builds a fixed-position relation graph where node labels can be edited in place. The screen shows a dotted canvas, blue straight links, and a floating helper window, while the nodes themselves demonstrate different border, color, size, shape, and fixed-position settings.\n\nThe primary user action is label maintenance. When editing is enabled, a double-click on a node swaps the normal label for a yellow inline input, and the changed text is written back to the graph without reloading the whole dataset.\n\nThe key design choice is that the node body is replaced through a custom node slot. That lets the example own focus handling, keyboard behavior, commit and cancel rules, and the global editing toggle at the component level.\n\n## How the Data Is Organized\n\nThe graph data is declared inline inside `initializeGraph()` as one `RGJsonData` object with `rootId`, a flat `nodes` array, and a `lines` array. Each node record carries fixed `x` and `y` coordinates, and several nodes also include visual overrides such as `borderWidth`, `borderColor`, `fontColor`, `color`, `width`, `height`, `fixed`, `className`, or a node-specific `nodeShape`.\n\nThere are two small preprocessing steps before `setJsonData()`. The code fills in missing line ids with `line-${index}`, and it converts numeric `nodeShape` values into the `RGNodeShape` enum expected by the current API. After that normalization, the full dataset is loaded once and all later label changes happen through targeted node updates.\n\nIn a real product, the same structure can stand for process nodes, equipment labels, organization units, floor-plan annotations, or knowledge-graph entities whose text needs quick maintenance without opening a separate form.\n\n## How relation-graph Is Used\n\nThe entry component wraps the demo in `RGProvider`, and `MyGraph` uses `RGHooks.useGraphInstance()` to initialize and mutate the graph. The main options set a `fixed` layout, rectangular nodes by default, straight lines, border junction points, blue line color, and line width `2`. Because the layout is fixed, the inline node coordinates determine the initial placement instead of a runtime tree or force layout.\n\nThe custom rendering path is centered on `RGSlotOnNode`. Each rendered node is replaced with `MyEditableNode`, which receives the runtime `node`, the global `isEditingEnabled` flag, and a callback that persists text changes through `graphInstance.updateNode(...)`. The current source does not use a line slot or an active view slot; the notable extension point here is the node slot.\n\nThe graph instance API is used in two layers. `MyGraph` calls `setJsonData()`, `moveToCenter()`, and `zoomToFit()` during mount, then uses `updateNode()` when a label edit is confirmed. The shared `CanvasSettingsPanel` inside `DraggableWindow` uses `RGHooks.useGraphStore()` to read current wheel and drag behavior, uses `setOptions()` to switch those behaviors at runtime, and runs the export pipeline with `prepareForImageGeneration()`, `getOptions()`, and `restoreAfterImageGeneration()`.\n\nStyling is split between graph options and CSS. The SCSS file customizes `.relation-graph` with canvas offset and scale variables plus a radial-gradient dot background, while the editable node component contributes the yellow input field and the `cursor-text` affordance when editing is available.\n\n## Key Interactions\n\nDouble-click is the main entry point. A node only enters inline editing when the global checkbox has enabled that mode, and the handler stops propagation so the graph does not interpret the same gesture as a normal node click.\n\nOnce editing starts, the input is focused automatically and its text is selected. Pressing Enter or blurring the input commits the change, while pressing Escape restores the previous node text and exits without saving.\n\nThe editing toggle is global rather than per-node. The checkbox in the floating window updates `isEditingEnabled` in `MyGraph`, and that boolean is passed into every slotted node renderer.\n\nThe floating window adds secondary controls. It can be dragged, minimized, expanded into a settings panel, used to switch wheel behavior between scroll, zoom, and none, used to switch canvas dragging between selection, move, and none, and used to export the current graph as an image.\n\n## Key Code Fragments\n\nThis fragment shows the fixed-layout graph configuration and the default visual rules that the custom node renderer builds on.\n\n```tsx\nconst graphOptions: RGOptions = {\n    defaultLineColor: '#43a2f1',\n    defaultLineWidth: 2,\n    layout: {\n        layoutName: 'fixed'\n    },\n    defaultNodeShape: RGNodeShape.rect,\n    defaultLineShape: RGLineShape.StandardStraight,\n    defaultJunctionPoint: RGJunctionPoint.border\n};\n```\n\nThis fragment shows that the example normalizes incoming data before loading it and then centers the loaded fixed-layout graph.\n\n```tsx\nmyJsonData.lines.forEach((line, index) => {\n    if (!line.id) {\n        line.id = `line-${index}`;\n    }\n});\n\nmyJsonData.nodes.forEach(node => {\n    if (node.nodeShape === 0) node.nodeShape = RGNodeShape.circle;\n    if (node.nodeShape === 1) node.nodeShape = RGNodeShape.rect;\n});\n\nawait graphInstance.setJsonData(myJsonData);\ngraphInstance.moveToCenter();\ngraphInstance.zoomToFit();\n```\n\nThis fragment proves that relation-graph's node slot is the mechanism that swaps the default node body for the editable renderer.\n\n```tsx\n\u003CRelationGraph options={graphOptions}>\n    \u003CRGSlotOnNode>\n        {({ node, checked, dragging }: RGNodeSlotProps) => (\n            \u003CMyEditableNode\n                node={node}\n                enableEditingMode={isEditingEnabled}\n                onNodeTextChange={onNodeTextChange}\n            />\n        )}\n    \u003C/RGSlotOnNode>\n\u003C/RelationGraph>\n```\n\nThis fragment shows how the custom node enters edit mode and immediately prepares the input for text replacement.\n\n```tsx\nuseEffect(() => {\n    if (isEditing && inputRef.current) {\n        inputRef.current.focus();\n        inputRef.current.select();\n    }\n}, [isEditing]);\n\nconst handleDoubleClick = (e: React.MouseEvent) => {\n    if (enableEditingMode) {\n        e.stopPropagation();\n        setIsEditing(true);\n    }\n};\n```\n\nThis fragment shows the commit and cancel flow, including the callback that eventually persists the text through `graphInstance.updateNode(...)`.\n\n```tsx\nconst handleKeyDown = (e: React.KeyboardEvent) => {\n    if (e.key === 'Enter') {\n        finishEditing();\n    } else if (e.key === 'Escape') {\n        setEditingText(node.text || '');\n        setIsEditing(false);\n    }\n};\n\nconst finishEditing = () => {\n    if (editingText !== node.text) {\n        onNodeTextChange(node, editingText);\n    }\n    setIsEditing(false);\n};\n```\n\nThis fragment shows the shared settings panel mutating live graph behavior through the active graph instance.\n\n```tsx\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={wheelMode}\n    onChange={(newValue: string) => { graphInstance.setOptions({ wheelEventAction: newValue }); }}\n/>\n```\n\n## What Makes This Example Distinct\n\nBased on the prepared doc-context, the distinctive part is not the shared floating window or the provider-and-hook setup, because nearby examples such as `deep-each`, `investment`, and `selections` also reuse that scaffolding. The rarer combination is the custom `MyEditableNode` renderer plus mode-gated double-click editing, automatic focus and text selection, Enter-or-blur commit, Escape cancel, and persistence through `updateNode()` on a fixed-layout graph.\n\nThe rarity records also mark the yellow inline editor state, the dotted editing canvas, and the fixed-position style-sample nodes as unusual in this example set. That makes this demo a more direct starting point for node-label maintenance than examples that emphasize selection, traversal, resizing, or broader editor behaviors.\n\nIt is also narrower than a full graph editor. The code does not add nodes, reconnect lines, or manage multi-step editing state. Its value is that it isolates one concrete capability: replace default node content with an inline editor and keep the persistence path small.\n\n## Where Else This Pattern Applies\n\nThis pattern transfers well to diagrams where the structure is already known but labels need quick correction in context. Examples include workflow naming tools, process maps, organization charts, equipment maps, topology labels, and knowledge-graph curation screens.\n\nA production version could keep the same slot-based editing strategy while replacing the inline sample data with server data, adding validation rules before `updateNode()`, storing audit history, or opening richer side panels for fields beyond the node text. The core idea still holds: let the graph stay loaded and edit only the label that changed.\n",false,500,1782615405363]