├── .gitignore ├── .nojekyll ├── LICENSE ├── README.md ├── _quarto.yml ├── docs ├── .nojekyll ├── index.html ├── search.json ├── site_libs │ ├── bootstrap │ │ ├── bootstrap-icons.css │ │ ├── bootstrap-icons.woff │ │ ├── bootstrap.min.css │ │ └── bootstrap.min.js │ ├── clipboard │ │ └── clipboard.min.js │ ├── quarto-html │ │ ├── anchor.min.js │ │ ├── popper.min.js │ │ ├── quarto-syntax-highlighting.css │ │ ├── quarto.js │ │ ├── tippy.css │ │ └── tippy.umd.min.js │ ├── quarto-nav │ │ └── quarto-nav.js │ ├── quarto-ojs │ │ ├── quarto-ojs-runtime.js │ │ └── quarto-ojs.css │ └── quarto-search │ │ ├── autocomplete.umd.js │ │ ├── fuse.min.js │ │ └── quarto-search.js ├── test-quarto-dynamic.html ├── test-quarto-static.html └── web-component-tut │ └── public │ └── build │ ├── Circles.js │ ├── Circles.js.map │ ├── bundle.css │ ├── bundle.js │ └── bundle.js.map ├── index.qmd ├── test-html-static.html ├── test-quarto-dynamic.qmd ├── test-quarto-static.qmd └── web-component-tut ├── .gitignore ├── README.md ├── package-lock.json ├── package.json ├── public ├── build │ ├── Circles.js │ ├── Circles.js.map │ ├── bundle.css │ ├── bundle.js │ └── bundle.js.map ├── favicon.png ├── global.css └── index.html ├── rollup.config.js ├── scripts └── setupTypeScript.js └── src ├── App.svelte ├── main.js └── widgets └── Circles.svelte /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | /.quarto/ 4 | -------------------------------------------------------------------------------- /.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimjam-slam/svelte-in-quarto/b9f0de1c42fc7728e84cc453d45e46213979c144/.nojekyll -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 James Goldie 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # svelte-in-quarto 2 | 3 | > **Update:** this work has been turned into a Quarto extension: [Sverto](https://github.com/360-info/sverto)! 4 | 5 | Proof-of-concept: render Svelte components in [Quarto](https://quarto.org) documents (and probably [Observable](https://observablehq.com) notebooks?), reactively updating them (transitions and all!) using Observable JS. 6 | 7 | Rendered demo (in `/docs`) is viewable at . 8 | -------------------------------------------------------------------------------- /_quarto.yml: -------------------------------------------------------------------------------- 1 | project: 2 | type: website 3 | output-dir: docs 4 | resources: 5 | - /web-component-tut/public/build/* 6 | -------------------------------------------------------------------------------- /docs/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimjam-slam/svelte-in-quarto/b9f0de1c42fc7728e84cc453d45e46213979c144/docs/.nojekyll -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | Svelt components in Quarto 13 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 62 | 63 | 64 | 65 | 66 | 67 | 68 |
69 | 70 |
71 | 72 | 73 | 74 | 75 |
76 | 77 |
78 |
79 |

Svelt components in Quarto

80 |
81 | 82 | 83 | 84 |
85 | 86 |
87 |
Author
88 |
89 |

James Goldie

90 |
91 |
92 | 93 |
94 |
Published
95 |
96 |

September 15, 2022

97 |
98 |
99 | 100 | 101 |
102 | 103 | 104 |
105 | 106 |
107 |
108 |
109 | 110 |
111 |
112 | Tip 113 |
114 |
115 |
116 |

This work has been turned into a Quarto extension: Sverto!

117 |
118 |
119 |

Okay, so we’re using this blog post on compiling Svelte components as Web Components, along with with this SO answer on making Svelte components as browser bundles, to see if we can write Svelte components that can be dropped into plain HTML, or even Quarto documents.

120 |

The end goal is to have something that can be instantiated in a Quarto document and then dynamically update its props (using reactive OJS code) without destroying the component - for example, to have a chart that transitions elements as the incoming data changes.

121 |

The component itself is Circles.svelte, a bunch of animating circles based on my earlier Svelte tests. It’s pretty simple: literally define an SVG of a bunch of circles, using Svelte’s built-in transitions to smoothly add and remove elements that newly enter or leave the dataset (equivalent to d3’s .enter() and .exit()), and regular CSS transitions for elements that are retained when the dataset changes.

122 |

The static test aims to use Web Component syntax to drop Svelte components in “statically” with HTML, rather than using JavaScript. Although I got this working, I’ve abandoned it, as I’m not sure that you can change the props easily, and that’s kind of what this is all about.

123 |

The dynamic test creates a Svelte component and exposes its props. The idea is to create a component, ibject it into an element, then have it update itself when the props are modified without it being destroyed and remade. That way Svelte can take care of the updates.

