{
  "input": {
    "board-dag_extension-ctx_add_block": true,
    "board-dag_extension-ctx_add_link": "super_data_block",
    "board-dag_extension-graph-contextmenu": {
      "type": "node",
      "id": "node-super_data_block"
    },
    "board-dag_extension-graph-initialized": true,
    "board-dag_extension-graph-mouse_position": "<shinytest2:preprocessed>",
    "board-dag_extension-graph-state": {
      "nodes": {
        "node-super_data_block": {
          "id": "node-super_data_block",
          "style": {
            "src": "<shinytest2:preprocessed>",
            "labelText": "Dataset",
            "size": 48,
            "ports": {
              "node-super_data_block-out": {
                "key": "node-super_data_block-out",
                "type": "output",
                "arity": "Infinity",
                "visibility": "hover",
                "fill": "#0072B2",
                "placement": "bottom",
                "r": 4
              }
            },
            "collapse": {
              "collapsed": false,
              "visibility": "hover",
              "placement": "right-top",
              "r": 6,
              "fill": "#fff",
              "stroke": "#D1D5DB",
              "lineWidth": 1,
              "iconStroke": "#9cabd4",
              "iconLineWidth": 1.4,
              "cursor": "pointer",
              "zIndex": 999
            },
            "zIndex": 0,
            "badges": [

            ]
          },
          "data": {

          },
          "children": [
            "node-super_head_block"
          ]
        },
        "node-super_head_block": {
          "id": "node-super_head_block",
          "style": {
            "src": "<shinytest2:preprocessed>",
            "labelText": "Head",
            "size": 48,
            "ports": {
              "node-super_head_block-data": {
                "key": "node-super_head_block-data",
                "type": "input",
                "arity": 1,
                "visibility": "hover",
                "label": "data",
                "fill": "#009E73",
                "placement": "top",
                "r": 4
              },
              "node-super_head_block-out": {
                "key": "node-super_head_block-out",
                "type": "output",
                "arity": "Infinity",
                "visibility": "hover",
                "fill": "#009E73",
                "placement": "bottom",
                "r": 4
              }
            },
            "collapse": {
              "collapsed": false,
              "visibility": "hover",
              "placement": "right-top",
              "r": 6,
              "fill": "#fff",
              "stroke": "#D1D5DB",
              "lineWidth": 1,
              "iconStroke": "#9cabd4",
              "iconLineWidth": 1.4,
              "cursor": "pointer",
              "zIndex": 999
            },
            "zIndex": 0,
            "badges": [

            ]
          },
          "data": {

          }
        }
      },
      "edges": {
        "edge-super_link": {
          "source": "node-super_data_block",
          "target": "node-super_head_block",
          "id": "edge-super_link",
          "type": "cubic-vertical",
          "style": {
            "labelText": "data",
            "sourcePort": "node-super_data_block-out",
            "targetPort": "node-super_head_block-data",
            "zIndex": -1,
            "sourceNode": "node-super_data_block",
            "targetNode": "node-super_head_block",
            "controlPoints": [
              [
                74,
                148,
                0
              ]
            ],
            "src": "<shinytest2:preprocessed>"
          },
          "data": {

          }
        }
      },
      "combos": {

      }
    },
    "board-dag_extension-tool_add_block": true
  },
  "output": {
    "board-dag_extension-graph": {
      "x": {
        "data": {
          "nodes": [

          ],
          "combos": [

          ]
        },
        "jsonUrl": null,
        "iconsUrl": "//at.alicdn.com/t/font_2678727_za4qjydwkkh.js",
        "mode": "dev",
        "preservePosition": false,
        "directed": true,
        "maxCollapseDepth": null,
        "node": {
          "type": "custom-image-node",
          "style": {
            "labelFill": "#6b7280",
            "labelBackground": true,
            "labelBackgroundFill": "#f3f4f6",
            "labelBackgroundStroke": "#e5e7eb",
            "labelBackgroundRadius": 4,
            "labelPlacement": "bottom",
            "labelOffsetY": 8,
            "labelBackgroundLineWidth": 1,
            "labelBackgroundRadius.1": 4,
            "labelBackgroundOpacity": 1,
            "labelPadding": [
              1,
              6,
              1,
              6
            ],
            "labelFontSize": 11,
            "labelFontFamily": "Open Sans, system-ui, sans-serif"
          },
          "state": {
            "selected": {
              "labelBackgroundFill": "#dbeafe",
              "labelBackgroundStroke": "#0D99FF",
              "labelFontWeight": 700
            }
          }
        },
        "edge": {
          "type": "cubic-vertical",
          "style": {
            "zIndex": -1,
            "endArrow": true,
            "stroke": "#D1D5DB",
            "lineWidth": 2,
            "increasedLineWidthForHitTesting": 25,
            "curveOffset": [
              15,
              -15
            ],
            "labelOpacity": 0,
            "labelFill": "#6b7280",
            "labelBackground": true,
            "labelBackgroundFill": "#FFFFFF",
            "labelBackgroundRadius": 4,
            "labelBackgroundOpacity": 0,
            "labelPadding": [
              2,
              4
            ]
          },
          "state": {
            "active": {
              "stroke": "#D1D5DB",
              "lineWidth": 2,
              "shadowBlur": 0,
              "shadowColor": "transparent",
              "halo": false,
              "labelOpacity": 1,
              "labelBackgroundOpacity": 1
            },
            "selected": {
              "stroke": "#9ca3af",
              "lineWidth": 2,
              "shadowBlur": 4,
              "shadowColor": "rgba(156, 163, 175, 0.5)",
              "halo": false
            }
          }
        },
        "combo": {
          "animation": false,
          "badge": true,
          "type": "rect-combo-with-extra-button",
          "style": {
            "padding": [
              20,
              20,
              40,
              20
            ]
          }
        },
        "animation": false,
        "autoResize": false,
        "cursor": "default",
        "renderer": "() => new SVGRenderer()",
        "rotation": 0,
        "zoom": 1,
        "zoomRange": [
          0.01,
          10
        ],
        "theme": "light",
        "layout": {
          "type": "antv-dagre",
          "rankdir": "TB",
          "align": "UL",
          "nodesep": 50,
          "ranksep": 50,
          "ranker": "network-simplex",
          "controlPoints": false,
          "begin": [
            150,
            150
          ],
          "sortByCombo": true,
          "edgeLabelSpace": true,
          "radial": false
        },
        "behaviors": [
          {
            "key": "zoom-canvas",
            "animation": {
              "duration": 200
            },
            "enable": true,
            "preventDefault": true,
            "sensitivity": 1,
            "type": "zoom-canvas"
          },
          {
            "key": "drag-canvas",
            "enable": "(e) => {\n          return e.targetType === 'canvas' && !e.shiftKey && !e.altKey;\n        }",
            "direction": "both",
            "sensitivity": 10,
            "type": "drag-canvas"
          },
          {
            "key": "drag-element",
            "enable": "(e) => {\n          if (e.shiftKey || e.altKey) return false;\n          // Access graph via HTMLWidgets and check if edge creation is in progress\n          const target = e.nativeEvent?.target;\n          const graph = HTMLWidgets.find(`#${target?.closest?.('.g6')?.id}`)?.getWidget();\n          try {\n            if (graph?.getNodeData?.('g6-create-edge-assist-node-id')) return false;\n          } catch (err) {}\n          return true;\n        }",
            "animation": true,
            "state": "selected",
            "dropEffect": "move",
            "hideEdge": "none",
            "shadow": false,
            "type": "drag-element"
          },
          {
            "key": "click-select",
            "animation": true,
            "degree": 0,
            "enable": true,
            "multiple": true,
            "state": "selected",
            "neighborState": "selected",
            "trigger": [
              "shift"
            ],
            "type": "click-select"
          },
          {
            "key": "brush-select",
            "animation": false,
            "enable": "(e) => {\n      return true;\n    }",
            "enableElements": [
              "node",
              "edge",
              "combo"
            ],
            "immediately": true,
            "mode": "default",
            "onSelect": "(states) => {\n          const selected = Object.getOwnPropertyNames(states);\n          const nodes = [];\n          const edges = [];\n          const combos = [];\n          const widget = HTMLWidgets.find('#board-dag_extension-graph').getWidget();\n          if (selected.length === 0) return states;\n          selected.forEach(id => {\n            const type = widget.getElementType(id);\n            if (type === 'node') nodes.push(id);\n            else if (type === 'edge') edges.push(id);\n            else if (type === 'combo') combos.push(id);\n          });\n          Shiny.setInputValue('board-dag_extension-graph-selected_node:g6R.brush_select', nodes, {priority: 'event'});\n          Shiny.setInputValue('board-dag_extension-graph-selected_edge:g6R.brush_select', edges, {priority: 'event'});\n          Shiny.setInputValue('board-dag_extension-graph-selected_combo:g6R.brush_select', combos, {priority: 'event'});\n          return states;\n        }",
            "state": "selected",
            "trigger": "Alt",
            "outputId": "board-dag_extension-graph",
            "type": "brush-select"
          },
          {
            "key": "collapse-expand",
            "animation": true,
            "enable": true,
            "trigger": "dblclick",
            "align": true,
            "type": "collapse-expand"
          },
          {
            "key": "hover-activate",
            "animation": false,
            "enable": "(e) => e.targetType === 'edge'",
            "degree": 0,
            "direction": "both",
            "state": "active",
            "type": "hover-activate"
          },
          {
            "key": "create-edge",
            "trigger": "drag",
            "enable": "(e) => {\n          return e.targetType === 'node' && e.targetType !== 'combo'\n        }",
            "onFinish": "(edge) => {\n            const graph = HTMLWidgets.find('#board-dag_extension-graph').getWidget();\n            // For canvas drops, the assist node is already removed, so check targetType first\n            if (edge.targetType === 'canvas') {\n              Shiny.setInputValue(\n                'board-dag_extension-added_edge',\n                {\n                  id: edge.id,\n                  source: edge.source.replace(/^node-/, ''),\n                  target: null,\n                  targetType: 'canvas',\n                  sourcePort: edge.style?.sourcePort,\n                  portType: edge.style?.portType\n                }\n              );\n              return;\n            }\n            const targetType = graph.getElementType(edge.target);\n            // Avoid to create edges in combos. If so, we remove it\n            if (targetType === 'combo') {\n              graph.removeEdgeData([edge.id]);\n            } else {\n              Shiny.setInputValue(\n                'board-dag_extension-added_edge',\n                {\n                  id: edge.id,\n                  source: edge.source.replace(/^node-/, ''),\n                  target: edge.target.replace(/^node-/, ''),\n                  targetType: edge.targetType,\n                  sourcePort: edge.style.sourcePort,\n                  targetPort: edge.style.targetPort\n                }\n              );\n              // We will recreate the edge from the R side with correct ID\n              graph.removeEdgeData([edge.id]);\n            }\n          }",
            "notify": false,
            "type": "create-edge"
          }
        ],
        "plugins": [
          {
            "key": "contextmenu",
            "className": "g6-contextmenu",
            "trigger": "contextmenu",
            "offset": [
              4,
              4
            ],
            "onClick": "(value, target, current) => {\nif (value === 'create_link') {\n((value, target, current) => {\n            if (current.id === undefined) return;\n            Shiny.setInputValue('board-dag_extension-ctx_add_link', current.id.replace(/^node-/, ''), {priority: 'event'});\n          })(value, target, current)\n} else if (value === 'remove_block') {\n((value, target, current) => {\n            if (current.id === undefined) return;\n            Shiny.setInputValue('board-dag_extension-ctx_remove_block', current.id.replace(/^node-/, ''));\n          })(value, target, current)\n} else if (value === 'remove_link') {\n((value, target, current) => {\n            if (current.id === undefined) return;\n            Shiny.setInputValue('board-dag_extension-ctx_remove_link', current.id.replace(/^edge-/, ''));\n          })(value, target, current)\n} else if (value === 'append_block') {\n((value, target, current) => {\n            Shiny.setInputValue(\n              'board-dag_extension-ctx_append_block',\n              current.id.replace(/^node-/, ''),\n              {priority: 'event'}\n            );\n          })(value, target, current)\n} else if (value === 'add_block') {\n((value, target, current) => {\n            Shiny.setInputValue('board-dag_extension-ctx_add_block', true, {priority: 'event'});\n          })(value, target, current)\n} else if (value === 'create_stack') {\n((value, target, current) => {\n            Shiny.setInputValue('board-dag_extension-ctx_create_stack', true, {priority: 'event'});\n          })(value, target, current)\n} else if (value === 'remove_stack') {\n((value, target, current) => {\n            if (current.id === undefined) return;\n            Shiny.setInputValue('board-dag_extension-ctx_remove_stack', current.id.replace(/^combo-/, ''));\n          })(value, target, current)\n} else if (value === 'edit_stack') {\n((value, target, current) => {\n            if (current.id === undefined) return;\n            Shiny.setInputValue(\n              'board-dag_extension-ctx_edit_stack',\n              current.id.replace(/^combo-/, ''),\n              {priority: 'event'}\n            );\n          })(value, target, current)\n} else if (value === 'copy') {\n((value, target, current) => {\n            Shiny.setInputValue('board-dag_extension-ctx_copy', true, {priority: 'event'});\n          })(value, target, current)\n} else if (value === 'cut') {\n((value, target, current) => {\n            Shiny.setInputValue('board-dag_extension-ctx_cut', true, {priority: 'event'});\n          })(value, target, current)\n} else if (value === 'paste') {\n(async (value, target, current) => {\n            try {\n              const text = await navigator.clipboard.readText();\n              const data = JSON.parse(text);\n              if (data && data.object === 'subboard') {\n                Shiny.setInputValue('board-dag_extension-ctx_paste', text, {priority: 'event'});\n              }\n            } catch (err) {}\n          })(value, target, current)\n}\n}",
            "getItems": "async (e) => {\n            var body;\n            if (e.targetType === 'canvas') {\n              body = {type: e.targetType};\n            } else {\n              body = {\n                id: e.target.id.replace(/^(node|edge|combo)-/, ''),\n                type: e.targetType\n              };\n            }\n            const response = await fetch(\n              'session/9a744a1bdf8658afbd8fbc6fbe9d2f6e/dataobj/board-dag_extension-context-menu-items?w=&nonce=<scrubbed>',\n              {\n                method: 'POST',\n                headers: {\n                  'Accept': 'application/json',\n                  'Content-Type': 'application/json'\n                },\n                body: JSON.stringify(body)\n              }\n            );\n            const items = await response.json();\n            return items;\n          }",
            "enable": "(e) => {\n          let cond = e.targetType === 'edge' ||\n            e.targetType === 'node' ||\n            e.targetType === 'canvas' ||\n            e.targetType === 'combo';\n          return cond;\n        }",
            "type": "contextmenu"
          },
          {
            "getItems": "( ) => [\n{ id : 'zoom-in' , value : 'zoom_in', title: 'Zoom in' },\n{ id : 'zoom-out' , value : 'zoom_out', title: 'Zoom out' },\n{ id : 'auto-fit' , value : 'auto_fit', title: 'Auto fit' },\n{ id : 'reset' , value : 'layout', title: 'Layout' },\n{ id : 'icon-roundaddfill' , value : 'add_block', title: 'Add block' },\n{ id : 'icon-cascades' , value : 'add_stack', title: 'Add stack' },\n{ id : 'icon-delete' , value : 'remove_selected', title: 'Remove selected' }\n]",
            "key": "toolbar",
            "position": "left",
            "style": {
              "backgroundColor": "#f5f5f5",
              "padding": "8px",
              "boxShadow": "0 2px 8px rgba(0, 0, 0, 0.15)",
              "borderRadius": "8px",
              "border": "1px solid #e8e8e8",
              "opacity": "0.9",
              "marginTop": "12px",
              "marginLeft": "12px"
            },
            "onClick": "(value, target, current) => {\nif (value === 'zoom_in') {\n((value, target, current) => {\n        const graph = HTMLWidgets.find(\n          `#${target.closest('.g6').id}`\n        ).getWidget();\n        graph.zoomTo(graph.getZoom() + 0.1);\n      })(value, target, current)\n} else if (value === 'zoom_out') {\n((value, target, current) => {\n        const graph = HTMLWidgets.find(\n          `#${target.closest('.g6').id}`\n        ).getWidget();\n        graph.zoomTo (graph.getZoom() - 0.1);\n      })(value, target, current)\n} else if (value === 'auto_fit') {\n((value, target, current) => {\n        const graph = HTMLWidgets.find(\n          `#${target.closest('.g6').id}`\n        ).getWidget();\n        graph.fitView();\n      })(value, target, current)\n} else if (value === 'layout') {\n((value, target, current) => {\n        const graph = HTMLWidgets.find(\n          `#${target.closest('.g6').id}`\n        ).getWidget();\n        graph.layout();\n      })(value, target, current)\n} else if (value === 'add_block') {\n((value, target, current) => {\n            Shiny.setInputValue('board-dag_extension-tool_add_block', true, {priority: 'event'});\n          })(value, target, current)\n} else if (value === 'add_stack') {\n((value, target, current) => {\n            Shiny.setInputValue('board-dag_extension-tool_add_stack', true, {priority: 'event'});\n          })(value, target, current)\n} else if (value === 'remove_selected') {\n((value, target, current) => {\n            Shiny.setInputValue('board-dag_extension-tool_rm_selected', true, {priority: 'event'});\n          })(value, target, current)\n}\n}",
            "type": "toolbar"
          }
        ]
      },
      "evals": [
        "renderer",
        "behaviors.1.enable",
        "behaviors.2.enable",
        "behaviors.4.enable",
        "behaviors.4.onSelect",
        "behaviors.6.enable",
        "behaviors.7.enable",
        "behaviors.7.onFinish",
        "plugins.0.onClick",
        "plugins.0.getItems",
        "plugins.0.enable",
        "plugins.1.getItems",
        "plugins.1.onClick"
      ],
      "jsHooks": [

      ],
      "deps": [

      ]
    }
  }
}
