diff --git a/.Rbuildignore b/.Rbuildignore index 927085c..83c1025 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -8,3 +8,12 @@ ^README\.Rmd$ ^[.]?air[.]toml$ ^\.vscode$ +^node_modules(/|$) +^package\.json$ +^package-lock\.json$ +^tsconfig\.json$ +^\.worktrees(/|$) +^srcts(/|$) +^tools/check-js\.mjs$ +^tools/update-vega\.sh$ +CLAUDE\.md diff --git a/.github/workflows/js-check.yaml b/.github/workflows/js-check.yaml new file mode 100644 index 0000000..2849c08 --- /dev/null +++ b/.github/workflows/js-check.yaml @@ -0,0 +1,28 @@ +on: + push: + branches: [main, master] + pull_request: + workflow_dispatch: + +name: js-check.yaml + +permissions: read-all + +jobs: + js-check: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: "22" + cache: npm + + - name: Install dependencies + run: npm ci + + - name: Run JS checks + run: npm run check diff --git a/.gitignore b/.gitignore index 985eb21..0ea1aed 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ docs +node_modules +.worktrees .claude src/vendor diff --git a/CLAUDE.md b/CLAUDE.md index 8befd67..664d460 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -51,6 +51,7 @@ Rust crate src/rust/ (depends on `ggsql` crate + polars + duckdb + extendr-api) | `tools/config.R` | Detects `DEBUG`, `NOT_CRAN`, webR/wasm target, vendor presence, and emits `src/Makevars{,.win}`. | | `tools/msrv.R` | Enforces Rust MSRV (read from DESCRIPTION `SystemRequirements`). | | `inst/ggsql.xml` | KDE-syntax highlighting definition installed for the knitr engine (added to Pandoc via `--syntax-definition`). | +| `srcts/` | TypeScript source of truth for the htmlwidgets runtime. `srcts/index.ts` bundles to `inst/htmlwidgets/ggsql_vega.js`; `srcts/vega/*.test.ts` covers widget behavior in Node. | | `inst/test_chunks.qmd` | Fixture Quarto doc used by engine tests. | | `vignettes/` | Quarto vignettes (`ggsql.qmd`, `engine.qmd`). `VignetteBuilder: quarto`. | | `tests/testthat/` | `test-engine.R`, `test-reader.R`, `test-spec.R`, `test-validate.R`, `test-writer.R` plus `_snaps/`. | @@ -80,6 +81,22 @@ recompiles) or `rextendr::document()` (also regenerates Offline/CRAN builds rely on `src/rust/vendor.tar.xz` (cargo vendor archive). If you bump Rust deps, regenerate the archive so CRAN builds keep working. +## TypeScript / JavaScript assets + +`srcts/` is the source of truth for the browser-side widget code. The built +artifact checked into the package is `inst/htmlwidgets/ggsql_vega.js`. + +The browser-side visualization runtime lives in `srcts/`, while `R/widget.R`, +`R/shiny.R`, and `R/engine.R` are the main R entry points that hand specs off +to that runtime. Files under `inst/htmlwidgets/` are generated package assets +or vendored browser dependencies, so prefer editing `srcts/` and rebuilding +rather than patching built assets by hand. + +After making any change under `srcts/`, rebuild the generated asset with +`npm run build`. Before committing JS/TS changes, run `npm run check`; it +typechecks, rebuilds the bundle, runs the Node tests, and fails if the +checked-in generated asset drifted from the TypeScript source. + ## The FFI contract When adding or changing a Rust-exposed function: diff --git a/DESCRIPTION b/DESCRIPTION index ac0deee..df8ade3 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -23,6 +23,7 @@ RoxygenNote: 7.3.3 Imports: cli, htmltools, + htmlwidgets, jsonlite, knitr, nanoarrow, @@ -35,6 +36,7 @@ Suggests: reticulate, rmarkdown, rsvg, + shiny, testthat (>= 3.0.0), V8, withr @@ -45,4 +47,5 @@ Depends: VignetteBuilder: quarto URL: https://r.ggsql.org, https://github.com/posit-dev/ggsql-r Config/Needs/website: tidyverse/tidytemplate +Config/Needs/js: node BugReports: https://github.com/posit-dev/ggsql-r/issues diff --git a/NAMESPACE b/NAMESPACE index 1a82369..3b45e1f 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -15,6 +15,7 @@ S3method(print,ggsql_validated) S3method(str,Spec) export(custom_reader) export(duckdb_reader) +export(ggsqlOutput) export(ggsql_execute) export(ggsql_execute_sql) export(ggsql_has_visual) @@ -26,6 +27,7 @@ export(ggsql_metadata) export(ggsql_register) export(ggsql_render) export(ggsql_save) +export(ggsql_session_reader) export(ggsql_sql) export(ggsql_stat_data) export(ggsql_stat_sql) @@ -36,6 +38,7 @@ export(ggsql_validate) export(ggsql_visual) export(ggsql_warnings) export(odbc_reader) +export(renderGgsql) export(snowflake_reader) export(vegalite_writer) import(rlang) diff --git a/R/aaa.R b/R/aaa.R index 32263e7..414b822 100644 --- a/R/aaa.R +++ b/R/aaa.R @@ -30,5 +30,9 @@ check_r6 <- function( arg = caller_arg(x), call = caller_env() ) { - check_custom(x, function(x) R6::is.R6(x) && inherits(x, class), paste0("a ", class, "/R6 object")) + check_custom( + x, + function(x) R6::is.R6(x) && inherits(x, class), + paste0("a ", class, "/R6 object") + ) } diff --git a/R/engine.R b/R/engine.R index 693548d..92fda46 100644 --- a/R/engine.R +++ b/R/engine.R @@ -161,7 +161,7 @@ names.ggsql_tables <- function(x) { # Data reference resolution (r: and py: prefixes) # --------------------------------------------------------------------------- -resolve_data_refs <- function(query, reader) { +resolve_data_refs <- function(query, reader, envir) { refs <- gregexpr( "(?:r|py):[a-zA-Z_][a-zA-Z0-9_.]*", query, @@ -182,10 +182,10 @@ resolve_data_refs <- function(query, reader) { df <- switch( tolower(prefix), r = try_fetch( - get(name, envir = knitr::knit_global()), + get(name, envir = envir), error = function(cnd) { cli::cli_abort( - "Column reference {.code {ref}}: object {.val {name}} not found in R environment." + "Data reference {.code {ref}}: object {.val {name}} not found in R environment." ) } ), @@ -197,7 +197,7 @@ resolve_data_refs <- function(query, reader) { obj <- reticulate::py[[name]] if (is.null(obj)) { cli::cli_abort( - "Column reference {.code {ref}}: object {.val {name}} not found in Python environment." + "Data reference {.code {ref}}: object {.val {name}} not found in Python environment." ) } obj @@ -205,10 +205,18 @@ resolve_data_refs <- function(query, reader) { ) if (!is.data.frame(df)) { - cli::cli_abort("{.code {ref}} does not refer to a data frame.") + cli::cli_abort( + "{.code {ref}} refers to a {.cls {class(df)}} object, not a data frame." + ) } - internal_name <- paste0("__", prefix, "_", gsub(".", "_ggsqldot_", name, fixed = TRUE), "__") + internal_name <- paste0( + "__", + prefix, + "_", + gsub(".", "_ggsqldot_", name, fixed = TRUE), + "__" + ) ggsql_register(reader, df, internal_name, replace = TRUE) query <- gsub(ref, internal_name, query, fixed = TRUE) } @@ -216,115 +224,6 @@ resolve_data_refs <- function(query, reader) { query } -# --------------------------------------------------------------------------- -# Vega-Lite HTML rendering -# --------------------------------------------------------------------------- - -vegalite_html <- function( - spec_json, - width = NULL, - height = NULL, - asp = NULL, - caption = NULL, - align = "center" -) { - ggsql_env$vis_counter <- (ggsql_env$vis_counter %||% 0L) + 1L - vis_id <- paste0("ggsql-vis-", ggsql_env$vis_counter) - - # Convert fig.width/fig.height (inches) to pixels at 96 dpi, - # or use defaults if not specified - css_width <- if (!is.null(width)) { - if (is.numeric(width)) paste0(round(width * 96), "px") else width - } else { - "100%" - } - css_height <- if (!is.null(height)) { - if (is.numeric(height)) paste0(round(height * 96), "px") else height - } - css_height <- if (is.null(asp)) { - paste0("height: ", css_height %||% "400px") - } else { - paste0("aspect-ratio: ", asp) - } - - margin_style <- switch( - align %||% "center", - center = "margin-left: auto; margin-right: auto;", - right = "margin-left: auto;", - "" - ) - - html <- sprintf( - '
0)throw new E('Operation `path` property must start with "/"',"OPERATION_PATH_INVALID",t,e,n);if(("move"===e.op||"copy"===e.op)&&"string"!=typeof e.from)throw new E("Operation `from` property is not present (applicable in `move` and `copy` operations)","OPERATION_FROM_REQUIRED",t,e,n);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&void 0===e.value)throw new E("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_REQUIRED",t,e,n);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&u(e.value))throw new E("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED",t,e,n);if(n)if("add"==e.op){var i=e.path.split("/").length,o=r.split("/").length;if(i!==o+1&&i!==o)throw new E("Cannot perform an `add` operation at the desired path","OPERATION_PATH_CANNOT_ADD",t,e,n)}else if("replace"===e.op||"remove"===e.op||"_get"===e.op){if(e.path!==r)throw new E("Cannot perform the operation at a path that does not exist","OPERATION_PATH_UNRESOLVABLE",t,e,n)}else if("move"===e.op||"copy"===e.op){var a=L([{op:"_get",path:e.from,value:void 0}],n);if(a&&"OPERATION_PATH_UNRESOLVABLE"===a.name)throw new E("Cannot perform the operation from a path that does not exist","OPERATION_FROM_UNRESOLVABLE",t,e,n)}}function L(e,t,n){try{if(!Array.isArray(e))throw new E("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");if(t)A(f(t),f(e),n||!0);else{n=n||I;for(var r=0;r >1)+h+t+k+E.slice(A);break;default:t=E+h+t+k}return s(t)}return m=void 0===m?6:/[gprs]/.test(v)?Math.max(1,Math.min(21,m)):Math.max(0,Math.min(20,m)),k.toString=function(){return t+""},k}return{format:f,formatPrefix:function(t,e){var n=f(((t=Ce(t)).type="f",t)),r=3*Math.max(-8,Math.min(8,Math.floor(Ae(e)/3))),i=Math.pow(10,-r),o=Re[8+r/3];return function(t){return n(i*t)+o}}}}function Ue(t){return Math.max(0,-Ae(Math.abs(t)))}function qe(t,e){return Math.max(0,3*Math.max(-8,Math.min(8,Math.floor(Ae(e)/3)))-Ae(Math.abs(t)))}function Pe(t,e){return t=Math.abs(t),e=Math.abs(e)-t,Math.max(0,Ae(e)-Ae(t))+1}!function(t){Be=Le(t),Ne=Be.format,ze=Be.formatPrefix}({thousands:",",grouping:[3],currency:["$",""]});const je=new Date,Ie=new Date;function We(t,e,n,r){function i(e){return t(e=0===arguments.length?new Date:new Date(+e)),e}return i.floor=e=>(t(e=new Date(+e)),e),i.ceil=n=>(t(n=new Date(n-1)),e(n,1),t(n),n),i.round=t=>{const e=i(t),n=i.ceil(t);return t-e t+(e<0?-1:e>0?1:0)),0))!==e.length&&n.warn("Log scale domain includes zero: "+wt(e)));return e}function nb(t,e,n){return Y(t)&&(e||n)?ip(t,rb(e||[0,1],n)):t}function rb(t,e){return e?t.slice().reverse():t}function ib(t){La.call(this,null,t)}st(tb,La,{transform(t,e){var n=e.dataflow,r=this.value,i=function(t){var e,n=t.type,r="";if(n===Ed)return Ed+"-"+_d;(function(t){const e=t.type;return Zd(e)&&e!==Md&&e!==Ad&&(t.scheme||t.range&&t.range.length&&t.range.every(pt))})(t)&&(r=2===(e=t.rawDomain?t.rawDomain.length:t.domain?t.domain.length+ +(null!=t.domainMid):0)?Ed+"-":3===e?Dd+"-":"");return(r+n||_d).toLowerCase()}(t);for(i in r&&i===r.type||(this.value=r=Vd(i)()),t)if(!Kx[i]){if("padding"===i&&Qx(r.type))continue;Y(r[i])?r[i](t[i]):n.warn("Unsupported scale property: "+i)}return function(t,e,n){var r=t.type,i=e.round||!1,o=e.range;if(null!=e.rangeStep)o=function(t,e,n){t!==Bd&&t!==Td&&s("Only band and point scales support rangeStep.");var r=(null!=e.paddingOuter?e.paddingOuter:e.padding)||0,i=t===Td?1:(null!=e.paddingInner?e.paddingInner:e.padding)||0;return[0,e.rangeStep*vd(n,i,r)]}(r,e,n);else if(e.scheme&&(o=function(t,e,n){var r,i=e.schemeExtent;_(e.scheme)?r=op(e.scheme,e.interpolate,e.interpolateGamma):(r=hp(e.scheme.toLowerCase()))||s(`Unrecognized scheme name: ${e.scheme}`);return n=t===Sd?n+1:t===Nd?n-1:t===Cd||t===Fd?+e.schemeCount||5:n,ep(t)?nb(r,i,e.reverse):Y(r)?ap(nb(r,i),n):t===$d?r:r.slice(0,n)}(r,e,n),Y(o))){if(t.interpolator)return t.interpolator(o);s(`Scale type ${r} does not support interpolating color schemes.`)}if(o&&ep(r))return t.interpolator(op(rb(o,e.reverse),e.interpolate,e.interpolateGamma));o&&e.interpolate&&t.interpolate?t.interpolate(up(e.interpolate,e.interpolateGamma)):Y(t.round)?t.round(i):Y(t.rangeRound)&&t.interpolate(i?ih:rh);o&&t.range(rb(o,e.reverse))}(r,t,function(t,e,n){let r=e.bins;if(r&&!_(r)){const e=t.domain(),n=e[0],i=A(e),o=r.step;let a=null==r.start?n:r.start,u=null==r.stop?i:r.stop;o||s("Scale bins parameter missing step property."),a${t(o)}
`),a&&(i+=``);const l=Object.keys(s);if(l.length>0){i+="
";for(const e of l){let r=s[e];void 0!==r&&(De(r)&&(r=Kt(r,n)),i+=`
"}return i||"{}"}return t(e)},baseURL:"",anchor:"cursor",position:["top","bottom","left","right","top-left","top-right","bottom-left","bottom-right"]};function rn(e,t,{offsetX:n,offsetY:r}){const i=on({x1:e.clientX,x2:e.clientX,y1:e.clientY,y2:e.clientY},t,n,r),o=["bottom-right","bottom-left","top-right","top-left"];for(const e of o)if(an(i[e],t))return i[e];return i["top-left"]}function on(e,t,n,r){const i=(e.x1+e.x2)/2,o=(e.y1+e.y2)/2,a=e.x1-t.width-n,s=i-t.width/2,l=e.x2+n,c=e.y1-t.height-r,f=o-t.height/2,d=e.y2+r;return{top:{x:s,y:c},bottom:{x:s,y:d},left:{x:a,y:f},right:{x:l,y:f},"top-left":{x:a,y:c},"top-right":{x:l,y:c},"bottom-left":{x:a,y:d},"bottom-right":{x:l,y:d}}}function an(e,t){return e.x>=0&&e.y>=0&&e.x+t.width<=window.innerWidth&&e.y+t.height<=window.innerHeight}function sn(e,t,n){return e.clientX>=t.x&&e.clientX<=t.x+n.width&&e.clientY>=t.y&&e.clientY<=t.y+n.height}class ln{call;options;el;constructor(e){this.options={...nn,...e};const t=this.options.id;if(this.el=null,this.call=this.tooltipHandler.bind(this),!this.options.disableDefaultStyle&&!document.getElementById(this.options.styleId)){const e=document.createElement("style");e.setAttribute("id",this.options.styleId),e.innerHTML=function(e){if(!/^[A-Za-z]+[-:.\w]*$/.test(e))throw new Error("Invalid HTML ID");return en.toString().replaceAll(tn,e)}(t);const n=document.head;n.childNodes.length>0?n.insertBefore(e,n.childNodes[0]):n.appendChild(e)}}tooltipHandler(e,t,n,r){if(this.el=document.getElementById(this.options.id),!this.el){this.el=document.createElement("div"),this.el.setAttribute("id",this.options.id),this.el.classList.add("vg-tooltip");(document.fullscreenElement??document.body).appendChild(this.el)}if(null==r||""===r)return void this.el.classList.remove("visible",`${this.options.theme}-theme`);this.el.innerHTML=this.options.formatTooltip(r,this.options.sanitize,this.options.maxDepth,this.options.baseURL),this.el.classList.add("visible",`${this.options.theme}-theme`);const{x:i,y:o}="mark"===this.options.anchor?function(e,t,n,r,i){const{position:o,offsetX:a,offsetY:s}=i,l=function(e,t,n){const r=n.isVoronoi?n.datum.bounds:n.bounds;let i=e.left+t[0]+r.x1,o=e.top+t[1]+r.y1,a=n;for(;a.mark.group;)a=a.mark.group,i+=a.x??0,o+=a.y??0;return{x1:i,x2:i+(r.x2-r.x1),y1:o,y2:o+(r.y2-r.y1)}}(e._el.getBoundingClientRect(),e._origin,n),c=on(l,r,a,s),f=Array.isArray(o)?o:[o];for(const e of f)if(an(c[e],r)&&!sn(t,c[e],r))return c[e];return rn(t,r,i)}(e,t,n,this.el.getBoundingClientRect(),this.options):rn(t,this.el.getBoundingClientRect(),this.options);this.el.style.top=`${o}px`,this.el.style.left=`${i}px`}}var cn='.vega-embed {\n position: relative;\n display: inline-block;\n box-sizing: border-box;\n}\n.vega-embed.has-actions {\n padding-right: 38px;\n}\n.vega-embed details:not([open]) > :not(summary) {\n display: none !important;\n}\n.vega-embed summary {\n list-style: none;\n position: absolute;\n top: 0;\n right: 0;\n padding: 6px;\n z-index: 1000;\n background: white;\n box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.1);\n color: #1b1e23;\n border: 1px solid #aaa;\n border-radius: 999px;\n opacity: 0.2;\n transition: opacity 0.4s ease-in;\n cursor: pointer;\n line-height: 0px;\n}\n.vega-embed summary::-webkit-details-marker {\n display: none;\n}\n.vega-embed summary:active {\n box-shadow: #aaa 0px 0px 0px 1px inset;\n}\n.vega-embed summary svg {\n width: 14px;\n height: 14px;\n}\n.vega-embed details[open] summary {\n opacity: 0.7;\n}\n.vega-embed:hover summary, .vega-embed:focus-within summary {\n opacity: 1 !important;\n transition: opacity 0.2s ease;\n}\n.vega-embed .vega-actions {\n position: absolute;\n z-index: 1001;\n top: 35px;\n right: -9px;\n display: flex;\n flex-direction: column;\n padding-bottom: 8px;\n padding-top: 8px;\n border-radius: 4px;\n box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.2);\n border: 1px solid #d9d9d9;\n background: white;\n animation-duration: 0.15s;\n animation-name: scale-in;\n animation-timing-function: cubic-bezier(0.2, 0, 0.13, 1.5);\n text-align: left;\n}\n.vega-embed .vega-actions a {\n padding: 8px 16px;\n font-family: sans-serif;\n font-size: 14px;\n font-weight: 600;\n white-space: nowrap;\n color: #434a56;\n text-decoration: none;\n}\n.vega-embed .vega-actions a:hover, .vega-embed .vega-actions a:focus {\n background-color: #f7f7f9;\n color: black;\n}\n.vega-embed .vega-actions::before, .vega-embed .vega-actions::after {\n content: "";\n display: inline-block;\n position: absolute;\n}\n.vega-embed .vega-actions::before {\n left: auto;\n right: 14px;\n top: -16px;\n border: 8px solid rgba(0, 0, 0, 0);\n border-bottom-color: #d9d9d9;\n}\n.vega-embed .vega-actions::after {\n left: auto;\n right: 15px;\n top: -14px;\n border: 7px solid rgba(0, 0, 0, 0);\n border-bottom-color: #fff;\n}\n.vega-embed .chart-wrapper.fit-x {\n width: 100%;\n}\n.vega-embed .chart-wrapper.fit-y {\n height: 100%;\n}\n\n.vega-embed-wrapper {\n max-width: 100%;\n overflow: auto;\n padding-right: 14px;\n}\n\n@keyframes scale-in {\n from {\n opacity: 0;\n transform: scale(0.6);\n }\n to {\n opacity: 1;\n transform: scale(1);\n }\n}\n';function fn(e,...t){for(const n of t)dn(e,n);return e}function dn(t,n){for(const r of Object.keys(n))e.writeConfig(t,r,n[r],!0)}const pn="7.1.0",hn=i;let un=o;const gn="undefined"!=typeof window?window:void 0;void 0===un&&gn?.vl?.compile&&(un=gn.vl);const mn={export:{svg:!0,png:!0},source:!0,compiled:!0,editor:!0},En={CLICK_TO_VIEW_ACTIONS:"Click to view actions",COMPILED_ACTION:"View Compiled Vega",EDITOR_ACTION:"Open in Vega Editor",PNG_ACTION:"Save as PNG",SOURCE_ACTION:"View Source",SVG_ACTION:"Save as SVG"},vn={vega:"Vega","vega-lite":"Vega-Lite"},bn={vega:hn.version,"vega-lite":un?un.version:"not available"},yn={vega:e=>e,"vega-lite":(e,t,n)=>un.compile(e,{config:n,logger:t}).spec},wn='\n',On="chart-wrapper";function An(e,t,n,r){const i=`${t} `)}i+="${t(e)} ${t(r)}
${n}`,a=window.open("");a.document.write(i+e+o),a.document.title=`${vn[r]} JSON Source`}function In(e){return!(!e||!("load"in e))}function Ln(e){return In(e)?e:hn.loader(e)}async function xn(t,n,r={}){let i,o;e.isString(n)?(o=Ln(r.loader),i=JSON.parse(await o.load(n))):i=n;const a=function(t){const n=t.usermeta?.embedOptions??{};return e.isString(n.defaultStyle)&&(n.defaultStyle=!1),n}(i),s=a.loader;o&&!s||(o=Ln(r.loader??s));const l=await Nn(a,o),c=await Nn(r,o),f={...fn(c,l),config:e.mergeConfig(c.config??{},l.config??{})};return await async function(t,n,r={},i){const o=r.theme?e.mergeConfig(Zt[r.theme],r.config??{}):r.config,a=e.isBoolean(r.actions)?r.actions:fn({},mn,r.actions??{}),s={...En,...r.i18n},l=r.renderer??"svg",c=r.logger??e.logger(hn.Warn);void 0!==r.logLevel&&c.level(r.logLevel);const f=r.downloadFileName??"visualization",d="string"==typeof t?document.querySelector(t):t;if(!d)throw new Error(`${t} does not exist`);if(!1!==r.defaultStyle){const e="vega-embed-style",{root:t,rootContainer:n}=function(e){const t=e.getRootNode?e.getRootNode():document;return t instanceof ShadowRoot?{root:t,rootContainer:t}:{root:document,rootContainer:document.head??document.body}}(d);if(!t.getElementById(e)){const t=document.createElement("style");t.id=e,t.innerHTML=void 0===r.defaultStyle||!0===r.defaultStyle?cn.toString():r.defaultStyle,n.appendChild(t)}}const p=function(e,t,n){if(e.$schema){const r=Ye(e.$schema);n&&n!==r.library&&t.warn(`The given visualization spec is written in ${vn[r.library]}, but mode argument sets ${vn[n]??n}.`);const i=r.library;return $e(bn[i],`^${r.version.slice(1)}`)||t.warn(`The input spec uses ${vn[i]} ${r.version}, but the current version of ${vn[i]} is v${bn[i]}.`),i}return"mark"in e||"encoding"in e||"layer"in e||"hconcat"in e||"vconcat"in e||"facet"in e||"repeat"in e?"vega-lite":"marks"in e||"signals"in e||"scales"in e||"axes"in e?"vega":n??"vega"}(n,c,r.mode);let h=yn[p](n,c,o);if("vega-lite"===p&&h.$schema){const e=Ye(h.$schema);$e(bn.vega,`^${e.version.slice(1)}`)||c.warn(`The compiled spec uses Vega ${e.version}, but current version is v${bn.vega}.`)}d.classList.add("vega-embed"),a&&d.classList.add("has-actions");d.innerHTML="";let u=d;if(a){const e=document.createElement("div");e.classList.add(On),d.appendChild(e),u=e}const g=r.patch;g&&(h=g instanceof Function?g(h):A(h,g,!0,!1).newDocument);r.formatLocale&&hn.formatLocale(r.formatLocale);r.timeFormatLocale&&hn.timeFormatLocale(r.timeFormatLocale);if(r.expressionFunctions)for(const e in r.expressionFunctions){const t=r.expressionFunctions[e];"fn"in t?hn.expressionFunction(e,t.fn,t.visitor):t instanceof Function&&hn.expressionFunction(e,t)}const{ast:m}=r,E=hn.parse(h,"vega-lite"===p?{}:o,{ast:m}),v=new(r.viewClass||hn.View)(E,{loader:i,logger:c,renderer:l,...m?{expr:hn.expressionInterpreter??r.expr??He}:{}});if(v.addSignalListener("autosize",((e,t)=>{const{type:n}=t;"fit-x"==n?(u.classList.add("fit-x"),u.classList.remove("fit-y")):"fit-y"==n?(u.classList.remove("fit-x"),u.classList.add("fit-y")):"fit"==n?u.classList.add("fit-x","fit-y"):u.classList.remove("fit-x","fit-y")})),!1!==r.tooltip){const{loader:e,tooltip:t}=r,n=e&&!In(e)?e?.baseURL:void 0,i="function"==typeof t?t:new ln({baseURL:n,...!0===t?{}:t}).call;v.tooltip(i)}let b,{hover:y}=r;void 0===y&&(y="vega"===p);if(y){const{hoverSet:e,updateSet:t}="boolean"==typeof y?{}:y;v.hover(e,t)}r&&(null!=r.width&&v.width(r.width),null!=r.height&&v.height(r.height),null!=r.padding&&v.padding(r.padding));if(await v.initialize(u,r.bind).runAsync(),!1!==a){let t=d;if(!1!==r.defaultStyle||r.forceActionsMenu){const e=document.createElement("details");e.title=s.CLICK_TO_VIEW_ACTIONS,d.append(e),t=e;const n=document.createElement("summary");n.innerHTML=wn,e.append(n),b=t=>{e.contains(t.target)||e.removeAttribute("open")},document.addEventListener("click",b)}const i=document.createElement("div");if(t.append(i),i.classList.add("vega-actions"),!0===a||!1!==a.export)for(const t of["svg","png"])if(!0===a||!0===a.export||a.export[t]){const n=s[`${t.toUpperCase()}_ACTION`],o=document.createElement("a"),a=e.isObject(r.scaleFactor)?r.scaleFactor[t]:r.scaleFactor;o.text=n,o.href="#",o.target="_blank",o.download=`${f}.${t}`,o.addEventListener("mousedown",(async function(e){e.preventDefault();const n=await v.toImageURL(t,a);this.href=n})),i.append(o)}if(!0===a||!1!==a.source){const e=document.createElement("a");e.text=s.SOURCE_ACTION,e.href="#",e.addEventListener("click",(function(e){An(k(n),r.sourceHeader??"",r.sourceFooter??"",p),e.preventDefault()})),i.append(e)}if("vega-lite"===p&&(!0===a||!1!==a.compiled)){const e=document.createElement("a");e.text=s.COMPILED_ACTION,e.href="#",e.addEventListener("click",(function(e){An(k(h),r.sourceHeader??"",r.sourceFooter??"","vega"),e.preventDefault()})),i.append(e)}if(!0===a||!1!==a.editor){const e=r.editorUrl??"https://vega.github.io/editor/",t=document.createElement("a");t.text=s.EDITOR_ACTION,t.href="#",t.addEventListener("click",(function(t){!function(e,t,n){const r=e.open(t),{origin:i}=new URL(t);let o=40;e.addEventListener("message",(function t(n){n.source===r&&(o=0,e.removeEventListener("message",t,!1))}),!1),setTimeout((function e(){o<=0||(r.postMessage(n,i),setTimeout(e,250),o-=1)}),250)}(window,e,{config:o,mode:g?"vega":p,renderer:l,spec:k(g?h:n)}),t.preventDefault()})),i.append(t)}}function w(){b&&document.removeEventListener("click",b),v.finalize()}return{view:v,spec:n,vgSpec:h,finalize:w,embedOptions:r}}(t,i,f,o)}async function Nn(t,n){const r=e.isString(t.config)?JSON.parse(await n.load(t.config)):t.config??{},i=e.isString(t.patch)?JSON.parse(await n.load(t.patch)):t.patch;return{...t,...i?{patch:i}:{},...r?{config:r}:{}}}async function $n(e,t={}){const n=document.createElement("div");n.classList.add("vega-embed-wrapper");const r=document.createElement("div");n.appendChild(r);const i=!0===t.actions||!1===t.actions?t.actions:{export:!0,source:!1,compiled:!0,editor:!0,...t.actions},o=await xn(r,e,{actions:i,...t});return n.value=o.view,n}const Rn=(...t)=>{return t.length>1&&(e.isString(t[0])&&!((n=t[0]).startsWith("http://")||n.startsWith("https://")||n.startsWith("//"))||t[0]instanceof HTMLElement||3===t.length)?xn(t[0],t[1],t[2]):$n(t[0],t[1]);var n};return Rn.vegaLite=un,Rn.vl=un,Rn.container=$n,Rn.embed=xn,Rn.vega=hn,Rn.default=xn,Rn.version=pn,Rn}));
+//# sourceMappingURL=vega-embed.min.js.map
diff --git a/inst/htmlwidgets/lib/vega-lite/vega-lite.min.js b/inst/htmlwidgets/lib/vega-lite/vega-lite.min.js
new file mode 100644
index 0000000..52eddcc
--- /dev/null
+++ b/inst/htmlwidgets/lib/vega-lite/vega-lite.min.js
@@ -0,0 +1,2 @@
+!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("vega")):"function"==typeof define&&define.amd?define(["exports","vega"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).vegaLite={},e.vega)}(this,function(e,t){"use strict";var n="6.4.2";function i(e){return Z(e,"or")}function r(e){return Z(e,"and")}function o(e){return Z(e,"not")}function a(e,t){if(o(e))a(e.not,t);else if(r(e))for(const n of e.and)a(n,t);else if(i(e))for(const n of e.or)a(n,t);else t(e)}function s(e,t){return o(e)?{not:s(e.not,t)}:r(e)?{and:e.and.map(e=>s(e,t))}:i(e)?{or:e.or.map(e=>s(e,t))}:t(e)}const c=structuredClone;function l(e){throw new Error(e)}function u(e,n){const i={};for(const r of n)t.hasOwnProperty(e,r)&&(i[r]=e[r]);return i}function f(e,t){const n={...e};for(const e of t)delete n[e];return n}function d(e){if(t.isNumber(e))return e;const n=t.isString(e)?e:K(e);if(n.length<250)return n;let i=0;for(let e=0;e`,o=`0))return[];if((t=+t)===(e=+e))return[t];const r=e=e)&&(n=e);else{let r=-1;for(let i of t)null!=(i=e(i,++r,t))&&(n=i)&&(n=i)}return n}function pe(t,e){let n;if(void 0===e)for(const e of t)null!=e&&(n>e||void 0===n&&e>=e)&&(n=e);else{let r=-1;for(let i of t)null!=(i=e(i,++r,t))&&(n>i||void 0===n&&i>=i)&&(n=i)}return n}function ge(t,e,n=0,r=1/0,i){if(e=Math.floor(e),n=Math.floor(Math.max(0,n)),r=Math.floor(Math.min(t.length-1,r)),!(n<=e&&e<=r))return t;for(i=void 0===i?oe:function(t=Wt){if(t===Wt)return oe;if("function"!=typeof t)throw new TypeError("compare is not a function");return(e,n)=>{const r=t(e,n);return r||0===r?r:(0===t(n,n))-(0===t(e,e))}}(i);r>n;){if(r-n>600){const o=r-n+1,a=e-n+1,s=Math.log(o),u=.5*Math.exp(2*s/3),l=.5*Math.sqrt(s*u*(o-u)/o)*(a-o/2<0?-1:1);ge(t,e,Math.max(n,Math.floor(e-a*u/o+l)),Math.min(r,Math.floor(e+(o-a)*u/o+l)),i)}const o=t[e];let a=n,s=r;for(me(t,n,e),i(t[r],o)>0&&me(t,n,r);a0;)--s}0===i(t[n],o)?me(t,n,s):(++s,me(t,s,r)),s<=e&&(n=s+1),e<=s&&(r=s-1)}return t}function me(t,e,n){const r=t[e];t[e]=t[n],t[n]=r}function ye(t,e,n){if(t=Float64Array.from(function*(t,e){if(void 0===e)for(let e of t)null!=e&&(e=+e)>=e&&(yield e);else{let n=-1;for(let r of t)null!=(r=e(r,++n,t))&&(r=+r)>=r&&(yield r)}}(t,n)),(r=t.length)&&!isNaN(e=+e)){if(e<=0||r<2)return pe(t);if(e>=1)return de(t);var r,i=(r-1)*e,o=Math.floor(i),a=de(ge(t,o).subarray(0,o+1));return a+(pe(t.subarray(o+1))-a)*(i-o)}}function ve(t,e,n=Vt){if((r=t.length)&&!isNaN(e=+e)){if(e<=0||r<2)return+n(t[0],0,t);if(e>=1)return+n(t[r-1],r-1,t);var r,i=(r-1)*e,o=Math.floor(i),a=+n(t[o],o,t);return a+(+n(t[o+1],o+1,t)-a)*(i-o)}}function _e(t,e){return ye(t,.5,e)}function xe(t){return Array.from(function*(t){for(const e of t)yield*e}(t))}function be(t,e,n){t=+t,e=+e,n=(i=arguments.length)<2?(e=t,t=0,1):i<3?1:+n;for(var r=-1,i=0|Math.max(0,Math.ceil((e-t)/n)),o=new Array(i);++r1?r[0]+r.slice(2):r,+t.slice(n+1)]}function Ae(t){return(t=Me(Math.abs(t)))?t[1]:NaN}var Ee,De=/^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;function Ce(t){if(!(e=De.exec(t)))throw new Error("invalid format: "+t);var e;return new Fe({fill:e[1],align:e[2],sign:e[3],symbol:e[4],zero:e[5],width:e[6],comma:e[7],precision:e[8]&&e[8].slice(1),trim:e[9],type:e[10]})}function Fe(t){this.fill=void 0===t.fill?" ":t.fill+"",this.align=void 0===t.align?">":t.align+"",this.sign=void 0===t.sign?"-":t.sign+"",this.symbol=void 0===t.symbol?"":t.symbol+"",this.zero=!!t.zero,this.width=void 0===t.width?void 0:+t.width,this.comma=!!t.comma,this.precision=void 0===t.precision?void 0:+t.precision,this.trim=!!t.trim,this.type=void 0===t.type?"":t.type+""}function Se(t,e){var n=Me(t,e);if(!n)return t+"";var r=n[0],i=n[1];return i<0?"0."+new Array(-i).join("0")+r:r.length>i+1?r.slice(0,i+1)+"."+r.slice(i+1):r+new Array(i-r.length+2).join("0")}Ce.prototype=Fe.prototype,Fe.prototype.toString=function(){return this.fill+this.align+this.sign+this.symbol+(this.zero?"0":"")+(void 0===this.width?"":Math.max(1,0|this.width))+(this.comma?",":"")+(void 0===this.precision?"":"."+Math.max(0,0|this.precision))+(this.trim?"~":"")+this.type};var $e={"%":(t,e)=>(100*t).toFixed(e),b:t=>Math.round(t).toString(2),c:t=>t+"",d:function(t){return Math.abs(t=Math.round(t))>=1e21?t.toLocaleString("en").replace(/,/g,""):t.toString(10)},e:(t,e)=>t.toExponential(e),f:(t,e)=>t.toFixed(e),g:(t,e)=>t.toPrecision(e),o:t=>Math.round(t).toString(8),p:(t,e)=>Se(100*t,e),r:Se,s:function(t,e){var n=Me(t,e);if(!n)return t+"";var r=n[0],i=n[1],o=i-(Ee=3*Math.max(-8,Math.min(8,Math.floor(i/3))))+1,a=r.length;return o===a?r:o>a?r+new Array(o-a+1).join("0"):o>0?r.slice(0,o)+"."+r.slice(o):"0."+new Array(1-o).join("0")+Me(t,Math.max(0,e+o-1))[0]},X:t=>Math.round(t).toString(16).toUpperCase(),x:t=>Math.round(t).toString(16)};function Te(t){return t}var Be,Ne,ze,Oe=Array.prototype.map,Re=["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];function Le(t){var e,n,r=void 0===t.grouping||void 0===t.thousands?Te:(e=Oe.call(t.grouping,Number),n=t.thousands+"",function(t,r){for(var i=t.length,o=[],a=0,s=e[0],u=0;i>0&&s>0&&(u+s+1>r&&(s=Math.max(1,r-u)),o.push(t.substring(i-=s,i+s)),!((u+=s+1)>r));)s=e[a=(a+1)%e.length];return o.reverse().join(n)}),i=void 0===t.currency?"":t.currency[0]+"",o=void 0===t.currency?"":t.currency[1]+"",a=void 0===t.decimal?".":t.decimal+"",s=void 0===t.numerals?Te:function(t){return function(e){return e.replace(/[0-9]/g,(function(e){return t[+e]}))}}(Oe.call(t.numerals,String)),u=void 0===t.percent?"%":t.percent+"",l=void 0===t.minus?"−":t.minus+"",c=void 0===t.nan?"NaN":t.nan+"";function f(t){var e=(t=Ce(t)).fill,n=t.align,f=t.sign,h=t.symbol,d=t.zero,p=t.width,g=t.comma,m=t.precision,y=t.trim,v=t.type;"n"===v?(g=!0,v="g"):$e[v]||(void 0===m&&(m=12),y=!0,v="g"),(d||"0"===e&&"="===n)&&(d=!0,e="0",n="=");var _="$"===h?i:"#"===h&&/[boxX]/.test(v)?"0"+v.toLowerCase():"",x="$"===h?o:/[%p]/.test(v)?u:"",b=$e[v],w=/[defgprs%]/.test(v);function k(t){var i,o,u,h=_,k=x;if("c"===v)k=b(t)+k,t="";else{var M=(t=+t)<0||1/t<0;if(t=isNaN(t)?c:b(Math.abs(t),m),y&&(t=function(t){t:for(var e,n=t.length,r=1,i=-1;r=u)return-1;if(37===(i=e.charCodeAt(a++))){if(i=e.charAt(a++),!(o=b[i in Zr?e.charAt(a++):i])||(r=o(t,n,r))<0)return-1}else if(i!=n.charCodeAt(r++))return-1}return r}return _.x=w(n,_),_.X=w(r,_),_.c=w(e,_),x.x=w(n,x),x.X=w(r,x),x.c=w(e,x),{format:function(t){var e=w(t+="",_);return e.toString=function(){return t},e},parse:function(t){var e=k(t+="",!1);return e.toString=function(){return t},e},utcFormat:function(t){var e=w(t+="",x);return e.toString=function(){return t},e},utcParse:function(t){var e=k(t+="",!0);return e.toString=function(){return t},e}}}var Yr,Gr,Vr,Xr,Jr,Zr={"-":"",_:" ",0:"0"},Qr=/^\s*\d+/,Kr=/^%/,ti=/[\\^$*+?|[\]().{}]/g;function ei(t,e,n){var r=t<0?"-":"",i=(r?-t:t)+"",o=i.length;return r+(o_*(t-=o)*t+x*t+b+a;return{coef:[b-x*o+_*o*o+a,x-2*_*o,_],predict:w,rSquared:_s(t,e,n,a,w)}}function As(t,e,n,r){if(0===r)return gs(t,e,n);if(1===r)return xs(t,e,n);if(2===r)return Ms(t,e,n);const[i,o,a,s]=ys(t,e,n),u=i.length,l=[],c=[],f=r+1;let h,d,p,g,m;for(h=0;ht.materialize(t.SOURCE).source}(e)),i=t.steps||t.minsteps||25,o=t.steps||t.maxsteps||200;let a=t.method||"pdf";"pdf"!==a&&"cdf"!==a&&s("Invalid density method: "+a),t.extent||r.data||s("Missing density extent parameter."),a=r[a];const u=t.as||["value","density"],l=$s(a,t.extent||et(r.data()),i,o).map((t=>{const e={};return e[u[0]]=t[0],e[u[1]]=t[1],sa(e)}));this.value&&(n.rem=this.value),this.value=n.add=n.source=l}return n}});function cu(t){La.call(this,null,t)}cu.Definition={type:"DotBin",metadata:{modifies:!0},params:[{name:"field",type:"field",required:!0},{name:"groupby",type:"field",array:!0},{name:"step",type:"number"},{name:"smooth",type:"boolean",default:!1},{name:"as",type:"string",default:"bin"}]};function fu(t){va.call(this,null,hu,t),this.modified(!0)}function hu(t){const i=t.expr;return this.value&&!t.modified("expr")?this.value:e((e=>i(e,t)),r(i),n(i))}function du(t){La.call(this,[void 0,void 0],t)}function pu(t,e){va.call(this,t),this.parent=e,this.count=0}function gu(t){La.call(this,{},t),this._keys=ot();const e=this._targets=[];e.active=0,e.forEach=t=>{for(let n=0,r=e.active;n{for(let e,n=0;n+t}function gg(t,e,n){return Math.max(e,Math.min(t,n))}function mg(){var t=cg,e=fg,n=hg,r=dg,i=pg(0),o=i,a=i,s=i,u=null;function l(l,c,f){var h,d=null!=c?c:+t.call(this,l),p=null!=f?f:+e.call(this,l),g=+n.call(this,l),m=+r.call(this,l),y=Math.min(g,m)/2,v=gg(+i.call(this,l),0,y),_=gg(+o.call(this,l),0,y),x=gg(+a.call(this,l),0,y),b=gg(+s.call(this,l),0,y);if(u||(u=h=Al()),v<=0&&_<=0&&x<=0&&b<=0)u.rect(d,p,g,m);else{var w=d+g,k=p+m;u.moveTo(d+v,p),u.lineTo(w-_,p),u.bezierCurveTo(w-lg*_,p,w,p+lg*_,w,p+_),u.lineTo(w,k-b),u.bezierCurveTo(w,k-lg*b,w-lg*b,k,w-b,k),u.lineTo(d+x,k),u.bezierCurveTo(d+lg*x,k,d,k-lg*x,d,k-x),u.lineTo(d,p+v),u.bezierCurveTo(d,p+lg*v,d+lg*v,p,d+v,p),u.closePath()}if(h)return u=null,h+""||null}return l.x=function(e){return arguments.length?(t=pg(e),l):t},l.y=function(t){return arguments.length?(e=pg(t),l):e},l.width=function(t){return arguments.length?(n=pg(t),l):n},l.height=function(t){return arguments.length?(r=pg(t),l):r},l.cornerRadius=function(t,e,n,r){return arguments.length?(i=pg(t),o=null!=e?pg(e):i,s=null!=n?pg(n):i,a=null!=r?pg(r):o,l):i},l.context=function(t){return arguments.length?(u=null==t?null:t,l):u},l}function yg(){var t,e,n,r,i,o,a,s,u=null;function l(t,e,n){const r=n/2;if(i){var l=a-e,c=t-o;if(l||c){var f=Math.hypot(l,c),h=(l/=f)*s,d=(c/=f)*s,p=Math.atan2(c,l);u.moveTo(o-h,a-d),u.lineTo(t-l*r,e-c*r),u.arc(t,e,r,p-Math.PI,p),u.lineTo(o+h,a+d),u.arc(o,a,s,p,p+Math.PI)}else u.arc(t,e,r,0,Xp);u.closePath()}else i=1;o=t,a=e,s=r}function c(o){var a,s,c,f=o.length,h=!1;for(null==u&&(u=c=Al()),a=0;a<=f;++a)!(a.5&&e<1.5?.5-Math.abs(e-1):0}function Pm(t,e){const n=qm(e);t("d",Sg(null,e,n,n))}function jm(t,e,n,r){const i=qm(e);t.beginPath(),Sg(t,e,(n||0)+i,(r||0)+i)}const Im=Sm(jm),Wm=Sm(jm,!1),Hm=Sm(jm,!0);var Ym={type:"group",tag:"g",nested:!1,attr:function(t,e){t("transform",Nm(e))},bound:function(t,e){if(!e.clip&&e.items){const n=e.items,r=n.length;for(let e=0;e=0;)if(!1!==t[o].defined&&(n=t[o].x-e[0])*n+(r=t[o].y-e[1])*r{if(!n||n.intersects(e.bounds)){var r=null==e.opacity?1:e.opacity;r&&oy(t,e,r)&&(gm(t,e),t.stroke())}}))},pick:Fm((function(t,e,n,r){return!!t.isPointInStroke&&(oy(t,e,1)&&t.isPointInStroke(n,r))})),isect:dm},sy=zm("shape",(function(t,e){return(e.mark.shape||e.shape).context(t)(e)})),uy=zm("symbol",(function(t,e){return Dg.context(t)(e)}),fm);const ly=yt();var cy={height:my,measureWidth:py,estimateWidth:hy,width:hy,canvas:fy};function fy(t){cy.width=t&&um?py:hy}function hy(t,e){return dy(xy(t,e),my(t))}function dy(t,e){return~~(.8*t.length*e)}function py(t,e){return my(t)<=0||!(e=xy(t,e))?0:gy(e,wy(t))}function gy(t,e){const n=`(${e}) ${t}`;let r=ly.get(n);return void 0===r&&(um.font=e,r=um.measureText(t).width,ly.set(n,r)),r}function my(t){return null!=t.fontSize?+t.fontSize||0:11}function yy(t){return null!=t.lineHeight?t.lineHeight:my(t)+2}function vy(t){return e=t.lineBreak&&t.text&&!_(t.text)?t.text.split(t.lineBreak):t.text,_(e)?e.length>1?e:e[0]:e;var e}function _y(t){const e=vy(t);return(_(e)?e.length-1:0)*yy(t)}function xy(t,e){const n=null==e?"":(e+"").trim();return t.limit>0&&n.length?function(t,e){var n=+t.limit,r=function(t){if(cy.width===py){const e=wy(t);return t=>gy(t,e)}if(cy.width===hy){const e=my(t);return t=>dy(t,e)}return e=>cy.width(t,e)}(t);if(r(e){(o=t.orient||C_)!==X_&&(e[o]||(e[o]=[])).push(t)}));for(const r in e){const i=e[r];Ax(t,i,$x(i,r,n.legends,h,d,l,c))}p.forEach((e=>{const r=e.bounds;if(r.equals(e._bounds)||(e.bounds=e._bounds,t.dirty(e),e.bounds=r,t.dirty(e)),!n.autosize||n.autosize.type!==Y_&&n.autosize.type!==G_&&n.autosize.type!==V_)f.union(r);else switch(e.orient){case D_:case C_:f.add(r.x1,0).add(r.x2,0);break;case E_:case F_:f.add(0,r.y1).add(0,r.y2)}}))}f.union(h).union(d),r&&f.union(function(t,e,n,r,i){var o,a=e.items[0],s=a.frame,u=a.orient,l=a.anchor,c=a.offset,f=a.padding,h=a.items[0].items[0],d=a.items[1]&&a.items[1].items[0],p=u===D_||u===C_?r:n,g=0,m=0,y=0,v=0,_=0;if(s!==B_?u===D_?(g=i.y2,p=i.y1):u===C_?(g=i.y1,p=i.y2):(g=i.x1,p=i.x2):u===D_&&(g=r,p=0),o=l===S_?g:l===T_?p:(g+p)/2,d&&d.text){switch(u){case E_:case F_:_=h.bounds.height()+f;break;case D_:v=h.bounds.width()+f;break;case C_:v=-h.bounds.width()-f}px.clear().union(d.bounds),px.translate(v-(d.x||0),_-(d.y||0)),gx(d,"x",v)|gx(d,"y",_)&&(t.dirty(d),d.bounds.clear().union(px),d.mark.bounds.clear().union(px),t.dirty(d)),px.clear().union(d.bounds)}else px.clear();switch(px.union(h.bounds),u){case E_:m=o,y=i.y1-px.height()-c;break;case D_:m=i.x1-px.width()-c,y=o;break;case C_:m=i.x2+px.width()+c,y=o;break;case F_:m=o,y=i.y2+c;break;default:m=a.x,y=a.y}return gx(a,"x",m)|gx(a,"y",y)&&(px.translate(m,y),t.dirty(a),a.bounds.clear().union(px),e.bounds.clear().union(px),t.dirty(a)),a.bounds}(t,r,l,c,f));e.clip&&f.set(0,0,e.width||0,e.height||0);!function(t,e,n,r){const i=r.autosize||{},o=i.type;if(t._autosize<1||!o)return;let a=t._width,s=t._height,u=Math.max(0,e.width||0),l=Math.max(0,Math.ceil(-n.x1)),c=Math.max(0,e.height||0),f=Math.max(0,Math.ceil(-n.y1));const h=Math.max(0,Math.ceil(n.x2-u)),d=Math.max(0,Math.ceil(n.y2-c));if(i.contains===H_){const e=t.padding();a-=e.left+e.right,s-=e.top+e.bottom}o===X_?(l=0,f=0,u=a,c=s):o===Y_?(u=Math.max(0,a-l-h),c=Math.max(0,s-f-d)):o===G_?(u=Math.max(0,a-l-h),s=c+f+d):o===V_?(a=u+l+h,c=Math.max(0,s-f-d)):"pad"===o&&(a=u+l+h,s=c+f+d);t._resizeView(a,s,u,c,[l,f],i.resize)}(t,e,f,n)}(n,e,t)})),function(t){return t&&"legend-entry"!==t.mark.role}(t.mark.group)?e.reflow():e}});var Ox=Object.freeze({__proto__:null,bound:ex,identifier:ix,mark:ox,overlap:ax,render:dx,viewlayout:zx});function Rx(t){La.call(this,null,t)}function Lx(t){La.call(this,null,t)}function Ux(){return sa({})}function qx(t){La.call(this,null,t)}function Px(t){La.call(this,[],t)}st(Rx,La,{transform(t,e){if(this.value&&!t.modified())return e.StopPropagation;var n=e.dataflow.locale(),r=e.fork(e.NO_SOURCE|e.NO_FIELDS),i=this.value,o=t.scale,a=yp(o,null==t.count?t.values?t.values.length:10:t.count,t.minstep),s=t.format||xp(n,o,a,t.formatSpecifier,t.formatType,!!t.values),u=t.values?vp(o,t.values,a):_p(o,a);return i&&(r.rem=i),i=u.map(((t,e)=>sa({index:e/(u.length-1||1),value:t,label:s(t)}))),t.extra&&i.length&&i.push(sa({index:-1,extra:{value:i[0].value},label:""})),r.source=i,r.add=i,this.value=i,r}}),st(Lx,La,{transform(t,e){var n=e.dataflow,r=e.fork(e.NO_SOURCE|e.NO_FIELDS),i=t.item||Ux,o=t.key||oa,a=this.value;return _(r.encode)&&(r.encode=null),a&&(t.modified("key")||e.modified(o))&&s("DataJoin does not support modified key function or fields."),a||(e=e.addAll(),this.value=a=function(t){const e=ot().test((t=>t.exit));return e.lookup=n=>e.get(t(n)),e}(o)),e.visit(e.ADD,(t=>{const e=o(t);let n=a.get(e);n?n.exit?(a.empty--,r.add.push(n)):r.mod.push(n):(n=i(t),a.set(e,n),r.add.push(n)),n.datum=t,n.exit=!1})),e.visit(e.MOD,(t=>{const e=o(t),n=a.get(e);n&&(n.datum=t,r.mod.push(n))})),e.visit(e.REM,(t=>{const e=o(t),n=a.get(e);t!==n.datum||n.exit||(r.rem.push(n),n.exit=!0,++a.empty)})),e.changed(e.ADD_MOD)&&r.modifies("datum"),(e.clean()||t.clean&&a.empty>n.cleanThreshold)&&n.runAfter(a.clean),r}}),st(qx,La,{transform(t,e){var n=e.fork(e.ADD_REM),r=t.mod||!1,i=t.encoders,o=e.encode;if(_(o)){if(!n.changed()&&!o.every((t=>i[t])))return e.StopPropagation;o=o[0],n.encode=null}var a="enter"===o,s=i.update||g,u=i.enter||g,l=i.exit||g,c=(o&&!a?i[o]:s)||g;if(e.changed(e.ADD)&&(e.visit(e.ADD,(e=>{u(e,t),s(e,t)})),n.modifies(u.output),n.modifies(s.output),c!==g&&c!==s&&(e.visit(e.ADD,(e=>{c(e,t)})),n.modifies(c.output))),e.changed(e.REM)&&l!==g&&(e.visit(e.REM,(e=>{l(e,t)})),n.modifies(l.output)),a||c!==g){const i=e.MOD|(t.modified()?e.REFLOW:0);a?(e.visit(i,(e=>{const i=u(e,t)||r;(c(e,t)||i)&&n.mod.push(e)})),n.mod.length&&n.modifies(u.output)):e.visit(i,(e=>{(c(e,t)||r)&&n.mod.push(e)})),n.mod.length&&n.modifies(c.output)}return n.changed()?n:e.StopPropagation}}),st(Px,La,{transform(t,e){if(null!=this.value&&!t.modified())return e.StopPropagation;var n,r,i,o,a,s=e.dataflow.locale(),u=e.fork(e.NO_SOURCE|e.NO_FIELDS),l=this.value,c=t.type||dp,f=t.scale,h=+t.limit,d=yp(f,null==t.count?5:t.count,t.minstep),p=!!t.values||c===dp,g=t.format||Ap(s,f,d,c,t.formatSpecifier,t.formatType,p),m=t.values||Mp(f,d);return l&&(u.rem=l),c===dp?(h&&m.length>h?(e.dataflow.warn("Symbol legend count exceeds limit, filtering items."),l=m.slice(0,h-1),a=!0):l=m,Y(i=t.size)?(t.values||0!==f(l[0])||(l=l.slice(1)),o=l.reduce(((e,n)=>Math.max(e,i(n,t))),0)):i=Q(o=i||8),l=l.map(((e,n)=>sa({index:n,label:g(e,n,l),value:e,offset:o,size:i(e,t)}))),a&&(a=m[l.length],l.push(sa({index:l.length,label:`…${m.length-l.length} entries`,value:a,offset:o,size:i(a,t)})))):"gradient"===c?(n=f.domain(),r=sp(f,n[0],A(n)),m.length<3&&!t.values&&n[0]!==A(n)&&(m=[n[0],A(n)]),l=m.map(((t,e)=>sa({index:e,label:g(t,e,m),value:t,perc:r(t)})))):(i=m.length-1,r=function(t){const e=t.domain(),n=e.length-1;let r=+e[0],i=+A(e),o=i-r;if(t.type===Sd){const t=n?o/n:.1;r-=t,i+=t,o=i-r}return t=>(t-r)/o}(f),l=m.map(((t,e)=>sa({index:e,label:g(t,e,m),value:t,perc:e?r(t):0,perc2:e===i?1:r(m[e+1])})))),u.source=l,u.add=l,this.value=l,u}});const jx=t=>t.source.x,Ix=t=>t.source.y,Wx=t=>t.target.x,Hx=t=>t.target.y;function Yx(t){La.call(this,{},t)}Yx.Definition={type:"LinkPath",metadata:{modifies:!0},params:[{name:"sourceX",type:"field",default:"source.x"},{name:"sourceY",type:"field",default:"source.y"},{name:"targetX",type:"field",default:"target.x"},{name:"targetY",type:"field",default:"target.y"},{name:"orient",type:"enum",default:"vertical",values:["horizontal","vertical","radial"]},{name:"shape",type:"enum",default:"line",values:["line","arc","curve","diagonal","orthogonal"]},{name:"require",type:"signal"},{name:"as",type:"string",default:"path"}]},st(Yx,La,{transform(t,e){var n=t.sourceX||jx,r=t.sourceY||Ix,i=t.targetX||Wx,o=t.targetY||Hx,a=t.as||"path",u=t.orient||"vertical",l=t.shape||"line",c=Jx.get(l+"-"+u)||Jx.get(l);return c||s("LinkPath unsupported type: "+t.shape+(t.orient?"-"+t.orient:"")),e.visit(e.SOURCE,(t=>{t[a]=c(n(t),r(t),i(t),o(t))})),e.reflow(t.modified()).modifies(a)}});const Gx=(t,e,n,r)=>"M"+t+","+e+"L"+n+","+r,Vx=(t,e,n,r)=>{var i=n-t,o=r-e,a=Math.hypot(i,o)/2;return"M"+t+","+e+"A"+a+","+a+" "+180*Math.atan2(o,i)/Math.PI+" 0 1 "+n+","+r},Xx=(t,e,n,r)=>{const i=n-t,o=r-e,a=.2*(i+o),s=.2*(o-i);return"M"+t+","+e+"C"+(t+a)+","+(e+s)+" "+(n+s)+","+(r-a)+" "+n+","+r},Jx=ot({line:Gx,"line-radial":(t,e,n,r)=>Gx(e*Math.cos(t),e*Math.sin(t),r*Math.cos(n),r*Math.sin(n)),arc:Vx,"arc-radial":(t,e,n,r)=>Vx(e*Math.cos(t),e*Math.sin(t),r*Math.cos(n),r*Math.sin(n)),curve:Xx,"curve-radial":(t,e,n,r)=>Xx(e*Math.cos(t),e*Math.sin(t),r*Math.cos(n),r*Math.sin(n)),"orthogonal-horizontal":(t,e,n,r)=>"M"+t+","+e+"V"+r+"H"+n,"orthogonal-vertical":(t,e,n,r)=>"M"+t+","+e+"H"+n+"V"+r,"orthogonal-radial":(t,e,n,r)=>{const i=Math.cos(t),o=Math.sin(t),a=Math.cos(n),s=Math.sin(n);return"M"+e*i+","+e*o+"A"+e+","+e+" 0 0,"+((Math.abs(n-t)>Math.PI?n<=t:n>t)?1:0)+" "+e*a+","+e*s+"L"+r*a+","+r*s},"diagonal-horizontal":(t,e,n,r)=>{const i=(t+n)/2;return"M"+t+","+e+"C"+i+","+e+" "+i+","+r+" "+n+","+r},"diagonal-vertical":(t,e,n,r)=>{const i=(e+r)/2;return"M"+t+","+e+"C"+t+","+i+" "+n+","+i+" "+n+","+r},"diagonal-radial":(t,e,n,r)=>{const i=Math.cos(t),o=Math.sin(t),a=Math.cos(n),s=Math.sin(n),u=(e+r)/2;return"M"+e*i+","+e*o+"C"+u*i+","+u*o+" "+u*a+","+u*s+" "+r*a+","+r*s}});function Zx(t){La.call(this,null,t)}Zx.Definition={type:"Pie",metadata:{modifies:!0},params:[{name:"field",type:"field"},{name:"startAngle",type:"number",default:0},{name:"endAngle",type:"number",default:6.283185307179586},{name:"sort",type:"boolean",default:!1},{name:"as",type:"string",array:!0,length:2,default:["startAngle","endAngle"]}]},st(Zx,La,{transform(t,e){var n,r,i,o=t.as||["startAngle","endAngle"],a=o[0],s=o[1],u=t.field||d,l=t.startAngle||0,c=null!=t.endAngle?t.endAngle:2*Math.PI,f=e.source,h=f.map(u),p=h.length,g=l,m=(c-l)/we(h),y=be(p);for(t.sort&&y.sort(((t,e)=>h[t]-h[e])),n=0;nQb&&(Qb=e)),l?t