    library(g6R)
    library(shiny)

## Graph data

### Data formats

To setup a `{g6R}` graph, you first have to define node, edges and combos (collection of nodes), like so:

    nodes <- data.frame(id = 1:10)
    nodes$label <- nodes$id

You could also pass these elements as list, which will be faster than the dataframe approach since under the hood, `{g6R}` has to send list to JavaScript:

    nodes <- lapply(seq_len(10), function(i) {
      list(id = i, label = i)
    })

We then define some random edges:

    # Set a seed for reproducibility
    set.seed(123)

    # Define the number of edges to create (e.g., 200 random connections)
    num_edges <- 5

    # Generate random edges
    edges <- data.frame(
      source = sample(nodes$id, num_edges, replace = TRUE),
      target = sample(nodes$id, num_edges, replace = TRUE)
    )

    edges$id <- paste0(edges$source, edges$target)
    duplicated_id <- which(duplicated(edges$id) == TRUE)
    if (length(duplicated_id)) {
      edges <- edges[-duplicated_id, ]
    }

### Performance

If you are dealing with large graphs, you might want to use the `jsonUrl` parameter to fetch the graph data from a hosted JSON file instead. If so, then leave `nodes`, `edges` and `combos` `NULL`. This allows to bypass the serialization of the graph data to JavaScript, which can be slow for large graphs. That’s done in the `shinyAppDir(system.file("examples", "json", package = "g6R"))` example.

    shinyAppDir(system.file("examples", "json", package = "g6R"))

## Initialise the graph

We leverage `g6` to create an instance of our network:

    g6(nodes, edges, width = 200, height = 200)

As you can see, the nodes don’t render well yet. Let’s add it some layout.

## Layout

`g6_layout()` allows to pass any supported layout. For this example, we select the `d3_force_layout()`:

    g <- g6(nodes, edges) |>
      g6_layout(d3_force_layout())
    g

That’s better! We could go further by displaying nodes label.

## Tweak options

`g6_options()` is your to go tool when it comes to change the style of the graph element such as nodes. Properties are selected from the documentation:

    g <- g |>
      g6_options(
        node = list(
          style = list(
            labelBackground = TRUE,
            labelBackgroundFill = '#FFB6C1',
            labelBackgroundRadius = 4,
            labelFontFamily = 'Arial',
            labelPadding = c(0, 4),
            labelText = JS(
              "(d) => {
                  return d.id
                }"
            )
          )
        )
      )
    g

## Plugins

Plugins allowing users to improve the user experience by adding graphical components to the canvas like minimaps or tooltips. We can pass them inside `g6_plugins` either as a character string with a reference to the plugin name or using the correponding function to pass more configuration options:

    # Use defaults
    g6_plugins("minimap")

    # Custom options
    g6_plugins(
      minimap(size = c(100, 100))
    )

    g <- g |>
      g6_plugins(
        minimap(size = c(100, 100))
      )
    g

## Behaviors

Behaviors correspond to interactions between users and the graph elements, such as dragging the nodes and selecting nodes. Be mindful that not all behaviors are compatible: dragging canvas and canvas elements would require to specify different triggers for each behavior. With `{g6R}` behaviors can be added with `g6_behaviors`, like plugins:

    g <- g |>
      g6_behaviors(
        "zoom-canvas",
        drag_element_force(fixed = TRUE),
        click_select(
          multiple = TRUE,
          onClick = JS(
            "(e) => {
                console.log(e);
              }"
          )
        ),
        brush_select()
      )
    g

Notice that we can pass callback functions from R to JavaScript. This is useful in combination with Shiny to set custom inputs, for instance.