hpcc-systems / Visualization

HPCC JavaScript Framework
https://hpcc-systems.github.io/Visualization/
Other
93 stars 62 forks source link

sending messages to and from dock panel shadow root #4201

Open seanbirchall opened 5 months ago

seanbirchall commented 5 months ago

I've been working on creating an IDE and stumbled across this within Lumino issues, very cool, but I'm not very familiar with shadow roots.

Probably not needed, but for some more details this IDE is to the R programming language now that it has somewhat recently been compiled to WASM. I'm pretty far along already but feel like this package has some components / features I'm going to need in the future and even now.

It's easy enough for me to create an R Shiny app with hpcc-dockpanel

library(shiny)
library(bslib)

dockpanel <- function(...) {
  tag("hpcc-dockpanel", list(...))
}

my_ui <- tagList(
  dockpanel(
    style = "height:99.5vh;width:100%;padding:0px;margin:0px;gap:0px;",
    tags$div(
      id = "script.R",
      "data-label" = "script.R",
      "data-mode" = "split-left",
      "data-closable" = "true",
      style = "overflow:auto;min-width:48px;min-height:48px",
      style = "padding:0px;margin:0px;gap:0px;", 
      tags$h1("CCCC HTML Ipsum Presents"),
      tags$p("Lorem ipsum...")
    ),
    tags$div(
      id = "console",
      "data-label" = "Console",
      "data-mode" = "split-bottom",
      "data-closable" = "false",
      style = "overflow:auto;min-width:48px;min-height:48px",
      tags$h1("CCCC HTML Ipsum Presents"),
      tags$p("Lorem ipsum...")
    ),
    tags$div(
      id = "environment",
      "data-label" = "Environment",
      "data-mode" = "split-right",
      "data-closable" = "false",
      style = "overflow:auto;min-width:48px;min-height:48px",
      tags$h1("CCCC HTML Ipsum Presents"),
      tags$p("Lorem ipsum...")
    ),
    tags$div(
      id = "viewer",
      "data-label" = "Viewer",
      "data-mode" = "tab-after",
      "data-ref" = "environment",
      "data-closable" = "false",
      style = "overflow:auto;min-width:48px;min-height:48px",
      reactable(iris),
      onClick = "console.log('clicked')"
    )
  )
)

ui <- bslib::page(
  my_ui,
  includeScript(
    "https://cdn.jsdelivr.net/npm/@hpcc-js/wc-layout"
  )
)

server <- function(input, output, session) {}

shinyApp(ui, server)

However what I'd like to be able to do is style the dockpanel (backgrounds, headers, tabs, handles) and programmatically click within the dockpanel (tabs). Is there some API to do that? I think I should probably just be reading up more about shadow root or just forking this repo at least for styling.

GordonSmith commented 5 months ago

There are style set / get protected methods down in the base class: https://github.com/hpcc-systems/Visualization/blob/trunk/components/core/src/element.ts#L34-L40 might be a matter of exposing a: @attribute({ type: "string" }) styles-ex = ""; or similar to allow overriding the default (have you tried simply setting styles on the html element)?

seanbirchall commented 5 months ago

Ya I can style the actual dockpanel, but it's limited. I tried shoving a css file inside a head div within the dockpanel tag but still no luck. Thanks for pointing out where I could expose this.

Within the browser console I can get the shadowRoot but once I try clicking via js or styling off that my querySelector / getElementByid can't find it.

Everything else works great just these few small things, but I think doing what you recommend above should solve it for me. I was also worried I wouldn't be able to access other elements created in shiny from outside the dockpanel, but had no issue with it today so that's good.

I'm going to fork and hard code a theme or do the above, I can probably put something on all the tabs to send a message back to shiny, that way I can probably simulate a click.

library(shiny)
library(bslib)
library(reactable)

dockpanel <- function(...) {
  tag("hpcc-dockpanel", list(...))
}

my_ui <- tagList(
  actionButton(
    inputId = "click",
    label = NULL
  ),
  dockpanel(
    style = "height:99.5vh;width:100%;padding:0px;margin:0px;gap:0px;background-color: rgb(246, 247, 249);",
    tags$div(
      id = "viewer",
      "data-label" = "Viewer",
      "data-mode" = "tab-after",
      "data-ref" = "environment",
      "data-closable" = "false",
      style = "overflow:auto;min-width:48px;min-height:48px",
      reactableOutput("table"),
      onClick = "console.log('clicked')"
    )
  )
)

ui <- bslib::page(
  my_ui,
  includeScript(
    "https://cdn.jsdelivr.net/npm/@hpcc-js/wc-layout"
  )
)

server <- function(input, output, session) {
  output$table <- renderReactable({
    reactable(iris)
  }) |>
    bindEvent(input$click, ignoreInit = TRUE)
}

shinyApp(ui, server)
GordonSmith commented 5 months ago

I have no experience with Shiny, but do have experience in embedding the core widget (which this web control wraps) in various environments (like React), not sure if that helps you, but it is a lot easier tweak to do what you want.