chore: import upstream snapshot with attribution
@@ -0,0 +1,79 @@
|
||||
/* APIs-tab sidebar loader (Pattern B).
|
||||
*
|
||||
* Fetches the single shared API-nav fragment (_static/api-nav.html), injects it into
|
||||
* the #api-nav-mount container, highlights the current page, collapses non-current
|
||||
* sections, and resolves the fragment's root-relative links against this page.
|
||||
* The fragment is fetched once and reused from the browser cache across pages.
|
||||
*/
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function init() {
|
||||
var mount = document.getElementById("api-nav-mount");
|
||||
if (!mount) return;
|
||||
|
||||
var navUrl = mount.getAttribute("data-api-nav-url");
|
||||
var pagename = mount.getAttribute("data-pagename") || "";
|
||||
// Path from this page back to the doc root (e.g. "../../"), derived from the
|
||||
// fetch URL so we don't depend on other globals.
|
||||
var root = navUrl.replace(/_static\/api-nav\.html(\?.*)?$/, "");
|
||||
|
||||
fetch(navUrl)
|
||||
.then(function (resp) {
|
||||
if (!resp.ok) throw new Error("HTTP " + resp.status);
|
||||
return resp.text();
|
||||
})
|
||||
.then(function (html) {
|
||||
mount.innerHTML = html;
|
||||
|
||||
var links = mount.querySelectorAll("a[href]");
|
||||
|
||||
// 1) Find + mark the current page (fragment hrefs are root-relative).
|
||||
var currentHref = pagename + ".html";
|
||||
var currentLink = null;
|
||||
links.forEach(function (a) {
|
||||
if (a.getAttribute("href") === currentHref) currentLink = a;
|
||||
});
|
||||
|
||||
// 2) Collapse every section, then re-open only the current page's ancestors.
|
||||
mount.querySelectorAll("details").forEach(function (d) {
|
||||
d.removeAttribute("open");
|
||||
});
|
||||
if (currentLink) {
|
||||
currentLink.classList.add("current");
|
||||
var li = currentLink.closest("li");
|
||||
if (li) li.classList.add("current", "active");
|
||||
var el = currentLink.parentElement;
|
||||
while (el && el !== mount) {
|
||||
if (el.tagName === "DETAILS") el.setAttribute("open", "");
|
||||
el = el.parentElement;
|
||||
}
|
||||
if (li) {
|
||||
var own = li.querySelector(":scope > details");
|
||||
if (own) own.setAttribute("open", "");
|
||||
}
|
||||
if (li && li.scrollIntoView) {
|
||||
li.scrollIntoView({ block: "nearest" });
|
||||
}
|
||||
}
|
||||
|
||||
// 3) Resolve root-relative hrefs against this page.
|
||||
links.forEach(function (a) {
|
||||
var h = a.getAttribute("href");
|
||||
if (h && !/^(https?:|\/|#|mailto:)/.test(h)) {
|
||||
a.setAttribute("href", root + h);
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch(function () {
|
||||
mount.innerHTML =
|
||||
'<p class="api-nav-status">API navigation failed to load.</p>';
|
||||
});
|
||||
}
|
||||
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", init);
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,177 @@
|
||||
/* Kapa Ask AI button */
|
||||
#kapa-widget-container figure {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.mantine-Modal-root figure {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.assistant-title {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.container-xl.blurred {
|
||||
filter: blur(5px);
|
||||
}
|
||||
|
||||
.chat-widget {
|
||||
position: fixed;
|
||||
bottom: 10px;
|
||||
right: 10px;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
@keyframes jump {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
box-shadow: 0 1px 2px rgba(0,0,0,.15);
|
||||
}
|
||||
100% {
|
||||
transform: scale(1.05);
|
||||
box-shadow: 0 4px 20px rgba(0,0,0,.1);
|
||||
}
|
||||
}
|
||||
.search-button__wrapper.show ~ .chat-widget {
|
||||
z-index: 1050;
|
||||
animation: .4s jump ease infinite alternate;
|
||||
filter: brightness(1.5);
|
||||
}
|
||||
|
||||
.chat-popup {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 20%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -20%);
|
||||
width: 55%;
|
||||
height: 75%;
|
||||
background-color: var(--pst-color-background);
|
||||
border: 1px solid var(--pst-color-border);
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 5px 10px var(--pst-color-shadow);
|
||||
z-index: 1032;
|
||||
max-height: 1000px;
|
||||
overflow: hidden;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
|
||||
.chatFooter {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
background-color: var(--pst-color-surface);
|
||||
}
|
||||
|
||||
#openChatBtn {
|
||||
border: 1px solid var(--pst-color-border);
|
||||
background-color: var(--pst-color-surface);
|
||||
color: var(--pst-color-text-base);
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#closeChatBtn {
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
color: var(--pst-color-text-base);
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
#closeChatBtn:hover {
|
||||
color: var(--pst-color-link-hover);
|
||||
}
|
||||
|
||||
#searchBar {
|
||||
border: 1px solid var(--pst-color-border);
|
||||
background-color: var(--pst-color-surface);
|
||||
margin: 0em 1em 0em 0em;
|
||||
border-radius: 4px;
|
||||
color: var(--pst-color-text-base);
|
||||
}
|
||||
|
||||
.chatHeader {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: .5rem;
|
||||
}
|
||||
|
||||
.chatHeader > .header-wrapper {
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.chatContentContainer {
|
||||
padding: 15px;
|
||||
max-height: calc(100% - 100px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.chatContentContainer input {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: none;
|
||||
height: 1px;
|
||||
/* Set the hr color */
|
||||
color: #333; /* old IE */
|
||||
background-color: #333; /* Modern Browsers */
|
||||
}
|
||||
|
||||
#result * {
|
||||
overflow-anchor: none;
|
||||
}
|
||||
|
||||
#anchor {
|
||||
overflow-anchor: auto;
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
#result {
|
||||
padding: 15px;
|
||||
border-radius: 10px;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
background-color: var(--pst-color-surface);
|
||||
max-height: 50vh; /* Ensure the result area does not take too much vertical space */
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.chatContentContainer textarea {
|
||||
flex-grow: 1;
|
||||
min-width: 50px;
|
||||
max-height: 40px;
|
||||
resize: none;
|
||||
}
|
||||
|
||||
#searchBtn {
|
||||
white-space: nowrap;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.input-group {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
#blurDiv {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
backdrop-filter: blur(5px);
|
||||
z-index: 1031;
|
||||
}
|
||||
|
||||
#blurDiv.blurDiv-hidden {
|
||||
display: none !important;
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/* CSAT widgets */
|
||||
#csat-inputs {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.csat-hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
#csat-feedback-label {
|
||||
color: var(--pst-color-text-base);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.csat-button {
|
||||
margin-left: 16px;
|
||||
padding: 8px 16px 8px 16px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--pst-color-border);
|
||||
background: var(--pst-color-background);
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
width: 85px;
|
||||
}
|
||||
|
||||
#csat-textarea-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#csat-submit {
|
||||
margin-left: auto;
|
||||
font-weight: 700;
|
||||
border: none;
|
||||
margin-top: 12px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#csat-feedback-received {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.csat-button-active {
|
||||
border: 1px solid var(--pst-color-border);
|
||||
}
|
||||
|
||||
.csat-icon {
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
#csat {
|
||||
padding: 1em;
|
||||
min-width: 60%;
|
||||
}
|
||||
|
||||
#csat-textarea {
|
||||
resize: none;
|
||||
background-color: var(--pst-color-on-background);
|
||||
border: 1px solid var(--pst-color-border);
|
||||
border-radius: 4px;
|
||||
color: var(--pst-color-text-base);
|
||||
}
|
||||
|
||||
#csat-textarea::placeholder {
|
||||
color: var(--pst-color-text-base);
|
||||
}
|
||||
|
||||
.csat-icon > path {
|
||||
fill: var(--pst-color-text-base);
|
||||
}
|
||||
@@ -0,0 +1,451 @@
|
||||
/* Override default colors used in the Sphinx theme. See
|
||||
* https://pydata-sphinx-theme.readthedocs.io/en/stable/user_guide/styling.html#css-theme-variables
|
||||
* for more information. `important!` is needed below to override
|
||||
* dark/light theme specific values, which normally take precedence over the PST defaults.
|
||||
* */
|
||||
html {
|
||||
--anyscale-blue: #0066FF;
|
||||
--ray-blue: #02A0CF; /* Ray blue color - use this for all ray branding */
|
||||
--pst-color-primary: var(--ray-blue) !important;
|
||||
--pst-color-inline-code-links: var(--ray-blue) !important;
|
||||
|
||||
/* Transparent highlight color; default yellow is hard on the eyes */
|
||||
--pst-color-target: #ffffff00 !important;
|
||||
--color-diff-delete-bg: rgba(212, 118, 22, 0.3);
|
||||
--color-diff-insert-bg: rgba(56, 139, 253, 0.3);
|
||||
--color-diff-nochange-bg: rgba(0, 0, 0, 0);
|
||||
|
||||
--pst-font-family-base: 'Inter', sans-serif;
|
||||
--stata-dark-background: #232629;
|
||||
}
|
||||
|
||||
html[data-theme='dark'] {
|
||||
--pst-color-background: #161a1d;
|
||||
--pst-color-on-background: #1d2125;
|
||||
--pst-color-text-base: #f1f2f4;
|
||||
--pst-color-text-muted: #b3b9c4;
|
||||
--pst-color-border: #2c333a;
|
||||
--bs-body-color: #f1f2f4;
|
||||
--heading-color: #ffffff;
|
||||
--base-pygments-code-color: #cccccc;
|
||||
--pst-color-link-hover: #cce0ff;
|
||||
--anyscale-border-color: #f1f2f4;
|
||||
}
|
||||
|
||||
html[data-theme='light'] {
|
||||
--pst-color-background: #ffffff;
|
||||
--pst-color-on-background: #ffffff;
|
||||
--pst-color-text-base: #22272b;
|
||||
--pst-color-text-muted: #454f59;
|
||||
--pst-color-border: #dcdfe4;
|
||||
--heading-color: #161a1d;
|
||||
--base-pygments-code-color: #cccccc;
|
||||
--pst-color-link-hover: #09326c;
|
||||
--anyscale-border-color: #161a1d;
|
||||
}
|
||||
|
||||
nav.bd-links li > a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration-thickness: unset;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
color: var(--heading-color);
|
||||
}
|
||||
|
||||
/* Gradient ellipse background */
|
||||
.bd-sidebar-secondary {
|
||||
background-color: transparent;
|
||||
}
|
||||
.bd-content:after {
|
||||
/* Commenting the code below to make more modifications after 2.10 release */
|
||||
/* background: linear-gradient(
|
||||
60deg,
|
||||
rgba(0, 85, 204, 0.18) 14%,
|
||||
rgba(110, 93, 198, 0.18) 49.2%,
|
||||
rgba(174, 71, 135, 0.18) 81.54%
|
||||
); */
|
||||
background-size: 746px 746px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
border-radius: 373px;
|
||||
background-origin: 50%;
|
||||
background-attachment: scroll;
|
||||
content: '';
|
||||
transform: translate(50%, 0%);
|
||||
width: 746px;
|
||||
height: 746px;
|
||||
position: absolute;
|
||||
filter: blur(100px);
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
/* Pygments diff code cell line colors; match github colorblind theme */
|
||||
div.highlight > pre > span.gd {
|
||||
background-color: var(--color-diff-delete-bg);
|
||||
}
|
||||
div.highlight > pre > span.gi {
|
||||
background-color: var(--color-diff-insert-bg);
|
||||
}
|
||||
div.highlight > pre > span.w {
|
||||
background-color: var(--color-diff-nochange-bg);
|
||||
}
|
||||
/* Fix some pygments styles that inadvertently get overridden by PST */
|
||||
.highlight pre {
|
||||
background-color: var(--stata-dark-background);
|
||||
color: var(--base-pygments-code-color);
|
||||
}
|
||||
|
||||
/* Make the article content take up all available space */
|
||||
.bd-main .bd-content .bd-article-container {
|
||||
max-width: 100%; /* default is 60em */
|
||||
}
|
||||
.bd-page-width {
|
||||
max-width: 100%; /* default is 88rem */
|
||||
}
|
||||
|
||||
/* Hide the "Hide Search Matches" button (we aren't highlighting search terms anyway) */
|
||||
#searchbox {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Top navbar styling */
|
||||
.navbar-toplevel p {
|
||||
margin: 0;
|
||||
padding-inline-start: 0;
|
||||
}
|
||||
.ref-container > p {
|
||||
height: 100%;
|
||||
}
|
||||
div.navbar-dropdown {
|
||||
display: none;
|
||||
position: relative;
|
||||
left: -50%;
|
||||
color: var(--pst-color-text-muted);
|
||||
}
|
||||
span.navbar-link-title {
|
||||
color: var(--pst-color-text-base);
|
||||
}
|
||||
.navbar-sublevel p a.reference {
|
||||
text-decoration: none;
|
||||
color: var(--pst-color-text-muted);
|
||||
}
|
||||
.navbar-sublevel p a.reference:hover > span.navbar-link-title {
|
||||
text-decoration: underline;
|
||||
color: var(--pst-color-link-hover);
|
||||
}
|
||||
.navbar-toplevel li {
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
padding: 0em 1em;
|
||||
}
|
||||
ul.navbar-toplevel li:hover > div.navbar-dropdown {
|
||||
display: block;
|
||||
}
|
||||
ul.navbar-toplevel {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
padding-left: 0;
|
||||
}
|
||||
.navbar-content ul.navbar-sublevel {
|
||||
position: absolute;
|
||||
background: var(--pst-color-on-background);
|
||||
white-space: pre;
|
||||
padding: 0em 1em;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: baseline;
|
||||
box-shadow: 0 5px 15px 0 rgb(0 0 0 / 10%);
|
||||
}
|
||||
div.navbar-content a {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: start;
|
||||
white-space: pre;
|
||||
justify-content: center;
|
||||
/* pydata-sphinx-theme 0.14's `.navbar-nav li a { height: 100% }` was
|
||||
scoped to `ul.navbar-nav li a` in 0.17, which no longer matches our
|
||||
`<nav class="navbar-nav">`. Without height: 100% on <a>, the <a>
|
||||
shrinks to text height (~26px) inside its 64px-tall <p> parent,
|
||||
leaving the link text top-aligned in the navbar and the chevron
|
||||
(which is centered on the .ref-container) visually below the text.
|
||||
Restoring height: 100% lets justify-content: center vertically
|
||||
center the text in the full-height anchor. */
|
||||
height: 100%;
|
||||
}
|
||||
div.navbar-content {
|
||||
height: 100%;
|
||||
}
|
||||
nav.navbar-nav {
|
||||
height: 100%;
|
||||
}
|
||||
.ref-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 0.5em;
|
||||
height: 100%;
|
||||
}
|
||||
/* Highlight active nav bar link */
|
||||
li.active-link {
|
||||
font-weight: bold;
|
||||
}
|
||||
.navbar-header-items__end {
|
||||
/* Prevent the anyscale button from wrapping */
|
||||
flex-flow: nowrap !important;
|
||||
}
|
||||
.navbar {
|
||||
box-shadow: 0px 4px 10px 0px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
/* Set the first .navbar-persistent--mobile element to have auto left margin */
|
||||
.navbar-persistent--mobile {
|
||||
margin-left: auto;
|
||||
}
|
||||
/* Set any .navbar-persistent--mobile preceeded by a .navbar-persistent--mobile to have */
|
||||
/* a 1em left margin */
|
||||
.navbar-persistent--mobile ~ .navbar-persistent--mobile {
|
||||
margin-left: 1em;
|
||||
}
|
||||
/* Disable underline for hovered links in the nav bar */
|
||||
.navbar-nav li a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
/* pydata-sphinx-theme 0.17 stopped removing text-decoration on
|
||||
<a class="reference internal"> inside the top navbar (the rule it
|
||||
ships now only matches <a class="nav-link">). Re-add it for our
|
||||
reference-internal anchors. */
|
||||
.navbar-toplevel a.reference {
|
||||
text-decoration: none;
|
||||
}
|
||||
/* pydata-sphinx-theme 0.17 stopped hiding the sidebar-header-items__title
|
||||
element (Ray's navbar-links.html template emits "Site Navigation" as
|
||||
a screen-reader heading). Hide it in the header context — it still
|
||||
renders in the actual sidebar drawer where the heading is useful. */
|
||||
.navbar-header-items .sidebar-header-items__title {
|
||||
display: none;
|
||||
}
|
||||
.navbar-header-items {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
/* Ray logo */
|
||||
.navbar-brand.logo > svg {
|
||||
width: 120px;
|
||||
}
|
||||
.navbar-brand.logo > svg path#ray-text {
|
||||
fill: var(--pst-color-text-base);
|
||||
}
|
||||
|
||||
/* Anyscale branding */
|
||||
#try-anyscale-text {
|
||||
color: var(--pst-color-text-base);
|
||||
border-radius: 2px;
|
||||
white-space: nowrap;
|
||||
padding: 0px 12px;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 1em;
|
||||
border: 1px solid var(--anyscale-border-color);
|
||||
}
|
||||
#try-anyscale-href {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* Remove margin for the release header in the sidebar, otherwise it's too much space */
|
||||
#release-header {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Center the Ray release header in the sidebar */
|
||||
div.sidebar-primary-item:nth-child(1) {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* Center the search button in the sidebar */
|
||||
div.sidebar-primary-item:nth-child(2) {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* Disable the "Back to top" button that appears if you scroll down */
|
||||
button#pst-back-to-top {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.bottom-right-promo-banner {
|
||||
position: fixed;
|
||||
bottom: 100px;
|
||||
right: 20px;
|
||||
width: 270px;
|
||||
}
|
||||
|
||||
@media (max-width: 1500px) {
|
||||
.bottom-right-promo-banner {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Nav sidebar styles */
|
||||
.bd-sidebar-primary {
|
||||
width: 280px;
|
||||
padding: 2em 2em 0em 2em;
|
||||
}
|
||||
/* Make sidebar take up full primary sidebar gutter, but don't wrap content */
|
||||
#main-sidebar {
|
||||
width: 100%;
|
||||
}
|
||||
nav.bd-links li > a {
|
||||
color: var(--pst-color-text-base);
|
||||
}
|
||||
/* Sidebar checkboxes are toggled by clicking on the label; hide actual checkboxes */
|
||||
.toctree-checkbox[type='checkbox']:checked ~ ul > li.current-page:before {
|
||||
background-color: var(--ray-blue);
|
||||
border-radius: 0.5px;
|
||||
}
|
||||
.toctree-checkbox[type='checkbox']:checked ~ ul > li:before {
|
||||
content: '';
|
||||
width: 1px;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
background-color: var(--pst-color-border);
|
||||
}
|
||||
/* Highlight and bold the primary sidebar entry for the current page */
|
||||
#main-sidebar li.current-page > a {
|
||||
color: var(--ray-blue) !important;
|
||||
font-weight: 600;
|
||||
}
|
||||
/* Bold the top level primary sidebar links */
|
||||
#main-sidebar > .navbar-nav > .nav.bd-sidenav > li > a {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* Fix some spacing issues associated with competition with PST styles */
|
||||
.sidebar-content dl {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.sidebar-content ol li > p:first-child,
|
||||
ul li > p:first-child {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
|
||||
/* Set autosummary API docs to have fixed two-col format, with alternating different background
|
||||
* on rows */
|
||||
table.autosummary {
|
||||
table-layout: fixed;
|
||||
}
|
||||
table.autosummary .row-odd {
|
||||
background-color: var(--pst-color-surface);
|
||||
}
|
||||
|
||||
/* Ensure that long function names get elided and show ellipses to not overflow their bounding boxes */
|
||||
table.autosummary tr > td:first-child > p > a > code {
|
||||
max-width: 100%;
|
||||
width: fit-content;
|
||||
display: block;
|
||||
}
|
||||
table.autosummary tr > td:first-child > p > a > code > span {
|
||||
display: block;
|
||||
overflow: clip;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
/* RTD footer container makes the parent */
|
||||
/* #main-sidebar always scrollable if you don't remove negative margin. */
|
||||
/* Restrict width to 30% of the window */
|
||||
.bd-sidebar-primary div#rtd-footer-container {
|
||||
margin: unset;
|
||||
max-width: 30vw;
|
||||
}
|
||||
|
||||
.query-param-ref-wrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: 1px solid var(--pst-color-border);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.query-param-ref-wrapper p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Styles for tables in example pages */
|
||||
.table.example-table {
|
||||
table-layout: fixed;
|
||||
}
|
||||
.table.example-table th:first-child {
|
||||
width: 30%;
|
||||
}
|
||||
|
||||
/* pydata-sphinx-theme 0.14 painted the announcement banner background via
|
||||
an absolutely-positioned `::after` pseudo-element. 0.17 replaced that
|
||||
with `background-color: var(--pst-color-secondary-bg)` directly on
|
||||
`.bd-header-announcement`, so the `::after` rule is now a no-op and
|
||||
pydata's default secondary-bg paints the banner lavender. Set the
|
||||
background directly on the element to keep Ray's teal. */
|
||||
.bd-header-announcement {
|
||||
color: var(--pst-color-light);
|
||||
background-color: var(--ray-blue);
|
||||
}
|
||||
|
||||
.bd-header-announcement a {
|
||||
color: var(--pst-color-light);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* Prevent the PyData theme Version Switcher from getting too large */
|
||||
.version-switcher__menu {
|
||||
max-height: 40rem;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
/* Right align the version switcher dropdown menu to prevent it from going off screen */
|
||||
.version-switcher__menu[data-bs-popper] {
|
||||
right: 0;
|
||||
left: unset;
|
||||
}
|
||||
|
||||
/* Hide the RTD version switcher since we are using PyData theme one */
|
||||
readthedocs-flyout {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Styling the experimental Anyscale upsell CTA */
|
||||
.anyscale-cta {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
|
||||
/* Prevent text wrapping around left-aligned images on ultra-wide screens */
|
||||
@media (min-width: 1600px) {
|
||||
.bd-content .align-left,
|
||||
.bd-content .figure.align-left,
|
||||
.bd-content img.align-left {
|
||||
float: none !important;
|
||||
display: block;
|
||||
clear: both;
|
||||
margin-left: 0 !important;
|
||||
margin-right: 0 !important;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#close-banner {
|
||||
background: none;
|
||||
border: none;
|
||||
color: inherit;
|
||||
font-size: 1.2em;
|
||||
cursor: pointer;
|
||||
padding: 0 5px;
|
||||
border-radius: 3px;
|
||||
transition: background-color 0.2s ease;
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 12px;
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
html {
|
||||
--remix-icon-color: #ffffff;
|
||||
}
|
||||
|
||||
html[data-theme='dark'] {
|
||||
--example-color: color-mix(in srgb, #ffffff, transparent 90%);
|
||||
}
|
||||
|
||||
html[data-theme='light'] {
|
||||
--example-color: #ffffff;
|
||||
}
|
||||
|
||||
#examples-search-input-label {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#examples-search-icon {
|
||||
fill: var(--pst-color-text-base);
|
||||
margin: 0em 1em;
|
||||
}
|
||||
|
||||
#examples-search-input {
|
||||
width: 100%;
|
||||
color: var(--pst-color-text-base);
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
#examples-search-input:focus-visible {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
#examples-search-input::placeholder {
|
||||
color: var(--pst-color-text-muted);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
#no-matches {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#no-matches-inner-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#no-matches.hidden,
|
||||
.gallery-item.hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.examples-search-area {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 0.75em 0em;
|
||||
border: 1px solid var(--pst-color-border);
|
||||
border-radius: 4px;
|
||||
background: var(--pst-color-background);
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 70%;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.content-wrapper {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.example-tags {
|
||||
color: var(--pst-color-text-muted);
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.example-list-area {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 2em;
|
||||
}
|
||||
|
||||
@media (min-width: 960px) {
|
||||
.example-list-area {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
.example-text-area {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#dropdown-area {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 2em;
|
||||
margin: 1.5em 0em 2.5em 0em;
|
||||
}
|
||||
|
||||
.filter-dropdown {
|
||||
border: 1px solid var(--dropdown-border-color);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.dropdown-checkbox {
|
||||
display: none;
|
||||
padding: 0.5em 1.5em;
|
||||
}
|
||||
|
||||
.dropdown-label {
|
||||
user-select: none;
|
||||
border: 1px solid var(--pst-color-border);
|
||||
border-radius: 4px;
|
||||
padding: 0.5em 1em;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 1em;
|
||||
}
|
||||
|
||||
/* When the dropdown is exposed, highlight the background of the parent div label */
|
||||
.dropdown-checkbox[type='checkbox']:checked ~ .dropdown-label {
|
||||
background-color: var(--pst-color-on-background);
|
||||
}
|
||||
|
||||
.dropdown-content {
|
||||
display: none;
|
||||
position: absolute;
|
||||
background: var(--pst-color-on-background);
|
||||
padding: 0.5em 1em;
|
||||
border: 1px solid var(--pst-color-border);
|
||||
border-radius: 4px;
|
||||
flex-direction: column;
|
||||
gap: 1em;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* Show dropdown when the checkbox is clicked */
|
||||
.dropdown-checkbox[type='checkbox']:checked ~ .dropdown-content {
|
||||
display: flex !important;
|
||||
}
|
||||
|
||||
/* Checkboxes */
|
||||
.checkbox-container {
|
||||
display: block;
|
||||
position: relative;
|
||||
padding-left: 35px;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.checkbox-container input {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
cursor: pointer;
|
||||
height: 0;
|
||||
width: 0;
|
||||
}
|
||||
.checkmark {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 25px;
|
||||
width: 25px;
|
||||
/* Color of an empty checkbox square */
|
||||
background-color: var(--pst-color-surface);
|
||||
}
|
||||
.checkbox-container input:checked ~ .checkmark {
|
||||
/* Color of checkbox when checked */
|
||||
background-color: var(--pst-color-primary-highlight);
|
||||
}
|
||||
.checkbox-container input:checked ~ .checkmark:after {
|
||||
display: block;
|
||||
}
|
||||
.checkmark:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
display: none;
|
||||
}
|
||||
.checkbox-container .checkmark:after {
|
||||
left: 10px;
|
||||
top: 6px;
|
||||
width: 6px;
|
||||
height: 12px;
|
||||
border: solid var(--pst-color-border);
|
||||
border-width: 0 3px 3px 0;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.example.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.example-icon-area {
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.example-icon {
|
||||
border-radius: 10px !important; /* Competes against pydata-sphinx-theme img styles */
|
||||
background-color: transparent !important; /* Competes against pydata-sphinx-theme img styles */
|
||||
min-width: 75px;
|
||||
min-height: 75px;
|
||||
}
|
||||
|
||||
.remix-icon {
|
||||
position: absolute;
|
||||
font-size: 28px;
|
||||
color: var(--remix-icon-color);
|
||||
}
|
||||
|
||||
.example-link {
|
||||
color: var(--pst-color-text-base) !important;
|
||||
text-decoration: none;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 1em;
|
||||
align-items: center;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
.example {
|
||||
border-radius: 4px;
|
||||
background-color: color-mix(
|
||||
in srgb,
|
||||
var(--pst-color-on-background) 70%,
|
||||
transparent
|
||||
);
|
||||
box-shadow: 0px 4px 15px color-mix(in srgb, black 5%, transparent);
|
||||
}
|
||||
|
||||
.example-other-keywords {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.community-text {
|
||||
color: var(--pst-color-text-muted);
|
||||
}
|
||||
|
||||
.community-emojis {
|
||||
padding-left: 0.5em;
|
||||
}
|
||||
@@ -0,0 +1,292 @@
|
||||
html[data-theme='dark'] {
|
||||
--community-box-color: var(--pst-color-surface);
|
||||
}
|
||||
html[data-theme='light'] {
|
||||
--community-box-color: var(--pst-color-background);
|
||||
}
|
||||
|
||||
.main-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0em 5em;
|
||||
}
|
||||
|
||||
.centered-heading {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding-bottom: 2em;
|
||||
}
|
||||
|
||||
.centered-heading > p {
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.clicky-tab-side-by-side {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 1em;
|
||||
}
|
||||
|
||||
/* Area which contains all the tab selector labels */
|
||||
.tab-selector {
|
||||
width: 30%;
|
||||
min-width: 30%;
|
||||
}
|
||||
|
||||
/* Area which contains all the tab panes */
|
||||
.tab-area {
|
||||
flex-grow: 1;
|
||||
overflow-x: auto;
|
||||
box-shadow: 0px 6px 30px 5px var(--pst-color-shadow);
|
||||
}
|
||||
|
||||
.tab-pane {
|
||||
border-radius: 4px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.tab-pane-links {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 1em;
|
||||
padding: 1em;
|
||||
background: var(--pst-color-surface);
|
||||
border-radius: 0px 0px 4px 4px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.tab-pane-links > a:not(:first-child) {
|
||||
border-left: 1px solid var(--pst-color-border);
|
||||
padding-left: 1em;
|
||||
}
|
||||
.tab-pane pre {
|
||||
margin: 0;
|
||||
padding: 0.5em 1em;
|
||||
overflow-y: auto;
|
||||
animation: fadeEffect 1s; /* Fading effect takes 1 second */
|
||||
border: none;
|
||||
}
|
||||
|
||||
.tab-pane .highlight {
|
||||
border-radius: 4px 4px 0px 0px;
|
||||
height: 14em;
|
||||
}
|
||||
|
||||
/* Go from zero to full opacity */
|
||||
@keyframes fadeEffect {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.header-button-icon {
|
||||
fill: var(--pst-color-text-base);
|
||||
width: 17px;
|
||||
height: 20px;
|
||||
min-width: 17px;
|
||||
min-height: 20px;
|
||||
}
|
||||
|
||||
.card-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 1em;
|
||||
}
|
||||
|
||||
.link-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5em;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.link-card-icon-label {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 0.5em;
|
||||
}
|
||||
|
||||
.link-card h4 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.card-text-area {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-left: 2.5em;
|
||||
}
|
||||
|
||||
.card-icon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.community-box {
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 1em;
|
||||
box-shadow: 0px 4px 10px 0px var(--pst-color-shadow);
|
||||
color: var(--pst-color-text-base) !important;
|
||||
align-items: center;
|
||||
background: var(--community-box-color);
|
||||
padding-left: 2em;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Make remix icons larger */
|
||||
.community-box i {
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
.community-box p {
|
||||
margin-top: 1rem;
|
||||
text-wrap: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.community-box > img {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.nav-pills {
|
||||
background-color: var(--pst-color-surface);
|
||||
padding: 1em;
|
||||
border-radius: 4px;
|
||||
justify-content: center;
|
||||
width: 30%;
|
||||
gap: 0.5em;
|
||||
}
|
||||
|
||||
.nav-pills .nav-link.active {
|
||||
background-color: var(--pst-color-background) !important;
|
||||
box-shadow: 0px 3px 14px 2px var(--pst-color-shadow);
|
||||
border-radius: 4px;
|
||||
color: var(--pst-color-text-base);
|
||||
}
|
||||
|
||||
#v-pills-tab > .nav-link:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#v-pills-tab > a {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#v-pills-tab > .nav-link {
|
||||
color: var(--pst-color-text-base);
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#v-pills-tabContent .row {
|
||||
background-color: var(--pst-color-background);
|
||||
}
|
||||
|
||||
#v-pills-tabContent {
|
||||
box-shadow: 0px 6px 30px 5px var(--pst-color-shadow);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.links-grid-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.links-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
gap: 2em;
|
||||
}
|
||||
|
||||
.links-grid > h4 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.bd-article {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
padding: 0em 5em;
|
||||
}
|
||||
|
||||
.heading-buttons {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
gap: 2em;
|
||||
}
|
||||
|
||||
.heading-buttons > a {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding: 1em 1em 1em 2em;
|
||||
border-radius: 4px;
|
||||
background: var(--community-box-color);
|
||||
color: var(--pst-color-text-base);
|
||||
font-weight: 500;
|
||||
text-wrap: nowrap;
|
||||
box-shadow: 0px 4px 10px 0px var(--pst-color-shadow);
|
||||
}
|
||||
|
||||
.header-button {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 1em;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.header-button i {
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.card-icon svg {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.card-icon path {
|
||||
stroke: var(--pst-color-link);
|
||||
}
|
||||
|
||||
#link-card-icon-filled {
|
||||
fill: var(--pst-color-link);
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin-bottom: 1em;
|
||||
margin-top: 4em;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.links-grid b {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
.sd-card.body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.sd-card-body > figure {
|
||||
height: 10em;
|
||||
}
|
||||
.card-figure {
|
||||
object-fit: contain;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#train-logo > #train-logo-icon > path, #train-logo > #train-logo-icon > circle {
|
||||
stroke: var(--ray-blue);
|
||||
stroke-width: 10;
|
||||
fill: transparent;
|
||||
}
|
||||
|
||||
#train-logo > #train-logo-text {
|
||||
stroke: var(--pst-color-text-base);
|
||||
fill: var(--pst-color-text-base);
|
||||
}
|
||||
|
||||
#train-logo {
|
||||
margin: 3em 0em;
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* termynal.js
|
||||
*
|
||||
* @author Ines Montani <ines@ines.io>
|
||||
* @version 0.0.1
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
:root {
|
||||
--color-bg: #252a33;
|
||||
--color-text: #eee;
|
||||
--color-text-subtle: #a2a2a2;
|
||||
}
|
||||
|
||||
[data-termynal] {
|
||||
width: auto;
|
||||
max-width: 100%;
|
||||
background: var(--color-bg);
|
||||
color: var(--color-text);
|
||||
font-size: 18px;
|
||||
font-family: 'Fira Mono', Consolas, Menlo, Monaco, 'Courier New', Courier, monospace;
|
||||
border-radius: 4px;
|
||||
padding: 75px 45px 35px;
|
||||
position: relative;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
[data-termynal]:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
left: 15px;
|
||||
display: inline-block;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
border-radius: 50%;
|
||||
/* A little hack to display the window buttons in one pseudo element. */
|
||||
background: #d9515d;
|
||||
-webkit-box-shadow: 25px 0 0 #f4c025, 50px 0 0 #3ec930;
|
||||
box-shadow: 25px 0 0 #f4c025, 50px 0 0 #3ec930;
|
||||
}
|
||||
|
||||
[data-termynal]:after {
|
||||
content: 'bash';
|
||||
position: absolute;
|
||||
color: var(--color-text-subtle);
|
||||
top: 5px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
[data-ty] {
|
||||
display: block;
|
||||
line-height: 2;
|
||||
}
|
||||
|
||||
[data-ty]:before {
|
||||
/* Set up defaults and ensure empty lines are displayed. */
|
||||
content: '';
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
[data-ty="input"]:before,
|
||||
[data-ty-prompt]:before {
|
||||
margin-right: 0.75em;
|
||||
color: var(--color-text-subtle);
|
||||
}
|
||||
|
||||
[data-ty="input"]:before {
|
||||
content: '$';
|
||||
}
|
||||
|
||||
[data-ty][data-ty-prompt]:before {
|
||||
content: attr(data-ty-prompt);
|
||||
}
|
||||
|
||||
[data-ty-cursor]:after {
|
||||
content: attr(data-ty-cursor);
|
||||
font-family: monospace;
|
||||
margin-left: 0.5em;
|
||||
-webkit-animation: blink 1s infinite;
|
||||
animation: blink 1s infinite;
|
||||
}
|
||||
|
||||
a[data-terminal-control] {
|
||||
text-align: right;
|
||||
display: block;
|
||||
color: #aebbff;
|
||||
}
|
||||
|
||||
|
||||
/* Cursor animation */
|
||||
|
||||
@-webkit-keyframes blink {
|
||||
50% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes blink {
|
||||
50% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
.example-gallery-link {
|
||||
padding: 1em 2em 1em 2em;
|
||||
text-decoration: none !important;
|
||||
color: var(--pst-color-text-base);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
svg.star-icon path.star-icon-path {
|
||||
fill: var(--pst-color-text-base);
|
||||
}
|
||||
|
||||
svg.star-icon {
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
After Width: | Height: | Size: 15 KiB |
@@ -0,0 +1,6 @@
|
||||
/* CSS for binder integration */
|
||||
|
||||
div.binder-badge {
|
||||
margin: 1em auto;
|
||||
vertical-align: middle;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/* Pandas dataframe css */
|
||||
/* Taken from: https://github.com/spatialaudio/nbsphinx/blob/fb3ba670fc1ba5f54d4c487573dbc1b4ecf7e9ff/src/nbsphinx.py#L587-L619 */
|
||||
|
||||
table.dataframe {
|
||||
border: none !important;
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
border-color: transparent;
|
||||
color: black;
|
||||
font-size: 12px;
|
||||
table-layout: fixed;
|
||||
}
|
||||
table.dataframe thead {
|
||||
border-bottom: 1px solid black;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
table.dataframe tr,
|
||||
table.dataframe th,
|
||||
table.dataframe td {
|
||||
text-align: right;
|
||||
vertical-align: middle;
|
||||
padding: 0.5em 0.5em;
|
||||
line-height: normal;
|
||||
white-space: normal;
|
||||
max-width: none;
|
||||
border: none;
|
||||
}
|
||||
table.dataframe th {
|
||||
font-weight: bold;
|
||||
}
|
||||
table.dataframe tbody tr:nth-child(odd) {
|
||||
background: #f5f5f5;
|
||||
}
|
||||
table.dataframe tbody tr:hover {
|
||||
background: rgba(66, 165, 245, 0.2);
|
||||
}
|
||||
|
After Width: | Height: | Size: 732 B |
|
After Width: | Height: | Size: 425 B |
|
After Width: | Height: | Size: 218 B |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 481 B |
|
After Width: | Height: | Size: 147 KiB |
|
After Width: | Height: | Size: 184 KiB |
|
After Width: | Height: | Size: 189 KiB |
|
After Width: | Height: | Size: 156 KiB |
|
After Width: | Height: | Size: 254 KiB |
|
After Width: | Height: | Size: 263 B |
|
After Width: | Height: | Size: 931 B |
|
After Width: | Height: | Size: 207 B |
|
After Width: | Height: | Size: 3.4 KiB |
@@ -0,0 +1,5 @@
|
||||
<svg width="400" height="201" viewBox="0 0 400 201" xmlns="http://www.w3.org/2000/svg">
|
||||
<path id="ray-text" d="M325.949 134.356V109.785L302.442 66.6406H314.244L330.495 97.3062H331.946L348.198 66.6406H360L336.493 109.785V134.356H325.949ZM253.043 134.364L272.391 66.648H290.771L310.021 134.364H299.283L294.834 118.402H268.328L263.878 134.364H253.043ZM270.94 108.728H292.222L282.354 73.1294H280.807L270.94 108.728ZM198.887 134.364V66.648H227.327C231.519 66.648 235.195 67.3896 238.355 68.8729C241.58 70.2918 244.063 72.3555 245.804 75.0641C247.61 77.7727 248.513 80.9973 248.513 84.7378V85.8019C248.513 90.0583 247.481 93.4763 245.417 96.0559C243.418 98.5711 240.967 100.345 238.065 101.376V102.924C240.516 103.053 242.483 103.892 243.966 105.439C245.449 106.923 246.191 109.083 246.191 111.921V134.364H235.647V113.372C235.647 111.631 235.195 110.244 234.292 109.212C233.39 108.18 231.938 107.664 229.939 107.664H209.334V134.364H198.887ZM209.334 98.1842H226.166C229.907 98.1842 232.809 97.249 234.873 95.3788C236.937 93.4441 237.968 90.8322 237.968 87.5431V86.7692C237.968 83.4802 236.937 80.9005 234.873 79.0303C232.874 77.0956 229.971 76.1282 226.166 76.1282H209.334V98.1842Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M143.63 101.311L98.3087 146.632L94.9903 143.313L140.311 97.9925L143.63 101.311ZM141.953 102.334L51.4454 102.334V97.6409L141.953 97.6409V102.334ZM94.992 55.9863L140.313 101.307L143.631 97.9886L98.3105 52.6679L94.992 55.9863Z" fill="#02A0CF"/>
|
||||
<path d="M40 88.3163H62.6604V110.977H40V88.3163ZM85.3207 88.3163H107.981V110.977H85.3207V88.3163ZM85.3207 43H107.981V65.6604H85.3207V43ZM85.3207 133.645H107.981V156.306H85.3207V133.645ZM130.641 88.3163H153.301V110.977H130.641V88.3163Z" fill="#02A0CF"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 279 B |
@@ -0,0 +1,20 @@
|
||||
<svg width="157" height="42" viewBox="0 0 157 42" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="157" height="41.9994" fill="#0066FF"/>
|
||||
<path d="M17.204 25.5V15.896H22.258C22.9113 15.896 23.4527 16.0173 23.882 16.26C24.3207 16.4933 24.6473 16.8247 24.862 17.254C25.0767 17.674 25.184 18.1593 25.184 18.71C25.184 19.3727 25.0347 19.942 24.736 20.418C24.4373 20.894 24.0267 21.2347 23.504 21.44L25.52 25.5H24.064L22.188 21.678H18.534V25.5H17.204ZM18.534 20.544H22.132C22.664 20.544 23.0793 20.3807 23.378 20.054C23.686 19.7273 23.84 19.2793 23.84 18.71C23.84 18.3553 23.7747 18.0567 23.644 17.814C23.5133 17.5713 23.322 17.3847 23.07 17.254C22.818 17.114 22.5053 17.044 22.132 17.044H18.534V20.544ZM29.2832 25.668C28.5738 25.668 28.0045 25.486 27.5752 25.122C27.1458 24.758 26.9312 24.1233 26.9312 23.218V18.136H28.1632V23.05C28.1632 23.358 28.2005 23.61 28.2752 23.806C28.3498 24.002 28.4572 24.156 28.5972 24.268C28.7372 24.38 28.9005 24.4593 29.0872 24.506C29.2832 24.5527 29.4932 24.576 29.7172 24.576C30.0718 24.576 30.3985 24.492 30.6972 24.324C30.9958 24.156 31.2385 23.9133 31.4252 23.596C31.6212 23.2693 31.7192 22.8913 31.7192 22.462V18.136H32.9512V25.5H31.9572L31.8452 24.394H31.7472C31.5512 24.6927 31.3272 24.9353 31.0752 25.122C30.8325 25.3087 30.5572 25.444 30.2492 25.528C29.9505 25.6213 29.6285 25.668 29.2832 25.668ZM34.8625 25.5V18.136H35.8565L35.9685 19.242H36.0665C36.2625 18.9433 36.4818 18.7007 36.7245 18.514C36.9765 18.3273 37.2518 18.192 37.5505 18.108C37.8585 18.0147 38.1852 17.968 38.5305 17.968C38.9972 17.968 39.4032 18.0473 39.7485 18.206C40.1032 18.3647 40.3785 18.6213 40.5745 18.976C40.7798 19.3307 40.8825 19.8113 40.8825 20.418V25.5H39.6505V20.586C39.6505 20.278 39.6085 20.026 39.5245 19.83C39.4498 19.634 39.3425 19.48 39.2025 19.368C39.0718 19.256 38.9085 19.1767 38.7125 19.13C38.5258 19.0833 38.3158 19.06 38.0825 19.06C37.7372 19.06 37.4105 19.144 37.1025 19.312C36.7945 19.48 36.5472 19.7227 36.3605 20.04C36.1832 20.3573 36.0945 20.7353 36.0945 21.174V25.5H34.8625ZM48.7009 25.668C47.9543 25.668 47.3243 25.5327 46.8109 25.262C46.3069 24.982 45.9196 24.5573 45.6489 23.988C45.3876 23.4187 45.2569 22.6953 45.2569 21.818C45.2569 20.9313 45.3876 20.208 45.6489 19.648C45.9196 19.0787 46.3069 18.6587 46.8109 18.388C47.3243 18.108 47.9543 17.968 48.7009 17.968C49.4476 17.968 50.0729 18.108 50.5769 18.388C51.0903 18.6587 51.4776 19.0787 51.7389 19.648C52.0003 20.208 52.1309 20.9313 52.1309 21.818C52.1309 22.6953 52.0003 23.4187 51.7389 23.988C51.4776 24.5573 51.0903 24.982 50.5769 25.262C50.0729 25.5327 49.4476 25.668 48.7009 25.668ZM48.7009 24.632C49.1769 24.632 49.5736 24.5387 49.8909 24.352C50.2083 24.1653 50.4463 23.876 50.6049 23.484C50.7729 23.0827 50.8569 22.5787 50.8569 21.972V21.664C50.8569 21.048 50.7729 20.544 50.6049 20.152C50.4463 19.76 50.2083 19.4707 49.8909 19.284C49.5736 19.0973 49.1769 19.004 48.7009 19.004C48.2249 19.004 47.8236 19.0973 47.4969 19.284C47.1796 19.4707 46.9416 19.76 46.7829 20.152C46.6243 20.544 46.5449 21.048 46.5449 21.664V21.972C46.5449 22.5787 46.6243 23.0827 46.7829 23.484C46.9416 23.876 47.1796 24.1653 47.4969 24.352C47.8236 24.5387 48.2249 24.632 48.7009 24.632ZM53.6613 25.5V18.136H54.6553L54.7673 19.242H54.8653C55.0613 18.9433 55.2806 18.7007 55.5233 18.514C55.7753 18.3273 56.0506 18.192 56.3493 18.108C56.6573 18.0147 56.984 17.968 57.3293 17.968C57.796 17.968 58.202 18.0473 58.5473 18.206C58.902 18.3647 59.1773 18.6213 59.3733 18.976C59.5786 19.3307 59.6813 19.8113 59.6813 20.418V25.5H58.4493V20.586C58.4493 20.278 58.4073 20.026 58.3233 19.83C58.2486 19.634 58.1413 19.48 58.0013 19.368C57.8706 19.256 57.7073 19.1767 57.5113 19.13C57.3246 19.0833 57.1146 19.06 56.8813 19.06C56.536 19.06 56.2093 19.144 55.9013 19.312C55.5933 19.48 55.346 19.7227 55.1593 20.04C54.982 20.3573 54.8933 20.7353 54.8933 21.174V25.5H53.6613Z" fill="white"/>
|
||||
<path d="M88.9463 25.4877L92.4723 16.4961H94.3464L97.885 25.4877H96.3122L95.5128 23.4033H91.2529L90.4535 25.4877H88.9463ZM91.725 22.1578H95.028L94.019 19.523C93.993 19.4448 93.9534 19.3354 93.9012 19.1957C93.8491 19.056 93.7944 18.9028 93.7371 18.7371C93.6799 18.5713 93.6235 18.403 93.5671 18.2321C93.5099 18.0613 93.4603 17.9065 93.4165 17.7668H93.3382C93.2861 17.9326 93.2204 18.1295 93.1413 18.3567C93.0631 18.5839 92.9865 18.8027 92.9116 19.0122C92.8375 19.2218 92.7744 19.3926 92.7214 19.523L91.725 22.1578Z" fill="white"/>
|
||||
<path d="M98.5137 25.4903V18.5957H99.6413L99.7591 19.5786H99.8509C100.017 19.3253 100.214 19.1158 100.441 18.9491C100.668 18.7834 100.919 18.6563 101.195 18.5688C101.47 18.4813 101.774 18.4375 102.105 18.4375C102.542 18.4375 102.927 18.5141 103.259 18.6672C103.591 18.8204 103.851 19.067 104.039 19.4078C104.227 19.7486 104.321 20.2072 104.321 20.7845V25.4903H102.958V20.994C102.958 20.7323 102.925 20.5135 102.859 20.3385C102.794 20.1643 102.699 20.0238 102.577 19.9194C102.455 19.8142 102.311 19.7402 102.145 19.6964C101.979 19.6527 101.795 19.6308 101.595 19.6308C101.28 19.6308 100.994 19.7074 100.736 19.8605C100.479 20.0137 100.271 20.2257 100.113 20.4959C99.9561 20.7668 99.8778 21.0858 99.8778 21.4527V25.4894H98.5145L98.5137 25.4903Z" fill="white"/>
|
||||
<path d="M114.649 25.6473C114.168 25.6473 113.744 25.5951 113.377 25.4899C113.011 25.3847 112.704 25.2408 112.46 25.0574C112.215 24.8739 112.029 24.6534 111.903 24.3959C111.776 24.1384 111.713 23.8523 111.713 23.5376C111.713 23.4938 111.715 23.4543 111.72 23.4198C111.724 23.3853 111.726 23.3541 111.726 23.328H113.076V23.4719C113.076 23.7429 113.15 23.9592 113.299 24.1207C113.447 24.2823 113.647 24.3959 113.896 24.4616C114.145 24.5272 114.418 24.56 114.715 24.56C114.977 24.56 115.22 24.5272 115.443 24.4616C115.666 24.3959 115.849 24.2975 115.993 24.167C116.137 24.0358 116.209 23.87 116.209 23.6689C116.209 23.4071 116.117 23.206 115.934 23.0663C115.751 22.9266 115.51 22.8156 115.213 22.7322C114.916 22.6489 114.605 22.5597 114.282 22.4638C113.993 22.3855 113.707 22.2997 113.424 22.208C113.139 22.1163 112.884 21.9959 112.657 21.8478C112.43 21.6997 112.246 21.5112 112.107 21.284C111.967 21.0568 111.897 20.7732 111.897 20.4324C111.897 20.1092 111.967 19.8248 112.107 19.5808C112.246 19.3359 112.441 19.1305 112.69 18.9648C112.939 18.799 113.236 18.6719 113.581 18.5844C113.926 18.4969 114.304 18.4531 114.715 18.4531C115.125 18.4531 115.523 18.4994 115.855 18.5911C116.187 18.6829 116.468 18.8116 116.701 18.9774C116.932 19.1432 117.109 19.3426 117.232 19.574C117.354 19.8054 117.415 20.052 117.415 20.3146C117.415 20.3667 117.413 20.4214 117.408 20.4787C117.404 20.5359 117.402 20.5729 117.402 20.5897H116.064V20.4719C116.064 20.2977 116.016 20.1395 115.921 19.9998C115.825 19.8601 115.673 19.7465 115.469 19.659C115.263 19.5715 114.991 19.5277 114.65 19.5277C114.423 19.5277 114.222 19.5471 114.046 19.5866C113.871 19.6262 113.728 19.6809 113.614 19.7507C113.5 19.8206 113.415 19.9039 113.358 19.9998C113.301 20.0958 113.273 20.2052 113.273 20.3272C113.273 20.5283 113.345 20.6831 113.489 20.7925C113.633 20.9019 113.823 20.9937 114.06 21.0677C114.296 21.1418 114.549 21.2226 114.82 21.3101C115.135 21.3976 115.454 21.4868 115.777 21.5785C116.1 21.6702 116.399 21.7864 116.675 21.9261C116.95 22.0658 117.173 22.2585 117.343 22.5025C117.514 22.7474 117.599 23.0747 117.599 23.4854C117.599 23.8616 117.525 24.1889 117.376 24.4683C117.227 24.7485 117.02 24.9732 116.753 25.1432C116.486 25.3132 116.174 25.4402 115.815 25.5236C115.457 25.6069 115.068 25.6481 114.649 25.6481V25.6473Z" fill="white"/>
|
||||
<path d="M121.374 25.6498C120.684 25.6498 120.107 25.5211 119.644 25.2636C119.181 25.0061 118.834 24.6106 118.602 24.0771C118.371 23.5444 118.255 22.8669 118.255 22.0456C118.255 21.2243 118.373 20.5494 118.609 20.0209C118.845 19.4925 119.197 19.0969 119.664 18.8344C120.132 18.5727 120.706 18.4414 121.388 18.4414C121.86 18.4414 122.271 18.5003 122.62 18.6181C122.969 18.7359 123.266 18.911 123.511 19.1424C123.756 19.3738 123.937 19.6599 124.055 20.0007C124.173 20.3416 124.231 20.7303 124.231 21.1671H122.856C122.856 20.8002 122.803 20.4989 122.698 20.2625C122.593 20.0268 122.431 19.8493 122.213 19.7315C121.995 19.6136 121.711 19.5547 121.362 19.5547C120.995 19.5547 120.684 19.6397 120.431 19.8106C120.178 19.9805 119.985 20.2389 119.855 20.5839C119.723 20.9289 119.658 21.3817 119.658 21.9404V22.1634C119.658 22.697 119.721 23.1396 119.848 23.4939C119.974 23.8473 120.167 24.1099 120.424 24.2799C120.682 24.4507 121.012 24.5357 121.414 24.5357C121.763 24.5357 122.045 24.4726 122.26 24.3455C122.473 24.2184 122.635 24.035 122.744 23.7951C122.854 23.5553 122.909 23.2641 122.909 22.9233H124.232C124.232 23.334 124.173 23.7059 124.056 24.0375C123.938 24.3699 123.759 24.656 123.518 24.8958C123.277 25.1365 122.978 25.3217 122.62 25.4529C122.261 25.5842 121.847 25.6498 121.374 25.6498Z" fill="white"/>
|
||||
<path d="M132.052 25.4877V16.4961H133.415V25.4877H132.052Z" fill="white"/>
|
||||
<path d="M137.772 25.6498C137.064 25.6498 136.471 25.5211 135.995 25.2636C135.519 25.0061 135.159 24.6106 134.914 24.0771C134.669 23.5444 134.547 22.8669 134.547 22.0456C134.547 21.2243 134.669 20.5359 134.914 20.0075C135.159 19.479 135.521 19.086 136.002 18.8277C136.482 18.5702 137.081 18.4414 137.798 18.4414C138.453 18.4414 139.001 18.566 139.443 18.815C139.884 19.0641 140.219 19.442 140.446 19.9486C140.673 20.4552 140.787 21.093 140.787 21.8622V22.3864H135.95C135.967 22.8762 136.041 23.2843 136.173 23.6117C136.304 23.939 136.503 24.1797 136.769 24.3329C137.036 24.486 137.374 24.5626 137.785 24.5626C138.038 24.5626 138.266 24.5298 138.467 24.4641C138.668 24.3985 138.838 24.3026 138.978 24.1755C139.117 24.0493 139.227 23.8961 139.305 23.7169C139.383 23.5376 139.423 23.3348 139.423 23.1076H140.76C140.76 23.5183 140.69 23.881 140.55 24.1957C140.411 24.5104 140.207 24.7747 139.941 24.9884C139.674 25.203 139.358 25.3663 138.991 25.4799C138.624 25.5935 138.218 25.6507 137.772 25.6507V25.6498ZM135.976 21.3892H139.358C139.358 21.0484 139.321 20.7623 139.247 20.5309C139.173 20.2995 139.065 20.1093 138.925 19.9603C138.786 19.8122 138.619 19.7045 138.427 19.6389C138.235 19.5732 138.017 19.5404 137.772 19.5404C137.405 19.5404 137.092 19.6061 136.834 19.7373C136.577 19.8686 136.377 20.0714 136.238 20.3466C136.098 20.6218 136.01 20.9693 135.976 21.3884V21.3892Z" fill="white"/>
|
||||
<path d="M130.344 19.4212C130.142 19.1065 129.843 18.8625 129.445 18.6933C129.047 18.5225 128.551 18.4375 127.957 18.4375C127.405 18.4375 126.92 18.5124 126.5 18.6605C126.08 18.8086 125.754 19.0257 125.522 19.3093C125.291 19.5946 125.175 19.9413 125.175 20.3528V20.511C125.175 20.5548 125.179 20.5985 125.187 20.6414H126.499V20.4454C126.499 20.288 126.54 20.1424 126.624 20.0052C126.707 19.8706 126.851 19.7562 127.056 19.6644C127.262 19.5727 127.548 19.5264 127.915 19.5264C128.282 19.5264 128.564 19.5744 128.761 19.6703C128.958 19.7663 129.094 19.9017 129.168 20.0768C129.242 20.2518 129.28 20.4529 129.28 20.6801V21.3626C128.632 21.3626 128.035 21.398 127.489 21.4686C126.942 21.5377 126.472 21.6605 126.078 21.8355C125.685 22.0106 125.378 22.2513 125.16 22.5559C124.941 22.8622 124.832 23.2518 124.832 23.7239C124.832 24.1262 124.902 24.4518 125.042 24.7018C125.181 24.9508 125.363 25.1452 125.586 25.2849C125.809 25.4255 126.047 25.5222 126.301 25.5744C126.554 25.6266 126.79 25.6527 127.009 25.6527C127.368 25.6527 127.692 25.6114 127.98 25.529C128.269 25.4457 128.525 25.327 128.748 25.1747C128.97 25.0224 129.161 24.8448 129.318 24.6437V25.4962H130.644V20.5632C130.644 20.1172 130.543 19.7368 130.342 19.4221L130.344 19.4212ZM129.281 22.7932C129.281 23.0465 129.233 23.2804 129.137 23.495C129.041 23.7096 128.909 23.8931 128.743 24.0462C128.578 24.2002 128.378 24.3172 128.147 24.4005C127.915 24.4838 127.664 24.525 127.393 24.525C127.157 24.525 126.951 24.4897 126.776 24.419C126.601 24.35 126.47 24.2473 126.382 24.1119C126.295 23.9764 126.251 23.8072 126.251 23.6069C126.251 23.2737 126.377 23.0145 126.631 22.8252C126.885 22.6375 127.24 22.5088 127.694 22.4389C128.149 22.3682 128.678 22.3346 129.282 22.3346V22.794L129.281 22.7932Z" fill="white"/>
|
||||
<path d="M105.409 26.7656V28.0405H106.784L107.226 26.7656H105.409Z" fill="white"/>
|
||||
<path d="M108.939 25.7197L111.42 18.5938H110.029L108.304 24.0645L108.229 23.8709L106.316 18.5938H104.839L107.581 25.7416L107.227 26.7657H108.577L108.939 25.7197Z" fill="white"/>
|
||||
<path d="M108.578 26.7656H107.228L106.786 28.0414H107.66C107.945 28.0414 108.199 27.8604 108.292 27.5912L108.579 26.7665L108.578 26.7656Z" fill="white"/>
|
||||
<path d="M79.7498 21.2812L77.3145 25.4998H82.2189C82.399 25.4998 82.5656 25.4038 82.6565 25.2473L84.9463 21.2812H79.7498Z" fill="white"/>
|
||||
<path d="M84.9463 20.7185L82.6565 16.7525C82.5665 16.5959 82.3998 16.5 82.2189 16.5H77.3145L79.7498 20.7185H84.9463Z" fill="white"/>
|
||||
<path d="M72.4434 16.4996H77.3142L74.8619 12.2525C74.7719 12.0959 74.6053 12 74.4243 12H69.8447L72.4425 16.4996H72.4434Z" fill="white"/>
|
||||
<path d="M69.3573 12.2812L67.0675 16.2473C66.9775 16.4038 66.9775 16.5957 67.0675 16.7522L69.5198 20.9994L71.9552 16.7808L69.3573 12.2812Z" fill="white"/>
|
||||
<path d="M71.956 25.2185L69.5206 21L67.0675 25.248C66.9775 25.4045 66.9775 25.5964 67.0675 25.7529L69.3573 29.719L71.9552 25.2194L71.956 25.2185Z" fill="white"/>
|
||||
<path d="M69.8447 29.9996H74.4243C74.6044 29.9996 74.7711 29.9037 74.8619 29.7471L77.3142 25.5H72.4434L69.8456 29.9996H69.8447Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 490 B |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 394 B |
@@ -0,0 +1,190 @@
|
||||
// Create chat-widget div
|
||||
var chatWidgetDiv = document.createElement('div');
|
||||
chatWidgetDiv.className = 'chat-widget';
|
||||
chatWidgetDiv.innerHTML = `
|
||||
<button id="openChatBtn">Ask AI</button>
|
||||
`;
|
||||
document.body.appendChild(chatWidgetDiv);
|
||||
|
||||
// Create chat-popup div
|
||||
const date = new Date();
|
||||
var chatPopupDiv = document.createElement('div');
|
||||
chatPopupDiv.className = 'chat-popup';
|
||||
chatPopupDiv.id = 'chatPopup';
|
||||
chatPopupDiv.innerHTML = `
|
||||
<div class="chatHeader">
|
||||
<div class="header-wrapper">
|
||||
<h3 class="assistant-title">Ray Docs AI - Ask a question</h3>
|
||||
</div>
|
||||
<button id="closeChatBtn" class="btn">
|
||||
<i class="fas fa-times"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div id="chatContainer" class="chatContentContainer">
|
||||
<div id="result">
|
||||
Please note that the results of this bot are automated and may be incorrect or contain inappropriate information.
|
||||
<div id="anchor"></div>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<textarea id="searchBar" class="input" rows="3" placeholder="Do not include any personal or confidential information."></textarea>
|
||||
<button id="searchBtn" class="btn btn-primary">Ask AI</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="chatFooter text-right p-2">
|
||||
© Copyright ${date.getFullYear()}, The Ray Team.
|
||||
</div>
|
||||
`;
|
||||
chatPopupDiv.messages = [];
|
||||
document.body.appendChild(chatPopupDiv);
|
||||
|
||||
const anchorDiv = document.getElementById('anchor');
|
||||
const chatContainerDiv = document.getElementById('chatContainer');
|
||||
|
||||
const blurDiv = document.createElement('div');
|
||||
blurDiv.id = 'blurDiv';
|
||||
blurDiv.classList.add('blurDiv-hidden');
|
||||
document.body.appendChild(blurDiv);
|
||||
|
||||
// blur background when chat popup is open
|
||||
document.getElementById('openChatBtn').addEventListener('click', function () {
|
||||
document.querySelector('.search-button__wrapper').classList.remove('show');
|
||||
document.getElementById('chatPopup').style.display = 'block';
|
||||
blurDiv.classList.remove('blurDiv-hidden');
|
||||
});
|
||||
|
||||
// un-blur background when chat popup is closed
|
||||
document.getElementById('closeChatBtn').addEventListener('click', function () {
|
||||
document.getElementById('chatPopup').style.display = 'none';
|
||||
blurDiv.classList.add('blurDiv-hidden');
|
||||
});
|
||||
|
||||
// set code highlighting options
|
||||
marked.setOptions({
|
||||
renderer: new marked.Renderer(),
|
||||
highlight: function (code) {
|
||||
return hljs.highlight('python', code).value;
|
||||
},
|
||||
});
|
||||
|
||||
function highlightCode() {
|
||||
document.querySelectorAll('pre code').forEach((block) => {
|
||||
hljs.highlightBlock(block);
|
||||
});
|
||||
}
|
||||
|
||||
function renderCopyButtons(resultDiv) {
|
||||
let preElements = resultDiv.querySelectorAll('pre');
|
||||
preElements.forEach((preElement, index) => {
|
||||
preElement.style.position = 'relative';
|
||||
|
||||
let uniqueId = `button-id-${index}`;
|
||||
preElement.id = uniqueId;
|
||||
|
||||
// Set the proper attributes to the button to make is a sphinx copy button
|
||||
let copyButton = document.createElement('button');
|
||||
copyButton.className = 'copybtn o-tooltip--left';
|
||||
copyButton.setAttribute('data-tooltip', 'Copy');
|
||||
copyButton.setAttribute('data-clipboard-target', `#${uniqueId}`);
|
||||
copyButton.style.position = 'absolute';
|
||||
copyButton.style.top = '10px';
|
||||
copyButton.style.right = '10px';
|
||||
copyButton.style.opacity = 'inherit';
|
||||
|
||||
let imgElement = document.createElement('img');
|
||||
imgElement.src = window.data.copyIconSrc;
|
||||
imgElement.alt = 'Copy to clipboard';
|
||||
|
||||
copyButton.appendChild(imgElement);
|
||||
preElement.appendChild(copyButton);
|
||||
});
|
||||
}
|
||||
|
||||
const searchBar = document.getElementById('searchBar');
|
||||
const searchBtn = document.getElementById('searchBtn');
|
||||
|
||||
function rayAssistant(event) {
|
||||
const resultDiv = document.getElementById('result');
|
||||
|
||||
const searchTerm = searchBar.value;
|
||||
// handle empty input
|
||||
if (!searchTerm) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
event.type === 'click' ||
|
||||
(event.type === 'keydown' && event.key === 'Enter')
|
||||
) {
|
||||
// for improved UX, we want to equate a carriage return as hitting the send button and prevent default behavior of entering a new line
|
||||
if (event.type === 'keydown' && event.key === 'Enter') {
|
||||
event.preventDefault();
|
||||
}
|
||||
// clear search bar value and change placeholder to prompt user to ask follow up question
|
||||
searchBar.value = '';
|
||||
searchBar.placeholder = 'Ask follow up question here';
|
||||
|
||||
// Add query to the list of messages
|
||||
chatPopupDiv.messages.push({role: 'user', content: searchTerm});
|
||||
|
||||
let msgBlock = document.createElement('div');
|
||||
|
||||
resultDiv.insertBefore(msgBlock, anchorDiv);
|
||||
|
||||
let divider = document.createElement('hr');
|
||||
msgBlock.appendChild(divider);
|
||||
|
||||
let msgHeader = document.createElement('div');
|
||||
msgHeader.style.fontWeight = 'bold';
|
||||
// capitalize first letter of question header
|
||||
msgHeader.innerHTML =
|
||||
searchTerm.charAt(0).toUpperCase() + searchTerm.slice(1);
|
||||
msgBlock.appendChild(msgHeader);
|
||||
|
||||
async function readStream() {
|
||||
try {
|
||||
const response = await fetch(
|
||||
'https://ray-assistant-public-bxauk.cld-kvedzwag2qa8i5bj.s.anyscaleuserdata.com/chat',
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'application/json',
|
||||
},
|
||||
body: JSON.stringify({messages: chatPopupDiv.messages}),
|
||||
}
|
||||
);
|
||||
const reader = response.body.getReader();
|
||||
let decoder = new TextDecoder('utf-8');
|
||||
let msgContent = document.createElement('div');
|
||||
msgBlock.appendChild(msgContent);
|
||||
msgContent.innerHTML = '';
|
||||
|
||||
let collectChunks = '';
|
||||
|
||||
while (true) {
|
||||
const {done, value} = await reader.read();
|
||||
if (done) {
|
||||
renderCopyButtons(resultDiv);
|
||||
break;
|
||||
}
|
||||
|
||||
const chunk = decoder.decode(value, {stream: true});
|
||||
collectChunks += chunk;
|
||||
let html = marked.parse(collectChunks);
|
||||
html = DOMPurify.sanitize(html);
|
||||
msgContent.innerHTML = html;
|
||||
highlightCode();
|
||||
}
|
||||
chatPopupDiv.messages.push({role: 'assistant', content: collectChunks});
|
||||
// we want to autoscroll to the bottom of the chat container after the answer is streamed in
|
||||
chatContainerDiv.scrollTo(0, chatContainerDiv.scrollHeight);
|
||||
} catch (error) {
|
||||
console.error('Fetch API failed:', error);
|
||||
}
|
||||
}
|
||||
readStream().then((res) => console.log(res));
|
||||
}
|
||||
}
|
||||
|
||||
searchBtn.addEventListener('click', rayAssistant);
|
||||
searchBar.addEventListener('keydown', rayAssistant);
|
||||
@@ -0,0 +1,83 @@
|
||||
// Handlers for CSAT events
|
||||
|
||||
/**
|
||||
* Upvote or downvote the documentation via Google Analytics.
|
||||
*
|
||||
* @param {string} vote 'Yes' or 'No' vote to send as feedback
|
||||
*/
|
||||
function sendVote(vote) {
|
||||
if (typeof window.dataLayer === 'undefined' || !Array.isArray(window.dataLayer)) {
|
||||
console.warn('Google Tag Manager dataLayer not available - CSAT vote not tracked');
|
||||
return;
|
||||
}
|
||||
|
||||
window.dataLayer.push({
|
||||
event: 'csat_vote',
|
||||
vote_type: vote,
|
||||
category: 'CSAT',
|
||||
page_location: window.location.href,
|
||||
page_title: document.title,
|
||||
value: vote === 'Yes' ? 1 : 0
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Documentation feedback via Google Analytics
|
||||
* @param {string} text Text to send as feedback
|
||||
*/
|
||||
function sendFeedback(text) {
|
||||
if (typeof window.dataLayer === 'undefined' || !Array.isArray(window.dataLayer)) {
|
||||
console.warn('Google Tag Manager dataLayer not available - CSAT feedback not tracked');
|
||||
return;
|
||||
}
|
||||
|
||||
window.dataLayer.push({
|
||||
event: 'csat_feedback',
|
||||
feedback_text: text.substring(0, 500),
|
||||
category: 'CSAT',
|
||||
page_location: window.location.href,
|
||||
page_title: document.title,
|
||||
feedback_length: text.length
|
||||
});
|
||||
}
|
||||
|
||||
window.addEventListener("DOMContentLoaded", () => {
|
||||
const yesButton = document.getElementById("csat-yes");
|
||||
const noButton = document.getElementById("csat-no");
|
||||
const yesIcon = document.getElementById("csat-yes-icon");
|
||||
const noIcon = document.getElementById("csat-no-icon");
|
||||
const text = document.getElementById("csat-textarea");
|
||||
const submitButton = document.getElementById("csat-submit");
|
||||
const csatGroup = document.getElementById("csat-textarea-group");
|
||||
const csatFeedbackReceived = document.getElementById("csat-feedback-received");
|
||||
const csatInputs = document.getElementById("csat-inputs")
|
||||
|
||||
yesButton.addEventListener("click", () => {
|
||||
text.placeholder = "We're glad you found it helpful. If you have any additional feedback, please let us know.";
|
||||
csatGroup.classList.remove("csat-hidden");
|
||||
yesIcon.classList.remove("csat-hidden");
|
||||
noIcon.classList.add("csat-hidden");
|
||||
yesButton.classList.add("csat-button-active");
|
||||
noButton.classList.remove("csat-button-active");
|
||||
submitButton.scrollIntoView();
|
||||
sendVote('Yes');
|
||||
})
|
||||
|
||||
noButton.addEventListener("click", () => {
|
||||
text.placeholder = "We value your feedback. Please let us know how we can improve our documentation.";
|
||||
csatGroup.classList.remove("csat-hidden");
|
||||
yesIcon.classList.add("csat-hidden");
|
||||
noIcon.classList.remove("csat-hidden");
|
||||
yesButton.classList.remove("csat-button-active");
|
||||
noButton.classList.add("csat-button-active");
|
||||
submitButton.scrollIntoView();
|
||||
sendVote('No');
|
||||
})
|
||||
|
||||
submitButton.addEventListener("click", () => {
|
||||
csatGroup.classList.add("csat-hidden");
|
||||
csatInputs.classList.add("csat-hidden");
|
||||
csatFeedbackReceived.classList.remove("csat-hidden");
|
||||
sendFeedback(text.value);
|
||||
}, {once: true})
|
||||
})
|
||||
@@ -0,0 +1,95 @@
|
||||
let new_termynals = [];
|
||||
|
||||
function createTermynals() {
|
||||
const containers = document.getElementsByClassName("termynal");
|
||||
Array.from(containers).forEach(addTermynal);
|
||||
}
|
||||
|
||||
function addTermynal(container) {
|
||||
const t = new Termynal(container, {
|
||||
noInit: true,
|
||||
});
|
||||
new_termynals.push(t);
|
||||
}
|
||||
|
||||
// Initialize Termynals that are visible on the page. Once initialized, remove
|
||||
// the Termynal from terminals that remain to be loaded.
|
||||
function loadVisibleTermynals() {
|
||||
new_termynals = new_termynals.filter(termynal => {
|
||||
if (termynal.container.getBoundingClientRect().top - innerHeight <= 0) {
|
||||
termynal.init();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
// Store the state of the page in the browser's local storage.
|
||||
// For now this includes just the sidebar scroll position.
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
const sidebar = document.getElementById("main-sidebar")
|
||||
|
||||
window.addEventListener("beforeunload", () => {
|
||||
if (sidebar) {
|
||||
localStorage.setItem("scroll", sidebar.scrollTop)
|
||||
}
|
||||
})
|
||||
|
||||
const storedScrollPosition = localStorage.getItem("scroll")
|
||||
if (storedScrollPosition) {
|
||||
if (sidebar) {
|
||||
sidebar.scrollTop = storedScrollPosition;
|
||||
}
|
||||
localStorage.removeItem("scroll");
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
// Send GA events any time a code block is copied
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
let codeButtons = document.querySelectorAll(".copybtn");
|
||||
for (let i = 0; i < codeButtons.length; i++) {
|
||||
const button = codeButtons[i];
|
||||
button.addEventListener("click", function() {
|
||||
if (typeof window.dataLayer === 'undefined' || !Array.isArray(window.dataLayer)) {
|
||||
console.warn('Google Tag Manager dataLayer not available - code copy not tracked');
|
||||
return;
|
||||
}
|
||||
|
||||
window.dataLayer.push({
|
||||
event: "code_copy_click",
|
||||
category: "ray_docs_copy_code",
|
||||
page_location: window.location.href,
|
||||
page_title: document.title,
|
||||
button_target: button.getAttribute("data-clipboard-target") || "unknown",
|
||||
value: 1,
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
let anyscaleButton = document.getElementById("try-anyscale")
|
||||
if (anyscaleButton) {
|
||||
anyscaleButton.onclick = () => {
|
||||
if (typeof window.dataLayer === 'undefined' || !Array.isArray(window.dataLayer)) {
|
||||
console.warn('Google Tag Manager dataLayer not available - try anyscale click not tracked');
|
||||
return;
|
||||
}
|
||||
|
||||
window.dataLayer.push({
|
||||
event: "try_anyscale_click",
|
||||
category: "TryAnyscale",
|
||||
page_location: window.location.href,
|
||||
page_title: document.title,
|
||||
link_url: "https://www.anyscale.com",
|
||||
value: 1,
|
||||
});
|
||||
window.open('https://www.anyscale.com', '_blank');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener("scroll", loadVisibleTermynals);
|
||||
createTermynals();
|
||||
loadVisibleTermynals();
|
||||
@@ -0,0 +1,24 @@
|
||||
// Dismissable banner functionality
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const banner = document.querySelector('.bd-header-announcement');
|
||||
const closeButton = document.getElementById('close-banner');
|
||||
const bannerKey = 'ray-docs-banner-dismissed';
|
||||
|
||||
// Check if banner was previously dismissed
|
||||
if (localStorage.getItem(bannerKey) === 'true') {
|
||||
if (banner) {
|
||||
banner.style.display = 'none';
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Add click handler for close button
|
||||
if (closeButton) {
|
||||
closeButton.addEventListener('click', function () {
|
||||
if (banner) {
|
||||
banner.style.display = 'none';
|
||||
localStorage.setItem(bannerKey, 'true');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,209 @@
|
||||
/**
|
||||
* Get the status (checked/unchecked) for each filter.
|
||||
*
|
||||
* @returns {Object} Arrays of the name and status of each filter, grouped together into filter
|
||||
* groups.
|
||||
*/
|
||||
function getFilterStatuses() {
|
||||
const useCases = Array.from(
|
||||
document.querySelectorAll('#use-case-dropdown .checkbox-container'),
|
||||
).map((label) => {
|
||||
return {
|
||||
name: label.textContent.toLowerCase(),
|
||||
isChecked: label.querySelector('input').checked,
|
||||
};
|
||||
});
|
||||
const libraries = Array.from(
|
||||
document.querySelectorAll('#library-dropdown .checkbox-container'),
|
||||
).map((label) => {
|
||||
return {
|
||||
name: label.textContent.toLowerCase(),
|
||||
isChecked: label.querySelector('input').checked,
|
||||
};
|
||||
});
|
||||
const frameworks = Array.from(
|
||||
document.querySelectorAll('#framework-dropdown .checkbox-container'),
|
||||
).map((label) => {
|
||||
return {
|
||||
name: label.textContent.toLowerCase(),
|
||||
isChecked: label.querySelector('input').checked,
|
||||
};
|
||||
});
|
||||
const contributor = Array.from(
|
||||
document.querySelectorAll('#all-examples-dropdown .checkbox-container'),
|
||||
).map((label) => {
|
||||
const inputElement = label.querySelector('input');
|
||||
return {
|
||||
name: inputElement.id.replace('-checkbox', ''),
|
||||
isChecked: inputElement.checked,
|
||||
};
|
||||
});
|
||||
return {
|
||||
useCases,
|
||||
libraries,
|
||||
frameworks,
|
||||
contributor,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether the tags of the given example panel match the requested filters.
|
||||
*
|
||||
* @param {any} tags Tags of the example panel
|
||||
* @param {any} filters Filter statuses for all the filter groups; this should be the output of
|
||||
* getFilterStatuses.
|
||||
* @returns {bool} True if the example panel matches the filters, or not.
|
||||
*/
|
||||
function panelMatchesFilters(tags, filters) {
|
||||
return Object.entries(filters).every(([group, groupTags]) => {
|
||||
// If there is no selection, consider the panel to be matched
|
||||
if (groupTags.filter(({isChecked}) => isChecked).length === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If "Any" is checked, consider the panel to be matched
|
||||
if (
|
||||
groupTags.filter(({name, isChecked}) => name === 'any' && isChecked)
|
||||
.length > 0
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise show the panel if any checked item matches the tags of the panel
|
||||
return groupTags
|
||||
.filter(({isChecked}) => isChecked)
|
||||
.some(({name}) => tags.includes(name));
|
||||
});
|
||||
}
|
||||
|
||||
/** Apply the currently selected filters to the example gallery, showing only the relevant examples. */
|
||||
function applyFilter() {
|
||||
const noMatchesElement = document.getElementById('no-matches');
|
||||
const panels = document.querySelectorAll('.example');
|
||||
const filters = getFilterStatuses();
|
||||
const searchTerm = document
|
||||
.getElementById('examples-search-input')
|
||||
.value.toLowerCase();
|
||||
|
||||
// Show all panels before hiding the ones that need to be hidden.
|
||||
panels.forEach((panel) => panel.classList.remove('hidden'));
|
||||
|
||||
// Check the title and tags of each example panel. If the tags match and the search term matches,
|
||||
// show the panel.
|
||||
panels.forEach((panel) => {
|
||||
const title = panel
|
||||
.querySelector('.example-title')
|
||||
.textContent.toLowerCase();
|
||||
const tags = panel
|
||||
.querySelector('.example-tags')
|
||||
.textContent.toLowerCase()
|
||||
.concat();
|
||||
const other_keywords = panel
|
||||
.querySelector('.example-other-keywords')
|
||||
.textContent.toLowerCase();
|
||||
const keywords = `${tags} ${other_keywords}`;
|
||||
const matchesSearch =
|
||||
title.includes(searchTerm) || keywords.includes(searchTerm);
|
||||
const matchesTags = panelMatchesFilters(keywords, filters);
|
||||
|
||||
// Hide panels that have no match
|
||||
if (matchesSearch && matchesTags) {
|
||||
panel.classList.remove('hidden');
|
||||
} else {
|
||||
panel.classList.add('hidden');
|
||||
}
|
||||
});
|
||||
|
||||
// If none are shown, show the "no matches" graphic.
|
||||
if (document.querySelectorAll('.example:not(.hidden)').length === 0) {
|
||||
noMatchesElement.classList.remove('hidden');
|
||||
} else {
|
||||
noMatchesElement.classList.add('hidden');
|
||||
}
|
||||
|
||||
// Set the URL to match the active filters using query parameters.
|
||||
const selectedTags = Object.entries(filters).map(([group, groupTags]) => {
|
||||
return {
|
||||
group,
|
||||
selected: groupTags
|
||||
.filter(({isChecked}) => isChecked)
|
||||
.map(({name}) => name),
|
||||
};
|
||||
});
|
||||
|
||||
const queryParam = selectedTags
|
||||
.filter(({group, selected}) => selected.length > 0)
|
||||
.map(({group, selected}) => `${group}=${selected.join(',')}`)
|
||||
.join('&');
|
||||
|
||||
history.replaceState(
|
||||
null,
|
||||
null,
|
||||
queryParam.length === 0 ? location.pathname : `?${queryParam}`,
|
||||
);
|
||||
}
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
// Listen for filter checkbox clicks.
|
||||
document.querySelectorAll('.filter-checkbox').forEach((tag) => {
|
||||
tag.addEventListener('click', () => applyFilter());
|
||||
});
|
||||
|
||||
// Add event listener for keypresses in the search bar.
|
||||
document
|
||||
.getElementById('examples-search-input')
|
||||
.addEventListener('keyup', (event) => {
|
||||
event.preventDefault();
|
||||
applyFilter();
|
||||
});
|
||||
|
||||
// Add the ability to provide URL query parameters to filter examples on page load.
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
if (urlParams.size > 0) {
|
||||
urlParams.forEach((params) => {
|
||||
params.split(',').forEach((param) => {
|
||||
const element = document.getElementById(`${param}-checkbox`);
|
||||
if (element) {
|
||||
element.checked = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Apply the filter in case there are URL query parameters.
|
||||
applyFilter();
|
||||
|
||||
const dropdowns = Array.from(
|
||||
document.querySelectorAll('.dropdown-content'),
|
||||
).map((dropdown) => {
|
||||
return {
|
||||
dropdown,
|
||||
input: dropdown.parentNode.querySelector('input'),
|
||||
inputContainer: dropdown.parentNode,
|
||||
};
|
||||
});
|
||||
document.addEventListener('click', (event) => {
|
||||
let targetEl = event.target; // clicked element
|
||||
|
||||
do {
|
||||
const unclicked = dropdowns.filter(({dropdown, inputContainer}) => {
|
||||
return !(targetEl == dropdown || targetEl == inputContainer);
|
||||
});
|
||||
if (unclicked.length !== dropdowns.length) {
|
||||
// There has been a click inside one of the dropdowns. Close unclicked dropdowns and return.
|
||||
unclicked.forEach(({input}) => {
|
||||
input.checked = false;
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Go up the DOM.
|
||||
targetEl = targetEl.parentNode;
|
||||
} while (targetEl);
|
||||
|
||||
// This is a click outside. Close all dropdowns.
|
||||
dropdowns.forEach(({dropdown, input}) => {
|
||||
input.checked = false;
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,52 @@
|
||||
function animateTabs() {
|
||||
const tabs = Array.from(document.getElementById('v-pills-tab').children);
|
||||
const contentTabs = Array.from(
|
||||
document.getElementById('v-pills-tabContent').children,
|
||||
);
|
||||
|
||||
tabs.forEach((item, index) => {
|
||||
item.onclick = () => {
|
||||
tabs.forEach((tab, i) => {
|
||||
if (i === index) {
|
||||
item.classList.add('active');
|
||||
} else {
|
||||
tab.classList.remove('active');
|
||||
}
|
||||
});
|
||||
contentTabs.forEach((tab, i) => {
|
||||
if (i === index) {
|
||||
tab.classList.add('active', 'show');
|
||||
} else {
|
||||
tab.classList.remove('active', 'show');
|
||||
}
|
||||
});
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function updateHighlight() {
|
||||
const {theme} = document.documentElement.dataset;
|
||||
['dark', 'light'].forEach((title) => {
|
||||
const stylesheet = document.querySelector(`link[title="${title}"]`);
|
||||
if (title === theme) {
|
||||
stylesheet.removeAttribute('disabled');
|
||||
} else {
|
||||
stylesheet.setAttribute('disabled', 'disabled');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function setHighlightListener() {
|
||||
const observer = new MutationObserver((mutations) => updateHighlight());
|
||||
observer.observe(document.documentElement, {
|
||||
attributes: true,
|
||||
attributeFilter: ['data-theme'],
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', animateTabs);
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
hljs.highlightAll();
|
||||
updateHighlight();
|
||||
});
|
||||
document.addEventListener('DOMContentLoaded', setHighlightListener);
|
||||
@@ -0,0 +1,229 @@
|
||||
/**
|
||||
* termynal.js
|
||||
* A lightweight, modern and extensible animated terminal window, using
|
||||
* async/await.
|
||||
*
|
||||
* @author Ines Montani <ines@ines.io>
|
||||
* @version 0.0.1
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/** Generate a terminal widget. */
|
||||
class Termynal {
|
||||
/**
|
||||
* Construct the widget's settings.
|
||||
* @param {(string|Node)=} container - Query selector or container element.
|
||||
* @param {{noInit: boolean}} options - Custom settings.
|
||||
* @param {string} options.prefix - Prefix to use for data attributes.
|
||||
* @param {number} options.startDelay - Delay before animation, in ms.
|
||||
* @param {number} options.typeDelay - Delay between each typed character, in ms.
|
||||
* @param {number} options.lineDelay - Delay between each line, in ms.
|
||||
* @param {number} options.progressLength - Number of characters displayed as progress bar.
|
||||
* @param {string} options.progressChar – Character to use for progress bar, defaults to █.
|
||||
* @param {number} options.progressPercent - Max percent of progress.
|
||||
* @param {string} options.cursor – Character to use for cursor, defaults to ▋.
|
||||
* @param {Object[]} lineData - Dynamically loaded line data objects.
|
||||
* @param {boolean} options.noInit - Don't initialise the animation.
|
||||
*/
|
||||
constructor(container = '#termynal', options = {}) {
|
||||
this.container = (typeof container === 'string') ? document.querySelector(container) : container;
|
||||
this.pfx = `data-${options.prefix || 'ty'}`;
|
||||
this.startDelay = options.startDelay
|
||||
|| parseFloat(this.container.getAttribute(`${this.pfx}-startDelay`)) || 600;
|
||||
this.typeDelay = options.typeDelay
|
||||
|| parseFloat(this.container.getAttribute(`${this.pfx}-typeDelay`)) || 90;
|
||||
this.lineDelay = options.lineDelay
|
||||
|| parseFloat(this.container.getAttribute(`${this.pfx}-lineDelay`)) || 1500;
|
||||
this.progressLength = options.progressLength
|
||||
|| parseFloat(this.container.getAttribute(`${this.pfx}-progressLength`)) || 40;
|
||||
this.progressChar = options.progressChar
|
||||
|| this.container.getAttribute(`${this.pfx}-progressChar`) || '█';
|
||||
this.progressPercent = options.progressPercent
|
||||
|| parseFloat(this.container.getAttribute(`${this.pfx}-progressPercent`)) || 100;
|
||||
this.cursor = options.cursor
|
||||
|| this.container.getAttribute(`${this.pfx}-cursor`) || '▋';
|
||||
this.lineData = this.lineDataToElements(options.lineData || []);
|
||||
this.loadLines()
|
||||
if (!options.noInit) this.init()
|
||||
}
|
||||
|
||||
|
||||
loadLines() {
|
||||
// Load all the lines and create the container so that the size is fixed
|
||||
// Otherwise it would be changing and the user viewport would be constantly
|
||||
// moving as she/he scrolls
|
||||
// Appends dynamically loaded lines to existing line elements.
|
||||
this.lines = [...this.container.querySelectorAll(`[${this.pfx}]`)].concat(this.lineData);
|
||||
for (let line of this.lines) {
|
||||
line.style.visibility = 'hidden'
|
||||
this.container.appendChild(line)
|
||||
}
|
||||
const restart = this.generateRestart()
|
||||
restart.style.visibility = 'hidden'
|
||||
this.container.appendChild(restart)
|
||||
this.container.setAttribute('data-termynal', '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the widget, get lines, clear container and start animation.
|
||||
*/
|
||||
init() {
|
||||
// Appends dynamically loaded lines to existing line elements.
|
||||
//this.lines = [...this.container.querySelectorAll(`[${this.pfx}]`)].concat(this.lineData);
|
||||
/**
|
||||
* Calculates width and height of Termynal container.
|
||||
* If container is empty and lines are dynamically loaded, defaults to browser `auto` or CSS.
|
||||
*/
|
||||
const containerStyle = getComputedStyle(this.container);
|
||||
this.container.style.width = containerStyle.width !== '0px' ?
|
||||
containerStyle.width : undefined;
|
||||
this.container.style.minHeight = containerStyle.height !== '0px' ?
|
||||
containerStyle.height : undefined;
|
||||
|
||||
this.container.setAttribute('data-termynal', '');
|
||||
this.container.innerHTML = '';
|
||||
for (let line of this.lines) {
|
||||
line.style.visibility = 'visible'
|
||||
}
|
||||
this.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the animation and rener the lines depending on their data attributes.
|
||||
*/
|
||||
async start() {
|
||||
await this._wait(this.startDelay);
|
||||
|
||||
for (let line of this.lines) {
|
||||
const type = line.getAttribute(this.pfx);
|
||||
const delay = line.getAttribute(`${this.pfx}-delay`) || this.lineDelay;
|
||||
|
||||
if (type == 'input') {
|
||||
line.setAttribute(`${this.pfx}-cursor`, this.cursor);
|
||||
await this.type(line);
|
||||
await this._wait(delay);
|
||||
}
|
||||
|
||||
else if (type == 'progress') {
|
||||
await this.progress(line);
|
||||
await this._wait(delay);
|
||||
}
|
||||
|
||||
else {
|
||||
this.container.appendChild(line);
|
||||
await this._wait(delay);
|
||||
}
|
||||
|
||||
line.removeAttribute(`${this.pfx}-cursor`);
|
||||
}
|
||||
this.addRestart()
|
||||
}
|
||||
|
||||
/**
|
||||
* Animate a typed line.
|
||||
* @param {Node} line - The line element to render.
|
||||
*/
|
||||
async type(line) {
|
||||
const chars = [...line.textContent];
|
||||
const delay = line.getAttribute(`${this.pfx}-typeDelay`) || this.typeDelay;
|
||||
line.textContent = '';
|
||||
this.container.appendChild(line);
|
||||
|
||||
for (let char of chars) {
|
||||
await this._wait(delay);
|
||||
line.textContent += char;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Animate a progress bar.
|
||||
* @param {Node} line - The line element to render.
|
||||
*/
|
||||
async progress(line) {
|
||||
const progressLength = line.getAttribute(`${this.pfx}-progressLength`)
|
||||
|| this.progressLength;
|
||||
const progressChar = line.getAttribute(`${this.pfx}-progressChar`)
|
||||
|| this.progressChar;
|
||||
const chars = progressChar.repeat(progressLength);
|
||||
const progressPercent = line.getAttribute(`${this.pfx}-progressPercent`)
|
||||
|| this.progressPercent;
|
||||
line.textContent = '';
|
||||
this.container.appendChild(line);
|
||||
|
||||
for (let i = 1; i < chars.length + 1; i++) {
|
||||
await this._wait(this.typeDelay);
|
||||
const percent = Math.round(i / chars.length * 100);
|
||||
line.textContent = `${chars.slice(0, i)} ${percent}%`;
|
||||
if (percent > progressPercent) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for animation delays, called with `await`.
|
||||
* @param {number} time - Timeout, in ms.
|
||||
*/
|
||||
_wait(time) {
|
||||
return new Promise(resolve => setTimeout(resolve, time));
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts line data objects into line elements.
|
||||
*
|
||||
* @param {Object[]} lineData - Dynamically loaded lines.
|
||||
* @param {Object} line - Line data object.
|
||||
* @returns {Element[]} - Array of line elements.
|
||||
*/
|
||||
lineDataToElements(lineData) {
|
||||
return lineData.map(line => {
|
||||
let div = document.createElement('div');
|
||||
div.innerHTML = `<span ${this._attributes(line)}>${line.value || ''}</span>`;
|
||||
|
||||
return div.firstElementChild;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for generating attributes string.
|
||||
*
|
||||
* @param {Object} line - Line data object.
|
||||
* @returns {string} - String of attributes.
|
||||
*/
|
||||
_attributes(line) {
|
||||
let attrs = '';
|
||||
for (let prop in line) {
|
||||
attrs += this.pfx;
|
||||
|
||||
if (prop === 'type') {
|
||||
attrs += `="${line[prop]}" `
|
||||
} else if (prop !== 'value') {
|
||||
attrs += `-${prop}="${line[prop]}" `
|
||||
}
|
||||
}
|
||||
|
||||
return attrs;
|
||||
}
|
||||
|
||||
// Taken from Typer Tiangolo
|
||||
generateRestart() {
|
||||
const restart = document.createElement('a')
|
||||
restart.onclick = (e) => {
|
||||
e.preventDefault()
|
||||
this.container.innerHTML = ''
|
||||
this.init()
|
||||
}
|
||||
restart.href = '#'
|
||||
restart.setAttribute('data-terminal-control', '')
|
||||
restart.innerHTML = "restart ↻"
|
||||
return restart
|
||||
}
|
||||
|
||||
addRestart() {
|
||||
const restart = this.generateRestart()
|
||||
this.container.appendChild(restart)
|
||||
}
|
||||
}
|
||||
|
||||