124 | 125 | 126 | 127 |
128 | 347 |
348 | 349 | 350 | 351 | -------------------------------------------------------------------------------- /docs/search.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "objectID": "test-quarto-static.html", 4 | "href": "test-quarto-static.html", 5 | "title": "Svelte components in Quarto (static)", 6 | "section": "", 7 | "text": "Okay, so we’re using this blog post on compiling Svelte components as Web Components, along with with this SO answer on making Svelte components as browser bundles, to see if we can write Svelte components that can be dropped into plain HTML, or even Quarto documents.\nThe end goal is to have something that can be instantiated in a Quarto document and then dynamically update its props (using reactive OJS code) without destroying the component - for example, to have a chart that transitions elements as the incoming data changes." 8 | }, 9 | { 10 | "objectID": "test-quarto-static.html#static-html-import", 11 | "href": "test-quarto-static.html#static-html-import", 12 | "title": "Svelte components in Quarto (static)", 13 | "section": "Static HTML import", 14 | "text": "Static HTML import\nIn this first approach, we’ll import the module in the YAML frontmatter and then use a static HTML block. (The container isn’t necessary, I just want to see where the chart’s coming in):\n```{html}\n
\n \n \n
\n```\n\n \n \n\nNice! But it’d be great to instantiate it with JavaScript and use a create-then-update-props pattern, such as this one used to integrate DeckGL with Observable in this blog post.\n\n\n\n\n\n\nNote\n\n\n\nOkay, this was working, but my efforts to get it working dynamically broke it here. Specifically, I switched rollup.config.js to use output.format = \"es\" instead of \"iife\".\n\n\nA further problem is that because of the Web Components interface, attribute props have to be strings. That’s not a super efficient way to pass larger datasets in. Maybe it’s not a problem when we instantiuate with JavaScript?\nLet’s try to fix these problems in test-quarto-dynamic.qmd." 15 | }, 16 | { 17 | "objectID": "index.html", 18 | "href": "index.html", 19 | "title": "Svelt components in Quarto", 20 | "section": "", 21 | "text": "Tip\n\n\n\nThis work has been turned into a Quarto extension: Sverto!\n\n\nOkay, so we’re using this blog post on compiling Svelte components as Web Components, along with with this SO answer on making Svelte components as browser bundles, to see if we can write Svelte components that can be dropped into plain HTML, or even Quarto documents.\nThe end goal is to have something that can be instantiated in a Quarto document and then dynamically update its props (using reactive OJS code) without destroying the component - for example, to have a chart that transitions elements as the incoming data changes.\nThe component itself is Circles.svelte, a bunch of animating circles based on my earlier Svelte tests. It’s pretty simple: literally define an SVG of a bunch of circles, using Svelte’s built-in transitions to smoothly add and remove elements that newly enter or leave the dataset (equivalent to d3’s .enter() and .exit()), and regular CSS transitions for elements that are retained when the dataset changes.\n❌ The static test aims to use Web Component syntax to drop Svelte components in “statically” with HTML, rather than using JavaScript. Although I got this working, I’ve abandoned it, as I’m not sure that you can change the props easily, and that’s kind of what this is all about.\n✅ The dynamic test creates a Svelte component and exposes its props. The idea is to create a component, ibject it into an element, then have it update itself when the props are modified without it being destroyed and remade. That way Svelte can take care of the updates." 22 | }, 23 | { 24 | "objectID": "test-quarto-dynamic.html", 25 | "href": "test-quarto-dynamic.html", 26 | "title": "Svelte components in Quarto (dynamic)", 27 | "section": "", 28 | "text": "Tip\n\n\n\nThis work has been turned into a Quarto extension: Sverto!" 29 | }, 30 | { 31 | "objectID": "test-quarto-dynamic.html#background", 32 | "href": "test-quarto-dynamic.html#background", 33 | "title": "Svelte components in Quarto (dynamic)", 34 | "section": "Background", 35 | "text": "Background\nOkay, so we’re using this blog post on compiling Svelte components as Web Components, along with with this SO answer on making Svelte components as browser bundles, to see if we can write Svelte components that can be dropped into plain HTML, or even Quarto documents.\nThe end goal is to have something that can be instantiated in a Quarto document and then dynamically update its props (using reactive OJS code) without destroying the component - for example, to have a chart that transitions elements as the incoming data changes.\n\n\n\n\n\n\nComponent tag name\n\n\n\nI’ve changed the tag attribute at the top of Circles.svelte from \"animated-circles\" to {null} in order to stop an error that crops up. it fixes that error here but prevents the component from being used in test-quarto-static.qmd with the static HTML syntax." 36 | }, 37 | { 38 | "objectID": "test-quarto-dynamic.html#dynamic-html-import", 39 | "href": "test-quarto-dynamic.html#dynamic-html-import", 40 | "title": "Svelte components in Quarto (dynamic)", 41 | "section": "Dynamic HTML import", 42 | "text": "Dynamic HTML import\nIn this second approach, we’ll import the module in JavaScript, create an instance, and finally update its props to pass new data in. The hope is that we can cirumvent OJS’s reactivity when creating the element, allowing it to transition its child elements (like bars or circles representing data) using its own reactivity. This notebook uses the same pattern to integrate DeckGL with Observable.\nFirst, let’s import the JavaScript. Since OJS blocks are naturally Promises, we should be able to use either require() or await import().\n\nCirclesOne = require(\"/web-component-tut/public/build/Circles.js\");\n\n\n\n\n\n\nHow’d that go? No? What about await import()?\n\nCircles = import(\"/web-component-tut/public/build/Circles.js\");\n\n\n\n\n\n\nBetter, I think!\n\nCircles\n\n\n\n\n\n\nAnd the default constructor?\n\nCircles.default" 43 | }, 44 | { 45 | "objectID": "test-quarto-dynamic.html#demo-animated-svelte-component", 46 | "href": "test-quarto-dynamic.html#demo-animated-svelte-component", 47 | "title": "Svelte components in Quarto (dynamic)", 48 | "section": "Demo: animated Svelte component", 49 | "text": "Demo: animated Svelte component\n\n\n\n\n\n\n\nLet’s create a CirclesTwo. I’ve create a target div, #mycircles, on the margin for it to load into first:\n\nmyCircles = new Circles.default({\n target: document.querySelector(\"#mycircles\"),\n props: {\n // data: \"10|5,30|15,50|25,70|17,90|8\"\n data: [\n {x: 10, r: 5},\n {x: 30, r: 15},\n {x: 50, r: 25},\n {x: 70, r: 17},\n {x: 90, r: 8}\n ]\n }\n});\n\n\n\n\n\n\nGreat! A little bit convoluted, but it’s working. Now we want to push some new data to it - the equivalent of setProps() in DeckGL.\nI can’t see anything that immediately stands out in myCircles, but inspecting the compiled code in Circles.js reveals that the class returned includes get data and set data.\nMaybe I can just write to the prop directly? Let’s set up some options to switch between reactively:\n\nviewof selectedDataset = Inputs.select(\n new Map([\n [\"Dataset A\", [\n {x: 10, r: 5},\n {x: 30, r: 15},\n {x: 50, r: 25},\n {x: 70, r: 17},\n {x: 90, r: 8}\n ]],\n [\"Dataset B\", [\n {x: 10, r: 25},\n {x: 30, r: 5},\n {x: 50, r: 5}\n ]],\n [\"Dataset C\", [\n {x: 5, r: 12},\n {x: 25, r: 5},\n {x: 32, r: 8},\n {x: 45, r: 21},\n {x: 70, r: 5}\n ]]\n ]), {\n label: \"Selected dataset\"\n });\n\n\n\n\n\n\nAnd now we’ll update the Svelte component with it:\n\nmyCircles.data = selectedDataset;\n\n\n\n\n\n\n\nInputs.table(selectedDataset)\n\n\n\n\n\n\n(These are keyed by the x value, not an independent index, so when you choose dataset C, most of the circles are treated as new elements that exit/enter, not existing ones that transition)\n\n\n\n\n\n\nNote\n\n\n\nI initially got an error:\n\n“Error: : Props cannot be set directly on the component instance unless compiling with ‘accessors: true’ or ‘’”\n\nAdding accessors to the svelte:options line at the start of Circles.svelte fixed this right up!" 50 | } 51 | ] -------------------------------------------------------------------------------- /docs/site_libs/bootstrap/bootstrap-icons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimjam-slam/svelte-in-quarto/b9f0de1c42fc7728e84cc453d45e46213979c144/docs/site_libs/bootstrap/bootstrap-icons.woff -------------------------------------------------------------------------------- /docs/site_libs/clipboard/clipboard.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * clipboard.js v2.0.11 3 | * https://clipboardjs.com/ 4 | * 5 | * Licensed MIT © Zeno Rocha 6 | */ 7 | !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return n={686:function(t,e,n){"use strict";n.d(e,{default:function(){return b}});var e=n(279),i=n.n(e),e=n(370),u=n.n(e),e=n(817),r=n.n(e);function c(t){try{return document.execCommand(t)}catch(t){return}}var a=function(t){t=r()(t);return c("cut"),t};function o(t,e){var n,o,t=(n=t,o="rtl"===document.documentElement.getAttribute("dir"),(t=document.createElement("textarea")).style.fontSize="12pt",t.style.border="0",t.style.padding="0",t.style.margin="0",t.style.position="absolute",t.style[o?"right":"left"]="-9999px",o=window.pageYOffset||document.documentElement.scrollTop,t.style.top="".concat(o,"px"),t.setAttribute("readonly",""),t.value=n,t);return e.container.appendChild(t),e=r()(t),c("copy"),t.remove(),e}var f=function(t){var e=1.anchorjs-link,.anchorjs-link:focus{opacity:1}",u.sheet.cssRules.length),u.sheet.insertRule("[data-anchorjs-icon]::after{content:attr(data-anchorjs-icon)}",u.sheet.cssRules.length),u.sheet.insertRule('@font-face{font-family:anchorjs-icons;src:url(data:n/a;base64,AAEAAAALAIAAAwAwT1MvMg8yG2cAAAE4AAAAYGNtYXDp3gC3AAABpAAAAExnYXNwAAAAEAAAA9wAAAAIZ2x5ZlQCcfwAAAH4AAABCGhlYWQHFvHyAAAAvAAAADZoaGVhBnACFwAAAPQAAAAkaG10eASAADEAAAGYAAAADGxvY2EACACEAAAB8AAAAAhtYXhwAAYAVwAAARgAAAAgbmFtZQGOH9cAAAMAAAAAunBvc3QAAwAAAAADvAAAACAAAQAAAAEAAHzE2p9fDzz1AAkEAAAAAADRecUWAAAAANQA6R8AAAAAAoACwAAAAAgAAgAAAAAAAAABAAADwP/AAAACgAAA/9MCrQABAAAAAAAAAAAAAAAAAAAAAwABAAAAAwBVAAIAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAMCQAGQAAUAAAKZAswAAACPApkCzAAAAesAMwEJAAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAAAAQAAg//0DwP/AAEADwABAAAAAAQAAAAAAAAAAAAAAIAAAAAAAAAIAAAACgAAxAAAAAwAAAAMAAAAcAAEAAwAAABwAAwABAAAAHAAEADAAAAAIAAgAAgAAACDpy//9//8AAAAg6cv//f///+EWNwADAAEAAAAAAAAAAAAAAAAACACEAAEAAAAAAAAAAAAAAAAxAAACAAQARAKAAsAAKwBUAAABIiYnJjQ3NzY2MzIWFxYUBwcGIicmNDc3NjQnJiYjIgYHBwYUFxYUBwYGIwciJicmNDc3NjIXFhQHBwYUFxYWMzI2Nzc2NCcmNDc2MhcWFAcHBgYjARQGDAUtLXoWOR8fORYtLTgKGwoKCjgaGg0gEhIgDXoaGgkJBQwHdR85Fi0tOAobCgoKOBoaDSASEiANehoaCQkKGwotLXoWOR8BMwUFLYEuehYXFxYugC44CQkKGwo4GkoaDQ0NDXoaShoKGwoFBe8XFi6ALjgJCQobCjgaShoNDQ0NehpKGgobCgoKLYEuehYXAAAADACWAAEAAAAAAAEACAAAAAEAAAAAAAIAAwAIAAEAAAAAAAMACAAAAAEAAAAAAAQACAAAAAEAAAAAAAUAAQALAAEAAAAAAAYACAAAAAMAAQQJAAEAEAAMAAMAAQQJAAIABgAcAAMAAQQJAAMAEAAMAAMAAQQJAAQAEAAMAAMAAQQJAAUAAgAiAAMAAQQJAAYAEAAMYW5jaG9yanM0MDBAAGEAbgBjAGgAbwByAGoAcwA0ADAAMABAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAH//wAP) format("truetype")}',u.sheet.cssRules.length)),u=document.querySelectorAll("[id]"),t=[].map.call(u,function(A){return A.id}),i=0;i\]./()*\\\n\t\b\v\u00A0]/g,"-").replace(/-{2,}/g,"-").substring(0,this.options.truncate).replace(/^-+|-+$/gm,"").toLowerCase()},this.hasAnchorJSLink=function(A){var e=A.firstChild&&-1<(" "+A.firstChild.className+" ").indexOf(" anchorjs-link "),A=A.lastChild&&-1<(" "+A.lastChild.className+" ").indexOf(" anchorjs-link ");return e||A||!1}}}); 9 | // @license-end -------------------------------------------------------------------------------- /docs/site_libs/quarto-html/popper.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @popperjs/core v2.11.4 - MIT License 3 | */ 4 | 5 | !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).Popper={})}(this,(function(e){"use strict";function t(e){if(null==e)return window;if("[object Window]"!==e.toString()){var t=e.ownerDocument;return t&&t.defaultView||window}return e}function n(e){return e instanceof t(e).Element||e instanceof Element}function r(e){return e instanceof t(e).HTMLElement||e instanceof HTMLElement}function o(e){return"undefined"!=typeof ShadowRoot&&(e instanceof t(e).ShadowRoot||e instanceof ShadowRoot)}var i=Math.max,a=Math.min,s=Math.round;function f(e,t){void 0===t&&(t=!1);var n=e.getBoundingClientRect(),o=1,i=1;if(r(e)&&t){var a=e.offsetHeight,f=e.offsetWidth;f>0&&(o=s(n.width)/f||1),a>0&&(i=s(n.height)/a||1)}return{width:n.width/o,height:n.height/i,top:n.top/i,right:n.right/o,bottom:n.bottom/i,left:n.left/o,x:n.left/o,y:n.top/i}}function c(e){var n=t(e);return{scrollLeft:n.pageXOffset,scrollTop:n.pageYOffset}}function p(e){return e?(e.nodeName||"").toLowerCase():null}function u(e){return((n(e)?e.ownerDocument:e.document)||window.document).documentElement}function l(e){return f(u(e)).left+c(e).scrollLeft}function d(e){return t(e).getComputedStyle(e)}function h(e){var t=d(e),n=t.overflow,r=t.overflowX,o=t.overflowY;return/auto|scroll|overlay|hidden/.test(n+o+r)}function m(e,n,o){void 0===o&&(o=!1);var i,a,d=r(n),m=r(n)&&function(e){var t=e.getBoundingClientRect(),n=s(t.width)/e.offsetWidth||1,r=s(t.height)/e.offsetHeight||1;return 1!==n||1!==r}(n),v=u(n),g=f(e,m),y={scrollLeft:0,scrollTop:0},b={x:0,y:0};return(d||!d&&!o)&&(("body"!==p(n)||h(v))&&(y=(i=n)!==t(i)&&r(i)?{scrollLeft:(a=i).scrollLeft,scrollTop:a.scrollTop}:c(i)),r(n)?((b=f(n,!0)).x+=n.clientLeft,b.y+=n.clientTop):v&&(b.x=l(v))),{x:g.left+y.scrollLeft-b.x,y:g.top+y.scrollTop-b.y,width:g.width,height:g.height}}function v(e){var t=f(e),n=e.offsetWidth,r=e.offsetHeight;return Math.abs(t.width-n)<=1&&(n=t.width),Math.abs(t.height-r)<=1&&(r=t.height),{x:e.offsetLeft,y:e.offsetTop,width:n,height:r}}function g(e){return"html"===p(e)?e:e.assignedSlot||e.parentNode||(o(e)?e.host:null)||u(e)}function y(e){return["html","body","#document"].indexOf(p(e))>=0?e.ownerDocument.body:r(e)&&h(e)?e:y(g(e))}function b(e,n){var r;void 0===n&&(n=[]);var o=y(e),i=o===(null==(r=e.ownerDocument)?void 0:r.body),a=t(o),s=i?[a].concat(a.visualViewport||[],h(o)?o:[]):o,f=n.concat(s);return i?f:f.concat(b(g(s)))}function x(e){return["table","td","th"].indexOf(p(e))>=0}function w(e){return r(e)&&"fixed"!==d(e).position?e.offsetParent:null}function O(e){for(var n=t(e),i=w(e);i&&x(i)&&"static"===d(i).position;)i=w(i);return i&&("html"===p(i)||"body"===p(i)&&"static"===d(i).position)?n:i||function(e){var t=-1!==navigator.userAgent.toLowerCase().indexOf("firefox");if(-1!==navigator.userAgent.indexOf("Trident")&&r(e)&&"fixed"===d(e).position)return null;var n=g(e);for(o(n)&&(n=n.host);r(n)&&["html","body"].indexOf(p(n))<0;){var i=d(n);if("none"!==i.transform||"none"!==i.perspective||"paint"===i.contain||-1!==["transform","perspective"].indexOf(i.willChange)||t&&"filter"===i.willChange||t&&i.filter&&"none"!==i.filter)return n;n=n.parentNode}return null}(e)||n}var j="top",E="bottom",D="right",A="left",L="auto",P=[j,E,D,A],M="start",k="end",W="viewport",B="popper",H=P.reduce((function(e,t){return e.concat([t+"-"+M,t+"-"+k])}),[]),T=[].concat(P,[L]).reduce((function(e,t){return e.concat([t,t+"-"+M,t+"-"+k])}),[]),R=["beforeRead","read","afterRead","beforeMain","main","afterMain","beforeWrite","write","afterWrite"];function S(e){var t=new Map,n=new Set,r=[];function o(e){n.add(e.name),[].concat(e.requires||[],e.requiresIfExists||[]).forEach((function(e){if(!n.has(e)){var r=t.get(e);r&&o(r)}})),r.push(e)}return e.forEach((function(e){t.set(e.name,e)})),e.forEach((function(e){n.has(e.name)||o(e)})),r}function C(e){return e.split("-")[0]}function q(e,t){var n=t.getRootNode&&t.getRootNode();if(e.contains(t))return!0;if(n&&o(n)){var r=t;do{if(r&&e.isSameNode(r))return!0;r=r.parentNode||r.host}while(r)}return!1}function V(e){return Object.assign({},e,{left:e.x,top:e.y,right:e.x+e.width,bottom:e.y+e.height})}function N(e,r){return r===W?V(function(e){var n=t(e),r=u(e),o=n.visualViewport,i=r.clientWidth,a=r.clientHeight,s=0,f=0;return o&&(i=o.width,a=o.height,/^((?!chrome|android).)*safari/i.test(navigator.userAgent)||(s=o.offsetLeft,f=o.offsetTop)),{width:i,height:a,x:s+l(e),y:f}}(e)):n(r)?function(e){var t=f(e);return t.top=t.top+e.clientTop,t.left=t.left+e.clientLeft,t.bottom=t.top+e.clientHeight,t.right=t.left+e.clientWidth,t.width=e.clientWidth,t.height=e.clientHeight,t.x=t.left,t.y=t.top,t}(r):V(function(e){var t,n=u(e),r=c(e),o=null==(t=e.ownerDocument)?void 0:t.body,a=i(n.scrollWidth,n.clientWidth,o?o.scrollWidth:0,o?o.clientWidth:0),s=i(n.scrollHeight,n.clientHeight,o?o.scrollHeight:0,o?o.clientHeight:0),f=-r.scrollLeft+l(e),p=-r.scrollTop;return"rtl"===d(o||n).direction&&(f+=i(n.clientWidth,o?o.clientWidth:0)-a),{width:a,height:s,x:f,y:p}}(u(e)))}function I(e,t,o){var s="clippingParents"===t?function(e){var t=b(g(e)),o=["absolute","fixed"].indexOf(d(e).position)>=0&&r(e)?O(e):e;return n(o)?t.filter((function(e){return n(e)&&q(e,o)&&"body"!==p(e)})):[]}(e):[].concat(t),f=[].concat(s,[o]),c=f[0],u=f.reduce((function(t,n){var r=N(e,n);return t.top=i(r.top,t.top),t.right=a(r.right,t.right),t.bottom=a(r.bottom,t.bottom),t.left=i(r.left,t.left),t}),N(e,c));return u.width=u.right-u.left,u.height=u.bottom-u.top,u.x=u.left,u.y=u.top,u}function _(e){return e.split("-")[1]}function F(e){return["top","bottom"].indexOf(e)>=0?"x":"y"}function U(e){var t,n=e.reference,r=e.element,o=e.placement,i=o?C(o):null,a=o?_(o):null,s=n.x+n.width/2-r.width/2,f=n.y+n.height/2-r.height/2;switch(i){case j:t={x:s,y:n.y-r.height};break;case E:t={x:s,y:n.y+n.height};break;case D:t={x:n.x+n.width,y:f};break;case A:t={x:n.x-r.width,y:f};break;default:t={x:n.x,y:n.y}}var c=i?F(i):null;if(null!=c){var p="y"===c?"height":"width";switch(a){case M:t[c]=t[c]-(n[p]/2-r[p]/2);break;case k:t[c]=t[c]+(n[p]/2-r[p]/2)}}return t}function z(e){return Object.assign({},{top:0,right:0,bottom:0,left:0},e)}function X(e,t){return t.reduce((function(t,n){return t[n]=e,t}),{})}function Y(e,t){void 0===t&&(t={});var r=t,o=r.placement,i=void 0===o?e.placement:o,a=r.boundary,s=void 0===a?"clippingParents":a,c=r.rootBoundary,p=void 0===c?W:c,l=r.elementContext,d=void 0===l?B:l,h=r.altBoundary,m=void 0!==h&&h,v=r.padding,g=void 0===v?0:v,y=z("number"!=typeof g?g:X(g,P)),b=d===B?"reference":B,x=e.rects.popper,w=e.elements[m?b:d],O=I(n(w)?w:w.contextElement||u(e.elements.popper),s,p),A=f(e.elements.reference),L=U({reference:A,element:x,strategy:"absolute",placement:i}),M=V(Object.assign({},x,L)),k=d===B?M:A,H={top:O.top-k.top+y.top,bottom:k.bottom-O.bottom+y.bottom,left:O.left-k.left+y.left,right:k.right-O.right+y.right},T=e.modifiersData.offset;if(d===B&&T){var R=T[i];Object.keys(H).forEach((function(e){var t=[D,E].indexOf(e)>=0?1:-1,n=[j,E].indexOf(e)>=0?"y":"x";H[e]+=R[n]*t}))}return H}var G={placement:"bottom",modifiers:[],strategy:"absolute"};function J(){for(var e=arguments.length,t=new Array(e),n=0;n=0?-1:1,i="function"==typeof n?n(Object.assign({},t,{placement:e})):n,a=i[0],s=i[1];return a=a||0,s=(s||0)*o,[A,D].indexOf(r)>=0?{x:s,y:a}:{x:a,y:s}}(n,t.rects,i),e}),{}),s=a[t.placement],f=s.x,c=s.y;null!=t.modifiersData.popperOffsets&&(t.modifiersData.popperOffsets.x+=f,t.modifiersData.popperOffsets.y+=c),t.modifiersData[r]=a}},ie={left:"right",right:"left",bottom:"top",top:"bottom"};function ae(e){return e.replace(/left|right|bottom|top/g,(function(e){return ie[e]}))}var se={start:"end",end:"start"};function fe(e){return e.replace(/start|end/g,(function(e){return se[e]}))}function ce(e,t){void 0===t&&(t={});var n=t,r=n.placement,o=n.boundary,i=n.rootBoundary,a=n.padding,s=n.flipVariations,f=n.allowedAutoPlacements,c=void 0===f?T:f,p=_(r),u=p?s?H:H.filter((function(e){return _(e)===p})):P,l=u.filter((function(e){return c.indexOf(e)>=0}));0===l.length&&(l=u);var d=l.reduce((function(t,n){return t[n]=Y(e,{placement:n,boundary:o,rootBoundary:i,padding:a})[C(n)],t}),{});return Object.keys(d).sort((function(e,t){return d[e]-d[t]}))}var pe={name:"flip",enabled:!0,phase:"main",fn:function(e){var t=e.state,n=e.options,r=e.name;if(!t.modifiersData[r]._skip){for(var o=n.mainAxis,i=void 0===o||o,a=n.altAxis,s=void 0===a||a,f=n.fallbackPlacements,c=n.padding,p=n.boundary,u=n.rootBoundary,l=n.altBoundary,d=n.flipVariations,h=void 0===d||d,m=n.allowedAutoPlacements,v=t.options.placement,g=C(v),y=f||(g===v||!h?[ae(v)]:function(e){if(C(e)===L)return[];var t=ae(e);return[fe(e),t,fe(t)]}(v)),b=[v].concat(y).reduce((function(e,n){return e.concat(C(n)===L?ce(t,{placement:n,boundary:p,rootBoundary:u,padding:c,flipVariations:h,allowedAutoPlacements:m}):n)}),[]),x=t.rects.reference,w=t.rects.popper,O=new Map,P=!0,k=b[0],W=0;W=0,S=R?"width":"height",q=Y(t,{placement:B,boundary:p,rootBoundary:u,altBoundary:l,padding:c}),V=R?T?D:A:T?E:j;x[S]>w[S]&&(V=ae(V));var N=ae(V),I=[];if(i&&I.push(q[H]<=0),s&&I.push(q[V]<=0,q[N]<=0),I.every((function(e){return e}))){k=B,P=!1;break}O.set(B,I)}if(P)for(var F=function(e){var t=b.find((function(t){var n=O.get(t);if(n)return n.slice(0,e).every((function(e){return e}))}));if(t)return k=t,"break"},U=h?3:1;U>0;U--){if("break"===F(U))break}t.placement!==k&&(t.modifiersData[r]._skip=!0,t.placement=k,t.reset=!0)}},requiresIfExists:["offset"],data:{_skip:!1}};function ue(e,t,n){return i(e,a(t,n))}var le={name:"preventOverflow",enabled:!0,phase:"main",fn:function(e){var t=e.state,n=e.options,r=e.name,o=n.mainAxis,s=void 0===o||o,f=n.altAxis,c=void 0!==f&&f,p=n.boundary,u=n.rootBoundary,l=n.altBoundary,d=n.padding,h=n.tether,m=void 0===h||h,g=n.tetherOffset,y=void 0===g?0:g,b=Y(t,{boundary:p,rootBoundary:u,padding:d,altBoundary:l}),x=C(t.placement),w=_(t.placement),L=!w,P=F(x),k="x"===P?"y":"x",W=t.modifiersData.popperOffsets,B=t.rects.reference,H=t.rects.popper,T="function"==typeof y?y(Object.assign({},t.rects,{placement:t.placement})):y,R="number"==typeof T?{mainAxis:T,altAxis:T}:Object.assign({mainAxis:0,altAxis:0},T),S=t.modifiersData.offset?t.modifiersData.offset[t.placement]:null,q={x:0,y:0};if(W){if(s){var V,N="y"===P?j:A,I="y"===P?E:D,U="y"===P?"height":"width",z=W[P],X=z+b[N],G=z-b[I],J=m?-H[U]/2:0,K=w===M?B[U]:H[U],Q=w===M?-H[U]:-B[U],Z=t.elements.arrow,$=m&&Z?v(Z):{width:0,height:0},ee=t.modifiersData["arrow#persistent"]?t.modifiersData["arrow#persistent"].padding:{top:0,right:0,bottom:0,left:0},te=ee[N],ne=ee[I],re=ue(0,B[U],$[U]),oe=L?B[U]/2-J-re-te-R.mainAxis:K-re-te-R.mainAxis,ie=L?-B[U]/2+J+re+ne+R.mainAxis:Q+re+ne+R.mainAxis,ae=t.elements.arrow&&O(t.elements.arrow),se=ae?"y"===P?ae.clientTop||0:ae.clientLeft||0:0,fe=null!=(V=null==S?void 0:S[P])?V:0,ce=z+ie-fe,pe=ue(m?a(X,z+oe-fe-se):X,z,m?i(G,ce):G);W[P]=pe,q[P]=pe-z}if(c){var le,de="x"===P?j:A,he="x"===P?E:D,me=W[k],ve="y"===k?"height":"width",ge=me+b[de],ye=me-b[he],be=-1!==[j,A].indexOf(x),xe=null!=(le=null==S?void 0:S[k])?le:0,we=be?ge:me-B[ve]-H[ve]-xe+R.altAxis,Oe=be?me+B[ve]+H[ve]-xe-R.altAxis:ye,je=m&&be?function(e,t,n){var r=ue(e,t,n);return r>n?n:r}(we,me,Oe):ue(m?we:ge,me,m?Oe:ye);W[k]=je,q[k]=je-me}t.modifiersData[r]=q}},requiresIfExists:["offset"]};var de={name:"arrow",enabled:!0,phase:"main",fn:function(e){var t,n=e.state,r=e.name,o=e.options,i=n.elements.arrow,a=n.modifiersData.popperOffsets,s=C(n.placement),f=F(s),c=[A,D].indexOf(s)>=0?"height":"width";if(i&&a){var p=function(e,t){return z("number"!=typeof(e="function"==typeof e?e(Object.assign({},t.rects,{placement:t.placement})):e)?e:X(e,P))}(o.padding,n),u=v(i),l="y"===f?j:A,d="y"===f?E:D,h=n.rects.reference[c]+n.rects.reference[f]-a[f]-n.rects.popper[c],m=a[f]-n.rects.reference[f],g=O(i),y=g?"y"===f?g.clientHeight||0:g.clientWidth||0:0,b=h/2-m/2,x=p[l],w=y-u[c]-p[d],L=y/2-u[c]/2+b,M=ue(x,L,w),k=f;n.modifiersData[r]=((t={})[k]=M,t.centerOffset=M-L,t)}},effect:function(e){var t=e.state,n=e.options.element,r=void 0===n?"[data-popper-arrow]":n;null!=r&&("string"!=typeof r||(r=t.elements.popper.querySelector(r)))&&q(t.elements.popper,r)&&(t.elements.arrow=r)},requires:["popperOffsets"],requiresIfExists:["preventOverflow"]};function he(e,t,n){return void 0===n&&(n={x:0,y:0}),{top:e.top-t.height-n.y,right:e.right-t.width+n.x,bottom:e.bottom-t.height+n.y,left:e.left-t.width-n.x}}function me(e){return[j,D,E,A].some((function(t){return e[t]>=0}))}var ve={name:"hide",enabled:!0,phase:"main",requiresIfExists:["preventOverflow"],fn:function(e){var t=e.state,n=e.name,r=t.rects.reference,o=t.rects.popper,i=t.modifiersData.preventOverflow,a=Y(t,{elementContext:"reference"}),s=Y(t,{altBoundary:!0}),f=he(a,r),c=he(s,o,i),p=me(f),u=me(c);t.modifiersData[n]={referenceClippingOffsets:f,popperEscapeOffsets:c,isReferenceHidden:p,hasPopperEscaped:u},t.attributes.popper=Object.assign({},t.attributes.popper,{"data-popper-reference-hidden":p,"data-popper-escaped":u})}},ge=K({defaultModifiers:[Z,$,ne,re]}),ye=[Z,$,ne,re,oe,pe,le,de,ve],be=K({defaultModifiers:ye});e.applyStyles=re,e.arrow=de,e.computeStyles=ne,e.createPopper=be,e.createPopperLite=ge,e.defaultModifiers=ye,e.detectOverflow=Y,e.eventListeners=Z,e.flip=pe,e.hide=ve,e.offset=oe,e.popperGenerator=K,e.popperOffsets=$,e.preventOverflow=le,Object.defineProperty(e,"__esModule",{value:!0})})); 6 | 7 | -------------------------------------------------------------------------------- /docs/site_libs/quarto-html/quarto-syntax-highlighting.css: -------------------------------------------------------------------------------- 1 | /* quarto syntax highlight colors */ 2 | :root { 3 | --quarto-hl-ot-color: #003B4F; 4 | --quarto-hl-at-color: #657422; 5 | --quarto-hl-ss-color: #20794D; 6 | --quarto-hl-an-color: #5E5E5E; 7 | --quarto-hl-fu-color: #4758AB; 8 | --quarto-hl-st-color: #20794D; 9 | --quarto-hl-cf-color: #003B4F; 10 | --quarto-hl-op-color: #5E5E5E; 11 | --quarto-hl-er-color: #AD0000; 12 | --quarto-hl-bn-color: #AD0000; 13 | --quarto-hl-al-color: #AD0000; 14 | --quarto-hl-va-color: #111111; 15 | --quarto-hl-bu-color: inherit; 16 | --quarto-hl-ex-color: inherit; 17 | --quarto-hl-pp-color: #AD0000; 18 | --quarto-hl-in-color: #5E5E5E; 19 | --quarto-hl-vs-color: #20794D; 20 | --quarto-hl-wa-color: #5E5E5E; 21 | --quarto-hl-do-color: #5E5E5E; 22 | --quarto-hl-im-color: #00769E; 23 | --quarto-hl-ch-color: #20794D; 24 | --quarto-hl-dt-color: #AD0000; 25 | --quarto-hl-fl-color: #AD0000; 26 | --quarto-hl-co-color: #5E5E5E; 27 | --quarto-hl-cv-color: #5E5E5E; 28 | --quarto-hl-cn-color: #8f5902; 29 | --quarto-hl-sc-color: #5E5E5E; 30 | --quarto-hl-dv-color: #AD0000; 31 | --quarto-hl-kw-color: #003B4F; 32 | } 33 | 34 | /* other quarto variables */ 35 | :root { 36 | --quarto-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; 37 | } 38 | 39 | pre > code.sourceCode > span { 40 | color: #003B4F; 41 | } 42 | 43 | code span { 44 | color: #003B4F; 45 | } 46 | 47 | code.sourceCode > span { 48 | color: #003B4F; 49 | } 50 | 51 | div.sourceCode, 52 | div.sourceCode pre.sourceCode { 53 | color: #003B4F; 54 | } 55 | 56 | code span.ot { 57 | color: #003B4F; 58 | } 59 | 60 | code span.at { 61 | color: #657422; 62 | } 63 | 64 | code span.ss { 65 | color: #20794D; 66 | } 67 | 68 | code span.an { 69 | color: #5E5E5E; 70 | } 71 | 72 | code span.fu { 73 | color: #4758AB; 74 | } 75 | 76 | code span.st { 77 | color: #20794D; 78 | } 79 | 80 | code span.cf { 81 | color: #003B4F; 82 | } 83 | 84 | code span.op { 85 | color: #5E5E5E; 86 | } 87 | 88 | code span.er { 89 | color: #AD0000; 90 | } 91 | 92 | code span.bn { 93 | color: #AD0000; 94 | } 95 | 96 | code span.al { 97 | color: #AD0000; 98 | } 99 | 100 | code span.va { 101 | color: #111111; 102 | } 103 | 104 | code span.pp { 105 | color: #AD0000; 106 | } 107 | 108 | code span.in { 109 | color: #5E5E5E; 110 | } 111 | 112 | code span.vs { 113 | color: #20794D; 114 | } 115 | 116 | code span.wa { 117 | color: #5E5E5E; 118 | font-style: italic; 119 | } 120 | 121 | code span.do { 122 | color: #5E5E5E; 123 | font-style: italic; 124 | } 125 | 126 | code span.im { 127 | color: #00769E; 128 | } 129 | 130 | code span.ch { 131 | color: #20794D; 132 | } 133 | 134 | code span.dt { 135 | color: #AD0000; 136 | } 137 | 138 | code span.fl { 139 | color: #AD0000; 140 | } 141 | 142 | code span.co { 143 | color: #5E5E5E; 144 | } 145 | 146 | code span.cv { 147 | color: #5E5E5E; 148 | font-style: italic; 149 | } 150 | 151 | code span.cn { 152 | color: #8f5902; 153 | } 154 | 155 | code span.sc { 156 | color: #5E5E5E; 157 | } 158 | 159 | code span.dv { 160 | color: #AD0000; 161 | } 162 | 163 | code span.kw { 164 | color: #003B4F; 165 | } 166 | 167 | .prevent-inlining { 168 | content: " { 17 | const sibling = el.previousElementSibling; 18 | if (sibling && sibling.tagName === "A") { 19 | return sibling.classList.contains("active"); 20 | } else { 21 | return false; 22 | } 23 | }; 24 | 25 | // fire slideEnter for bootstrap tab activations (for htmlwidget resize behavior) 26 | function fireSlideEnter(e) { 27 | const event = window.document.createEvent("Event"); 28 | event.initEvent("slideenter", true, true); 29 | window.document.dispatchEvent(event); 30 | } 31 | const tabs = window.document.querySelectorAll('a[data-bs-toggle="tab"]'); 32 | tabs.forEach((tab) => { 33 | tab.addEventListener("shown.bs.tab", fireSlideEnter); 34 | }); 35 | 36 | // fire slideEnter for tabby tab activations (for htmlwidget resize behavior) 37 | document.addEventListener("tabby", fireSlideEnter, false); 38 | 39 | // Track scrolling and mark TOC links as active 40 | // get table of contents and sidebar (bail if we don't have at least one) 41 | const tocLinks = tocEl 42 | ? [...tocEl.querySelectorAll("a[data-scroll-target]")] 43 | : []; 44 | const makeActive = (link) => tocLinks[link].classList.add("active"); 45 | const removeActive = (link) => tocLinks[link].classList.remove("active"); 46 | const removeAllActive = () => 47 | [...Array(tocLinks.length).keys()].forEach((link) => removeActive(link)); 48 | 49 | // activate the anchor for a section associated with this TOC entry 50 | tocLinks.forEach((link) => { 51 | link.addEventListener("click", () => { 52 | if (link.href.indexOf("#") !== -1) { 53 | const anchor = link.href.split("#")[1]; 54 | const heading = window.document.querySelector( 55 | `[data-anchor-id=${anchor}]` 56 | ); 57 | if (heading) { 58 | // Add the class 59 | heading.classList.add("reveal-anchorjs-link"); 60 | 61 | // function to show the anchor 62 | const handleMouseout = () => { 63 | heading.classList.remove("reveal-anchorjs-link"); 64 | heading.removeEventListener("mouseout", handleMouseout); 65 | }; 66 | 67 | // add a function to clear the anchor when the user mouses out of it 68 | heading.addEventListener("mouseout", handleMouseout); 69 | } 70 | } 71 | }); 72 | }); 73 | 74 | const sections = tocLinks.map((link) => { 75 | const target = link.getAttribute("data-scroll-target"); 76 | if (target.startsWith("#")) { 77 | return window.document.getElementById(decodeURI(`${target.slice(1)}`)); 78 | } else { 79 | return window.document.querySelector(decodeURI(`${target}`)); 80 | } 81 | }); 82 | 83 | const sectionMargin = 200; 84 | let currentActive = 0; 85 | // track whether we've initialized state the first time 86 | let init = false; 87 | 88 | const updateActiveLink = () => { 89 | // The index from bottom to top (e.g. reversed list) 90 | let sectionIndex = -1; 91 | if ( 92 | window.innerHeight + window.pageYOffset >= 93 | window.document.body.offsetHeight 94 | ) { 95 | sectionIndex = 0; 96 | } else { 97 | sectionIndex = [...sections].reverse().findIndex((section) => { 98 | if (section) { 99 | return window.pageYOffset >= section.offsetTop - sectionMargin; 100 | } else { 101 | return false; 102 | } 103 | }); 104 | } 105 | if (sectionIndex > -1) { 106 | const current = sections.length - sectionIndex - 1; 107 | if (current !== currentActive) { 108 | removeAllActive(); 109 | currentActive = current; 110 | makeActive(current); 111 | if (init) { 112 | window.dispatchEvent(sectionChanged); 113 | } 114 | init = true; 115 | } 116 | } 117 | }; 118 | 119 | const inHiddenRegion = (top, bottom, hiddenRegions) => { 120 | for (const region of hiddenRegions) { 121 | if (top <= region.bottom && bottom >= region.top) { 122 | return true; 123 | } 124 | } 125 | return false; 126 | }; 127 | 128 | const categorySelector = "header.quarto-title-block .quarto-category"; 129 | const activateCategories = (href) => { 130 | // Find any categories 131 | // Surround them with a link pointing back to: 132 | // #category=Authoring 133 | try { 134 | const categoryEls = window.document.querySelectorAll(categorySelector); 135 | for (const categoryEl of categoryEls) { 136 | const categoryText = categoryEl.textContent; 137 | if (categoryText) { 138 | const link = `${href}#category=${encodeURIComponent(categoryText)}`; 139 | const linkEl = window.document.createElement("a"); 140 | linkEl.setAttribute("href", link); 141 | for (const child of categoryEl.childNodes) { 142 | linkEl.append(child); 143 | } 144 | categoryEl.appendChild(linkEl); 145 | } 146 | } 147 | } catch { 148 | // Ignore errors 149 | } 150 | }; 151 | function hasTitleCategories() { 152 | return window.document.querySelector(categorySelector) !== null; 153 | } 154 | 155 | function offsetRelativeUrl(url) { 156 | const offset = getMeta("quarto:offset"); 157 | return offset ? offset + url : url; 158 | } 159 | 160 | function offsetAbsoluteUrl(url) { 161 | const offset = getMeta("quarto:offset"); 162 | const baseUrl = new URL(offset, window.location); 163 | 164 | const projRelativeUrl = url.replace(baseUrl, ""); 165 | if (projRelativeUrl.startsWith("/")) { 166 | return projRelativeUrl; 167 | } else { 168 | return "/" + projRelativeUrl; 169 | } 170 | } 171 | 172 | // read a meta tag value 173 | function getMeta(metaName) { 174 | const metas = window.document.getElementsByTagName("meta"); 175 | for (let i = 0; i < metas.length; i++) { 176 | if (metas[i].getAttribute("name") === metaName) { 177 | return metas[i].getAttribute("content"); 178 | } 179 | } 180 | return ""; 181 | } 182 | 183 | async function findAndActivateCategories() { 184 | const currentPagePath = offsetAbsoluteUrl(window.location.href); 185 | const response = await fetch(offsetRelativeUrl("listings.json")); 186 | if (response.status == 200) { 187 | return response.json().then(function (listingPaths) { 188 | const listingHrefs = []; 189 | for (const listingPath of listingPaths) { 190 | const pathWithoutLeadingSlash = listingPath.listing.substring(1); 191 | for (const item of listingPath.items) { 192 | if ( 193 | item === currentPagePath || 194 | item === currentPagePath + "index.html" 195 | ) { 196 | // Resolve this path against the offset to be sure 197 | // we already are using the correct path to the listing 198 | // (this adjusts the listing urls to be rooted against 199 | // whatever root the page is actually running against) 200 | const relative = offsetRelativeUrl(pathWithoutLeadingSlash); 201 | const baseUrl = window.location; 202 | const resolvedPath = new URL(relative, baseUrl); 203 | listingHrefs.push(resolvedPath.pathname); 204 | break; 205 | } 206 | } 207 | } 208 | 209 | // Look up the tree for a nearby linting and use that if we find one 210 | const nearestListing = findNearestParentListing( 211 | offsetAbsoluteUrl(window.location.pathname), 212 | listingHrefs 213 | ); 214 | if (nearestListing) { 215 | activateCategories(nearestListing); 216 | } else { 217 | // See if the referrer is a listing page for this item 218 | const referredRelativePath = offsetAbsoluteUrl(document.referrer); 219 | const referrerListing = listingHrefs.find((listingHref) => { 220 | const isListingReferrer = 221 | listingHref === referredRelativePath || 222 | listingHref === referredRelativePath + "index.html"; 223 | return isListingReferrer; 224 | }); 225 | 226 | if (referrerListing) { 227 | // Try to use the referrer if possible 228 | activateCategories(referrerListing); 229 | } else if (listingHrefs.length > 0) { 230 | // Otherwise, just fall back to the first listing 231 | activateCategories(listingHrefs[0]); 232 | } 233 | } 234 | }); 235 | } 236 | } 237 | if (hasTitleCategories()) { 238 | findAndActivateCategories(); 239 | } 240 | 241 | const findNearestParentListing = (href, listingHrefs) => { 242 | if (!href || !listingHrefs) { 243 | return undefined; 244 | } 245 | // Look up the tree for a nearby linting and use that if we find one 246 | const relativeParts = href.substring(1).split("/"); 247 | while (relativeParts.length > 0) { 248 | const path = relativeParts.join("/"); 249 | for (const listingHref of listingHrefs) { 250 | if (listingHref.startsWith(path)) { 251 | return listingHref; 252 | } 253 | } 254 | relativeParts.pop(); 255 | } 256 | 257 | return undefined; 258 | }; 259 | 260 | const manageSidebarVisiblity = (el, placeholderDescriptor) => { 261 | let isVisible = true; 262 | let elRect; 263 | 264 | return (hiddenRegions) => { 265 | if (el === null) { 266 | return; 267 | } 268 | 269 | // Find the last element of the TOC 270 | const lastChildEl = el.lastElementChild; 271 | 272 | if (lastChildEl) { 273 | // Converts the sidebar to a menu 274 | const convertToMenu = () => { 275 | for (const child of el.children) { 276 | child.style.opacity = 0; 277 | child.style.overflow = "hidden"; 278 | } 279 | 280 | nexttick(() => { 281 | const toggleContainer = window.document.createElement("div"); 282 | toggleContainer.style.width = "100%"; 283 | toggleContainer.classList.add("zindex-over-content"); 284 | toggleContainer.classList.add("quarto-sidebar-toggle"); 285 | toggleContainer.classList.add("headroom-target"); // Marks this to be managed by headeroom 286 | toggleContainer.id = placeholderDescriptor.id; 287 | toggleContainer.style.position = "fixed"; 288 | 289 | const toggleIcon = window.document.createElement("i"); 290 | toggleIcon.classList.add("quarto-sidebar-toggle-icon"); 291 | toggleIcon.classList.add("bi"); 292 | toggleIcon.classList.add("bi-caret-down-fill"); 293 | 294 | const toggleTitle = window.document.createElement("div"); 295 | const titleEl = window.document.body.querySelector( 296 | placeholderDescriptor.titleSelector 297 | ); 298 | if (titleEl) { 299 | toggleTitle.append( 300 | titleEl.textContent || titleEl.innerText, 301 | toggleIcon 302 | ); 303 | } 304 | toggleTitle.classList.add("zindex-over-content"); 305 | toggleTitle.classList.add("quarto-sidebar-toggle-title"); 306 | toggleContainer.append(toggleTitle); 307 | 308 | const toggleContents = window.document.createElement("div"); 309 | toggleContents.classList = el.classList; 310 | toggleContents.classList.add("zindex-over-content"); 311 | toggleContents.classList.add("quarto-sidebar-toggle-contents"); 312 | for (const child of el.children) { 313 | if (child.id === "toc-title") { 314 | continue; 315 | } 316 | 317 | const clone = child.cloneNode(true); 318 | clone.style.opacity = 1; 319 | clone.style.display = null; 320 | toggleContents.append(clone); 321 | } 322 | toggleContents.style.height = "0px"; 323 | const positionToggle = () => { 324 | // position the element (top left of parent, same width as parent) 325 | if (!elRect) { 326 | elRect = el.getBoundingClientRect(); 327 | } 328 | toggleContainer.style.left = `${elRect.left}px`; 329 | toggleContainer.style.top = `${elRect.top}px`; 330 | toggleContainer.style.width = `${elRect.width}px`; 331 | }; 332 | positionToggle(); 333 | 334 | toggleContainer.append(toggleContents); 335 | el.parentElement.prepend(toggleContainer); 336 | 337 | // Process clicks 338 | let tocShowing = false; 339 | // Allow the caller to control whether this is dismissed 340 | // when it is clicked (e.g. sidebar navigation supports 341 | // opening and closing the nav tree, so don't dismiss on click) 342 | const clickEl = placeholderDescriptor.dismissOnClick 343 | ? toggleContainer 344 | : toggleTitle; 345 | 346 | const closeToggle = () => { 347 | if (tocShowing) { 348 | toggleContainer.classList.remove("expanded"); 349 | toggleContents.style.height = "0px"; 350 | tocShowing = false; 351 | } 352 | }; 353 | 354 | // Get rid of any expanded toggle if the user scrolls 355 | window.document.addEventListener( 356 | "scroll", 357 | throttle(() => { 358 | closeToggle(); 359 | }, 50) 360 | ); 361 | 362 | // Handle positioning of the toggle 363 | window.addEventListener( 364 | "resize", 365 | throttle(() => { 366 | elRect = undefined; 367 | positionToggle(); 368 | }, 50) 369 | ); 370 | 371 | window.addEventListener("quarto-hrChanged", () => { 372 | elRect = undefined; 373 | }); 374 | 375 | // Process the click 376 | clickEl.onclick = () => { 377 | if (!tocShowing) { 378 | toggleContainer.classList.add("expanded"); 379 | toggleContents.style.height = null; 380 | tocShowing = true; 381 | } else { 382 | closeToggle(); 383 | } 384 | }; 385 | }); 386 | }; 387 | 388 | // Converts a sidebar from a menu back to a sidebar 389 | const convertToSidebar = () => { 390 | for (const child of el.children) { 391 | child.style.opacity = 1; 392 | child.style.overflow = null; 393 | } 394 | 395 | const placeholderEl = window.document.getElementById( 396 | placeholderDescriptor.id 397 | ); 398 | if (placeholderEl) { 399 | placeholderEl.remove(); 400 | } 401 | 402 | el.classList.remove("rollup"); 403 | }; 404 | 405 | if (isReaderMode()) { 406 | convertToMenu(); 407 | isVisible = false; 408 | } else { 409 | // Find the top and bottom o the element that is being managed 410 | const elTop = el.offsetTop; 411 | const elBottom = 412 | elTop + lastChildEl.offsetTop + lastChildEl.offsetHeight; 413 | 414 | if (!isVisible) { 415 | // If the element is current not visible reveal if there are 416 | // no conflicts with overlay regions 417 | if (!inHiddenRegion(elTop, elBottom, hiddenRegions)) { 418 | convertToSidebar(); 419 | isVisible = true; 420 | } 421 | } else { 422 | // If the element is visible, hide it if it conflicts with overlay regions 423 | // and insert a placeholder toggle (or if we're in reader mode) 424 | if (inHiddenRegion(elTop, elBottom, hiddenRegions)) { 425 | convertToMenu(); 426 | isVisible = false; 427 | } 428 | } 429 | } 430 | } 431 | }; 432 | }; 433 | 434 | // Find any conflicting margin elements and add margins to the 435 | // top to prevent overlap 436 | const marginChildren = window.document.querySelectorAll( 437 | ".column-margin.column-container > * " 438 | ); 439 | 440 | const layoutMarginEls = () => { 441 | let lastBottom = 0; 442 | for (const marginChild of marginChildren) { 443 | if (marginChild.offsetParent !== null) { 444 | // clear the top margin so we recompute it 445 | marginChild.style.marginTop = null; 446 | const top = marginChild.getBoundingClientRect().top + window.scrollY; 447 | if (top < lastBottom) { 448 | const margin = lastBottom - top; 449 | marginChild.style.marginTop = `${margin}px`; 450 | } 451 | const styles = window.getComputedStyle(marginChild); 452 | const marginTop = parseFloat(styles["marginTop"]); 453 | lastBottom = 454 | top + marginChild.getBoundingClientRect().height + marginTop; 455 | } 456 | } 457 | }; 458 | nexttick(layoutMarginEls); 459 | 460 | const tabEls = document.querySelectorAll('a[data-bs-toggle="tab"]'); 461 | for (const tabEl of tabEls) { 462 | const id = tabEl.getAttribute("data-bs-target"); 463 | if (id) { 464 | const columnEl = document.querySelector(`${id} .column-margin`); 465 | if (columnEl) 466 | tabEl.addEventListener("shown.bs.tab", function (_event) { 467 | layoutMarginEls(); 468 | }); 469 | } 470 | } 471 | 472 | // Manage the visibility of the toc and the sidebar 473 | const marginScrollVisibility = manageSidebarVisiblity(marginSidebarEl, { 474 | id: "quarto-toc-toggle", 475 | titleSelector: "#toc-title", 476 | dismissOnClick: true, 477 | }); 478 | const sidebarScrollVisiblity = manageSidebarVisiblity(sidebarEl, { 479 | id: "quarto-sidebarnav-toggle", 480 | titleSelector: ".title", 481 | dismissOnClick: false, 482 | }); 483 | let tocLeftScrollVisibility; 484 | if (leftTocEl) { 485 | tocLeftScrollVisibility = manageSidebarVisiblity(leftTocEl, { 486 | id: "quarto-lefttoc-toggle", 487 | titleSelector: "#toc-title", 488 | dismissOnClick: true, 489 | }); 490 | } 491 | 492 | // Find the first element that uses formatting in special columns 493 | const conflictingEls = window.document.body.querySelectorAll( 494 | '[class^="column-"], [class*=" column-"], aside, [class*="margin-caption"], [class*=" margin-caption"], [class*="margin-ref"], [class*=" margin-ref"]' 495 | ); 496 | 497 | // Filter all the possibly conflicting elements into ones 498 | // the do conflict on the left or ride side 499 | const arrConflictingEls = Array.from(conflictingEls); 500 | const leftSideConflictEls = arrConflictingEls.filter((el) => { 501 | if (el.tagName === "ASIDE") { 502 | return false; 503 | } 504 | return Array.from(el.classList).find((className) => { 505 | return ( 506 | className !== "column-body" && 507 | className.startsWith("column-") && 508 | !className.endsWith("right") && 509 | !className.endsWith("container") && 510 | className !== "column-margin" 511 | ); 512 | }); 513 | }); 514 | const rightSideConflictEls = arrConflictingEls.filter((el) => { 515 | if (el.tagName === "ASIDE") { 516 | return true; 517 | } 518 | 519 | const hasMarginCaption = Array.from(el.classList).find((className) => { 520 | return className == "margin-caption"; 521 | }); 522 | if (hasMarginCaption) { 523 | return true; 524 | } 525 | 526 | return Array.from(el.classList).find((className) => { 527 | return ( 528 | className !== "column-body" && 529 | !className.endsWith("container") && 530 | className.startsWith("column-") && 531 | !className.endsWith("left") 532 | ); 533 | }); 534 | }); 535 | 536 | const kOverlapPaddingSize = 10; 537 | function toRegions(els) { 538 | return els.map((el) => { 539 | const boundRect = el.getBoundingClientRect(); 540 | const top = 541 | boundRect.top + 542 | document.documentElement.scrollTop - 543 | kOverlapPaddingSize; 544 | return { 545 | top, 546 | bottom: top + el.scrollHeight + 2 * kOverlapPaddingSize, 547 | }; 548 | }); 549 | } 550 | 551 | let hasObserved = false; 552 | const visibleItemObserver = (els) => { 553 | let visibleElements = [...els]; 554 | const intersectionObserver = new IntersectionObserver( 555 | (entries, _observer) => { 556 | entries.forEach((entry) => { 557 | if (entry.isIntersecting) { 558 | if (visibleElements.indexOf(entry.target) === -1) { 559 | visibleElements.push(entry.target); 560 | } 561 | } else { 562 | visibleElements = visibleElements.filter((visibleEntry) => { 563 | return visibleEntry !== entry; 564 | }); 565 | } 566 | }); 567 | 568 | if (!hasObserved) { 569 | hideOverlappedSidebars(); 570 | } 571 | hasObserved = true; 572 | }, 573 | {} 574 | ); 575 | els.forEach((el) => { 576 | intersectionObserver.observe(el); 577 | }); 578 | 579 | return { 580 | getVisibleEntries: () => { 581 | return visibleElements; 582 | }, 583 | }; 584 | }; 585 | 586 | const rightElementObserver = visibleItemObserver(rightSideConflictEls); 587 | const leftElementObserver = visibleItemObserver(leftSideConflictEls); 588 | 589 | const hideOverlappedSidebars = () => { 590 | marginScrollVisibility(toRegions(rightElementObserver.getVisibleEntries())); 591 | sidebarScrollVisiblity(toRegions(leftElementObserver.getVisibleEntries())); 592 | if (tocLeftScrollVisibility) { 593 | tocLeftScrollVisibility( 594 | toRegions(leftElementObserver.getVisibleEntries()) 595 | ); 596 | } 597 | }; 598 | 599 | window.quartoToggleReader = () => { 600 | // Applies a slow class (or removes it) 601 | // to update the transition speed 602 | const slowTransition = (slow) => { 603 | const manageTransition = (id, slow) => { 604 | const el = document.getElementById(id); 605 | if (el) { 606 | if (slow) { 607 | el.classList.add("slow"); 608 | } else { 609 | el.classList.remove("slow"); 610 | } 611 | } 612 | }; 613 | 614 | manageTransition("TOC", slow); 615 | manageTransition("quarto-sidebar", slow); 616 | }; 617 | 618 | const readerMode = !isReaderMode(); 619 | setReaderModeValue(readerMode); 620 | 621 | // If we're entering reader mode, slow the transition 622 | if (readerMode) { 623 | slowTransition(readerMode); 624 | } 625 | highlightReaderToggle(readerMode); 626 | 627 | // If we're exiting reader mode, restore the non-slow transition 628 | if (!readerMode) { 629 | slowTransition(!readerMode); 630 | } 631 | }; 632 | 633 | const highlightReaderToggle = (readerMode) => { 634 | const els = document.querySelectorAll(".quarto-reader-toggle"); 635 | if (els) { 636 | els.forEach((el) => { 637 | if (readerMode) { 638 | el.classList.add("reader"); 639 | } else { 640 | el.classList.remove("reader"); 641 | } 642 | }); 643 | } 644 | }; 645 | 646 | const setReaderModeValue = (val) => { 647 | if (window.location.protocol !== "file:") { 648 | window.localStorage.setItem("quarto-reader-mode", val); 649 | } else { 650 | localReaderMode = val; 651 | } 652 | }; 653 | 654 | const isReaderMode = () => { 655 | if (window.location.protocol !== "file:") { 656 | return window.localStorage.getItem("quarto-reader-mode") === "true"; 657 | } else { 658 | return localReaderMode; 659 | } 660 | }; 661 | let localReaderMode = null; 662 | 663 | // Walk the TOC and collapse/expand nodes 664 | // Nodes are expanded if: 665 | // - they are top level 666 | // - they have children that are 'active' links 667 | // - they are directly below an link that is 'active' 668 | const walk = (el, depth) => { 669 | // Tick depth when we enter a UL 670 | if (el.tagName === "UL") { 671 | depth = depth + 1; 672 | } 673 | 674 | // It this is active link 675 | let isActiveNode = false; 676 | if (el.tagName === "A" && el.classList.contains("active")) { 677 | isActiveNode = true; 678 | } 679 | 680 | // See if there is an active child to this element 681 | let hasActiveChild = false; 682 | for (child of el.children) { 683 | hasActiveChild = walk(child, depth) || hasActiveChild; 684 | } 685 | 686 | // Process the collapse state if this is an UL 687 | if (el.tagName === "UL") { 688 | if (depth === 1 || hasActiveChild || prevSiblingIsActiveLink(el)) { 689 | el.classList.remove("collapse"); 690 | } else { 691 | el.classList.add("collapse"); 692 | } 693 | 694 | // untick depth when we leave a UL 695 | depth = depth - 1; 696 | } 697 | return hasActiveChild || isActiveNode; 698 | }; 699 | 700 | // walk the TOC and expand / collapse any items that should be shown 701 | 702 | if (tocEl) { 703 | walk(tocEl, 0); 704 | updateActiveLink(); 705 | } 706 | 707 | // Throttle the scroll event and walk peridiocally 708 | window.document.addEventListener( 709 | "scroll", 710 | throttle(() => { 711 | if (tocEl) { 712 | updateActiveLink(); 713 | walk(tocEl, 0); 714 | } 715 | if (!isReaderMode()) { 716 | hideOverlappedSidebars(); 717 | } 718 | }, 5) 719 | ); 720 | window.addEventListener( 721 | "resize", 722 | throttle(() => { 723 | if (!isReaderMode()) { 724 | hideOverlappedSidebars(); 725 | } 726 | }, 10) 727 | ); 728 | hideOverlappedSidebars(); 729 | highlightReaderToggle(isReaderMode()); 730 | }); 731 | 732 | // grouped tabsets 733 | window.addEventListener("pageshow", (_event) => { 734 | function getTabSettings() { 735 | const data = localStorage.getItem("quarto-persistent-tabsets-data"); 736 | if (!data) { 737 | localStorage.setItem("quarto-persistent-tabsets-data", "{}"); 738 | return {}; 739 | } 740 | if (data) { 741 | return JSON.parse(data); 742 | } 743 | } 744 | 745 | function setTabSettings(data) { 746 | localStorage.setItem( 747 | "quarto-persistent-tabsets-data", 748 | JSON.stringify(data) 749 | ); 750 | } 751 | 752 | function setTabState(groupName, groupValue) { 753 | const data = getTabSettings(); 754 | data[groupName] = groupValue; 755 | setTabSettings(data); 756 | } 757 | 758 | function toggleTab(tab, active) { 759 | const tabPanelId = tab.getAttribute("aria-controls"); 760 | const tabPanel = document.getElementById(tabPanelId); 761 | if (active) { 762 | tab.classList.add("active"); 763 | tabPanel.classList.add("active"); 764 | } else { 765 | tab.classList.remove("active"); 766 | tabPanel.classList.remove("active"); 767 | } 768 | } 769 | 770 | function toggleAll(selectedGroup, selectorsToSync) { 771 | for (const [thisGroup, tabs] of Object.entries(selectorsToSync)) { 772 | const active = selectedGroup === thisGroup; 773 | for (const tab of tabs) { 774 | toggleTab(tab, active); 775 | } 776 | } 777 | } 778 | 779 | function findSelectorsToSyncByLanguage() { 780 | const result = {}; 781 | const tabs = Array.from( 782 | document.querySelectorAll(`div[data-group] a[id^='tabset-']`) 783 | ); 784 | for (const item of tabs) { 785 | const div = item.parentElement.parentElement.parentElement; 786 | const group = div.getAttribute("data-group"); 787 | if (!result[group]) { 788 | result[group] = {}; 789 | } 790 | const selectorsToSync = result[group]; 791 | const value = item.innerHTML; 792 | if (!selectorsToSync[value]) { 793 | selectorsToSync[value] = []; 794 | } 795 | selectorsToSync[value].push(item); 796 | } 797 | return result; 798 | } 799 | 800 | function setupSelectorSync() { 801 | const selectorsToSync = findSelectorsToSyncByLanguage(); 802 | Object.entries(selectorsToSync).forEach(([group, tabSetsByValue]) => { 803 | Object.entries(tabSetsByValue).forEach(([value, items]) => { 804 | items.forEach((item) => { 805 | item.addEventListener("click", (_event) => { 806 | setTabState(group, value); 807 | toggleAll(value, selectorsToSync[group]); 808 | }); 809 | }); 810 | }); 811 | }); 812 | return selectorsToSync; 813 | } 814 | 815 | const selectorsToSync = setupSelectorSync(); 816 | for (const [group, selectedName] of Object.entries(getTabSettings())) { 817 | const selectors = selectorsToSync[group]; 818 | // it's possible that stale state gives us empty selections, so we explicitly check here. 819 | if (selectors) { 820 | toggleAll(selectedName, selectors); 821 | } 822 | } 823 | }); 824 | 825 | function throttle(func, wait) { 826 | let waiting = false; 827 | return function () { 828 | if (!waiting) { 829 | func.apply(this, arguments); 830 | waiting = true; 831 | setTimeout(function () { 832 | waiting = false; 833 | }, wait); 834 | } 835 | }; 836 | } 837 | 838 | function nexttick(func) { 839 | return setTimeout(func, 0); 840 | } 841 | -------------------------------------------------------------------------------- /docs/site_libs/quarto-html/tippy.css: -------------------------------------------------------------------------------- 1 | .tippy-box[data-animation=fade][data-state=hidden]{opacity:0}[data-tippy-root]{max-width:calc(100vw - 10px)}.tippy-box{position:relative;background-color:#333;color:#fff;border-radius:4px;font-size:14px;line-height:1.4;white-space:normal;outline:0;transition-property:transform,visibility,opacity}.tippy-box[data-placement^=top]>.tippy-arrow{bottom:0}.tippy-box[data-placement^=top]>.tippy-arrow:before{bottom:-7px;left:0;border-width:8px 8px 0;border-top-color:initial;transform-origin:center top}.tippy-box[data-placement^=bottom]>.tippy-arrow{top:0}.tippy-box[data-placement^=bottom]>.tippy-arrow:before{top:-7px;left:0;border-width:0 8px 8px;border-bottom-color:initial;transform-origin:center bottom}.tippy-box[data-placement^=left]>.tippy-arrow{right:0}.tippy-box[data-placement^=left]>.tippy-arrow:before{border-width:8px 0 8px 8px;border-left-color:initial;right:-7px;transform-origin:center left}.tippy-box[data-placement^=right]>.tippy-arrow{left:0}.tippy-box[data-placement^=right]>.tippy-arrow:before{left:-7px;border-width:8px 8px 8px 0;border-right-color:initial;transform-origin:center right}.tippy-box[data-inertia][data-state=visible]{transition-timing-function:cubic-bezier(.54,1.5,.38,1.11)}.tippy-arrow{width:16px;height:16px;color:#333}.tippy-arrow:before{content:"";position:absolute;border-color:transparent;border-style:solid}.tippy-content{position:relative;padding:5px 9px;z-index:1} -------------------------------------------------------------------------------- /docs/site_libs/quarto-html/tippy.umd.min.js: -------------------------------------------------------------------------------- 1 | !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("@popperjs/core")):"function"==typeof define&&define.amd?define(["@popperjs/core"],t):(e=e||self).tippy=t(e.Popper)}(this,(function(e){"use strict";var t={passive:!0,capture:!0},n=function(){return document.body};function r(e,t,n){if(Array.isArray(e)){var r=e[t];return null==r?Array.isArray(n)?n[t]:n:r}return e}function o(e,t){var n={}.toString.call(e);return 0===n.indexOf("[object")&&n.indexOf(t+"]")>-1}function i(e,t){return"function"==typeof e?e.apply(void 0,t):e}function a(e,t){return 0===t?e:function(r){clearTimeout(n),n=setTimeout((function(){e(r)}),t)};var n}function s(e,t){var n=Object.assign({},e);return t.forEach((function(e){delete n[e]})),n}function u(e){return[].concat(e)}function c(e,t){-1===e.indexOf(t)&&e.push(t)}function p(e){return e.split("-")[0]}function f(e){return[].slice.call(e)}function l(e){return Object.keys(e).reduce((function(t,n){return void 0!==e[n]&&(t[n]=e[n]),t}),{})}function d(){return document.createElement("div")}function v(e){return["Element","Fragment"].some((function(t){return o(e,t)}))}function m(e){return o(e,"MouseEvent")}function g(e){return!(!e||!e._tippy||e._tippy.reference!==e)}function h(e){return v(e)?[e]:function(e){return o(e,"NodeList")}(e)?f(e):Array.isArray(e)?e:f(document.querySelectorAll(e))}function b(e,t){e.forEach((function(e){e&&(e.style.transitionDuration=t+"ms")}))}function y(e,t){e.forEach((function(e){e&&e.setAttribute("data-state",t)}))}function w(e){var t,n=u(e)[0];return null!=n&&null!=(t=n.ownerDocument)&&t.body?n.ownerDocument:document}function E(e,t,n){var r=t+"EventListener";["transitionend","webkitTransitionEnd"].forEach((function(t){e[r](t,n)}))}function O(e,t){for(var n=t;n;){var r;if(e.contains(n))return!0;n=null==n.getRootNode||null==(r=n.getRootNode())?void 0:r.host}return!1}var x={isTouch:!1},C=0;function T(){x.isTouch||(x.isTouch=!0,window.performance&&document.addEventListener("mousemove",A))}function A(){var e=performance.now();e-C<20&&(x.isTouch=!1,document.removeEventListener("mousemove",A)),C=e}function L(){var e=document.activeElement;if(g(e)){var t=e._tippy;e.blur&&!t.state.isVisible&&e.blur()}}var D=!!("undefined"!=typeof window&&"undefined"!=typeof document)&&!!window.msCrypto,R=Object.assign({appendTo:n,aria:{content:"auto",expanded:"auto"},delay:0,duration:[300,250],getReferenceClientRect:null,hideOnClick:!0,ignoreAttributes:!1,interactive:!1,interactiveBorder:2,interactiveDebounce:0,moveTransition:"",offset:[0,10],onAfterUpdate:function(){},onBeforeUpdate:function(){},onCreate:function(){},onDestroy:function(){},onHidden:function(){},onHide:function(){},onMount:function(){},onShow:function(){},onShown:function(){},onTrigger:function(){},onUntrigger:function(){},onClickOutside:function(){},placement:"top",plugins:[],popperOptions:{},render:null,showOnCreate:!1,touch:!0,trigger:"mouseenter focus",triggerTarget:null},{animateFill:!1,followCursor:!1,inlinePositioning:!1,sticky:!1},{allowHTML:!1,animation:"fade",arrow:!0,content:"",inertia:!1,maxWidth:350,role:"tooltip",theme:"",zIndex:9999}),k=Object.keys(R);function P(e){var t=(e.plugins||[]).reduce((function(t,n){var r,o=n.name,i=n.defaultValue;o&&(t[o]=void 0!==e[o]?e[o]:null!=(r=R[o])?r:i);return t}),{});return Object.assign({},e,t)}function j(e,t){var n=Object.assign({},t,{content:i(t.content,[e])},t.ignoreAttributes?{}:function(e,t){return(t?Object.keys(P(Object.assign({},R,{plugins:t}))):k).reduce((function(t,n){var r=(e.getAttribute("data-tippy-"+n)||"").trim();if(!r)return t;if("content"===n)t[n]=r;else try{t[n]=JSON.parse(r)}catch(e){t[n]=r}return t}),{})}(e,t.plugins));return n.aria=Object.assign({},R.aria,n.aria),n.aria={expanded:"auto"===n.aria.expanded?t.interactive:n.aria.expanded,content:"auto"===n.aria.content?t.interactive?null:"describedby":n.aria.content},n}function M(e,t){e.innerHTML=t}function V(e){var t=d();return!0===e?t.className="tippy-arrow":(t.className="tippy-svg-arrow",v(e)?t.appendChild(e):M(t,e)),t}function I(e,t){v(t.content)?(M(e,""),e.appendChild(t.content)):"function"!=typeof t.content&&(t.allowHTML?M(e,t.content):e.textContent=t.content)}function S(e){var t=e.firstElementChild,n=f(t.children);return{box:t,content:n.find((function(e){return e.classList.contains("tippy-content")})),arrow:n.find((function(e){return e.classList.contains("tippy-arrow")||e.classList.contains("tippy-svg-arrow")})),backdrop:n.find((function(e){return e.classList.contains("tippy-backdrop")}))}}function N(e){var t=d(),n=d();n.className="tippy-box",n.setAttribute("data-state","hidden"),n.setAttribute("tabindex","-1");var r=d();function o(n,r){var o=S(t),i=o.box,a=o.content,s=o.arrow;r.theme?i.setAttribute("data-theme",r.theme):i.removeAttribute("data-theme"),"string"==typeof r.animation?i.setAttribute("data-animation",r.animation):i.removeAttribute("data-animation"),r.inertia?i.setAttribute("data-inertia",""):i.removeAttribute("data-inertia"),i.style.maxWidth="number"==typeof r.maxWidth?r.maxWidth+"px":r.maxWidth,r.role?i.setAttribute("role",r.role):i.removeAttribute("role"),n.content===r.content&&n.allowHTML===r.allowHTML||I(a,e.props),r.arrow?s?n.arrow!==r.arrow&&(i.removeChild(s),i.appendChild(V(r.arrow))):i.appendChild(V(r.arrow)):s&&i.removeChild(s)}return r.className="tippy-content",r.setAttribute("data-state","hidden"),I(r,e.props),t.appendChild(n),n.appendChild(r),o(e.props,e.props),{popper:t,onUpdate:o}}N.$$tippy=!0;var B=1,H=[],U=[];function _(o,s){var v,g,h,C,T,A,L,k,M=j(o,Object.assign({},R,P(l(s)))),V=!1,I=!1,N=!1,_=!1,F=[],W=a(we,M.interactiveDebounce),X=B++,Y=(k=M.plugins).filter((function(e,t){return k.indexOf(e)===t})),$={id:X,reference:o,popper:d(),popperInstance:null,props:M,state:{isEnabled:!0,isVisible:!1,isDestroyed:!1,isMounted:!1,isShown:!1},plugins:Y,clearDelayTimeouts:function(){clearTimeout(v),clearTimeout(g),cancelAnimationFrame(h)},setProps:function(e){if($.state.isDestroyed)return;ae("onBeforeUpdate",[$,e]),be();var t=$.props,n=j(o,Object.assign({},t,l(e),{ignoreAttributes:!0}));$.props=n,he(),t.interactiveDebounce!==n.interactiveDebounce&&(ce(),W=a(we,n.interactiveDebounce));t.triggerTarget&&!n.triggerTarget?u(t.triggerTarget).forEach((function(e){e.removeAttribute("aria-expanded")})):n.triggerTarget&&o.removeAttribute("aria-expanded");ue(),ie(),J&&J(t,n);$.popperInstance&&(Ce(),Ae().forEach((function(e){requestAnimationFrame(e._tippy.popperInstance.forceUpdate)})));ae("onAfterUpdate",[$,e])},setContent:function(e){$.setProps({content:e})},show:function(){var e=$.state.isVisible,t=$.state.isDestroyed,o=!$.state.isEnabled,a=x.isTouch&&!$.props.touch,s=r($.props.duration,0,R.duration);if(e||t||o||a)return;if(te().hasAttribute("disabled"))return;if(ae("onShow",[$],!1),!1===$.props.onShow($))return;$.state.isVisible=!0,ee()&&(z.style.visibility="visible");ie(),de(),$.state.isMounted||(z.style.transition="none");if(ee()){var u=re(),p=u.box,f=u.content;b([p,f],0)}A=function(){var e;if($.state.isVisible&&!_){if(_=!0,z.offsetHeight,z.style.transition=$.props.moveTransition,ee()&&$.props.animation){var t=re(),n=t.box,r=t.content;b([n,r],s),y([n,r],"visible")}se(),ue(),c(U,$),null==(e=$.popperInstance)||e.forceUpdate(),ae("onMount",[$]),$.props.animation&&ee()&&function(e,t){me(e,t)}(s,(function(){$.state.isShown=!0,ae("onShown",[$])}))}},function(){var e,t=$.props.appendTo,r=te();e=$.props.interactive&&t===n||"parent"===t?r.parentNode:i(t,[r]);e.contains(z)||e.appendChild(z);$.state.isMounted=!0,Ce()}()},hide:function(){var e=!$.state.isVisible,t=$.state.isDestroyed,n=!$.state.isEnabled,o=r($.props.duration,1,R.duration);if(e||t||n)return;if(ae("onHide",[$],!1),!1===$.props.onHide($))return;$.state.isVisible=!1,$.state.isShown=!1,_=!1,V=!1,ee()&&(z.style.visibility="hidden");if(ce(),ve(),ie(!0),ee()){var i=re(),a=i.box,s=i.content;$.props.animation&&(b([a,s],o),y([a,s],"hidden"))}se(),ue(),$.props.animation?ee()&&function(e,t){me(e,(function(){!$.state.isVisible&&z.parentNode&&z.parentNode.contains(z)&&t()}))}(o,$.unmount):$.unmount()},hideWithInteractivity:function(e){ne().addEventListener("mousemove",W),c(H,W),W(e)},enable:function(){$.state.isEnabled=!0},disable:function(){$.hide(),$.state.isEnabled=!1},unmount:function(){$.state.isVisible&&$.hide();if(!$.state.isMounted)return;Te(),Ae().forEach((function(e){e._tippy.unmount()})),z.parentNode&&z.parentNode.removeChild(z);U=U.filter((function(e){return e!==$})),$.state.isMounted=!1,ae("onHidden",[$])},destroy:function(){if($.state.isDestroyed)return;$.clearDelayTimeouts(),$.unmount(),be(),delete o._tippy,$.state.isDestroyed=!0,ae("onDestroy",[$])}};if(!M.render)return $;var q=M.render($),z=q.popper,J=q.onUpdate;z.setAttribute("data-tippy-root",""),z.id="tippy-"+$.id,$.popper=z,o._tippy=$,z._tippy=$;var G=Y.map((function(e){return e.fn($)})),K=o.hasAttribute("aria-expanded");return he(),ue(),ie(),ae("onCreate",[$]),M.showOnCreate&&Le(),z.addEventListener("mouseenter",(function(){$.props.interactive&&$.state.isVisible&&$.clearDelayTimeouts()})),z.addEventListener("mouseleave",(function(){$.props.interactive&&$.props.trigger.indexOf("mouseenter")>=0&&ne().addEventListener("mousemove",W)})),$;function Q(){var e=$.props.touch;return Array.isArray(e)?e:[e,0]}function Z(){return"hold"===Q()[0]}function ee(){var e;return!(null==(e=$.props.render)||!e.$$tippy)}function te(){return L||o}function ne(){var e=te().parentNode;return e?w(e):document}function re(){return S(z)}function oe(e){return $.state.isMounted&&!$.state.isVisible||x.isTouch||C&&"focus"===C.type?0:r($.props.delay,e?0:1,R.delay)}function ie(e){void 0===e&&(e=!1),z.style.pointerEvents=$.props.interactive&&!e?"":"none",z.style.zIndex=""+$.props.zIndex}function ae(e,t,n){var r;(void 0===n&&(n=!0),G.forEach((function(n){n[e]&&n[e].apply(n,t)})),n)&&(r=$.props)[e].apply(r,t)}function se(){var e=$.props.aria;if(e.content){var t="aria-"+e.content,n=z.id;u($.props.triggerTarget||o).forEach((function(e){var r=e.getAttribute(t);if($.state.isVisible)e.setAttribute(t,r?r+" "+n:n);else{var o=r&&r.replace(n,"").trim();o?e.setAttribute(t,o):e.removeAttribute(t)}}))}}function ue(){!K&&$.props.aria.expanded&&u($.props.triggerTarget||o).forEach((function(e){$.props.interactive?e.setAttribute("aria-expanded",$.state.isVisible&&e===te()?"true":"false"):e.removeAttribute("aria-expanded")}))}function ce(){ne().removeEventListener("mousemove",W),H=H.filter((function(e){return e!==W}))}function pe(e){if(!x.isTouch||!N&&"mousedown"!==e.type){var t=e.composedPath&&e.composedPath()[0]||e.target;if(!$.props.interactive||!O(z,t)){if(u($.props.triggerTarget||o).some((function(e){return O(e,t)}))){if(x.isTouch)return;if($.state.isVisible&&$.props.trigger.indexOf("click")>=0)return}else ae("onClickOutside",[$,e]);!0===$.props.hideOnClick&&($.clearDelayTimeouts(),$.hide(),I=!0,setTimeout((function(){I=!1})),$.state.isMounted||ve())}}}function fe(){N=!0}function le(){N=!1}function de(){var e=ne();e.addEventListener("mousedown",pe,!0),e.addEventListener("touchend",pe,t),e.addEventListener("touchstart",le,t),e.addEventListener("touchmove",fe,t)}function ve(){var e=ne();e.removeEventListener("mousedown",pe,!0),e.removeEventListener("touchend",pe,t),e.removeEventListener("touchstart",le,t),e.removeEventListener("touchmove",fe,t)}function me(e,t){var n=re().box;function r(e){e.target===n&&(E(n,"remove",r),t())}if(0===e)return t();E(n,"remove",T),E(n,"add",r),T=r}function ge(e,t,n){void 0===n&&(n=!1),u($.props.triggerTarget||o).forEach((function(r){r.addEventListener(e,t,n),F.push({node:r,eventType:e,handler:t,options:n})}))}function he(){var e;Z()&&(ge("touchstart",ye,{passive:!0}),ge("touchend",Ee,{passive:!0})),(e=$.props.trigger,e.split(/\s+/).filter(Boolean)).forEach((function(e){if("manual"!==e)switch(ge(e,ye),e){case"mouseenter":ge("mouseleave",Ee);break;case"focus":ge(D?"focusout":"blur",Oe);break;case"focusin":ge("focusout",Oe)}}))}function be(){F.forEach((function(e){var t=e.node,n=e.eventType,r=e.handler,o=e.options;t.removeEventListener(n,r,o)})),F=[]}function ye(e){var t,n=!1;if($.state.isEnabled&&!xe(e)&&!I){var r="focus"===(null==(t=C)?void 0:t.type);C=e,L=e.currentTarget,ue(),!$.state.isVisible&&m(e)&&H.forEach((function(t){return t(e)})),"click"===e.type&&($.props.trigger.indexOf("mouseenter")<0||V)&&!1!==$.props.hideOnClick&&$.state.isVisible?n=!0:Le(e),"click"===e.type&&(V=!n),n&&!r&&De(e)}}function we(e){var t=e.target,n=te().contains(t)||z.contains(t);"mousemove"===e.type&&n||function(e,t){var n=t.clientX,r=t.clientY;return e.every((function(e){var t=e.popperRect,o=e.popperState,i=e.props.interactiveBorder,a=p(o.placement),s=o.modifiersData.offset;if(!s)return!0;var u="bottom"===a?s.top.y:0,c="top"===a?s.bottom.y:0,f="right"===a?s.left.x:0,l="left"===a?s.right.x:0,d=t.top-r+u>i,v=r-t.bottom-c>i,m=t.left-n+f>i,g=n-t.right-l>i;return d||v||m||g}))}(Ae().concat(z).map((function(e){var t,n=null==(t=e._tippy.popperInstance)?void 0:t.state;return n?{popperRect:e.getBoundingClientRect(),popperState:n,props:M}:null})).filter(Boolean),e)&&(ce(),De(e))}function Ee(e){xe(e)||$.props.trigger.indexOf("click")>=0&&V||($.props.interactive?$.hideWithInteractivity(e):De(e))}function Oe(e){$.props.trigger.indexOf("focusin")<0&&e.target!==te()||$.props.interactive&&e.relatedTarget&&z.contains(e.relatedTarget)||De(e)}function xe(e){return!!x.isTouch&&Z()!==e.type.indexOf("touch")>=0}function Ce(){Te();var t=$.props,n=t.popperOptions,r=t.placement,i=t.offset,a=t.getReferenceClientRect,s=t.moveTransition,u=ee()?S(z).arrow:null,c=a?{getBoundingClientRect:a,contextElement:a.contextElement||te()}:o,p=[{name:"offset",options:{offset:i}},{name:"preventOverflow",options:{padding:{top:2,bottom:2,left:5,right:5}}},{name:"flip",options:{padding:5}},{name:"computeStyles",options:{adaptive:!s}},{name:"$$tippy",enabled:!0,phase:"beforeWrite",requires:["computeStyles"],fn:function(e){var t=e.state;if(ee()){var n=re().box;["placement","reference-hidden","escaped"].forEach((function(e){"placement"===e?n.setAttribute("data-placement",t.placement):t.attributes.popper["data-popper-"+e]?n.setAttribute("data-"+e,""):n.removeAttribute("data-"+e)})),t.attributes.popper={}}}}];ee()&&u&&p.push({name:"arrow",options:{element:u,padding:3}}),p.push.apply(p,(null==n?void 0:n.modifiers)||[]),$.popperInstance=e.createPopper(c,z,Object.assign({},n,{placement:r,onFirstUpdate:A,modifiers:p}))}function Te(){$.popperInstance&&($.popperInstance.destroy(),$.popperInstance=null)}function Ae(){return f(z.querySelectorAll("[data-tippy-root]"))}function Le(e){$.clearDelayTimeouts(),e&&ae("onTrigger",[$,e]),de();var t=oe(!0),n=Q(),r=n[0],o=n[1];x.isTouch&&"hold"===r&&o&&(t=o),t?v=setTimeout((function(){$.show()}),t):$.show()}function De(e){if($.clearDelayTimeouts(),ae("onUntrigger",[$,e]),$.state.isVisible){if(!($.props.trigger.indexOf("mouseenter")>=0&&$.props.trigger.indexOf("click")>=0&&["mouseleave","mousemove"].indexOf(e.type)>=0&&V)){var t=oe(!1);t?g=setTimeout((function(){$.state.isVisible&&$.hide()}),t):h=requestAnimationFrame((function(){$.hide()}))}}else ve()}}function F(e,n){void 0===n&&(n={});var r=R.plugins.concat(n.plugins||[]);document.addEventListener("touchstart",T,t),window.addEventListener("blur",L);var o=Object.assign({},n,{plugins:r}),i=h(e).reduce((function(e,t){var n=t&&_(t,o);return n&&e.push(n),e}),[]);return v(e)?i[0]:i}F.defaultProps=R,F.setDefaultProps=function(e){Object.keys(e).forEach((function(t){R[t]=e[t]}))},F.currentInput=x;var W=Object.assign({},e.applyStyles,{effect:function(e){var t=e.state,n={popper:{position:t.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}};Object.assign(t.elements.popper.style,n.popper),t.styles=n,t.elements.arrow&&Object.assign(t.elements.arrow.style,n.arrow)}}),X={mouseover:"mouseenter",focusin:"focus",click:"click"};var Y={name:"animateFill",defaultValue:!1,fn:function(e){var t;if(null==(t=e.props.render)||!t.$$tippy)return{};var n=S(e.popper),r=n.box,o=n.content,i=e.props.animateFill?function(){var e=d();return e.className="tippy-backdrop",y([e],"hidden"),e}():null;return{onCreate:function(){i&&(r.insertBefore(i,r.firstElementChild),r.setAttribute("data-animatefill",""),r.style.overflow="hidden",e.setProps({arrow:!1,animation:"shift-away"}))},onMount:function(){if(i){var e=r.style.transitionDuration,t=Number(e.replace("ms",""));o.style.transitionDelay=Math.round(t/10)+"ms",i.style.transitionDuration=e,y([i],"visible")}},onShow:function(){i&&(i.style.transitionDuration="0ms")},onHide:function(){i&&y([i],"hidden")}}}};var $={clientX:0,clientY:0},q=[];function z(e){var t=e.clientX,n=e.clientY;$={clientX:t,clientY:n}}var J={name:"followCursor",defaultValue:!1,fn:function(e){var t=e.reference,n=w(e.props.triggerTarget||t),r=!1,o=!1,i=!0,a=e.props;function s(){return"initial"===e.props.followCursor&&e.state.isVisible}function u(){n.addEventListener("mousemove",f)}function c(){n.removeEventListener("mousemove",f)}function p(){r=!0,e.setProps({getReferenceClientRect:null}),r=!1}function f(n){var r=!n.target||t.contains(n.target),o=e.props.followCursor,i=n.clientX,a=n.clientY,s=t.getBoundingClientRect(),u=i-s.left,c=a-s.top;!r&&e.props.interactive||e.setProps({getReferenceClientRect:function(){var e=t.getBoundingClientRect(),n=i,r=a;"initial"===o&&(n=e.left+u,r=e.top+c);var s="horizontal"===o?e.top:r,p="vertical"===o?e.right:n,f="horizontal"===o?e.bottom:r,l="vertical"===o?e.left:n;return{width:p-l,height:f-s,top:s,right:p,bottom:f,left:l}}})}function l(){e.props.followCursor&&(q.push({instance:e,doc:n}),function(e){e.addEventListener("mousemove",z)}(n))}function d(){0===(q=q.filter((function(t){return t.instance!==e}))).filter((function(e){return e.doc===n})).length&&function(e){e.removeEventListener("mousemove",z)}(n)}return{onCreate:l,onDestroy:d,onBeforeUpdate:function(){a=e.props},onAfterUpdate:function(t,n){var i=n.followCursor;r||void 0!==i&&a.followCursor!==i&&(d(),i?(l(),!e.state.isMounted||o||s()||u()):(c(),p()))},onMount:function(){e.props.followCursor&&!o&&(i&&(f($),i=!1),s()||u())},onTrigger:function(e,t){m(t)&&($={clientX:t.clientX,clientY:t.clientY}),o="focus"===t.type},onHidden:function(){e.props.followCursor&&(p(),c(),i=!0)}}}};var G={name:"inlinePositioning",defaultValue:!1,fn:function(e){var t,n=e.reference;var r=-1,o=!1,i=[],a={name:"tippyInlinePositioning",enabled:!0,phase:"afterWrite",fn:function(o){var a=o.state;e.props.inlinePositioning&&(-1!==i.indexOf(a.placement)&&(i=[]),t!==a.placement&&-1===i.indexOf(a.placement)&&(i.push(a.placement),e.setProps({getReferenceClientRect:function(){return function(e){return function(e,t,n,r){if(n.length<2||null===e)return t;if(2===n.length&&r>=0&&n[0].left>n[1].right)return n[r]||t;switch(e){case"top":case"bottom":var o=n[0],i=n[n.length-1],a="top"===e,s=o.top,u=i.bottom,c=a?o.left:i.left,p=a?o.right:i.right;return{top:s,bottom:u,left:c,right:p,width:p-c,height:u-s};case"left":case"right":var f=Math.min.apply(Math,n.map((function(e){return e.left}))),l=Math.max.apply(Math,n.map((function(e){return e.right}))),d=n.filter((function(t){return"left"===e?t.left===f:t.right===l})),v=d[0].top,m=d[d.length-1].bottom;return{top:v,bottom:m,left:f,right:l,width:l-f,height:m-v};default:return t}}(p(e),n.getBoundingClientRect(),f(n.getClientRects()),r)}(a.placement)}})),t=a.placement)}};function s(){var t;o||(t=function(e,t){var n;return{popperOptions:Object.assign({},e.popperOptions,{modifiers:[].concat(((null==(n=e.popperOptions)?void 0:n.modifiers)||[]).filter((function(e){return e.name!==t.name})),[t])})}}(e.props,a),o=!0,e.setProps(t),o=!1)}return{onCreate:s,onAfterUpdate:s,onTrigger:function(t,n){if(m(n)){var o=f(e.reference.getClientRects()),i=o.find((function(e){return e.left-2<=n.clientX&&e.right+2>=n.clientX&&e.top-2<=n.clientY&&e.bottom+2>=n.clientY})),a=o.indexOf(i);r=a>-1?a:r}},onHidden:function(){r=-1}}}};var K={name:"sticky",defaultValue:!1,fn:function(e){var t=e.reference,n=e.popper;function r(t){return!0===e.props.sticky||e.props.sticky===t}var o=null,i=null;function a(){var s=r("reference")?(e.popperInstance?e.popperInstance.state.elements.reference:t).getBoundingClientRect():null,u=r("popper")?n.getBoundingClientRect():null;(s&&Q(o,s)||u&&Q(i,u))&&e.popperInstance&&e.popperInstance.update(),o=s,i=u,e.state.isMounted&&requestAnimationFrame(a)}return{onMount:function(){e.props.sticky&&a()}}}};function Q(e,t){return!e||!t||(e.top!==t.top||e.right!==t.right||e.bottom!==t.bottom||e.left!==t.left)}return F.setDefaultProps({plugins:[Y,J,G,K],render:N}),F.createSingleton=function(e,t){var n;void 0===t&&(t={});var r,o=e,i=[],a=[],c=t.overrides,p=[],f=!1;function l(){a=o.map((function(e){return u(e.props.triggerTarget||e.reference)})).reduce((function(e,t){return e.concat(t)}),[])}function v(){i=o.map((function(e){return e.reference}))}function m(e){o.forEach((function(t){e?t.enable():t.disable()}))}function g(e){return o.map((function(t){var n=t.setProps;return t.setProps=function(o){n(o),t.reference===r&&e.setProps(o)},function(){t.setProps=n}}))}function h(e,t){var n=a.indexOf(t);if(t!==r){r=t;var s=(c||[]).concat("content").reduce((function(e,t){return e[t]=o[n].props[t],e}),{});e.setProps(Object.assign({},s,{getReferenceClientRect:"function"==typeof s.getReferenceClientRect?s.getReferenceClientRect:function(){var e;return null==(e=i[n])?void 0:e.getBoundingClientRect()}}))}}m(!1),v(),l();var b={fn:function(){return{onDestroy:function(){m(!0)},onHidden:function(){r=null},onClickOutside:function(e){e.props.showOnCreate&&!f&&(f=!0,r=null)},onShow:function(e){e.props.showOnCreate&&!f&&(f=!0,h(e,i[0]))},onTrigger:function(e,t){h(e,t.currentTarget)}}}},y=F(d(),Object.assign({},s(t,["overrides"]),{plugins:[b].concat(t.plugins||[]),triggerTarget:a,popperOptions:Object.assign({},t.popperOptions,{modifiers:[].concat((null==(n=t.popperOptions)?void 0:n.modifiers)||[],[W])})})),w=y.show;y.show=function(e){if(w(),!r&&null==e)return h(y,i[0]);if(!r||null!=e){if("number"==typeof e)return i[e]&&h(y,i[e]);if(o.indexOf(e)>=0){var t=e.reference;return h(y,t)}return i.indexOf(e)>=0?h(y,e):void 0}},y.showNext=function(){var e=i[0];if(!r)return y.show(0);var t=i.indexOf(r);y.show(i[t+1]||e)},y.showPrevious=function(){var e=i[i.length-1];if(!r)return y.show(e);var t=i.indexOf(r),n=i[t-1]||e;y.show(n)};var E=y.setProps;return y.setProps=function(e){c=e.overrides||c,E(e)},y.setInstances=function(e){m(!0),p.forEach((function(e){return e()})),o=e,m(!1),v(),l(),p=g(y),y.setProps({triggerTarget:a})},p=g(y),y},F.delegate=function(e,n){var r=[],o=[],i=!1,a=n.target,c=s(n,["target"]),p=Object.assign({},c,{trigger:"manual",touch:!1}),f=Object.assign({touch:R.touch},c,{showOnCreate:!0}),l=F(e,p);function d(e){if(e.target&&!i){var t=e.target.closest(a);if(t){var r=t.getAttribute("data-tippy-trigger")||n.trigger||R.trigger;if(!t._tippy&&!("touchstart"===e.type&&"boolean"==typeof f.touch||"touchstart"!==e.type&&r.indexOf(X[e.type])<0)){var s=F(t,f);s&&(o=o.concat(s))}}}}function v(e,t,n,o){void 0===o&&(o=!1),e.addEventListener(t,n,o),r.push({node:e,eventType:t,handler:n,options:o})}return u(l).forEach((function(e){var n=e.destroy,a=e.enable,s=e.disable;e.destroy=function(e){void 0===e&&(e=!0),e&&o.forEach((function(e){e.destroy()})),o=[],r.forEach((function(e){var t=e.node,n=e.eventType,r=e.handler,o=e.options;t.removeEventListener(n,r,o)})),r=[],n()},e.enable=function(){a(),o.forEach((function(e){return e.enable()})),i=!1},e.disable=function(){s(),o.forEach((function(e){return e.disable()})),i=!0},function(e){var n=e.reference;v(n,"touchstart",d,t),v(n,"mouseover",d),v(n,"focusin",d),v(n,"click",d)}(e)})),l},F.hideAll=function(e){var t=void 0===e?{}:e,n=t.exclude,r=t.duration;U.forEach((function(e){var t=!1;if(n&&(t=g(n)?e.reference===n:e.popper===n.popper),!t){var o=e.props.duration;e.setProps({duration:r}),e.hide(),e.state.isDestroyed||e.setProps({duration:o})}}))},F.roundArrow='',F})); 2 | 3 | -------------------------------------------------------------------------------- /docs/site_libs/quarto-nav/quarto-nav.js: -------------------------------------------------------------------------------- 1 | const headroomChanged = new CustomEvent("quarto-hrChanged", { 2 | detail: {}, 3 | bubbles: true, 4 | cancelable: false, 5 | composed: false, 6 | }); 7 | 8 | window.document.addEventListener("DOMContentLoaded", function () { 9 | let init = false; 10 | 11 | function throttle(func, wait) { 12 | var timeout; 13 | return function () { 14 | const context = this; 15 | const args = arguments; 16 | const later = function () { 17 | clearTimeout(timeout); 18 | timeout = null; 19 | func.apply(context, args); 20 | }; 21 | 22 | if (!timeout) { 23 | timeout = setTimeout(later, wait); 24 | } 25 | }; 26 | } 27 | 28 | function headerOffset() { 29 | // Set an offset if there is are fixed top navbar 30 | const headerEl = window.document.querySelector("header.fixed-top"); 31 | if (headerEl) { 32 | return headerEl.clientHeight; 33 | } else { 34 | return 0; 35 | } 36 | } 37 | 38 | function footerOffset() { 39 | const footerEl = window.document.querySelector("footer.footer"); 40 | if (footerEl) { 41 | return footerEl.clientHeight; 42 | } else { 43 | return 0; 44 | } 45 | } 46 | 47 | function updateDocumentOffsetWithoutAnimation() { 48 | updateDocumentOffset(false); 49 | } 50 | 51 | function updateDocumentOffset(animated) { 52 | // set body offset 53 | const topOffset = headerOffset(); 54 | const bodyOffset = topOffset + footerOffset(); 55 | const bodyEl = window.document.body; 56 | bodyEl.setAttribute("data-bs-offset", topOffset); 57 | bodyEl.style.paddingTop = topOffset + "px"; 58 | 59 | // deal with sidebar offsets 60 | const sidebars = window.document.querySelectorAll( 61 | ".sidebar, .headroom-target" 62 | ); 63 | sidebars.forEach((sidebar) => { 64 | if (!animated) { 65 | sidebar.classList.add("notransition"); 66 | // Remove the no transition class after the animation has time to complete 67 | setTimeout(function () { 68 | sidebar.classList.remove("notransition"); 69 | }, 201); 70 | } 71 | 72 | if (window.Headroom && sidebar.classList.contains("sidebar-unpinned")) { 73 | sidebar.style.top = "0"; 74 | sidebar.style.maxHeight = "100vh"; 75 | } else { 76 | sidebar.style.top = topOffset + "px"; 77 | sidebar.style.maxHeight = "calc(100vh - " + topOffset + "px)"; 78 | } 79 | }); 80 | 81 | // allow space for footer 82 | const mainContainer = window.document.querySelector(".quarto-container"); 83 | if (mainContainer) { 84 | mainContainer.style.minHeight = "calc(100vh - " + bodyOffset + "px)"; 85 | } 86 | 87 | // link offset 88 | let linkStyle = window.document.querySelector("#quarto-target-style"); 89 | if (!linkStyle) { 90 | linkStyle = window.document.createElement("style"); 91 | linkStyle.setAttribute("id", "quarto-target-style"); 92 | window.document.head.appendChild(linkStyle); 93 | } 94 | while (linkStyle.firstChild) { 95 | linkStyle.removeChild(linkStyle.firstChild); 96 | } 97 | if (topOffset > 0) { 98 | linkStyle.appendChild( 99 | window.document.createTextNode(` 100 | section:target::before { 101 | content: ""; 102 | display: block; 103 | height: ${topOffset}px; 104 | margin: -${topOffset}px 0 0; 105 | }`) 106 | ); 107 | } 108 | if (init) { 109 | window.dispatchEvent(headroomChanged); 110 | } 111 | init = true; 112 | } 113 | 114 | // initialize headroom 115 | var header = window.document.querySelector("#quarto-header"); 116 | if (header && window.Headroom) { 117 | const headroom = new window.Headroom(header, { 118 | tolerance: 5, 119 | onPin: function () { 120 | const sidebars = window.document.querySelectorAll( 121 | ".sidebar, .headroom-target" 122 | ); 123 | sidebars.forEach((sidebar) => { 124 | sidebar.classList.remove("sidebar-unpinned"); 125 | }); 126 | updateDocumentOffset(); 127 | }, 128 | onUnpin: function () { 129 | const sidebars = window.document.querySelectorAll( 130 | ".sidebar, .headroom-target" 131 | ); 132 | sidebars.forEach((sidebar) => { 133 | sidebar.classList.add("sidebar-unpinned"); 134 | }); 135 | updateDocumentOffset(); 136 | }, 137 | }); 138 | headroom.init(); 139 | 140 | let frozen = false; 141 | window.quartoToggleHeadroom = function () { 142 | if (frozen) { 143 | headroom.unfreeze(); 144 | frozen = false; 145 | } else { 146 | headroom.freeze(); 147 | frozen = true; 148 | } 149 | }; 150 | } 151 | 152 | window.addEventListener( 153 | "hashchange", 154 | function (e) { 155 | window.scrollTo(0, window.pageYOffset - headerOffset()); 156 | }, 157 | false 158 | ); 159 | 160 | // Observe size changed for the header 161 | const headerEl = window.document.querySelector("header.fixed-top"); 162 | if (headerEl && window.ResizeObserver) { 163 | const observer = new window.ResizeObserver( 164 | updateDocumentOffsetWithoutAnimation 165 | ); 166 | observer.observe(headerEl, { 167 | attributes: true, 168 | childList: true, 169 | characterData: true, 170 | }); 171 | } else { 172 | window.addEventListener( 173 | "resize", 174 | throttle(updateDocumentOffsetWithoutAnimation, 50) 175 | ); 176 | } 177 | setTimeout(updateDocumentOffsetWithoutAnimation, 250); 178 | 179 | // fixup index.html links if we aren't on the filesystem 180 | if (window.location.protocol !== "file:") { 181 | const links = window.document.querySelectorAll("a"); 182 | for (let i = 0; i < links.length; i++) { 183 | if (links[i].href) { 184 | links[i].href = links[i].href.replace(/\/index\.html/, "/"); 185 | } 186 | } 187 | 188 | // Fixup any sharing links that require urls 189 | // Append url to any sharing urls 190 | const sharingLinks = window.document.querySelectorAll( 191 | "a.sidebar-tools-main-item" 192 | ); 193 | for (let i = 0; i < sharingLinks.length; i++) { 194 | const sharingLink = sharingLinks[i]; 195 | const href = sharingLink.getAttribute("href"); 196 | if (href) { 197 | sharingLink.setAttribute( 198 | "href", 199 | href.replace("|url|", window.location.href) 200 | ); 201 | } 202 | } 203 | 204 | // Scroll the active navigation item into view, if necessary 205 | const navSidebar = window.document.querySelector("nav#quarto-sidebar"); 206 | if (navSidebar) { 207 | // Find the active item 208 | const activeItem = navSidebar.querySelector("li.sidebar-item a.active"); 209 | if (activeItem) { 210 | // Wait for the scroll height and height to resolve by observing size changes on the 211 | // nav element that is scrollable 212 | const resizeObserver = new ResizeObserver((_entries) => { 213 | // The bottom of the element 214 | const elBottom = activeItem.offsetTop; 215 | const viewBottom = navSidebar.scrollTop + navSidebar.clientHeight; 216 | 217 | // The element height and scroll height are the same, then we are still loading 218 | if (viewBottom !== navSidebar.scrollHeight) { 219 | // Determine if the item isn't visible and scroll to it 220 | if (elBottom >= viewBottom) { 221 | navSidebar.scrollTop = elBottom; 222 | } 223 | 224 | // stop observing now since we've completed the scroll 225 | resizeObserver.unobserve(navSidebar); 226 | } 227 | }); 228 | resizeObserver.observe(navSidebar); 229 | } 230 | } 231 | } 232 | }); 233 | -------------------------------------------------------------------------------- /docs/site_libs/quarto-ojs/quarto-ojs.css: -------------------------------------------------------------------------------- 1 | span.ojs-inline span div { 2 | display: inline-block; 3 | } 4 | 5 | /* add some breathing room between display outputs and text especially */ 6 | div.cell + section, 7 | div.cell + h1, 8 | div.cell + h2, 9 | div.cell + h3, 10 | div.cell + h4, 11 | div.cell + h5, 12 | div.cell + h6, 13 | div.cell + p { 14 | margin-top: 1rem; 15 | } 16 | 17 | div[nodetype="declaration"]:not([data-output="all"]) 18 | div.observablehq:not(observablehq--error) { 19 | display: none; 20 | } 21 | 22 | /* mimic bootstrap behavior which is always correct in observablehq outputs */ 23 | .observablehq a:not([href]):not([class]), 24 | .observablehq a:not([href]):not([class]):hover { 25 | color: inherit; 26 | text-decoration: none; 27 | } 28 | 29 | .observablehq .observablehq--inspect { 30 | --code-fallback: Consolas, monaco, monospace; 31 | font-family: var(--bs-font-monospace, var(--code-fallback)); 32 | font-size: 0.8em; 33 | } 34 | 35 | .observablehq--field { 36 | margin-left: 1rem; 37 | } 38 | 39 | .observablehq--caret { 40 | margin-right: 2px; 41 | vertical-align: baseline; 42 | } 43 | 44 | .observablehq--collapsed, 45 | .observablehq--expanded.observablehq--inspect a { 46 | cursor: pointer; 47 | } 48 | 49 | /* classes directly from observable's runtime */ 50 | .observablehq--key, 51 | .observablehq--index { 52 | color: var(--quarto-hl-dt-color); 53 | } 54 | 55 | .observablehq--string { 56 | color: var(--quarto-hl-st-color); 57 | } 58 | 59 | .observablehq--bigint, 60 | .observablehq--date, 61 | .observablehq--number, 62 | .observablehq--regexp, 63 | .observablehq--symbol { 64 | color: var(--quarto-hl-dv-color); 65 | } 66 | 67 | .observablehq--null, 68 | .observablehq--boolean, 69 | .observablehq--undefined, 70 | .observablehq--keyword { 71 | color: var(--quarto-hl-kw-color); 72 | } 73 | 74 | /* In addition, their import statements specifically come highlighted by hljs. 75 | (probably some legacy feature of theirs?) We handle those here as well. 76 | 77 | Just to be on the safe side, we select on observable's 'md-pre' 78 | class as well, in case someone else uses hljs and wishes to put 79 | their own highlighting. 80 | 81 | TODO Note that to make our highlighting consistent, we're 82 | overriding the "im" class to present like a keyword. I should make 83 | sure this looks right everywhere, but I don't know how to test it 84 | comprehensively. 85 | */ 86 | 87 | code.javascript span.im { 88 | color: var(--quarto-hl-kw-color); 89 | } 90 | 91 | pre.observablehq--md-pre span.hljs-keyword { 92 | color: var(--quarto-hl-kw-color); 93 | } 94 | 95 | pre.observablehq--md-pre span.hljs-string { 96 | color: var(--quarto-hl-st-color); 97 | } 98 | 99 | pre.observablehq--md-pre .span.hljs-date, 100 | pre.observablehq--md-pre .span.hljs-number, 101 | pre.observablehq--md-pre .span.hljs-regexp, 102 | pre.observablehq--md-pre .span.hljs-symbol { 103 | color: var(--quarto-hl-dv-color); 104 | } 105 | 106 | /* Other general niceties, but it's possible that we should do this on a page-by-page basis */ 107 | 108 | input { 109 | vertical-align: middle; 110 | } 111 | 112 | input[type="radio"], 113 | input[type="checkbox"] { 114 | margin: 0px 0px 3px 0px; 115 | } 116 | 117 | .observable-in-a-box-waiting-for-module-import { 118 | visibility: hidden; 119 | } 120 | 121 | /* play nicely w/ sidebar layout */ 122 | .panel-sidebar .observablehq > form[class^="oi-"] { 123 | flex-wrap: wrap !important; 124 | } 125 | 126 | /* likely that this only makes sense with bootstrap. TODO check with charles */ 127 | .observablehq table { 128 | font-size: 0.9em !important; 129 | } 130 | 131 | .quarto-ojs-hide { 132 | display: none; 133 | } 134 | 135 | .quarto-ojs-error-pinpoint { 136 | border-bottom: 2px dotted #e51400; 137 | font-weight: 700; 138 | cursor: pointer; 139 | } 140 | 141 | code span.quarto-ojs-error-pinpoint { 142 | color: inherit; 143 | } 144 | 145 | .observablehq--error .observablehq--inspect { 146 | font-size: 0.875em !important; 147 | } 148 | 149 | .observablehq--error .callout { 150 | margin-bottom: 0; 151 | margin-top: 0; 152 | } 153 | 154 | /* this counteracts the negative margin which observablehq uses in their tables at runtime */ 155 | .quarto-ojs-table-fixup { 156 | padding-left: 14px; 157 | } 158 | 159 | div.observablehq input[type="date"] { 160 | border-style: solid; 161 | padding: 0.8em 0.5em 0.8em 0.5em; 162 | border-color: rgba(220, 220, 220, 0.3); 163 | } 164 | -------------------------------------------------------------------------------- /docs/site_libs/quarto-search/fuse.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Fuse.js v6.6.2 - Lightweight fuzzy-search (http://fusejs.io) 3 | * 4 | * Copyright (c) 2022 Kiro Risk (http://kiro.me) 5 | * All Rights Reserved. Apache Software License 2.0 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | */ 9 | var e,t;e=this,t=function(){"use strict";function e(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function t(t){for(var n=1;ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n0&&void 0!==arguments[0]?arguments[0]:1,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:3,n=new Map,r=Math.pow(10,t);return{get:function(t){var i=t.match(C).length;if(n.has(i))return n.get(i);var o=1/Math.pow(i,.5*e),c=parseFloat(Math.round(o*r)/r);return n.set(i,c),c},clear:function(){n.clear()}}}var $=function(){function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=t.getFn,i=void 0===n?I.getFn:n,o=t.fieldNormWeight,c=void 0===o?I.fieldNormWeight:o;r(this,e),this.norm=E(c,3),this.getFn=i,this.isCreated=!1,this.setIndexRecords()}return o(e,[{key:"setSources",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];this.docs=e}},{key:"setIndexRecords",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];this.records=e}},{key:"setKeys",value:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];this.keys=t,this._keysMap={},t.forEach((function(t,n){e._keysMap[t.id]=n}))}},{key:"create",value:function(){var e=this;!this.isCreated&&this.docs.length&&(this.isCreated=!0,g(this.docs[0])?this.docs.forEach((function(t,n){e._addString(t,n)})):this.docs.forEach((function(t,n){e._addObject(t,n)})),this.norm.clear())}},{key:"add",value:function(e){var t=this.size();g(e)?this._addString(e,t):this._addObject(e,t)}},{key:"removeAt",value:function(e){this.records.splice(e,1);for(var t=e,n=this.size();t2&&void 0!==arguments[2]?arguments[2]:{},r=n.getFn,i=void 0===r?I.getFn:r,o=n.fieldNormWeight,c=void 0===o?I.fieldNormWeight:o,a=new $({getFn:i,fieldNormWeight:c});return a.setKeys(e.map(_)),a.setSources(t),a.create(),a}function R(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=t.errors,r=void 0===n?0:n,i=t.currentLocation,o=void 0===i?0:i,c=t.expectedLocation,a=void 0===c?0:c,s=t.distance,u=void 0===s?I.distance:s,h=t.ignoreLocation,l=void 0===h?I.ignoreLocation:h,f=r/e.length;if(l)return f;var d=Math.abs(a-o);return u?f+d/u:d?1:f}function N(){for(var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:I.minMatchCharLength,n=[],r=-1,i=-1,o=0,c=e.length;o=t&&n.push([r,i]),r=-1)}return e[o-1]&&o-r>=t&&n.push([r,o-1]),n}var P=32;function W(e){for(var t={},n=0,r=e.length;n1&&void 0!==arguments[1]?arguments[1]:{},o=i.location,c=void 0===o?I.location:o,a=i.threshold,s=void 0===a?I.threshold:a,u=i.distance,h=void 0===u?I.distance:u,l=i.includeMatches,f=void 0===l?I.includeMatches:l,d=i.findAllMatches,v=void 0===d?I.findAllMatches:d,g=i.minMatchCharLength,y=void 0===g?I.minMatchCharLength:g,p=i.isCaseSensitive,m=void 0===p?I.isCaseSensitive:p,k=i.ignoreLocation,M=void 0===k?I.ignoreLocation:k;if(r(this,e),this.options={location:c,threshold:s,distance:h,includeMatches:f,findAllMatches:v,minMatchCharLength:y,isCaseSensitive:m,ignoreLocation:M},this.pattern=m?t:t.toLowerCase(),this.chunks=[],this.pattern.length){var b=function(e,t){n.chunks.push({pattern:e,alphabet:W(e),startIndex:t})},x=this.pattern.length;if(x>P){for(var w=0,L=x%P,S=x-L;w3&&void 0!==arguments[3]?arguments[3]:{},i=r.location,o=void 0===i?I.location:i,c=r.distance,a=void 0===c?I.distance:c,s=r.threshold,u=void 0===s?I.threshold:s,h=r.findAllMatches,l=void 0===h?I.findAllMatches:h,f=r.minMatchCharLength,d=void 0===f?I.minMatchCharLength:f,v=r.includeMatches,g=void 0===v?I.includeMatches:v,y=r.ignoreLocation,p=void 0===y?I.ignoreLocation:y;if(t.length>P)throw new Error(w(P));for(var m,k=t.length,M=e.length,b=Math.max(0,Math.min(o,M)),x=u,L=b,S=d>1||g,_=S?Array(M):[];(m=e.indexOf(t,L))>-1;){var O=R(t,{currentLocation:m,expectedLocation:b,distance:a,ignoreLocation:p});if(x=Math.min(O,x),L=m+k,S)for(var j=0;j=z;q-=1){var B=q-1,J=n[e.charAt(B)];if(S&&(_[B]=+!!J),K[q]=(K[q+1]<<1|1)&J,F&&(K[q]|=(A[q+1]|A[q])<<1|1|A[q+1]),K[q]&$&&(C=R(t,{errors:F,currentLocation:B,expectedLocation:b,distance:a,ignoreLocation:p}))<=x){if(x=C,(L=B)<=b)break;z=Math.max(1,2*b-L)}}if(R(t,{errors:F+1,currentLocation:b,expectedLocation:b,distance:a,ignoreLocation:p})>x)break;A=K}var U={isMatch:L>=0,score:Math.max(.001,C)};if(S){var V=N(_,d);V.length?g&&(U.indices=V):U.isMatch=!1}return U}(e,n,i,{location:c+o,distance:a,threshold:s,findAllMatches:u,minMatchCharLength:h,includeMatches:r,ignoreLocation:l}),p=y.isMatch,m=y.score,k=y.indices;p&&(g=!0),v+=m,p&&k&&(d=[].concat(f(d),f(k)))}));var y={isMatch:g,score:g?v/this.chunks.length:1};return g&&r&&(y.indices=d),y}}]),e}(),z=function(){function e(t){r(this,e),this.pattern=t}return o(e,[{key:"search",value:function(){}}],[{key:"isMultiMatch",value:function(e){return D(e,this.multiRegex)}},{key:"isSingleMatch",value:function(e){return D(e,this.singleRegex)}}]),e}();function D(e,t){var n=e.match(t);return n?n[1]:null}var K=function(e){a(n,e);var t=l(n);function n(e){return r(this,n),t.call(this,e)}return o(n,[{key:"search",value:function(e){var t=e===this.pattern;return{isMatch:t,score:t?0:1,indices:[0,this.pattern.length-1]}}}],[{key:"type",get:function(){return"exact"}},{key:"multiRegex",get:function(){return/^="(.*)"$/}},{key:"singleRegex",get:function(){return/^=(.*)$/}}]),n}(z),q=function(e){a(n,e);var t=l(n);function n(e){return r(this,n),t.call(this,e)}return o(n,[{key:"search",value:function(e){var t=-1===e.indexOf(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,e.length-1]}}}],[{key:"type",get:function(){return"inverse-exact"}},{key:"multiRegex",get:function(){return/^!"(.*)"$/}},{key:"singleRegex",get:function(){return/^!(.*)$/}}]),n}(z),B=function(e){a(n,e);var t=l(n);function n(e){return r(this,n),t.call(this,e)}return o(n,[{key:"search",value:function(e){var t=e.startsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,this.pattern.length-1]}}}],[{key:"type",get:function(){return"prefix-exact"}},{key:"multiRegex",get:function(){return/^\^"(.*)"$/}},{key:"singleRegex",get:function(){return/^\^(.*)$/}}]),n}(z),J=function(e){a(n,e);var t=l(n);function n(e){return r(this,n),t.call(this,e)}return o(n,[{key:"search",value:function(e){var t=!e.startsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,e.length-1]}}}],[{key:"type",get:function(){return"inverse-prefix-exact"}},{key:"multiRegex",get:function(){return/^!\^"(.*)"$/}},{key:"singleRegex",get:function(){return/^!\^(.*)$/}}]),n}(z),U=function(e){a(n,e);var t=l(n);function n(e){return r(this,n),t.call(this,e)}return o(n,[{key:"search",value:function(e){var t=e.endsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[e.length-this.pattern.length,e.length-1]}}}],[{key:"type",get:function(){return"suffix-exact"}},{key:"multiRegex",get:function(){return/^"(.*)"\$$/}},{key:"singleRegex",get:function(){return/^(.*)\$$/}}]),n}(z),V=function(e){a(n,e);var t=l(n);function n(e){return r(this,n),t.call(this,e)}return o(n,[{key:"search",value:function(e){var t=!e.endsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,e.length-1]}}}],[{key:"type",get:function(){return"inverse-suffix-exact"}},{key:"multiRegex",get:function(){return/^!"(.*)"\$$/}},{key:"singleRegex",get:function(){return/^!(.*)\$$/}}]),n}(z),G=function(e){a(n,e);var t=l(n);function n(e){var i,o=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},c=o.location,a=void 0===c?I.location:c,s=o.threshold,u=void 0===s?I.threshold:s,h=o.distance,l=void 0===h?I.distance:h,f=o.includeMatches,d=void 0===f?I.includeMatches:f,v=o.findAllMatches,g=void 0===v?I.findAllMatches:v,y=o.minMatchCharLength,p=void 0===y?I.minMatchCharLength:y,m=o.isCaseSensitive,k=void 0===m?I.isCaseSensitive:m,M=o.ignoreLocation,b=void 0===M?I.ignoreLocation:M;return r(this,n),(i=t.call(this,e))._bitapSearch=new T(e,{location:a,threshold:u,distance:l,includeMatches:d,findAllMatches:g,minMatchCharLength:p,isCaseSensitive:k,ignoreLocation:b}),i}return o(n,[{key:"search",value:function(e){return this._bitapSearch.searchIn(e)}}],[{key:"type",get:function(){return"fuzzy"}},{key:"multiRegex",get:function(){return/^"(.*)"$/}},{key:"singleRegex",get:function(){return/^(.*)$/}}]),n}(z),H=function(e){a(n,e);var t=l(n);function n(e){return r(this,n),t.call(this,e)}return o(n,[{key:"search",value:function(e){for(var t,n=0,r=[],i=this.pattern.length;(t=e.indexOf(this.pattern,n))>-1;)n=t+i,r.push([t,n-1]);var o=!!r.length;return{isMatch:o,score:o?0:1,indices:r}}}],[{key:"type",get:function(){return"include"}},{key:"multiRegex",get:function(){return/^'"(.*)"$/}},{key:"singleRegex",get:function(){return/^'(.*)$/}}]),n}(z),Q=[K,H,B,J,V,U,q,G],X=Q.length,Y=/ +(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/;function Z(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return e.split("|").map((function(e){for(var n=e.trim().split(Y).filter((function(e){return e&&!!e.trim()})),r=[],i=0,o=n.length;i1&&void 0!==arguments[1]?arguments[1]:{},i=n.isCaseSensitive,o=void 0===i?I.isCaseSensitive:i,c=n.includeMatches,a=void 0===c?I.includeMatches:c,s=n.minMatchCharLength,u=void 0===s?I.minMatchCharLength:s,h=n.ignoreLocation,l=void 0===h?I.ignoreLocation:h,f=n.findAllMatches,d=void 0===f?I.findAllMatches:f,v=n.location,g=void 0===v?I.location:v,y=n.threshold,p=void 0===y?I.threshold:y,m=n.distance,k=void 0===m?I.distance:m;r(this,e),this.query=null,this.options={isCaseSensitive:o,includeMatches:a,minMatchCharLength:u,findAllMatches:d,ignoreLocation:l,location:g,threshold:p,distance:k},this.pattern=o?t:t.toLowerCase(),this.query=Z(this.pattern,this.options)}return o(e,[{key:"searchIn",value:function(e){var t=this.query;if(!t)return{isMatch:!1,score:1};var n=this.options,r=n.includeMatches;e=n.isCaseSensitive?e:e.toLowerCase();for(var i=0,o=[],c=0,a=0,s=t.length;a-1&&(n.refIndex=e.idx),t.matches.push(n)}}))}function ve(e,t){t.score=e.score}function ge(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},r=n.includeMatches,i=void 0===r?I.includeMatches:r,o=n.includeScore,c=void 0===o?I.includeScore:o,a=[];return i&&a.push(de),c&&a.push(ve),e.map((function(e){var n=e.idx,r={item:t[n],refIndex:n};return a.length&&a.forEach((function(t){t(e,r)})),r}))}var ye=function(){function e(n){var i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},o=arguments.length>2?arguments[2]:void 0;r(this,e),this.options=t(t({},I),i),this.options.useExtendedSearch,this._keyStore=new S(this.options.keys),this.setCollection(n,o)}return o(e,[{key:"setCollection",value:function(e,t){if(this._docs=e,t&&!(t instanceof $))throw new Error("Incorrect 'index' type");this._myIndex=t||F(this.options.keys,this._docs,{getFn:this.options.getFn,fieldNormWeight:this.options.fieldNormWeight})}},{key:"add",value:function(e){k(e)&&(this._docs.push(e),this._myIndex.add(e))}},{key:"remove",value:function(){for(var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:function(){return!1},t=[],n=0,r=this._docs.length;n1&&void 0!==arguments[1]?arguments[1]:{},n=t.limit,r=void 0===n?-1:n,i=this.options,o=i.includeMatches,c=i.includeScore,a=i.shouldSort,s=i.sortFn,u=i.ignoreFieldNorm,h=g(e)?g(this._docs[0])?this._searchStringList(e):this._searchObjectList(e):this._searchLogical(e);return fe(h,{ignoreFieldNorm:u}),a&&h.sort(s),y(r)&&r>-1&&(h=h.slice(0,r)),ge(h,this._docs,{includeMatches:o,includeScore:c})}},{key:"_searchStringList",value:function(e){var t=re(e,this.options),n=this._myIndex.records,r=[];return n.forEach((function(e){var n=e.v,i=e.i,o=e.n;if(k(n)){var c=t.searchIn(n),a=c.isMatch,s=c.score,u=c.indices;a&&r.push({item:n,idx:i,matches:[{score:s,value:n,norm:o,indices:u}]})}})),r}},{key:"_searchLogical",value:function(e){var t=this,n=function(e,t){var n=(arguments.length>2&&void 0!==arguments[2]?arguments[2]:{}).auto,r=void 0===n||n,i=function e(n){var i=Object.keys(n),o=ue(n);if(!o&&i.length>1&&!se(n))return e(le(n));if(he(n)){var c=o?n[ce]:i[0],a=o?n[ae]:n[c];if(!g(a))throw new Error(x(c));var s={keyId:j(c),pattern:a};return r&&(s.searcher=re(a,t)),s}var u={children:[],operator:i[0]};return i.forEach((function(t){var r=n[t];v(r)&&r.forEach((function(t){u.children.push(e(t))}))})),u};return se(e)||(e=le(e)),i(e)}(e,this.options),r=function e(n,r,i){if(!n.children){var o=n.keyId,c=n.searcher,a=t._findMatches({key:t._keyStore.get(o),value:t._myIndex.getValueForItemAtKeyId(r,o),searcher:c});return a&&a.length?[{idx:i,item:r,matches:a}]:[]}for(var s=[],u=0,h=n.children.length;u1&&void 0!==arguments[1]?arguments[1]:{},n=t.getFn,r=void 0===n?I.getFn:n,i=t.fieldNormWeight,o=void 0===i?I.fieldNormWeight:i,c=e.keys,a=e.records,s=new $({getFn:r,fieldNormWeight:o});return s.setKeys(c),s.setIndexRecords(a),s},ye.config=I,function(){ne.push.apply(ne,arguments)}(te),ye},"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).Fuse=t(); -------------------------------------------------------------------------------- /docs/test-quarto-static.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Svelte components in Quarto (static) 12 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 124 | 125 | 126 | 127 | 128 | 129 | 130 |
131 | 132 |
133 | 134 | 135 | 136 | 137 |
138 | 139 | 140 |
141 |
142 |

Svelte components in Quarto (static)

143 |
144 | 145 | 146 | 147 |
148 | 149 |
150 |
Author
151 |
152 |

James Goldie

153 |
154 |
155 | 156 | 157 | 158 |
159 | 160 | 161 |
162 | 163 |
164 |

Background

165 |

Okay, so we’re using this blog post on compiling Svelte components as Web Components, along with with this SO answer on making Svelte components as browser bundles, to see if we can write Svelte components that can be dropped into plain HTML, or even Quarto documents.

166 |

The end goal is to have something that can be instantiated in a Quarto document and then dynamically update its props (using reactive OJS code) without destroying the component - for example, to have a chart that transitions elements as the incoming data changes.

167 |
168 |
169 |

Static HTML import

170 |

In this first approach, we’ll import the module in the YAML frontmatter and then use a static HTML block. (The container isn’t necessary, I just want to see where the chart’s coming in):

171 |
```{html}
172 | <div class="container" style="background-color:#dddddd;">
173 |   <animated-circles my_dataset="10|5,30|15,50|25,70|17,90|8">
174 |   </animated-circles>
175 | </div>
176 | ```
177 |
178 | 179 | 180 |
181 |

Nice! But it’d be great to instantiate it with JavaScript and use a create-then-update-props pattern, such as this one used to integrate DeckGL with Observable in this blog post.

182 |
183 |
184 |
185 | 186 |
187 |
188 | Note 189 |
190 |
191 |
192 |

Okay, this was working, but my efforts to get it working dynamically broke it here. Specifically, I switched rollup.config.js to use output.format = "es" instead of "iife".

193 |
194 |
195 |

A further problem is that because of the Web Components interface, attribute props have to be strings. That’s not a super efficient way to pass larger datasets in. Maybe it’s not a problem when we instantiuate with JavaScript?

196 |

Let’s try to fix these problems in test-quarto-dynamic.qmd.

197 | 198 | 199 |
200 | 201 |
202 | 421 |
422 | 423 | 424 | 425 | -------------------------------------------------------------------------------- /docs/web-component-tut/public/build/bundle.css: -------------------------------------------------------------------------------- 1 | main.svelte-1tky8bj{text-align:center;padding:1em;max-width:240px;margin:0 auto}h1.svelte-1tky8bj{color:#ff3e00;text-transform:uppercase;font-size:4em;font-weight:100}@media(min-width: 640px){main.svelte-1tky8bj{max-width:none}} -------------------------------------------------------------------------------- /index.qmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Svelt components in Quarto" 3 | author: "James Goldie" 4 | date: "2022-09-15" 5 | --- 6 | 7 | :::{.callout-tip} 8 | This work has been turned into a Quarto extension: [Sverto](https://github.com/360-info/sverto)! 9 | ::: 10 | 11 | Okay, so we're using [this blog post on compiling Svelte components as Web Components](https://blog.logrocket.com/build-web-components-svelte), along with with [this SO answer on making Svelte components as browser bundles](https://stackoverflow.com/a/65522522/3246758), to see if we can write Svelte components that can be dropped into plain HTML, or even Quarto documents. 12 | 13 | The end goal is to have something that can be instantiated in a Quarto document and then dynamically update its props (using reactive OJS code) without destroying the component - for example, to have a chart that transitions elements as the incoming data changes. 14 | 15 | The component itself is [`Circles.svelte`](https://github.com/jimjam-slam/svelte-in-quarto/tree/main/web-component-tut/src/widgets/Circles.svelte), a bunch of animating circles based on [my earlier Svelte tests](https://github.com/jimjam-slam/svelte-experiments/tree/main/src/routes/1-animated-circles). It's pretty simple: literally define an SVG of a bunch of circles, using Svelte's built-in transitions to smoothly add and remove elements that newly enter or leave the dataset (equivalent to d3's `.enter()` and `.exit()`), and regular CSS transitions for elements that are retained when the dataset changes. 16 | 17 | ❌ [**The static test**](./test-quarto-static.qmd) aims to use Web Component syntax to drop Svelte components in "statically" with HTML, rather than using JavaScript. Although I got this working, I've abandoned it, as I'm not sure that you can change the props easily, and that's kind of what this is all about. 18 | 19 | ✅ [**The dynamic test**](./test-quarto-dynamic.qmd) creates a Svelte component and exposes its props. The idea is to create a component, ibject it into an element, then have it update itself when the props are modified _without it being destroyed and remade_. That way Svelte can take care of the updates. 20 | -------------------------------------------------------------------------------- /test-html-static.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Svelte components in HTML 5 | 6 | 7 | 8 | 9 |

Background

10 |

11 | Okay, so we're using this blog post on compiling Svelte components as Web Components, along with with this SO answer on making Svelte components as browser bundles, to see if we can write Svelte components that can be dropped into plain HTML, or even Quarto documents. 12 |

13 |

14 | The end goal is to have something that can be instantiated in a Quarto document and then dynamically update its props (using reactive OJS code) without destroying the component - for example, to have a chart that transitions elements as the incoming data changes. 15 |

16 |

Static web component using HTML Web Component

17 |

Data:

10|5,30|15,50|25,70|17,90|8

18 | 22 | 23 |

Let's instantiate one here with JavaScript

24 |
25 | 38 | 39 | -------------------------------------------------------------------------------- /test-quarto-dynamic.qmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Svelte components in Quarto (dynamic)" 3 | author: "James Goldie" 4 | format: 5 | html: 6 | toc: true 7 | --- 8 | 9 | :::{.callout-tip} 10 | This work has been turned into a Quarto extension: [Sverto](https://github.com/360-info/sverto)! 11 | ::: 12 | 13 | ## Background 14 | 15 | Okay, so we're using [this blog post on compiling Svelte components as Web Components](https://blog.logrocket.com/build-web-components-svelte), along with with [this SO answer on making Svelte components as browser bundles](https://stackoverflow.com/a/65522522/3246758), to see if we can write Svelte components that can be dropped into plain HTML, or even Quarto documents. 16 | 17 | The end goal is to have something that can be instantiated in a Quarto document and then dynamically update its props (using reactive OJS code) without destroying the component - for example, to have a chart that transitions elements as the incoming data changes. 18 | 19 | :::{.callout-note} 20 | # Component tag name 21 | 22 | I've changed the `tag` attribute at the top of `Circles.svelte` from `"animated-circles"` to `{null}` in order to stop an error that crops up. it fixes that error here but prevents the component from being used in [`test-quarto-static.qmd`](./`test-quarto-static.qmd`) with the static HTML syntax. 23 | ::: 24 | 25 | ## Dynamic HTML import 26 | 27 | In this second approach, we'll import the module in JavaScript, create an instance, and finally update its props to pass new data in. The hope is that we can cirumvent OJS's reactivity when creating the element, allowing it to transition its child elements (like bars or circles representing data) using its own reactivity. [This notebook uses the same pattern to integrate DeckGL with Observable](https://observablehq.com/@tmcw/using-mapbox-gl-js). 28 | 29 | First, let's import the JavaScript. Since OJS blocks are naturally Promises, we should be able to use either `require()` or `await import()`. 30 | 31 | ```{ojs} 32 | CirclesOne = require("/web-component-tut/public/build/Circles.js"); 33 | ``` 34 | 35 | How'd that go? No? What about `await import()`? 36 | 37 | ```{ojs} 38 | Circles = import("/web-component-tut/public/build/Circles.js"); 39 | ``` 40 | 41 | Better, I think! 42 | 43 | ```{ojs} 44 | Circles 45 | ``` 46 | 47 | And the default constructor? 48 | 49 | ```{ojs} 50 | Circles.default 51 | ``` 52 | 53 | ## Demo: animated Svelte component 54 | 55 | ::::{.column-margin} 56 | ```{=html} 57 | 58 | 63 | ``` 64 | ::: {#mycircles style="background-color:#ffffffcc"} 65 | ::: 66 | :::: 67 | 68 | Let's create a `CirclesTwo`. I've create a target div, `#mycircles`, on the margin for it to load into first: 69 | 70 | ```{ojs} 71 | myCircles = new Circles.default({ 72 | target: document.querySelector("#mycircles"), 73 | props: { 74 | // data: "10|5,30|15,50|25,70|17,90|8" 75 | data: [ 76 | {x: 10, r: 5}, 77 | {x: 30, r: 15}, 78 | {x: 50, r: 25}, 79 | {x: 70, r: 17}, 80 | {x: 90, r: 8} 81 | ] 82 | } 83 | }); 84 | ``` 85 | 86 | Great! A little bit convoluted, but it's working. Now we want to push some new data to it - the equivalent of `setProps()` in DeckGL. 87 | 88 | I can't see anything that immediately stands out in `myCircles`, but inspecting the compiled code in `Circles.js` reveals that the class returned includes `get data` and `set data`. 89 | 90 | Maybe I can just write to the prop directly? Let's set up some options to switch between reactively: 91 | 92 | ```{ojs} 93 | viewof selectedDataset = Inputs.select( 94 | new Map([ 95 | ["Dataset A", [ 96 | {x: 10, r: 5}, 97 | {x: 30, r: 15}, 98 | {x: 50, r: 25}, 99 | {x: 70, r: 17}, 100 | {x: 90, r: 8} 101 | ]], 102 | ["Dataset B", [ 103 | {x: 10, r: 25}, 104 | {x: 30, r: 5}, 105 | {x: 50, r: 5} 106 | ]], 107 | ["Dataset C", [ 108 | {x: 5, r: 12}, 109 | {x: 25, r: 5}, 110 | {x: 32, r: 8}, 111 | {x: 45, r: 21}, 112 | {x: 70, r: 5} 113 | ]] 114 | ]), { 115 | label: "Selected dataset" 116 | }); 117 | ``` 118 | 119 | And now we'll update the Svelte component with it: 120 | 121 | ```{ojs} 122 | //| output: false 123 | myCircles.data = selectedDataset; 124 | ``` 125 | 126 | ```{ojs} 127 | Inputs.table(selectedDataset) 128 | ``` 129 | 130 | (These are keyed by the `x` value, not an independent index, so when you choose dataset C, most of the circles are treated as new elements that exit/enter, not existing ones that transition) 131 | 132 | :::{.callout-note} 133 | I initially got an error: 134 | 135 | > "Error: : Props cannot be set directly on the component instance unless compiling with 'accessors: true' or ''" 136 | 137 | Adding `accessors` to the `svelte:options` line at the start of `Circles.svelte` fixed this right up! 138 | ::: 139 | -------------------------------------------------------------------------------- /test-quarto-static.qmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Svelte components in Quarto (static)" 3 | author: "James Goldie" 4 | include-before-body: 5 | text: | 6 | 7 | --- 8 | 9 | ## Background 10 | 11 | Okay, so we're using [this blog post on compiling Svelte components as Web Components](https://blog.logrocket.com/build-web-components-svelte), along with with [this SO answer on making Svelte components as browser bundles](https://stackoverflow.com/a/65522522/3246758), to see if we can write Svelte components that can be dropped into plain HTML, or even Quarto documents. 12 | 13 | The end goal is to have something that can be instantiated in a Quarto document and then dynamically update its props (using reactive OJS code) without destroying the component - for example, to have a chart that transitions elements as the incoming data changes. 14 | 15 | ## Static HTML import 16 | 17 | In this first approach, we'll import the module in the YAML frontmatter and then use a static HTML block. (The container isn't necessary, I just want to see where the chart's coming in): 18 | 19 | ```{{html}} 20 |
21 | 22 | 23 |
24 | ``` 25 | ```{=html} 26 |
27 | 28 | 29 |
30 | ``` 31 | 32 | Nice! But it'd be great to instantiate it with JavaScript and use a create-then-update-props pattern, such as [this one used to integrate DeckGL with Observable in this blog post](https://observablehq.com/@tmcw/using-mapbox-gl-js). 33 | 34 | ::: {.callout-note} 35 | Okay, this _was_ working, but my efforts to get it working dynamically broke it here. Specifically, I switched `rollup.config.js` to use `output.format` = `"es"` instead of `"iife"`. 36 | ::: 37 | 38 | A further problem is that because of the Web Components interface, attribute props have to be strings. That's not a super efficient way to pass larger datasets in. Maybe it's not a problem when we instantiuate with JavaScript? 39 | 40 | Let's try to fix these problems in [`test-quarto-dynamic.qmd`](./test-quarto-dynamic.qmd). -------------------------------------------------------------------------------- /web-component-tut/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | 3 | 4 | .DS_Store 5 | -------------------------------------------------------------------------------- /web-component-tut/README.md: -------------------------------------------------------------------------------- 1 | # This repo is no longer maintained. Consider using `npm init vite` and selecting the `svelte` option or — if you want a full-fledged app framework and don't mind using pre-1.0 software — use [SvelteKit](https://kit.svelte.dev), the official application framework for Svelte. 2 | 3 | --- 4 | 5 | # svelte app 6 | 7 | This is a project template for [Svelte](https://svelte.dev) apps. It lives at https://github.com/sveltejs/template. 8 | 9 | To create a new project based on this template using [degit](https://github.com/Rich-Harris/degit): 10 | 11 | ```bash 12 | npx degit sveltejs/template svelte-app 13 | cd svelte-app 14 | ``` 15 | 16 | *Note that you will need to have [Node.js](https://nodejs.org) installed.* 17 | 18 | 19 | ## Get started 20 | 21 | Install the dependencies... 22 | 23 | ```bash 24 | cd svelte-app 25 | npm install 26 | ``` 27 | 28 | ...then start [Rollup](https://rollupjs.org): 29 | 30 | ```bash 31 | npm run dev 32 | ``` 33 | 34 | Navigate to [localhost:8080](http://localhost:8080). You should see your app running. Edit a component file in `src`, save it, and reload the page to see your changes. 35 | 36 | By default, the server will only respond to requests from localhost. To allow connections from other computers, edit the `sirv` commands in package.json to include the option `--host 0.0.0.0`. 37 | 38 | If you're using [Visual Studio Code](https://code.visualstudio.com/) we recommend installing the official extension [Svelte for VS Code](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode). If you are using other editors you may need to install a plugin in order to get syntax highlighting and intellisense. 39 | 40 | ## Building and running in production mode 41 | 42 | To create an optimised version of the app: 43 | 44 | ```bash 45 | npm run build 46 | ``` 47 | 48 | You can run the newly built app with `npm run start`. This uses [sirv](https://github.com/lukeed/sirv), which is included in your package.json's `dependencies` so that the app will work when you deploy to platforms like [Heroku](https://heroku.com). 49 | 50 | 51 | ## Single-page app mode 52 | 53 | By default, sirv will only respond to requests that match files in `public`. This is to maximise compatibility with static fileservers, allowing you to deploy your app anywhere. 54 | 55 | If you're building a single-page app (SPA) with multiple routes, sirv needs to be able to respond to requests for *any* path. You can make it so by editing the `"start"` command in package.json: 56 | 57 | ```js 58 | "start": "sirv public --single" 59 | ``` 60 | 61 | ## Using TypeScript 62 | 63 | This template comes with a script to set up a TypeScript development environment, you can run it immediately after cloning the template with: 64 | 65 | ```bash 66 | node scripts/setupTypeScript.js 67 | ``` 68 | 69 | Or remove the script via: 70 | 71 | ```bash 72 | rm scripts/setupTypeScript.js 73 | ``` 74 | 75 | If you want to use `baseUrl` or `path` aliases within your `tsconfig`, you need to set up `@rollup/plugin-alias` to tell Rollup to resolve the aliases. For more info, see [this StackOverflow question](https://stackoverflow.com/questions/63427935/setup-tsconfig-path-in-svelte). 76 | 77 | ## Deploying to the web 78 | 79 | ### With [Vercel](https://vercel.com) 80 | 81 | Install `vercel` if you haven't already: 82 | 83 | ```bash 84 | npm install -g vercel 85 | ``` 86 | 87 | Then, from within your project folder: 88 | 89 | ```bash 90 | cd public 91 | vercel deploy --name my-project 92 | ``` 93 | 94 | ### With [surge](https://surge.sh/) 95 | 96 | Install `surge` if you haven't already: 97 | 98 | ```bash 99 | npm install -g surge 100 | ``` 101 | 102 | Then, from within your project folder: 103 | 104 | ```bash 105 | npm run build 106 | surge public my-project.surge.sh 107 | ``` 108 | -------------------------------------------------------------------------------- /web-component-tut/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "svelte-app", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "build": "rollup -c", 7 | "dev": "rollup -c -w", 8 | "start": "sirv public --no-clear" 9 | }, 10 | "devDependencies": { 11 | "@rollup/plugin-commonjs": "^17.0.0", 12 | "@rollup/plugin-node-resolve": "^11.0.0", 13 | "rollup": "^2.3.4", 14 | "rollup-plugin-css-only": "^3.1.0", 15 | "rollup-plugin-livereload": "^2.0.0", 16 | "rollup-plugin-svelte": "^7.0.0", 17 | "rollup-plugin-terser": "^7.0.0", 18 | "svelte": "^3.0.0" 19 | }, 20 | "dependencies": { 21 | "sirv-cli": "^2.0.0", 22 | "d3-random": "^3.0.1", 23 | "d3-scale": "^4.0.2", 24 | "d3-scale-chromatic": "^3.0.0" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /web-component-tut/public/build/bundle.css: -------------------------------------------------------------------------------- 1 | main.svelte-1tky8bj{text-align:center;padding:1em;max-width:240px;margin:0 auto}h1.svelte-1tky8bj{color:#ff3e00;text-transform:uppercase;font-size:4em;font-weight:100}@media(min-width: 640px){main.svelte-1tky8bj{max-width:none}} -------------------------------------------------------------------------------- /web-component-tut/public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimjam-slam/svelte-in-quarto/b9f0de1c42fc7728e84cc453d45e46213979c144/web-component-tut/public/favicon.png -------------------------------------------------------------------------------- /web-component-tut/public/global.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | position: relative; 3 | width: 100%; 4 | height: 100%; 5 | } 6 | 7 | body { 8 | color: #333; 9 | margin: 0; 10 | padding: 8px; 11 | box-sizing: border-box; 12 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; 13 | } 14 | 15 | a { 16 | color: rgb(0,100,200); 17 | text-decoration: none; 18 | } 19 | 20 | a:hover { 21 | text-decoration: underline; 22 | } 23 | 24 | a:visited { 25 | color: rgb(0,80,160); 26 | } 27 | 28 | label { 29 | display: block; 30 | } 31 | 32 | input, button, select, textarea { 33 | font-family: inherit; 34 | font-size: inherit; 35 | -webkit-padding: 0.4em 0; 36 | padding: 0.4em; 37 | margin: 0 0 0.5em 0; 38 | box-sizing: border-box; 39 | border: 1px solid #ccc; 40 | border-radius: 2px; 41 | } 42 | 43 | input:disabled { 44 | color: #ccc; 45 | } 46 | 47 | button { 48 | color: #333; 49 | background-color: #f4f4f4; 50 | outline: none; 51 | } 52 | 53 | button:disabled { 54 | color: #999; 55 | } 56 | 57 | button:not(:disabled):active { 58 | background-color: #ddd; 59 | } 60 | 61 | button:focus { 62 | border-color: #666; 63 | } 64 | -------------------------------------------------------------------------------- /web-component-tut/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Svelte app 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /web-component-tut/rollup.config.js: -------------------------------------------------------------------------------- 1 | import svelte from 'rollup-plugin-svelte'; 2 | import commonjs from '@rollup/plugin-commonjs'; 3 | import resolve from '@rollup/plugin-node-resolve'; 4 | import livereload from 'rollup-plugin-livereload'; 5 | import { terser } from 'rollup-plugin-terser'; 6 | import css from 'rollup-plugin-css-only'; 7 | 8 | const production = !process.env.ROLLUP_WATCH; 9 | 10 | function serve() { 11 | let server; 12 | 13 | function toExit() { 14 | if (server) server.kill(0); 15 | } 16 | 17 | return { 18 | writeBundle() { 19 | if (server) return; 20 | server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { 21 | stdio: ['ignore', 'inherit', 'inherit'], 22 | shell: true 23 | }); 24 | 25 | process.on('SIGTERM', toExit); 26 | process.on('exit', toExit); 27 | } 28 | }; 29 | } 30 | 31 | const cmp = "Circles" 32 | 33 | // you can also export an array of these configs, so we could do one for 34 | // each file... 35 | export default { 36 | // input: 'src/main.js', 37 | // output: { 38 | // sourcemap: true, 39 | // format: 'iife', 40 | // name: 'app', 41 | // file: 'public/build/bundle.js' 42 | // }, 43 | input: 'src/widgets/Circles.svelte', 44 | output: { 45 | format: "es", 46 | dir: "public/build", 47 | sourcemap: true 48 | }, 49 | plugins: [ 50 | svelte({ 51 | compilerOptions: { 52 | accessors: true, 53 | dev: !production, 54 | } 55 | }), 56 | css({ output: 'bundle.css' }), 57 | resolve({ 58 | browser: true, 59 | dedupe: ['svelte'] 60 | }), 61 | commonjs(), 62 | !production && serve(), 63 | !production && livereload('public'), 64 | production && terser() 65 | ], 66 | watch: { 67 | clearScreen: false 68 | } 69 | }; 70 | -------------------------------------------------------------------------------- /web-component-tut/scripts/setupTypeScript.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | 3 | /** This script modifies the project to support TS code in .svelte files like: 4 | 5 | 8 | 9 | As well as validating the code for CI. 10 | */ 11 | 12 | /** To work on this script: 13 | rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template 14 | */ 15 | 16 | const fs = require("fs") 17 | const path = require("path") 18 | const { argv } = require("process") 19 | 20 | const projectRoot = argv[2] || path.join(__dirname, "..") 21 | 22 | // Add deps to pkg.json 23 | const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) 24 | packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { 25 | "svelte-check": "^2.0.0", 26 | "svelte-preprocess": "^4.0.0", 27 | "@rollup/plugin-typescript": "^8.0.0", 28 | "typescript": "^4.0.0", 29 | "tslib": "^2.0.0", 30 | "@tsconfig/svelte": "^2.0.0" 31 | }) 32 | 33 | // Add script for checking 34 | packageJSON.scripts = Object.assign(packageJSON.scripts, { 35 | "check": "svelte-check --tsconfig ./tsconfig.json" 36 | }) 37 | 38 | // Write the package JSON 39 | fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) 40 | 41 | // mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too 42 | const beforeMainJSPath = path.join(projectRoot, "src", "main.js") 43 | const afterMainTSPath = path.join(projectRoot, "src", "main.ts") 44 | fs.renameSync(beforeMainJSPath, afterMainTSPath) 45 | 46 | // Switch the app.svelte file to use TS 47 | const appSveltePath = path.join(projectRoot, "src", "App.svelte") 48 | let appFile = fs.readFileSync(appSveltePath, "utf8") 49 | appFile = appFile.replace(" 4 | 5 |
6 |

Hello {name}!

7 |

Visit the Svelte tutorial to learn how to build Svelte apps.

8 |
9 | 10 | -------------------------------------------------------------------------------- /web-component-tut/src/main.js: -------------------------------------------------------------------------------- 1 | import App from './App.svelte'; 2 | import Circles from './Circles.svelte'; 3 | 4 | const app = new App({ 5 | target: document.body, 6 | props: { 7 | name: 'world' 8 | } 9 | }); 10 | 11 | export default app; -------------------------------------------------------------------------------- /web-component-tut/src/widgets/Circles.svelte: -------------------------------------------------------------------------------- 1 | 2 | 3 | 24 | 25 | 28 | 29 | {#each data as d, i (d.x)} 30 | 36 | {/each} 37 | --------------------------------------------------------------------------------