diff --git a/.eslintrc.yml b/.eslintrc.yml
index b5a4e155f..a04c28308 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -14,6 +14,8 @@ parser: '@typescript-eslint/parser'
parserOptions:
ecmaVersion: 2018
sourceType: module
+ project:
+ - './tsconfig.json'
plugins:
- '@typescript-eslint'
- prettier
@@ -68,6 +70,10 @@ rules:
"@typescript-eslint/consistent-type-imports":
- error
+
+ "@typescript-eslint/no-floating-promises":
+ - error
+
"@typescript-eslint/naming-convention":
- error
diff --git a/DESCRIPTION b/DESCRIPTION
index 0fb6d071a..813a07c65 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -49,13 +49,14 @@ Suggests:
magrittr,
rappdirs,
rmarkdown (>= 2.7),
- shiny (>= 1.6.0),
+ shiny (>= 1.7.5.9001),
testthat,
thematic,
withr
Remotes:
- rstudio/htmltools
-Config/Needs/deploy:
+ rstudio/htmltools,
+ rstudio/shiny
+Config/Needs/deploy:
BH,
chiflights22,
colourpicker,
diff --git a/inst/components/dist/components.js b/inst/components/dist/components.js
index 6e048afa2..d41c5e641 100644
--- a/inst/components/dist/components.js
+++ b/inst/components/dist/components.js
@@ -1,9 +1,35 @@
/*! bslib 0.5.1.9000 | (c) 2012-2023 RStudio, PBC. | License: MIT + file LICENSE */
"use strict";
(() => {
- // srcts/src/components/_utils.ts
- var InputBinding = window.Shiny ? Shiny.InputBinding : class {
+ var __getOwnPropNames = Object.getOwnPropertyNames;
+ var __esm = (fn, res) => function __init() {
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
+ };
+ var __commonJS = (cb, mod) => function __require() {
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
};
+ var __async = (__this, __arguments, generator) => {
+ return new Promise((resolve, reject) => {
+ var fulfilled = (value) => {
+ try {
+ step(generator.next(value));
+ } catch (e) {
+ reject(e);
+ }
+ };
+ var rejected = (value) => {
+ try {
+ step(generator.throw(value));
+ } catch (e) {
+ reject(e);
+ }
+ };
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
+ step((generator = generator.apply(__this, __arguments)).next());
+ });
+ };
+
+ // srcts/src/components/_utils.ts
function registerBinding(inputBindingClass, name) {
if (window.Shiny) {
Shiny.inputBindings.register(new inputBindingClass(), "bslib." + name);
@@ -32,843 +58,898 @@
const focusable = el.querySelectorAll(selectors.join(", "));
return Array.from(focusable);
}
-
- // srcts/src/components/accordion.ts
- var AccordionInputBinding = class extends InputBinding {
- find(scope) {
- return $(scope).find(".accordion.bslib-accordion-input");
- }
- getValue(el) {
- const items = this._getItemInfo(el);
- const selected = items.filter((x) => x.isOpen()).map((x) => x.value);
- return selected.length === 0 ? null : selected;
- }
- subscribe(el, callback) {
- $(el).on(
- "shown.bs.collapse.accordionInputBinding hidden.bs.collapse.accordionInputBinding",
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- function(event) {
- callback(true);
- }
- );
- }
- unsubscribe(el) {
- $(el).off(".accordionInputBinding");
- }
- receiveMessage(el, data) {
- const method = data.method;
- if (method === "set") {
- this._setItems(el, data);
- } else if (method === "open") {
- this._openItems(el, data);
- } else if (method === "close") {
- this._closeItems(el, data);
- } else if (method === "remove") {
- this._removeItem(el, data);
- } else if (method === "insert") {
- this._insertItem(el, data);
- } else if (method === "update") {
- this._updateItem(el, data);
- } else {
- throw new Error(`Method not yet implemented: ${method}`);
+ function shinyRenderContent(...args) {
+ return __async(this, null, function* () {
+ if (!window.Shiny) {
+ throw new Error("This function must be called in a Shiny app.");
}
- }
- _setItems(el, data) {
- const items = this._getItemInfo(el);
- const vals = this._getValues(el, items, data.values);
- items.forEach((x) => {
- vals.indexOf(x.value) > -1 ? x.show() : x.hide();
- });
- }
- _openItems(el, data) {
- const items = this._getItemInfo(el);
- const vals = this._getValues(el, items, data.values);
- items.forEach((x) => {
- if (vals.indexOf(x.value) > -1)
- x.show();
- });
- }
- _closeItems(el, data) {
- const items = this._getItemInfo(el);
- const vals = this._getValues(el, items, data.values);
- items.forEach((x) => {
- if (vals.indexOf(x.value) > -1)
- x.hide();
- });
- }
- _insertItem(el, data) {
- let targetItem = this._findItem(el, data.target);
- if (!targetItem) {
- targetItem = data.position === "before" ? el.firstElementChild : el.lastElementChild;
- }
- const panel = data.panel;
- if (targetItem) {
- Shiny.renderContent(
- targetItem,
- panel,
- data.position === "before" ? "beforeBegin" : "afterEnd"
- );
+ if (Shiny.renderContentAsync) {
+ return yield Shiny.renderContentAsync.apply(null, args);
} else {
- Shiny.renderContent(el, panel);
- }
- if (this._isAutoClosing(el)) {
- const val = $(panel.html).attr("data-value");
- $(el).find(`[data-value="${val}"] .accordion-collapse`).attr("data-bs-parent", "#" + el.id);
+ return yield Shiny.renderContent.apply(null, args);
}
+ });
+ }
+ var InputBinding;
+ var init_utils = __esm({
+ "srcts/src/components/_utils.ts"() {
+ "use strict";
+ InputBinding = window.Shiny ? Shiny.InputBinding : class {
+ };
}
- _removeItem(el, data) {
- const targetItems = this._getItemInfo(el).filter(
- (x) => data.target.indexOf(x.value) > -1
- );
- const unbindAll = Shiny == null ? void 0 : Shiny.unbindAll;
- targetItems.forEach((x) => {
- if (unbindAll)
- unbindAll(x.item);
- x.item.remove();
- });
- }
- _updateItem(el, data) {
- const target = this._findItem(el, data.target);
- if (!target) {
- throw new Error(
- `Unable to find an accordion_panel() with a value of ${data.target}`
- );
- }
- if (hasDefinedProperty(data, "value")) {
- target.dataset.value = data.value;
- }
- if (hasDefinedProperty(data, "body")) {
- const body = target.querySelector(".accordion-body");
- Shiny.renderContent(body, data.body);
- }
- const header = target.querySelector(".accordion-header");
- if (hasDefinedProperty(data, "title")) {
- const title = header.querySelector(".accordion-title");
- Shiny.renderContent(title, data.title);
- }
- if (hasDefinedProperty(data, "icon")) {
- const icon = header.querySelector(
- ".accordion-button > .accordion-icon"
- );
- Shiny.renderContent(icon, data.icon);
- }
- }
- _getItemInfo(el) {
- const items = Array.from(
- el.querySelectorAll(":scope > .accordion-item")
- );
- return items.map((x) => this._getSingleItemInfo(x));
- }
- _getSingleItemInfo(x) {
- const collapse = x.querySelector(".accordion-collapse");
- const isOpen = () => $(collapse).hasClass("show");
- return {
- item: x,
- value: x.dataset.value,
- isOpen,
- show: () => {
- if (!isOpen())
- $(collapse).collapse("show");
- },
- hide: () => {
- if (isOpen())
- $(collapse).collapse("hide");
+ });
+
+ // srcts/src/components/accordion.ts
+ var AccordionInputBinding;
+ var init_accordion = __esm({
+ "srcts/src/components/accordion.ts"() {
+ "use strict";
+ init_utils();
+ AccordionInputBinding = class extends InputBinding {
+ find(scope) {
+ return $(scope).find(".accordion.bslib-accordion-input");
+ }
+ getValue(el) {
+ const items = this._getItemInfo(el);
+ const selected = items.filter((x) => x.isOpen()).map((x) => x.value);
+ return selected.length === 0 ? null : selected;
+ }
+ subscribe(el, callback) {
+ $(el).on(
+ "shown.bs.collapse.accordionInputBinding hidden.bs.collapse.accordionInputBinding",
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ function(event) {
+ callback(true);
+ }
+ );
+ }
+ unsubscribe(el) {
+ $(el).off(".accordionInputBinding");
+ }
+ receiveMessage(el, data) {
+ return __async(this, null, function* () {
+ const method = data.method;
+ if (method === "set") {
+ this._setItems(el, data);
+ } else if (method === "open") {
+ this._openItems(el, data);
+ } else if (method === "close") {
+ this._closeItems(el, data);
+ } else if (method === "remove") {
+ this._removeItem(el, data);
+ } else if (method === "insert") {
+ yield this._insertItem(el, data);
+ } else if (method === "update") {
+ yield this._updateItem(el, data);
+ } else {
+ throw new Error(`Method not yet implemented: ${method}`);
+ }
+ });
+ }
+ _setItems(el, data) {
+ const items = this._getItemInfo(el);
+ const vals = this._getValues(el, items, data.values);
+ items.forEach((x) => {
+ vals.indexOf(x.value) > -1 ? x.show() : x.hide();
+ });
+ }
+ _openItems(el, data) {
+ const items = this._getItemInfo(el);
+ const vals = this._getValues(el, items, data.values);
+ items.forEach((x) => {
+ if (vals.indexOf(x.value) > -1)
+ x.show();
+ });
+ }
+ _closeItems(el, data) {
+ const items = this._getItemInfo(el);
+ const vals = this._getValues(el, items, data.values);
+ items.forEach((x) => {
+ if (vals.indexOf(x.value) > -1)
+ x.hide();
+ });
+ }
+ _insertItem(el, data) {
+ return __async(this, null, function* () {
+ let targetItem = this._findItem(el, data.target);
+ if (!targetItem) {
+ targetItem = data.position === "before" ? el.firstElementChild : el.lastElementChild;
+ }
+ const panel = data.panel;
+ if (targetItem) {
+ yield shinyRenderContent(
+ targetItem,
+ panel,
+ data.position === "before" ? "beforeBegin" : "afterEnd"
+ );
+ } else {
+ yield shinyRenderContent(el, panel);
+ }
+ if (this._isAutoClosing(el)) {
+ const val = $(panel.html).attr("data-value");
+ $(el).find(`[data-value="${val}"] .accordion-collapse`).attr("data-bs-parent", "#" + el.id);
+ }
+ });
+ }
+ _removeItem(el, data) {
+ const targetItems = this._getItemInfo(el).filter(
+ (x) => data.target.indexOf(x.value) > -1
+ );
+ const unbindAll = Shiny == null ? void 0 : Shiny.unbindAll;
+ targetItems.forEach((x) => {
+ if (unbindAll)
+ unbindAll(x.item);
+ x.item.remove();
+ });
+ }
+ _updateItem(el, data) {
+ return __async(this, null, function* () {
+ const target = this._findItem(el, data.target);
+ if (!target) {
+ throw new Error(
+ `Unable to find an accordion_panel() with a value of ${data.target}`
+ );
+ }
+ if (hasDefinedProperty(data, "value")) {
+ target.dataset.value = data.value;
+ }
+ if (hasDefinedProperty(data, "body")) {
+ const body = target.querySelector(".accordion-body");
+ yield shinyRenderContent(body, data.body);
+ }
+ const header = target.querySelector(".accordion-header");
+ if (hasDefinedProperty(data, "title")) {
+ const title = header.querySelector(".accordion-title");
+ yield shinyRenderContent(title, data.title);
+ }
+ if (hasDefinedProperty(data, "icon")) {
+ const icon = header.querySelector(
+ ".accordion-button > .accordion-icon"
+ );
+ yield shinyRenderContent(icon, data.icon);
+ }
+ });
+ }
+ _getItemInfo(el) {
+ const items = Array.from(
+ el.querySelectorAll(":scope > .accordion-item")
+ );
+ return items.map((x) => this._getSingleItemInfo(x));
+ }
+ _getSingleItemInfo(x) {
+ const collapse = x.querySelector(".accordion-collapse");
+ const isOpen = () => $(collapse).hasClass("show");
+ return {
+ item: x,
+ value: x.dataset.value,
+ isOpen,
+ show: () => {
+ if (!isOpen())
+ $(collapse).collapse("show");
+ },
+ hide: () => {
+ if (isOpen())
+ $(collapse).collapse("hide");
+ }
+ };
+ }
+ _getValues(el, items, values) {
+ let vals = values !== true ? values : items.map((x) => x.value);
+ const autoclose = this._isAutoClosing(el);
+ if (autoclose) {
+ vals = vals.slice(vals.length - 1, vals.length);
+ }
+ return vals;
+ }
+ _findItem(el, value) {
+ return el.querySelector(`[data-value="${value}"]`);
+ }
+ _isAutoClosing(el) {
+ return el.classList.contains("autoclose");
}
};
+ registerBinding(AccordionInputBinding, "accordion");
}
- _getValues(el, items, values) {
- let vals = values !== true ? values : items.map((x) => x.value);
- const autoclose = this._isAutoClosing(el);
- if (autoclose) {
- vals = vals.slice(vals.length - 1, vals.length);
- }
- return vals;
- }
- _findItem(el, value) {
- return el.querySelector(`[data-value="${value}"]`);
- }
- _isAutoClosing(el) {
- return el.classList.contains("autoclose");
- }
- };
- registerBinding(AccordionInputBinding, "accordion");
+ });
// srcts/src/components/_shinyResizeObserver.ts
- var ShinyResizeObserver = class {
- /**
- * Watch containers for size changes and ensure that Shiny outputs and
- * htmlwidgets within resize appropriately.
- *
- * @details
- * The ShinyResizeObserver is used to watch the containers, such as Sidebars
- * and Cards for size changes, in particular when the sidebar state is toggled
- * or the card body is expanded full screen. It performs two primary tasks:
- *
- * 1. Dispatches a `resize` event on the window object. This is necessary to
- * ensure that Shiny outputs resize appropriately. In general, the window
- * resizing is throttled and the output update occurs when the transition
- * is complete.
- * 2. If an output with a resize method on the output binding is detected, we
- * directly call the `.onResize()` method of the binding. This ensures that
- * htmlwidgets transition smoothly. In static mode, htmlwidgets does this
- * already.
- *
- * @note
- * This resize observer also handles race conditions in some complex
- * fill-based layouts with multiple outputs (e.g., plotly), where shiny
- * initializes with the correct sizing, but in-between the 1st and last
- * renderValue(), the size of the output containers can change, meaning every
- * output but the 1st gets initialized with the wrong size during their
- * renderValue(). Then, after the render phase, shiny won't know to trigger a
- * resize since all the widgets will return to their original size (and thus,
- * Shiny thinks there isn't any resizing to do). The resize observer works
- * around this by ensuring that the output is resized whenever its container
- * size changes.
- * @constructor
- */
- constructor() {
- this.resizeObserverEntries = [];
- this.resizeObserver = new ResizeObserver((entries) => {
- const resizeEvent = new Event("resize");
- window.dispatchEvent(resizeEvent);
- if (!window.Shiny)
- return;
- const resized = [];
- for (const entry of entries) {
- if (!(entry.target instanceof HTMLElement))
- continue;
- if (!entry.target.querySelector(".shiny-bound-output"))
- continue;
- entry.target.querySelectorAll(".shiny-bound-output").forEach((el) => {
- if (resized.includes(el))
+ var ShinyResizeObserver;
+ var init_shinyResizeObserver = __esm({
+ "srcts/src/components/_shinyResizeObserver.ts"() {
+ "use strict";
+ ShinyResizeObserver = class {
+ /**
+ * Watch containers for size changes and ensure that Shiny outputs and
+ * htmlwidgets within resize appropriately.
+ *
+ * @details
+ * The ShinyResizeObserver is used to watch the containers, such as Sidebars
+ * and Cards for size changes, in particular when the sidebar state is toggled
+ * or the card body is expanded full screen. It performs two primary tasks:
+ *
+ * 1. Dispatches a `resize` event on the window object. This is necessary to
+ * ensure that Shiny outputs resize appropriately. In general, the window
+ * resizing is throttled and the output update occurs when the transition
+ * is complete.
+ * 2. If an output with a resize method on the output binding is detected, we
+ * directly call the `.onResize()` method of the binding. This ensures that
+ * htmlwidgets transition smoothly. In static mode, htmlwidgets does this
+ * already.
+ *
+ * @note
+ * This resize observer also handles race conditions in some complex
+ * fill-based layouts with multiple outputs (e.g., plotly), where shiny
+ * initializes with the correct sizing, but in-between the 1st and last
+ * renderValue(), the size of the output containers can change, meaning every
+ * output but the 1st gets initialized with the wrong size during their
+ * renderValue(). Then, after the render phase, shiny won't know to trigger a
+ * resize since all the widgets will return to their original size (and thus,
+ * Shiny thinks there isn't any resizing to do). The resize observer works
+ * around this by ensuring that the output is resized whenever its container
+ * size changes.
+ * @constructor
+ */
+ constructor() {
+ this.resizeObserverEntries = [];
+ this.resizeObserver = new ResizeObserver((entries) => {
+ const resizeEvent = new Event("resize");
+ window.dispatchEvent(resizeEvent);
+ if (!window.Shiny)
return;
- const { binding, onResize } = $(el).data("shinyOutputBinding");
- if (!binding || !binding.resize)
- return;
- const owner = el.shinyResizeObserver;
- if (owner && owner !== this)
- return;
- if (!owner)
- el.shinyResizeObserver = this;
- onResize(el);
- resized.push(el);
- if (!el.classList.contains("shiny-plot-output"))
- return;
- const img = el.querySelector(
- 'img:not([width="100%"])'
- );
- if (img)
- img.setAttribute("width", "100%");
+ const resized = [];
+ for (const entry of entries) {
+ if (!(entry.target instanceof HTMLElement))
+ continue;
+ if (!entry.target.querySelector(".shiny-bound-output"))
+ continue;
+ entry.target.querySelectorAll(".shiny-bound-output").forEach((el) => {
+ if (resized.includes(el))
+ return;
+ const { binding, onResize } = $(el).data("shinyOutputBinding");
+ if (!binding || !binding.resize)
+ return;
+ const owner = el.shinyResizeObserver;
+ if (owner && owner !== this)
+ return;
+ if (!owner)
+ el.shinyResizeObserver = this;
+ onResize(el);
+ resized.push(el);
+ if (!el.classList.contains("shiny-plot-output"))
+ return;
+ const img = el.querySelector(
+ 'img:not([width="100%"])'
+ );
+ if (img)
+ img.setAttribute("width", "100%");
+ });
+ }
});
}
- });
- }
- /**
- * Observe an element for size changes.
- * @param {HTMLElement} el - The element to observe.
- */
- observe(el) {
- this.resizeObserver.observe(el);
- this.resizeObserverEntries.push(el);
- }
- /**
- * Stop observing an element for size changes.
- * @param {HTMLElement} el - The element to stop observing.
- */
- unobserve(el) {
- const idxEl = this.resizeObserverEntries.indexOf(el);
- if (idxEl < 0)
- return;
- this.resizeObserver.unobserve(el);
- this.resizeObserverEntries.splice(idxEl, 1);
- }
- /**
- * This method checks that we're not continuing to watch elements that no
- * longer exist in the DOM. If any are found, we stop observing them and
- * remove them from our array of observed elements.
- *
- * @private
- * @static
- */
- flush() {
- this.resizeObserverEntries.forEach((el) => {
- if (!document.body.contains(el))
- this.unobserve(el);
- });
+ /**
+ * Observe an element for size changes.
+ * @param {HTMLElement} el - The element to observe.
+ */
+ observe(el) {
+ this.resizeObserver.observe(el);
+ this.resizeObserverEntries.push(el);
+ }
+ /**
+ * Stop observing an element for size changes.
+ * @param {HTMLElement} el - The element to stop observing.
+ */
+ unobserve(el) {
+ const idxEl = this.resizeObserverEntries.indexOf(el);
+ if (idxEl < 0)
+ return;
+ this.resizeObserver.unobserve(el);
+ this.resizeObserverEntries.splice(idxEl, 1);
+ }
+ /**
+ * This method checks that we're not continuing to watch elements that no
+ * longer exist in the DOM. If any are found, we stop observing them and
+ * remove them from our array of observed elements.
+ *
+ * @private
+ * @static
+ */
+ flush() {
+ this.resizeObserverEntries.forEach((el) => {
+ if (!document.body.contains(el))
+ this.unobserve(el);
+ });
+ }
+ };
}
- };
+ });
// srcts/src/components/card.ts
- var _Card = class {
- /**
- * Creates an instance of a bslib Card component.
- *
- * @constructor
- * @param {HTMLElement} card
- */
- constructor(card) {
- var _a;
- card.removeAttribute(_Card.attr.ATTR_INIT);
- (_a = card.querySelector(`script[${_Card.attr.ATTR_INIT}]`)) == null ? void 0 : _a.remove();
- this.card = card;
- _Card.instanceMap.set(card, this);
- _Card.shinyResizeObserver.observe(this.card);
- this._addEventListeners();
- this.overlay = this._createOverlay();
- this._exitFullScreenOnEscape = this._exitFullScreenOnEscape.bind(this);
- this._trapFocusExit = this._trapFocusExit.bind(this);
- }
- /**
- * Enter the card's full screen mode, either programmatically or via an event
- * handler. Full screen mode is activated by adding a class to the card that
- * positions it absolutely and expands it to fill the viewport. In addition,
- * we add a full screen overlay element behind the card and we trap focus in
- * the expanded card while in full screen mode.
- *
- * @param {?Event} [event]
- */
- enterFullScreen(event) {
- var _a;
- if (event)
- event.preventDefault();
- document.addEventListener("keydown", this._exitFullScreenOnEscape, false);
- document.addEventListener("keydown", this._trapFocusExit, true);
- this.card.setAttribute(_Card.attr.ATTR_FULL_SCREEN, "true");
- document.body.classList.add(_Card.attr.CLASS_HAS_FULL_SCREEN);
- this.card.insertAdjacentElement("beforebegin", this.overlay.container);
- if (!this.card.contains(document.activeElement) || ((_a = document.activeElement) == null ? void 0 : _a.classList.contains(
- _Card.attr.CLASS_FULL_SCREEN_ENTER
- ))) {
- this.card.setAttribute("tabindex", "-1");
- this.card.focus();
- }
- }
- /**
- * Exit full screen mode. This removes the full screen overlay element,
- * removes the full screen class from the card, and removes the keyboard event
- * listeners that were added when entering full screen mode.
- */
- exitFullScreen() {
- document.removeEventListener(
- "keydown",
- this._exitFullScreenOnEscape,
- false
- );
- document.removeEventListener("keydown", this._trapFocusExit, true);
- this.overlay.container.remove();
- this.card.setAttribute(_Card.attr.ATTR_FULL_SCREEN, "false");
- this.card.removeAttribute("tabindex");
- document.body.classList.remove(_Card.attr.CLASS_HAS_FULL_SCREEN);
- }
- /**
- * Adds general card-specific event listeners.
- * @private
- */
- _addEventListeners() {
- const btnFullScreen = this.card.querySelector(
- `:scope > * > .${_Card.attr.CLASS_FULL_SCREEN_ENTER}`
- );
- if (!btnFullScreen)
- return;
- btnFullScreen.addEventListener("click", (ev) => this.enterFullScreen(ev));
- }
- /**
- * An event handler to exit full screen mode when the Escape key is pressed.
- * @private
- * @param {KeyboardEvent} event
- */
- _exitFullScreenOnEscape(event) {
- if (!(event.target instanceof HTMLElement))
- return;
- const selOpenSelectInput = ["select[open]", "input[aria-expanded='true']"];
- if (event.target.matches(selOpenSelectInput.join(", ")))
- return;
- if (event.key === "Escape") {
- this.exitFullScreen();
- }
- }
- /**
- * An event handler to trap focus within the card when in full screen mode.
- *
- * @description
- * This keyboard event handler ensures that tab focus stays within the card
- * when in full screen mode. When the card is first expanded,
- * we move focus to the card element itself. If focus somehow leaves the card,
- * we returns focus to the card container.
- *
- * Within the card, we handle only tabbing from the close anchor or the last
- * focusable element and only when tab focus would have otherwise left the
- * card. In those cases, we cycle focus to the last focusable element or back
- * to the anchor. If the card doesn't have any focusable elements, we move
- * focus to the close anchor.
- *
- * @note
- * Because the card contents may change, we check for focusable elements
- * every time the handler is called.
- *
- * @private
- * @param {KeyboardEvent} event
- */
- _trapFocusExit(event) {
- if (!(event instanceof KeyboardEvent))
- return;
- if (event.key !== "Tab")
- return;
- const isFocusedContainer = event.target === this.card;
- const isFocusedAnchor = event.target === this.overlay.anchor;
- const isFocusedWithin = this.card.contains(event.target);
- const stopEvent = () => {
- event.preventDefault();
- event.stopImmediatePropagation();
- };
- if (!(isFocusedWithin || isFocusedContainer || isFocusedAnchor)) {
- stopEvent();
- this.card.focus();
- return;
- }
- const focusableElements = getAllFocusableChildren(this.card).filter(
- (el) => !el.classList.contains(_Card.attr.CLASS_FULL_SCREEN_ENTER)
- );
- const hasFocusableElements = focusableElements.length > 0;
- if (!hasFocusableElements) {
- stopEvent();
- this.overlay.anchor.focus();
- return;
- }
- if (isFocusedContainer)
- return;
- const lastFocusable = focusableElements[focusableElements.length - 1];
- const isFocusedLast = event.target === lastFocusable;
- if (isFocusedAnchor && event.shiftKey) {
- stopEvent();
- lastFocusable.focus();
- return;
- }
- if (isFocusedLast && !event.shiftKey) {
- stopEvent();
- this.overlay.anchor.focus();
- return;
- }
- }
- /**
- * Creates the full screen overlay.
- * @private
- * @returns {CardFullScreenOverlay}
- */
- _createOverlay() {
- const container = document.createElement("div");
- container.id = _Card.attr.ID_FULL_SCREEN_OVERLAY;
- container.onclick = this.exitFullScreen.bind(this);
- const anchor = this._createOverlayCloseAnchor();
- container.appendChild(anchor);
- return { container, anchor };
- }
- /**
- * Creates the anchor element used to exit the full screen mode.
- * @private
- * @returns {HTMLAnchorElement}
- */
- _createOverlayCloseAnchor() {
- const anchor = document.createElement("a");
- anchor.classList.add(_Card.attr.CLASS_FULL_SCREEN_EXIT);
- anchor.tabIndex = 0;
- anchor.onclick = () => this.exitFullScreen();
- anchor.onkeydown = (ev) => {
- if (ev.key === "Enter" || ev.key === " ") {
- this.exitFullScreen();
+ var _Card, Card;
+ var init_card = __esm({
+ "srcts/src/components/card.ts"() {
+ "use strict";
+ init_utils();
+ init_shinyResizeObserver();
+ _Card = class {
+ /**
+ * Creates an instance of a bslib Card component.
+ *
+ * @constructor
+ * @param {HTMLElement} card
+ */
+ constructor(card) {
+ var _a;
+ card.removeAttribute(_Card.attr.ATTR_INIT);
+ (_a = card.querySelector(`script[${_Card.attr.ATTR_INIT}]`)) == null ? void 0 : _a.remove();
+ this.card = card;
+ _Card.instanceMap.set(card, this);
+ _Card.shinyResizeObserver.observe(this.card);
+ this._addEventListeners();
+ this.overlay = this._createOverlay();
+ this._exitFullScreenOnEscape = this._exitFullScreenOnEscape.bind(this);
+ this._trapFocusExit = this._trapFocusExit.bind(this);
}
- };
- anchor.innerHTML = this._overlayCloseHtml();
- return anchor;
- }
- /**
- * Returns the HTML for the close icon.
- * @private
- * @returns {string}
- */
- _overlayCloseHtml() {
- return "Close ";
- }
- /**
- * Returns the card instance associated with the given element, if any.
- * @public
- * @static
- * @param {HTMLElement} el
- * @returns {(Card | undefined)}
- */
- static getInstance(el) {
- return _Card.instanceMap.get(el);
- }
- /**
- * Initializes all cards that require initialization on the page, or schedules
- * initialization if the DOM is not yet ready.
- * @public
- * @static
- * @param {boolean} [flushResizeObserver=true]
- */
- static initializeAllCards(flushResizeObserver = true) {
- if (document.readyState === "loading") {
- if (!_Card.onReadyScheduled) {
- _Card.onReadyScheduled = true;
- document.addEventListener("DOMContentLoaded", () => {
- _Card.initializeAllCards(false);
- });
+ /**
+ * Enter the card's full screen mode, either programmatically or via an event
+ * handler. Full screen mode is activated by adding a class to the card that
+ * positions it absolutely and expands it to fill the viewport. In addition,
+ * we add a full screen overlay element behind the card and we trap focus in
+ * the expanded card while in full screen mode.
+ *
+ * @param {?Event} [event]
+ */
+ enterFullScreen(event) {
+ var _a;
+ if (event)
+ event.preventDefault();
+ document.addEventListener("keydown", this._exitFullScreenOnEscape, false);
+ document.addEventListener("keydown", this._trapFocusExit, true);
+ this.card.setAttribute(_Card.attr.ATTR_FULL_SCREEN, "true");
+ document.body.classList.add(_Card.attr.CLASS_HAS_FULL_SCREEN);
+ this.card.insertAdjacentElement("beforebegin", this.overlay.container);
+ if (!this.card.contains(document.activeElement) || ((_a = document.activeElement) == null ? void 0 : _a.classList.contains(
+ _Card.attr.CLASS_FULL_SCREEN_ENTER
+ ))) {
+ this.card.setAttribute("tabindex", "-1");
+ this.card.focus();
+ }
}
- return;
- }
- if (flushResizeObserver) {
- _Card.shinyResizeObserver.flush();
- }
- const initSelector = `.${_Card.attr.CLASS_CARD}[${_Card.attr.ATTR_INIT}]`;
- if (!document.querySelector(initSelector)) {
- return;
- }
- const cards = document.querySelectorAll(initSelector);
- cards.forEach((card) => new _Card(card));
+ /**
+ * Exit full screen mode. This removes the full screen overlay element,
+ * removes the full screen class from the card, and removes the keyboard event
+ * listeners that were added when entering full screen mode.
+ */
+ exitFullScreen() {
+ document.removeEventListener(
+ "keydown",
+ this._exitFullScreenOnEscape,
+ false
+ );
+ document.removeEventListener("keydown", this._trapFocusExit, true);
+ this.overlay.container.remove();
+ this.card.setAttribute(_Card.attr.ATTR_FULL_SCREEN, "false");
+ this.card.removeAttribute("tabindex");
+ document.body.classList.remove(_Card.attr.CLASS_HAS_FULL_SCREEN);
+ }
+ /**
+ * Adds general card-specific event listeners.
+ * @private
+ */
+ _addEventListeners() {
+ const btnFullScreen = this.card.querySelector(
+ `:scope > * > .${_Card.attr.CLASS_FULL_SCREEN_ENTER}`
+ );
+ if (!btnFullScreen)
+ return;
+ btnFullScreen.addEventListener("click", (ev) => this.enterFullScreen(ev));
+ }
+ /**
+ * An event handler to exit full screen mode when the Escape key is pressed.
+ * @private
+ * @param {KeyboardEvent} event
+ */
+ _exitFullScreenOnEscape(event) {
+ if (!(event.target instanceof HTMLElement))
+ return;
+ const selOpenSelectInput = ["select[open]", "input[aria-expanded='true']"];
+ if (event.target.matches(selOpenSelectInput.join(", ")))
+ return;
+ if (event.key === "Escape") {
+ this.exitFullScreen();
+ }
+ }
+ /**
+ * An event handler to trap focus within the card when in full screen mode.
+ *
+ * @description
+ * This keyboard event handler ensures that tab focus stays within the card
+ * when in full screen mode. When the card is first expanded,
+ * we move focus to the card element itself. If focus somehow leaves the card,
+ * we returns focus to the card container.
+ *
+ * Within the card, we handle only tabbing from the close anchor or the last
+ * focusable element and only when tab focus would have otherwise left the
+ * card. In those cases, we cycle focus to the last focusable element or back
+ * to the anchor. If the card doesn't have any focusable elements, we move
+ * focus to the close anchor.
+ *
+ * @note
+ * Because the card contents may change, we check for focusable elements
+ * every time the handler is called.
+ *
+ * @private
+ * @param {KeyboardEvent} event
+ */
+ _trapFocusExit(event) {
+ if (!(event instanceof KeyboardEvent))
+ return;
+ if (event.key !== "Tab")
+ return;
+ const isFocusedContainer = event.target === this.card;
+ const isFocusedAnchor = event.target === this.overlay.anchor;
+ const isFocusedWithin = this.card.contains(event.target);
+ const stopEvent = () => {
+ event.preventDefault();
+ event.stopImmediatePropagation();
+ };
+ if (!(isFocusedWithin || isFocusedContainer || isFocusedAnchor)) {
+ stopEvent();
+ this.card.focus();
+ return;
+ }
+ const focusableElements = getAllFocusableChildren(this.card).filter(
+ (el) => !el.classList.contains(_Card.attr.CLASS_FULL_SCREEN_ENTER)
+ );
+ const hasFocusableElements = focusableElements.length > 0;
+ if (!hasFocusableElements) {
+ stopEvent();
+ this.overlay.anchor.focus();
+ return;
+ }
+ if (isFocusedContainer)
+ return;
+ const lastFocusable = focusableElements[focusableElements.length - 1];
+ const isFocusedLast = event.target === lastFocusable;
+ if (isFocusedAnchor && event.shiftKey) {
+ stopEvent();
+ lastFocusable.focus();
+ return;
+ }
+ if (isFocusedLast && !event.shiftKey) {
+ stopEvent();
+ this.overlay.anchor.focus();
+ return;
+ }
+ }
+ /**
+ * Creates the full screen overlay.
+ * @private
+ * @returns {CardFullScreenOverlay}
+ */
+ _createOverlay() {
+ const container = document.createElement("div");
+ container.id = _Card.attr.ID_FULL_SCREEN_OVERLAY;
+ container.onclick = this.exitFullScreen.bind(this);
+ const anchor = this._createOverlayCloseAnchor();
+ container.appendChild(anchor);
+ return { container, anchor };
+ }
+ /**
+ * Creates the anchor element used to exit the full screen mode.
+ * @private
+ * @returns {HTMLAnchorElement}
+ */
+ _createOverlayCloseAnchor() {
+ const anchor = document.createElement("a");
+ anchor.classList.add(_Card.attr.CLASS_FULL_SCREEN_EXIT);
+ anchor.tabIndex = 0;
+ anchor.onclick = () => this.exitFullScreen();
+ anchor.onkeydown = (ev) => {
+ if (ev.key === "Enter" || ev.key === " ") {
+ this.exitFullScreen();
+ }
+ };
+ anchor.innerHTML = this._overlayCloseHtml();
+ return anchor;
+ }
+ /**
+ * Returns the HTML for the close icon.
+ * @private
+ * @returns {string}
+ */
+ _overlayCloseHtml() {
+ return "Close ";
+ }
+ /**
+ * Returns the card instance associated with the given element, if any.
+ * @public
+ * @static
+ * @param {HTMLElement} el
+ * @returns {(Card | undefined)}
+ */
+ static getInstance(el) {
+ return _Card.instanceMap.get(el);
+ }
+ /**
+ * Initializes all cards that require initialization on the page, or schedules
+ * initialization if the DOM is not yet ready.
+ * @public
+ * @static
+ * @param {boolean} [flushResizeObserver=true]
+ */
+ static initializeAllCards(flushResizeObserver = true) {
+ if (document.readyState === "loading") {
+ if (!_Card.onReadyScheduled) {
+ _Card.onReadyScheduled = true;
+ document.addEventListener("DOMContentLoaded", () => {
+ _Card.initializeAllCards(false);
+ });
+ }
+ return;
+ }
+ if (flushResizeObserver) {
+ _Card.shinyResizeObserver.flush();
+ }
+ const initSelector = `.${_Card.attr.CLASS_CARD}[${_Card.attr.ATTR_INIT}]`;
+ if (!document.querySelector(initSelector)) {
+ return;
+ }
+ const cards = document.querySelectorAll(initSelector);
+ cards.forEach((card) => new _Card(card));
+ }
+ };
+ Card = _Card;
+ /**
+ * Key bslib-specific classes and attributes used by the card component.
+ * @private
+ * @static
+ * @type {{ ATTR_INIT: string; CLASS_CARD: string; CLASS_FULL_SCREEN: string; CLASS_HAS_FULL_SCREEN: string; CLASS_FULL_SCREEN_ENTER: string; CLASS_FULL_SCREEN_EXIT: string; ID_FULL_SCREEN_OVERLAY: string; }}
+ */
+ Card.attr = {
+ // eslint-disable-next-line @typescript-eslint/naming-convention
+ ATTR_INIT: "data-bslib-card-init",
+ // eslint-disable-next-line @typescript-eslint/naming-convention
+ CLASS_CARD: "bslib-card",
+ // eslint-disable-next-line @typescript-eslint/naming-convention
+ ATTR_FULL_SCREEN: "data-full-screen",
+ // eslint-disable-next-line @typescript-eslint/naming-convention
+ CLASS_HAS_FULL_SCREEN: "bslib-has-full-screen",
+ // eslint-disable-next-line @typescript-eslint/naming-convention
+ CLASS_FULL_SCREEN_ENTER: "bslib-full-screen-enter",
+ // eslint-disable-next-line @typescript-eslint/naming-convention
+ CLASS_FULL_SCREEN_EXIT: "bslib-full-screen-exit",
+ // eslint-disable-next-line @typescript-eslint/naming-convention
+ ID_FULL_SCREEN_OVERLAY: "bslib-full-screen-overlay"
+ };
+ /**
+ * A Shiny-specific resize observer that ensures Shiny outputs in within the
+ * card resize appropriately.
+ * @private
+ * @type {ShinyResizeObserver}
+ * @static
+ */
+ Card.shinyResizeObserver = new ShinyResizeObserver();
+ /**
+ * The registry of card instances and their associated DOM elements.
+ * @private
+ * @static
+ * @type {WeakMap}
+ */
+ Card.instanceMap = /* @__PURE__ */ new WeakMap();
+ /**
+ * If cards are initialized before the DOM is ready, we re-schedule the
+ * initialization to occur on DOMContentLoaded.
+ * @private
+ * @static
+ * @type {boolean}
+ */
+ Card.onReadyScheduled = false;
+ window.bslib = window.bslib || {};
+ window.bslib.Card = Card;
}
- };
- var Card = _Card;
- /**
- * Key bslib-specific classes and attributes used by the card component.
- * @private
- * @static
- * @type {{ ATTR_INIT: string; CLASS_CARD: string; CLASS_FULL_SCREEN: string; CLASS_HAS_FULL_SCREEN: string; CLASS_FULL_SCREEN_ENTER: string; CLASS_FULL_SCREEN_EXIT: string; ID_FULL_SCREEN_OVERLAY: string; }}
- */
- Card.attr = {
- // eslint-disable-next-line @typescript-eslint/naming-convention
- ATTR_INIT: "data-bslib-card-init",
- // eslint-disable-next-line @typescript-eslint/naming-convention
- CLASS_CARD: "bslib-card",
- // eslint-disable-next-line @typescript-eslint/naming-convention
- ATTR_FULL_SCREEN: "data-full-screen",
- // eslint-disable-next-line @typescript-eslint/naming-convention
- CLASS_HAS_FULL_SCREEN: "bslib-has-full-screen",
- // eslint-disable-next-line @typescript-eslint/naming-convention
- CLASS_FULL_SCREEN_ENTER: "bslib-full-screen-enter",
- // eslint-disable-next-line @typescript-eslint/naming-convention
- CLASS_FULL_SCREEN_EXIT: "bslib-full-screen-exit",
- // eslint-disable-next-line @typescript-eslint/naming-convention
- ID_FULL_SCREEN_OVERLAY: "bslib-full-screen-overlay"
- };
- /**
- * A Shiny-specific resize observer that ensures Shiny outputs in within the
- * card resize appropriately.
- * @private
- * @type {ShinyResizeObserver}
- * @static
- */
- Card.shinyResizeObserver = new ShinyResizeObserver();
- /**
- * The registry of card instances and their associated DOM elements.
- * @private
- * @static
- * @type {WeakMap}
- */
- Card.instanceMap = /* @__PURE__ */ new WeakMap();
- /**
- * If cards are initialized before the DOM is ready, we re-schedule the
- * initialization to occur on DOMContentLoaded.
- * @private
- * @static
- * @type {boolean}
- */
- Card.onReadyScheduled = false;
- window.bslib = window.bslib || {};
- window.bslib.Card = Card;
+ });
// srcts/src/components/sidebar.ts
- var _Sidebar = class {
- /**
- * Creates an instance of a collapsible bslib Sidebar.
- * @constructor
- * @param {HTMLElement} container
- */
- constructor(container) {
- var _a;
- _Sidebar.instanceMap.set(container, this);
- this.layout = {
- container,
- main: container.querySelector(":scope > .main"),
- sidebar: container.querySelector(":scope > .sidebar"),
- toggle: container.querySelector(
- ":scope > .collapse-toggle"
- )
- };
- const sideAccordion = this.layout.sidebar.querySelector(
- ":scope > .sidebar-content > .accordion"
- );
- if (sideAccordion) {
- (_a = sideAccordion == null ? void 0 : sideAccordion.parentElement) == null ? void 0 : _a.classList.add("has-accordion");
- sideAccordion.classList.add("accordion-flush");
- }
- if (this.layout.toggle) {
- this._initEventListeners();
- this._initSidebarCounters();
- this._initDesktop();
- }
- _Sidebar.shinyResizeObserver.observe(this.layout.main);
- container.removeAttribute("data-bslib-sidebar-init");
- const initScript = container.querySelector(
- ":scope > script[data-bslib-sidebar-init]"
- );
- if (initScript) {
- container.removeChild(initScript);
- }
- }
- /**
- * Read the current state of the sidebar. Note that, when calling this method,
- * the sidebar may be transitioning into the state returned by this method.
- *
- * @description
- * The sidebar state works as follows, starting from the open state. When the
- * sidebar is closed:
- * 1. We add both the `COLLAPSE` and `TRANSITIONING` classes to the sidebar.
- * 2. The sidebar collapse begins to animate. On desktop devices, and where it
- * is supported, we transition the `grid-template-columns` property of the
- * sidebar layout. On mobile, the sidebar is hidden immediately. In both
- * cases, the collapse icon rotates and we use this rotation to determine
- * when the transition is complete.
- * 3. If another sidebar state toggle is requested while closing the sidebar,
- * we remove the `COLLAPSE` class and the animation immediately starts to
- * reverse.
- * 4. When the `transition` is complete, we remove the `TRANSITIONING` class.
- * @readonly
- * @type {boolean}
- */
- get isClosed() {
- return this.layout.container.classList.contains(_Sidebar.classes.COLLAPSE);
- }
- /**
- * Given a sidebar container, return the Sidebar instance associated with it.
- * @public
- * @static
- * @param {HTMLElement} el
- * @returns {(Sidebar | undefined)}
- */
- static getInstance(el) {
- return _Sidebar.instanceMap.get(el);
- }
- /**
- * Initialize all collapsible sidebars on the page.
- * @public
- * @static
- * @param {boolean} [flushResizeObserver=true] When `true`, we remove
- * non-existent elements from the ResizeObserver. This is required
- * periodically to prevent memory leaks. To avoid over-checking, we only flush
- * the ResizeObserver when initializing sidebars after page load.
- */
- static initCollapsibleAll(flushResizeObserver = true) {
- if (document.readyState === "loading") {
- if (!_Sidebar.onReadyScheduled) {
- _Sidebar.onReadyScheduled = true;
- document.addEventListener("DOMContentLoaded", () => {
- _Sidebar.initCollapsibleAll(false);
+ var _Sidebar, Sidebar, SidebarInputBinding;
+ var init_sidebar = __esm({
+ "srcts/src/components/sidebar.ts"() {
+ "use strict";
+ init_utils();
+ init_shinyResizeObserver();
+ _Sidebar = class {
+ /**
+ * Creates an instance of a collapsible bslib Sidebar.
+ * @constructor
+ * @param {HTMLElement} container
+ */
+ constructor(container) {
+ var _a;
+ _Sidebar.instanceMap.set(container, this);
+ this.layout = {
+ container,
+ main: container.querySelector(":scope > .main"),
+ sidebar: container.querySelector(":scope > .sidebar"),
+ toggle: container.querySelector(
+ ":scope > .collapse-toggle"
+ )
+ };
+ const sideAccordion = this.layout.sidebar.querySelector(
+ ":scope > .sidebar-content > .accordion"
+ );
+ if (sideAccordion) {
+ (_a = sideAccordion == null ? void 0 : sideAccordion.parentElement) == null ? void 0 : _a.classList.add("has-accordion");
+ sideAccordion.classList.add("accordion-flush");
+ }
+ if (this.layout.toggle) {
+ this._initEventListeners();
+ this._initSidebarCounters();
+ this._initDesktop();
+ }
+ _Sidebar.shinyResizeObserver.observe(this.layout.main);
+ container.removeAttribute("data-bslib-sidebar-init");
+ const initScript = container.querySelector(
+ ":scope > script[data-bslib-sidebar-init]"
+ );
+ if (initScript) {
+ container.removeChild(initScript);
+ }
+ }
+ /**
+ * Read the current state of the sidebar. Note that, when calling this method,
+ * the sidebar may be transitioning into the state returned by this method.
+ *
+ * @description
+ * The sidebar state works as follows, starting from the open state. When the
+ * sidebar is closed:
+ * 1. We add both the `COLLAPSE` and `TRANSITIONING` classes to the sidebar.
+ * 2. The sidebar collapse begins to animate. On desktop devices, and where it
+ * is supported, we transition the `grid-template-columns` property of the
+ * sidebar layout. On mobile, the sidebar is hidden immediately. In both
+ * cases, the collapse icon rotates and we use this rotation to determine
+ * when the transition is complete.
+ * 3. If another sidebar state toggle is requested while closing the sidebar,
+ * we remove the `COLLAPSE` class and the animation immediately starts to
+ * reverse.
+ * 4. When the `transition` is complete, we remove the `TRANSITIONING` class.
+ * @readonly
+ * @type {boolean}
+ */
+ get isClosed() {
+ return this.layout.container.classList.contains(_Sidebar.classes.COLLAPSE);
+ }
+ /**
+ * Given a sidebar container, return the Sidebar instance associated with it.
+ * @public
+ * @static
+ * @param {HTMLElement} el
+ * @returns {(Sidebar | undefined)}
+ */
+ static getInstance(el) {
+ return _Sidebar.instanceMap.get(el);
+ }
+ /**
+ * Initialize all collapsible sidebars on the page.
+ * @public
+ * @static
+ * @param {boolean} [flushResizeObserver=true] When `true`, we remove
+ * non-existent elements from the ResizeObserver. This is required
+ * periodically to prevent memory leaks. To avoid over-checking, we only flush
+ * the ResizeObserver when initializing sidebars after page load.
+ */
+ static initCollapsibleAll(flushResizeObserver = true) {
+ if (document.readyState === "loading") {
+ if (!_Sidebar.onReadyScheduled) {
+ _Sidebar.onReadyScheduled = true;
+ document.addEventListener("DOMContentLoaded", () => {
+ _Sidebar.initCollapsibleAll(false);
+ });
+ }
+ return;
+ }
+ const initSelector = `.${_Sidebar.classes.LAYOUT}[data-bslib-sidebar-init]`;
+ if (!document.querySelector(initSelector)) {
+ return;
+ }
+ if (flushResizeObserver)
+ _Sidebar.shinyResizeObserver.flush();
+ const containers = document.querySelectorAll(initSelector);
+ containers.forEach((container) => new _Sidebar(container));
+ }
+ /**
+ * Initialize event listeners for the sidebar toggle button.
+ * @private
+ */
+ _initEventListeners() {
+ var _a;
+ const { toggle } = this.layout;
+ toggle.addEventListener("click", (ev) => {
+ ev.preventDefault();
+ this.toggle("toggle");
});
+ (_a = toggle.querySelector(".collapse-icon")) == null ? void 0 : _a.addEventListener("transitionend", () => this._finalizeState());
}
- return;
- }
- const initSelector = `.${_Sidebar.classes.LAYOUT}[data-bslib-sidebar-init]`;
- if (!document.querySelector(initSelector)) {
- return;
- }
- if (flushResizeObserver)
- _Sidebar.shinyResizeObserver.flush();
- const containers = document.querySelectorAll(initSelector);
- containers.forEach((container) => new _Sidebar(container));
- }
- /**
- * Initialize event listeners for the sidebar toggle button.
- * @private
- */
- _initEventListeners() {
- var _a;
- const { toggle } = this.layout;
- toggle.addEventListener("click", (ev) => {
- ev.preventDefault();
- this.toggle("toggle");
- });
- (_a = toggle.querySelector(".collapse-icon")) == null ? void 0 : _a.addEventListener("transitionend", () => this._finalizeState());
- }
- /**
- * Initialize nested sidebar counters.
- *
- * @description
- * This function walks up the DOM tree, adding CSS variables to each direct
- * parent sidebar layout that count the layout's position in the stack of
- * nested layouts. We use these counters to keep the collapse toggles from
- * overlapping. Note that always-open sidebars that don't have collapse
- * toggles break the chain of nesting.
- * @private
- */
- _initSidebarCounters() {
- const { container } = this.layout;
- const selectorChildLayouts = `.${_Sidebar.classes.LAYOUT}> .main > .${_Sidebar.classes.LAYOUT}:not([data-bslib-sidebar-open="always"])`;
- const isInnermostLayout = container.querySelector(selectorChildLayouts) === null;
- if (!isInnermostLayout) {
- return;
- }
- function nextSidebarParent(el) {
- el = el ? el.parentElement : null;
- if (el && el.classList.contains("main")) {
- el = el.parentElement;
+ /**
+ * Initialize nested sidebar counters.
+ *
+ * @description
+ * This function walks up the DOM tree, adding CSS variables to each direct
+ * parent sidebar layout that count the layout's position in the stack of
+ * nested layouts. We use these counters to keep the collapse toggles from
+ * overlapping. Note that always-open sidebars that don't have collapse
+ * toggles break the chain of nesting.
+ * @private
+ */
+ _initSidebarCounters() {
+ const { container } = this.layout;
+ const selectorChildLayouts = `.${_Sidebar.classes.LAYOUT}> .main > .${_Sidebar.classes.LAYOUT}:not([data-bslib-sidebar-open="always"])`;
+ const isInnermostLayout = container.querySelector(selectorChildLayouts) === null;
+ if (!isInnermostLayout) {
+ return;
+ }
+ function nextSidebarParent(el) {
+ el = el ? el.parentElement : null;
+ if (el && el.classList.contains("main")) {
+ el = el.parentElement;
+ }
+ if (el && el.classList.contains(_Sidebar.classes.LAYOUT)) {
+ return el;
+ }
+ return null;
+ }
+ const layouts = [container];
+ let parent = nextSidebarParent(container);
+ while (parent) {
+ layouts.unshift(parent);
+ parent = nextSidebarParent(parent);
+ }
+ const count = { left: 0, right: 0 };
+ layouts.forEach(function(x) {
+ const isRight = x.classList.contains("sidebar-right");
+ const thisCount = isRight ? count.right++ : count.left++;
+ x.style.setProperty("--_js-toggle-count-this-side", thisCount.toString());
+ x.style.setProperty(
+ "--_js-toggle-count-max-side",
+ Math.max(count.right, count.left).toString()
+ );
+ });
}
- if (el && el.classList.contains(_Sidebar.classes.LAYOUT)) {
- return el;
+ /**
+ * Initialize the sidebar's initial state when `open = "desktop"`.
+ * @private
+ */
+ _initDesktop() {
+ var _a;
+ const { container } = this.layout;
+ if (((_a = container.dataset.bslibSidebarOpen) == null ? void 0 : _a.trim()) !== "desktop") {
+ return;
+ }
+ const initCollapsed = window.getComputedStyle(container).getPropertyValue("--bslib-sidebar-js-init-collapsed");
+ if (initCollapsed.trim() === "true") {
+ this.toggle("close");
+ }
}
- return null;
- }
- const layouts = [container];
- let parent = nextSidebarParent(container);
- while (parent) {
- layouts.unshift(parent);
- parent = nextSidebarParent(parent);
- }
- const count = { left: 0, right: 0 };
- layouts.forEach(function(x) {
- const isRight = x.classList.contains("sidebar-right");
- const thisCount = isRight ? count.right++ : count.left++;
- x.style.setProperty("--_js-toggle-count-this-side", thisCount.toString());
- x.style.setProperty(
- "--_js-toggle-count-max-side",
- Math.max(count.right, count.left).toString()
- );
- });
- }
- /**
- * Initialize the sidebar's initial state when `open = "desktop"`.
- * @private
- */
- _initDesktop() {
- var _a;
- const { container } = this.layout;
- if (((_a = container.dataset.bslibSidebarOpen) == null ? void 0 : _a.trim()) !== "desktop") {
- return;
- }
- const initCollapsed = window.getComputedStyle(container).getPropertyValue("--bslib-sidebar-js-init-collapsed");
- if (initCollapsed.trim() === "true") {
- this.toggle("close");
- }
- }
- /**
- * Toggle the sidebar's open/closed state.
- * @public
- * @param {SidebarToggleMethod | undefined} method Whether to `"open"`,
- * `"close"` or `"toggle"` the sidebar. If `.toggle()` is called without an
- * argument, it will toggle the sidebar's state.
- */
- toggle(method) {
- if (typeof method === "undefined") {
- method = "toggle";
- }
- const { container, sidebar } = this.layout;
- const isClosed = this.isClosed;
- if (["open", "close", "toggle"].indexOf(method) === -1) {
- throw new Error(`Unknown method ${method}`);
- }
- if (method === "toggle") {
- method = isClosed ? "open" : "close";
- }
- if (isClosed && method === "close" || !isClosed && method === "open") {
- return;
- }
- if (method === "open") {
- sidebar.hidden = false;
- }
- container.classList.add(_Sidebar.classes.TRANSITIONING);
- container.classList.toggle(_Sidebar.classes.COLLAPSE);
- }
- /**
- * When the sidebar open/close transition ends, finalize the sidebar's state.
- * @private
- */
- _finalizeState() {
- const { container, sidebar, toggle } = this.layout;
- container.classList.remove(_Sidebar.classes.TRANSITIONING);
- sidebar.hidden = this.isClosed;
- toggle.setAttribute("aria-expanded", this.isClosed ? "false" : "true");
- const event = new CustomEvent("bslib.sidebar", {
- bubbles: true,
- detail: { open: !this.isClosed }
- });
- sidebar.dispatchEvent(event);
- $(sidebar).trigger("toggleCollapse.sidebarInputBinding");
- $(sidebar).trigger(this.isClosed ? "hidden" : "shown");
- }
- };
- var Sidebar = _Sidebar;
- /**
- * A Shiny-specific resize observer that ensures Shiny outputs in the main
- * content areas of the sidebar resize appropriately.
- * @private
- * @type {ShinyResizeObserver}
- * @static
- */
- Sidebar.shinyResizeObserver = new ShinyResizeObserver();
- /**
- * Static classes related to the sidebar layout or state.
- * @public
- * @static
- * @readonly
- * @type {{ LAYOUT: string; COLLAPSE: string; TRANSITIONING: string; }}
- */
- Sidebar.classes = {
- // eslint-disable-next-line @typescript-eslint/naming-convention
- LAYOUT: "bslib-sidebar-layout",
- // eslint-disable-next-line @typescript-eslint/naming-convention
- COLLAPSE: "sidebar-collapsed",
- // eslint-disable-next-line @typescript-eslint/naming-convention
- TRANSITIONING: "transitioning"
- };
- /**
- * If sidebars are initialized before the DOM is ready, we re-schedule the
- * initialization to occur on DOMContentLoaded.
- * @private
- * @static
- * @type {boolean}
- */
- Sidebar.onReadyScheduled = false;
- /**
- * A map of initialized sidebars to their respective Sidebar instances.
- * @private
- * @static
- * @type {WeakMap}
- */
- Sidebar.instanceMap = /* @__PURE__ */ new WeakMap();
- var SidebarInputBinding = class extends InputBinding {
- find(scope) {
- return $(scope).find(`.${Sidebar.classes.LAYOUT} > .bslib-sidebar-input`);
- }
- getValue(el) {
- const sb = Sidebar.getInstance(el.parentElement);
- if (!sb)
- return false;
- return !sb.isClosed;
- }
- setValue(el, value) {
- const method = value ? "open" : "close";
- this.receiveMessage(el, { method });
- }
- subscribe(el, callback) {
- $(el).on(
- "toggleCollapse.sidebarInputBinding",
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- function(event) {
- callback(true);
- }
- );
- }
- unsubscribe(el) {
- $(el).off(".sidebarInputBinding");
- }
- receiveMessage(el, data) {
- const sb = Sidebar.getInstance(el.parentElement);
- if (sb)
- sb.toggle(data.method);
+ /**
+ * Toggle the sidebar's open/closed state.
+ * @public
+ * @param {SidebarToggleMethod | undefined} method Whether to `"open"`,
+ * `"close"` or `"toggle"` the sidebar. If `.toggle()` is called without an
+ * argument, it will toggle the sidebar's state.
+ */
+ toggle(method) {
+ if (typeof method === "undefined") {
+ method = "toggle";
+ }
+ const { container, sidebar } = this.layout;
+ const isClosed = this.isClosed;
+ if (["open", "close", "toggle"].indexOf(method) === -1) {
+ throw new Error(`Unknown method ${method}`);
+ }
+ if (method === "toggle") {
+ method = isClosed ? "open" : "close";
+ }
+ if (isClosed && method === "close" || !isClosed && method === "open") {
+ return;
+ }
+ if (method === "open") {
+ sidebar.hidden = false;
+ }
+ container.classList.add(_Sidebar.classes.TRANSITIONING);
+ container.classList.toggle(_Sidebar.classes.COLLAPSE);
+ }
+ /**
+ * When the sidebar open/close transition ends, finalize the sidebar's state.
+ * @private
+ */
+ _finalizeState() {
+ const { container, sidebar, toggle } = this.layout;
+ container.classList.remove(_Sidebar.classes.TRANSITIONING);
+ sidebar.hidden = this.isClosed;
+ toggle.setAttribute("aria-expanded", this.isClosed ? "false" : "true");
+ const event = new CustomEvent("bslib.sidebar", {
+ bubbles: true,
+ detail: { open: !this.isClosed }
+ });
+ sidebar.dispatchEvent(event);
+ $(sidebar).trigger("toggleCollapse.sidebarInputBinding");
+ $(sidebar).trigger(this.isClosed ? "hidden" : "shown");
+ }
+ };
+ Sidebar = _Sidebar;
+ /**
+ * A Shiny-specific resize observer that ensures Shiny outputs in the main
+ * content areas of the sidebar resize appropriately.
+ * @private
+ * @type {ShinyResizeObserver}
+ * @static
+ */
+ Sidebar.shinyResizeObserver = new ShinyResizeObserver();
+ /**
+ * Static classes related to the sidebar layout or state.
+ * @public
+ * @static
+ * @readonly
+ * @type {{ LAYOUT: string; COLLAPSE: string; TRANSITIONING: string; }}
+ */
+ Sidebar.classes = {
+ // eslint-disable-next-line @typescript-eslint/naming-convention
+ LAYOUT: "bslib-sidebar-layout",
+ // eslint-disable-next-line @typescript-eslint/naming-convention
+ COLLAPSE: "sidebar-collapsed",
+ // eslint-disable-next-line @typescript-eslint/naming-convention
+ TRANSITIONING: "transitioning"
+ };
+ /**
+ * If sidebars are initialized before the DOM is ready, we re-schedule the
+ * initialization to occur on DOMContentLoaded.
+ * @private
+ * @static
+ * @type {boolean}
+ */
+ Sidebar.onReadyScheduled = false;
+ /**
+ * A map of initialized sidebars to their respective Sidebar instances.
+ * @private
+ * @static
+ * @type {WeakMap}
+ */
+ Sidebar.instanceMap = /* @__PURE__ */ new WeakMap();
+ SidebarInputBinding = class extends InputBinding {
+ find(scope) {
+ return $(scope).find(`.${Sidebar.classes.LAYOUT} > .bslib-sidebar-input`);
+ }
+ getValue(el) {
+ const sb = Sidebar.getInstance(el.parentElement);
+ if (!sb)
+ return false;
+ return !sb.isClosed;
+ }
+ setValue(el, value) {
+ const method = value ? "open" : "close";
+ this.receiveMessage(el, { method });
+ }
+ subscribe(el, callback) {
+ $(el).on(
+ "toggleCollapse.sidebarInputBinding",
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ function(event) {
+ callback(true);
+ }
+ );
+ }
+ unsubscribe(el) {
+ $(el).off(".sidebarInputBinding");
+ }
+ receiveMessage(el, data) {
+ const sb = Sidebar.getInstance(el.parentElement);
+ if (sb)
+ sb.toggle(data.method);
+ }
+ };
+ registerBinding(SidebarInputBinding, "sidebar");
+ window.bslib = window.bslib || {};
+ window.bslib.Sidebar = Sidebar;
}
- };
- registerBinding(SidebarInputBinding, "sidebar");
- window.bslib = window.bslib || {};
- window.bslib.Sidebar = Sidebar;
+ });
// srcts/src/components/_shinyAddCustomMessageHandlers.ts
function shinyAddCustomMessageHandlers(handlers) {
@@ -879,33 +960,45 @@
Shiny.addCustomMessageHandler(name, handler);
}
}
+ var init_shinyAddCustomMessageHandlers = __esm({
+ "srcts/src/components/_shinyAddCustomMessageHandlers.ts"() {
+ "use strict";
+ }
+ });
// srcts/src/components/index.ts
- var bslibMessageHandlers = {
- // eslint-disable-next-line @typescript-eslint/naming-convention
- "bslib.toggle-input-binary": (msg) => {
- const el = document.getElementById(msg.id);
- if (!el) {
- console.warn("[bslib.toggle-input-binary] No element found", msg);
- }
- const binding = $(el).data("shiny-input-binding");
- if (!(binding instanceof InputBinding)) {
- console.warn("[bslib.toggle-input-binary] No input binding found", msg);
- return;
- }
- let value = msg.value;
- if (typeof value === "undefined") {
- value = !binding.getValue(el);
+ var require_components = __commonJS({
+ "srcts/src/components/index.ts"(exports) {
+ init_accordion();
+ init_card();
+ init_sidebar();
+ init_utils();
+ init_shinyAddCustomMessageHandlers();
+ var bslibMessageHandlers = {
+ // eslint-disable-next-line @typescript-eslint/naming-convention
+ "bslib.toggle-input-binary": (msg) => __async(exports, null, function* () {
+ const el = document.getElementById(msg.id);
+ if (!el) {
+ console.warn("[bslib.toggle-input-binary] No element found", msg);
+ }
+ const binding = $(el).data("shiny-input-binding");
+ if (!(binding instanceof InputBinding)) {
+ console.warn("[bslib.toggle-input-binary] No input binding found", msg);
+ return;
+ }
+ let value = msg.value;
+ if (typeof value === "undefined") {
+ value = !binding.getValue(el);
+ }
+ yield binding.receiveMessage(el, { value });
+ })
+ };
+ if (window.Shiny) {
+ shinyAddCustomMessageHandlers(bslibMessageHandlers);
}
- binding.receiveMessage(el, { value });
- }
- };
- if (window.Shiny) {
- shinyAddCustomMessageHandlers(bslibMessageHandlers);
- }
- function insertSvgGradient() {
- const temp = document.createElement("div");
- temp.innerHTML = `
+ function insertSvgGradient() {
+ const temp = document.createElement("div");
+ temp.innerHTML = `
`;
- document.body.appendChild(temp.children[0]);
- }
- if (document.readyState === "complete") {
- insertSvgGradient();
- } else {
- document.addEventListener("DOMContentLoaded", insertSvgGradient);
- }
+ document.body.appendChild(temp.children[0]);
+ }
+ if (document.readyState === "complete") {
+ insertSvgGradient();
+ } else {
+ document.addEventListener("DOMContentLoaded", insertSvgGradient);
+ }
+ }
+ });
+ require_components();
})();
//# sourceMappingURL=components.js.map
diff --git a/inst/components/dist/components.js.map b/inst/components/dist/components.js.map
index 466642a69..c3fb21dd5 100644
--- a/inst/components/dist/components.js.map
+++ b/inst/components/dist/components.js.map
@@ -1,7 +1,7 @@
{
"version": 3,
"sources": ["../../../srcts/src/components/_utils.ts", "../../../srcts/src/components/accordion.ts", "../../../srcts/src/components/_shinyResizeObserver.ts", "../../../srcts/src/components/card.ts", "../../../srcts/src/components/sidebar.ts", "../../../srcts/src/components/_shinyAddCustomMessageHandlers.ts", "../../../srcts/src/components/index.ts"],
- "sourcesContent": ["import type { HtmlDep } from \"rstudio-shiny/srcts/types/src/shiny/render\";\n\nimport type { InputBinding as InputBindingType } from \"rstudio-shiny/srcts/types/src/bindings/input\";\n\n// Exclude undefined from T\ntype NotUndefined = T extends undefined ? never : T;\n\n// eslint-disable-next-line @typescript-eslint/naming-convention\nconst InputBinding = (\n window.Shiny ? Shiny.InputBinding : class {}\n) as typeof InputBindingType;\n\nfunction registerBinding(\n inputBindingClass: new () => InputBindingType,\n name: string\n): void {\n if (window.Shiny) {\n Shiny.inputBindings.register(new inputBindingClass(), \"bslib.\" + name);\n }\n}\n\n// Return true if the key exists on the object and the value is not undefined.\n//\n// This method is mainly used in input bindings' `receiveMessage` method.\n// Since we know that the values are sent by Shiny via `{jsonlite}`,\n// then we know that there are no `undefined` values. `null` is possible, but not `undefined`.\nfunction hasDefinedProperty<\n Prop extends keyof X,\n X extends { [key: string]: any }\n>(\n obj: X,\n prop: Prop\n): obj is X & { [key in NonNullable]: NotUndefined } {\n return (\n Object.prototype.hasOwnProperty.call(obj, prop) && obj[prop] !== undefined\n );\n}\n\n// TODO: Shiny should trigger resize events when the output\n// https://github.com/rstudio/shiny/pull/3682\nfunction doWindowResizeOnElementResize(el: HTMLElement): void {\n if ($(el).data(\"window-resize-observer\")) {\n return;\n }\n const resizeEvent = new Event(\"resize\");\n const ro = new ResizeObserver(() => {\n window.dispatchEvent(resizeEvent);\n });\n ro.observe(el);\n $(el).data(\"window-resize-observer\", ro);\n}\n\nfunction getAllFocusableChildren(el: HTMLElement): HTMLElement[] {\n // Cross-referenced with https://allyjs.io/data-tables/focusable.html\n const base = [\n \"a[href]\",\n \"area[href]\",\n \"button\",\n \"details summary\",\n \"input\",\n \"iframe\",\n \"select\",\n \"textarea\",\n '[contentEditable=\"\"]',\n '[contentEditable=\"true\"]',\n '[contentEditable=\"TRUE\"]',\n \"[tabindex]\",\n ];\n const modifiers = [':not([tabindex=\"-1\"])', \":not([disabled])\"];\n const selectors = base.map((b) => b + modifiers.join(\"\"));\n const focusable = el.querySelectorAll(selectors.join(\", \"));\n return Array.from(focusable) as HTMLElement[];\n}\n\nexport {\n InputBinding,\n registerBinding,\n hasDefinedProperty,\n doWindowResizeOnElementResize,\n getAllFocusableChildren,\n};\nexport type { HtmlDep };\n", "import type { HtmlDep } from \"./_utils\";\nimport { InputBinding, registerBinding, hasDefinedProperty } from \"./_utils\";\n\ntype AccordionItem = {\n item: HTMLElement;\n value: string;\n isOpen: () => boolean;\n show: () => void;\n hide: () => void;\n};\n\ntype HTMLContent = {\n html: string;\n deps?: HtmlDep[];\n};\n\ntype SetMessage = {\n method: \"set\";\n values: string[];\n};\n\ntype OpenMessage = {\n method: \"open\";\n values: string[] | true;\n};\n\ntype CloseMessage = {\n method: \"close\";\n values: string[] | true;\n};\n\ntype InsertMessage = {\n method: \"insert\";\n panel: HTMLContent;\n target: string;\n position: \"after\" | \"before\";\n};\n\ntype RemoveMessage = {\n method: \"remove\";\n target: string[];\n};\n\ntype UpdateMessage = {\n method: \"update\";\n target: string;\n value: string;\n body: HTMLContent;\n title: HTMLContent;\n icon: HTMLContent;\n};\n\ntype MessageData =\n | CloseMessage\n | InsertMessage\n | OpenMessage\n | RemoveMessage\n | SetMessage\n | UpdateMessage;\n\nclass AccordionInputBinding extends InputBinding {\n find(scope: HTMLElement) {\n return $(scope).find(\".accordion.bslib-accordion-input\");\n }\n\n getValue(el: HTMLElement): string[] | null {\n const items = this._getItemInfo(el);\n const selected = items.filter((x) => x.isOpen()).map((x) => x.value);\n return selected.length === 0 ? null : selected;\n }\n\n subscribe(el: HTMLElement, callback: (x: boolean) => void) {\n $(el).on(\n \"shown.bs.collapse.accordionInputBinding hidden.bs.collapse.accordionInputBinding\",\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n function (event) {\n callback(true);\n }\n );\n }\n\n unsubscribe(el: HTMLElement) {\n $(el).off(\".accordionInputBinding\");\n }\n\n receiveMessage(el: HTMLElement, data: MessageData) {\n const method = data.method;\n if (method === \"set\") {\n this._setItems(el, data);\n } else if (method === \"open\") {\n this._openItems(el, data);\n } else if (method === \"close\") {\n this._closeItems(el, data);\n } else if (method === \"remove\") {\n this._removeItem(el, data);\n } else if (method === \"insert\") {\n this._insertItem(el, data);\n } else if (method === \"update\") {\n this._updateItem(el, data);\n } else {\n throw new Error(`Method not yet implemented: ${method}`);\n }\n }\n\n protected _setItems(el: HTMLElement, data: SetMessage) {\n const items = this._getItemInfo(el);\n const vals = this._getValues(el, items, data.values);\n items.forEach((x) => {\n vals.indexOf(x.value) > -1 ? x.show() : x.hide();\n });\n }\n\n protected _openItems(el: HTMLElement, data: OpenMessage) {\n const items = this._getItemInfo(el);\n const vals = this._getValues(el, items, data.values);\n items.forEach((x) => {\n if (vals.indexOf(x.value) > -1) x.show();\n });\n }\n\n protected _closeItems(el: HTMLElement, data: CloseMessage) {\n const items = this._getItemInfo(el);\n const vals = this._getValues(el, items, data.values);\n items.forEach((x) => {\n if (vals.indexOf(x.value) > -1) x.hide();\n });\n }\n\n protected _insertItem(el: HTMLElement, data: InsertMessage) {\n let targetItem = this._findItem(el, data.target);\n\n // If no target was specified, or the target was not found, then default\n // to the first or last item, depending on the position\n if (!targetItem) {\n targetItem = (\n data.position === \"before\" ? el.firstElementChild : el.lastElementChild\n ) as HTMLElement;\n }\n\n const panel = data.panel;\n\n // If there is still no targetItem, then there are no items in the accordion\n if (targetItem) {\n Shiny.renderContent(\n targetItem,\n panel,\n data.position === \"before\" ? \"beforeBegin\" : \"afterEnd\"\n );\n } else {\n Shiny.renderContent(el, panel);\n }\n\n // Need to add a reference to the parent id that makes autoclose to work\n if (this._isAutoClosing(el)) {\n const val = $(panel.html).attr(\"data-value\");\n $(el)\n .find(`[data-value=\"${val}\"] .accordion-collapse`)\n .attr(\"data-bs-parent\", \"#\" + el.id);\n }\n }\n\n protected _removeItem(el: HTMLElement, data: RemoveMessage) {\n const targetItems = this._getItemInfo(el).filter(\n (x) => data.target.indexOf(x.value) > -1\n );\n\n const unbindAll = Shiny?.unbindAll;\n\n targetItems.forEach((x) => {\n if (unbindAll) unbindAll(x.item);\n x.item.remove();\n });\n }\n\n protected _updateItem(el: HTMLElement, data: UpdateMessage) {\n const target = this._findItem(el, data.target);\n\n if (!target) {\n throw new Error(\n `Unable to find an accordion_panel() with a value of ${data.target}`\n );\n }\n\n if (hasDefinedProperty(data, \"value\")) {\n target.dataset.value = data.value;\n }\n\n if (hasDefinedProperty(data, \"body\")) {\n const body = target.querySelector(\".accordion-body\") as HTMLElement; // always exists\n Shiny.renderContent(body, data.body);\n }\n\n const header = target.querySelector(\".accordion-header\") as HTMLElement; // always exists\n\n if (hasDefinedProperty(data, \"title\")) {\n const title = header.querySelector(\".accordion-title\") as HTMLElement; // always exists\n Shiny.renderContent(title, data.title);\n }\n\n if (hasDefinedProperty(data, \"icon\")) {\n const icon = header.querySelector(\n \".accordion-button > .accordion-icon\"\n ) as HTMLElement; // always exists\n Shiny.renderContent(icon, data.icon);\n }\n }\n\n protected _getItemInfo(el: HTMLElement): AccordionItem[] {\n const items = Array.from(\n el.querySelectorAll(\":scope > .accordion-item\")\n ) as HTMLElement[];\n return items.map((x) => this._getSingleItemInfo(x));\n }\n\n protected _getSingleItemInfo(x: HTMLElement): AccordionItem {\n const collapse = x.querySelector(\".accordion-collapse\") as HTMLElement;\n const isOpen = () => $(collapse).hasClass(\"show\");\n return {\n item: x,\n value: x.dataset.value as string,\n isOpen: isOpen,\n show: () => {\n if (!isOpen()) $(collapse).collapse(\"show\");\n },\n hide: () => {\n if (isOpen()) $(collapse).collapse(\"hide\");\n },\n };\n }\n\n protected _getValues(\n el: HTMLElement,\n items: AccordionItem[],\n values: string[] | true\n ): string[] {\n let vals = values !== true ? values : items.map((x) => x.value);\n const autoclose = this._isAutoClosing(el);\n if (autoclose) {\n vals = vals.slice(vals.length - 1, vals.length);\n }\n return vals;\n }\n\n protected _findItem(el: HTMLElement, value: string): HTMLElement | null {\n return el.querySelector(`[data-value=\"${value}\"]`);\n }\n\n protected _isAutoClosing(el: HTMLElement): boolean {\n return el.classList.contains(\"autoclose\");\n }\n}\n\nregisterBinding(AccordionInputBinding, \"accordion\");\n", "/**\n * A resize observer that ensures Shiny outputs resize during or just after\n * their parent container size changes. Useful, in particular, for sidebar\n * transitions or for full-screen card transitions.\n *\n * @class ShinyResizeObserver\n * @typedef {ShinyResizeObserver}\n */\nclass ShinyResizeObserver {\n /**\n * The actual ResizeObserver instance.\n * @private\n * @type {ResizeObserver}\n */\n private resizeObserver: ResizeObserver;\n /**\n * An array of elements that are currently being watched by the Resize\n * Observer.\n *\n * @details\n * We don't currently have lifecycle hooks that allow us to unobserve elements\n * when they are removed from the DOM. As a result, we need to manually check\n * that the elements we're watching still exist in the DOM. This array keeps\n * track of the elements we're watching so that we can check them later.\n * @private\n * @type {HTMLElement[]}\n */\n private resizeObserverEntries: HTMLElement[];\n\n /**\n * Watch containers for size changes and ensure that Shiny outputs and\n * htmlwidgets within resize appropriately.\n *\n * @details\n * The ShinyResizeObserver is used to watch the containers, such as Sidebars\n * and Cards for size changes, in particular when the sidebar state is toggled\n * or the card body is expanded full screen. It performs two primary tasks:\n *\n * 1. Dispatches a `resize` event on the window object. This is necessary to\n * ensure that Shiny outputs resize appropriately. In general, the window\n * resizing is throttled and the output update occurs when the transition\n * is complete.\n * 2. If an output with a resize method on the output binding is detected, we\n * directly call the `.onResize()` method of the binding. This ensures that\n * htmlwidgets transition smoothly. In static mode, htmlwidgets does this\n * already.\n *\n * @note\n * This resize observer also handles race conditions in some complex\n * fill-based layouts with multiple outputs (e.g., plotly), where shiny\n * initializes with the correct sizing, but in-between the 1st and last\n * renderValue(), the size of the output containers can change, meaning every\n * output but the 1st gets initialized with the wrong size during their\n * renderValue(). Then, after the render phase, shiny won't know to trigger a\n * resize since all the widgets will return to their original size (and thus,\n * Shiny thinks there isn't any resizing to do). The resize observer works\n * around this by ensuring that the output is resized whenever its container\n * size changes.\n * @constructor\n */\n constructor() {\n this.resizeObserverEntries = [];\n this.resizeObserver = new ResizeObserver((entries) => {\n const resizeEvent = new Event(\"resize\");\n window.dispatchEvent(resizeEvent);\n\n // the rest of this callback is only relevant in Shiny apps\n if (!window.Shiny) return;\n\n const resized = [] as HTMLElement[];\n\n for (const entry of entries) {\n if (!(entry.target instanceof HTMLElement)) continue;\n if (!entry.target.querySelector(\".shiny-bound-output\")) continue;\n\n entry.target\n .querySelectorAll(\".shiny-bound-output\")\n .forEach((el) => {\n if (resized.includes(el)) return;\n\n const { binding, onResize } = $(el).data(\"shinyOutputBinding\");\n if (!binding || !binding.resize) return;\n\n // if this output is owned by another observer, skip it\n const owner = (el as any).shinyResizeObserver;\n if (owner && owner !== this) return;\n // mark this output as owned by this shinyResizeObserver instance\n if (!owner) (el as any).shinyResizeObserver = this;\n\n // trigger immediate resizing of outputs with a resize method\n onResize(el);\n // only once per output and resize event\n resized.push(el);\n\n // set plot images to 100% width temporarily during the transition\n if (!el.classList.contains(\"shiny-plot-output\")) return;\n const img = el.querySelector(\n 'img:not([width=\"100%\"])'\n );\n if (img) img.setAttribute(\"width\", \"100%\");\n });\n }\n });\n }\n\n /**\n * Observe an element for size changes.\n * @param {HTMLElement} el - The element to observe.\n */\n observe(el: HTMLElement): void {\n this.resizeObserver.observe(el);\n this.resizeObserverEntries.push(el);\n }\n\n /**\n * Stop observing an element for size changes.\n * @param {HTMLElement} el - The element to stop observing.\n */\n unobserve(el: HTMLElement): void {\n const idxEl = this.resizeObserverEntries.indexOf(el);\n if (idxEl < 0) return;\n\n this.resizeObserver.unobserve(el);\n this.resizeObserverEntries.splice(idxEl, 1);\n }\n\n /**\n * This method checks that we're not continuing to watch elements that no\n * longer exist in the DOM. If any are found, we stop observing them and\n * remove them from our array of observed elements.\n *\n * @private\n * @static\n */\n flush(): void {\n this.resizeObserverEntries.forEach((el) => {\n if (!document.body.contains(el)) this.unobserve(el);\n });\n }\n}\n\nexport { ShinyResizeObserver };\n", "import { getAllFocusableChildren } from \"./_utils\";\nimport { ShinyResizeObserver } from \"./_shinyResizeObserver\";\n\n/**\n * The overlay element that is placed behind the card when expanded full screen.\n *\n * @interface CardFullScreenOverlay\n * @typedef {CardFullScreenOverlay}\n */\ninterface CardFullScreenOverlay {\n /**\n * The full screen overlay container.\n * @type {HTMLDivElement}\n */\n container: HTMLDivElement;\n /**\n * The anchor element used to close the full screen overlay.\n * @type {HTMLAnchorElement}\n */\n anchor: HTMLAnchorElement;\n}\n\n/**\n * The bslib card component class.\n *\n * @class Card\n * @typedef {Card}\n */\nclass Card {\n /**\n * The card container element.\n * @private\n * @type {HTMLElement}\n */\n private card: HTMLElement;\n /**\n * The card's full screen overlay element. We create this element once and add\n * and remove it from the DOM as needed (this simplifies focus management\n * while in full screen mode).\n * @private\n * @type {CardFullScreenOverlay}\n */\n private overlay: CardFullScreenOverlay;\n\n /**\n * Key bslib-specific classes and attributes used by the card component.\n * @private\n * @static\n * @type {{ ATTR_INIT: string; CLASS_CARD: string; CLASS_FULL_SCREEN: string; CLASS_HAS_FULL_SCREEN: string; CLASS_FULL_SCREEN_ENTER: string; CLASS_FULL_SCREEN_EXIT: string; ID_FULL_SCREEN_OVERLAY: string; }}\n */\n private static attr = {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n ATTR_INIT: \"data-bslib-card-init\",\n // eslint-disable-next-line @typescript-eslint/naming-convention\n CLASS_CARD: \"bslib-card\",\n // eslint-disable-next-line @typescript-eslint/naming-convention\n ATTR_FULL_SCREEN: \"data-full-screen\",\n // eslint-disable-next-line @typescript-eslint/naming-convention\n CLASS_HAS_FULL_SCREEN: \"bslib-has-full-screen\",\n // eslint-disable-next-line @typescript-eslint/naming-convention\n CLASS_FULL_SCREEN_ENTER: \"bslib-full-screen-enter\",\n // eslint-disable-next-line @typescript-eslint/naming-convention\n CLASS_FULL_SCREEN_EXIT: \"bslib-full-screen-exit\",\n // eslint-disable-next-line @typescript-eslint/naming-convention\n ID_FULL_SCREEN_OVERLAY: \"bslib-full-screen-overlay\",\n };\n\n /**\n * A Shiny-specific resize observer that ensures Shiny outputs in within the\n * card resize appropriately.\n * @private\n * @type {ShinyResizeObserver}\n * @static\n */\n private static shinyResizeObserver = new ShinyResizeObserver();\n\n /**\n * Creates an instance of a bslib Card component.\n *\n * @constructor\n * @param {HTMLElement} card\n */\n constructor(card: HTMLElement) {\n // remove initialization attribute and script\n card.removeAttribute(Card.attr.ATTR_INIT);\n card\n .querySelector(`script[${Card.attr.ATTR_INIT}]`)\n ?.remove();\n\n this.card = card;\n Card.instanceMap.set(card, this);\n\n // Let Shiny know to trigger resize when the card size changes\n // TODO: shiny could/should do this itself (rstudio/shiny#3682)\n Card.shinyResizeObserver.observe(this.card);\n\n this._addEventListeners();\n this.overlay = this._createOverlay();\n\n // bind event handler methods to this card instance\n this._exitFullScreenOnEscape = this._exitFullScreenOnEscape.bind(this);\n this._trapFocusExit = this._trapFocusExit.bind(this);\n }\n\n /**\n * Enter the card's full screen mode, either programmatically or via an event\n * handler. Full screen mode is activated by adding a class to the card that\n * positions it absolutely and expands it to fill the viewport. In addition,\n * we add a full screen overlay element behind the card and we trap focus in\n * the expanded card while in full screen mode.\n *\n * @param {?Event} [event]\n */\n enterFullScreen(event?: Event): void {\n if (event) event.preventDefault();\n\n document.addEventListener(\"keydown\", this._exitFullScreenOnEscape, false);\n\n // trap focus in the fullscreen container, listening for Tab key on the\n // capture phase so we have the best chance of preventing other handlers\n document.addEventListener(\"keydown\", this._trapFocusExit, true);\n\n this.card.setAttribute(Card.attr.ATTR_FULL_SCREEN, \"true\");\n document.body.classList.add(Card.attr.CLASS_HAS_FULL_SCREEN);\n this.card.insertAdjacentElement(\"beforebegin\", this.overlay.container);\n\n // Set initial focus on the card, if not already\n if (\n !this.card.contains(document.activeElement) ||\n document.activeElement?.classList.contains(\n Card.attr.CLASS_FULL_SCREEN_ENTER\n )\n ) {\n this.card.setAttribute(\"tabindex\", \"-1\");\n this.card.focus();\n }\n }\n\n /**\n * Exit full screen mode. This removes the full screen overlay element,\n * removes the full screen class from the card, and removes the keyboard event\n * listeners that were added when entering full screen mode.\n */\n exitFullScreen(): void {\n document.removeEventListener(\n \"keydown\",\n this._exitFullScreenOnEscape,\n false\n );\n document.removeEventListener(\"keydown\", this._trapFocusExit, true);\n\n // Remove overlay and remove full screen classes from card\n this.overlay.container.remove();\n this.card.setAttribute(Card.attr.ATTR_FULL_SCREEN, \"false\");\n this.card.removeAttribute(\"tabindex\");\n document.body.classList.remove(Card.attr.CLASS_HAS_FULL_SCREEN);\n }\n\n /**\n * Adds general card-specific event listeners.\n * @private\n */\n private _addEventListeners(): void {\n const btnFullScreen = this.card.querySelector(\n `:scope > * > .${Card.attr.CLASS_FULL_SCREEN_ENTER}`\n );\n if (!btnFullScreen) return;\n btnFullScreen.addEventListener(\"click\", (ev) => this.enterFullScreen(ev));\n }\n\n /**\n * An event handler to exit full screen mode when the Escape key is pressed.\n * @private\n * @param {KeyboardEvent} event\n */\n private _exitFullScreenOnEscape(event: KeyboardEvent): void {\n if (!(event.target instanceof HTMLElement)) return;\n // If the user is in the middle of a select input choice, don't exit\n const selOpenSelectInput = [\"select[open]\", \"input[aria-expanded='true']\"];\n if (event.target.matches(selOpenSelectInput.join(\", \"))) return;\n\n if (event.key === \"Escape\") {\n this.exitFullScreen();\n }\n }\n\n /**\n * An event handler to trap focus within the card when in full screen mode.\n *\n * @description\n * This keyboard event handler ensures that tab focus stays within the card\n * when in full screen mode. When the card is first expanded,\n * we move focus to the card element itself. If focus somehow leaves the card,\n * we returns focus to the card container.\n *\n * Within the card, we handle only tabbing from the close anchor or the last\n * focusable element and only when tab focus would have otherwise left the\n * card. In those cases, we cycle focus to the last focusable element or back\n * to the anchor. If the card doesn't have any focusable elements, we move\n * focus to the close anchor.\n *\n * @note\n * Because the card contents may change, we check for focusable elements\n * every time the handler is called.\n *\n * @private\n * @param {KeyboardEvent} event\n */\n private _trapFocusExit(event: KeyboardEvent): void {\n if (!(event instanceof KeyboardEvent)) return;\n if (event.key !== \"Tab\") return;\n\n const isFocusedContainer = event.target === this.card;\n const isFocusedAnchor = event.target === this.overlay.anchor;\n const isFocusedWithin = this.card.contains(event.target as Node);\n\n const stopEvent = () => {\n event.preventDefault();\n event.stopImmediatePropagation();\n };\n\n if (!(isFocusedWithin || isFocusedContainer || isFocusedAnchor)) {\n // If focus is outside the card, return to the card\n stopEvent();\n this.card.focus();\n return;\n }\n\n // Check focusables every time because the card contents may have changed\n // but exclude the full screen enter button from this list of elements\n const focusableElements = getAllFocusableChildren(this.card).filter(\n (el) => !el.classList.contains(Card.attr.CLASS_FULL_SCREEN_ENTER)\n );\n const hasFocusableElements = focusableElements.length > 0;\n\n // We need to handle five cases:\n // 1. The card has no focusable elements --> focus the anchor\n // 2. Focus is on the card container (do nothing, natural tab order)\n // 3. Focus is on the anchor and the user pressed Tab + Shift (backwards)\n // -> Move to the last focusable element (end of card)\n // 4. Focus is on the last focusable element and the user pressed Tab\n // (forwards) -> Move to the anchor (top of card)\n // 5. otherwise we don't interfere\n\n if (!hasFocusableElements) {\n // case 1\n stopEvent();\n this.overlay.anchor.focus();\n return;\n }\n\n // case 2\n if (isFocusedContainer) return;\n\n const lastFocusable = focusableElements[focusableElements.length - 1];\n const isFocusedLast = event.target === lastFocusable;\n\n if (isFocusedAnchor && event.shiftKey) {\n stopEvent();\n lastFocusable.focus();\n return;\n }\n\n if (isFocusedLast && !event.shiftKey) {\n stopEvent();\n this.overlay.anchor.focus();\n return;\n }\n }\n\n /**\n * Creates the full screen overlay.\n * @private\n * @returns {CardFullScreenOverlay}\n */\n private _createOverlay(): CardFullScreenOverlay {\n const container = document.createElement(\"div\");\n container.id = Card.attr.ID_FULL_SCREEN_OVERLAY;\n container.onclick = this.exitFullScreen.bind(this);\n\n const anchor = this._createOverlayCloseAnchor();\n container.appendChild(anchor);\n\n return { container, anchor };\n }\n\n /**\n * Creates the anchor element used to exit the full screen mode.\n * @private\n * @returns {HTMLAnchorElement}\n */\n private _createOverlayCloseAnchor(): HTMLAnchorElement {\n const anchor = document.createElement(\"a\");\n anchor.classList.add(Card.attr.CLASS_FULL_SCREEN_EXIT);\n anchor.tabIndex = 0;\n anchor.onclick = () => this.exitFullScreen();\n anchor.onkeydown = (ev) => {\n if (ev.key === \"Enter\" || ev.key === \" \") {\n this.exitFullScreen();\n }\n };\n anchor.innerHTML = this._overlayCloseHtml();\n\n return anchor;\n }\n\n /**\n * Returns the HTML for the close icon.\n * @private\n * @returns {string}\n */\n private _overlayCloseHtml(): string {\n return (\n \"Close \" +\n \"\"\n );\n }\n\n /**\n * The registry of card instances and their associated DOM elements.\n * @private\n * @static\n * @type {WeakMap}\n */\n private static instanceMap: WeakMap = new WeakMap();\n\n /**\n * Returns the card instance associated with the given element, if any.\n * @public\n * @static\n * @param {HTMLElement} el\n * @returns {(Card | undefined)}\n */\n public static getInstance(el: HTMLElement): Card | undefined {\n return Card.instanceMap.get(el);\n }\n\n /**\n * If cards are initialized before the DOM is ready, we re-schedule the\n * initialization to occur on DOMContentLoaded.\n * @private\n * @static\n * @type {boolean}\n */\n private static onReadyScheduled = false;\n\n /**\n * Initializes all cards that require initialization on the page, or schedules\n * initialization if the DOM is not yet ready.\n * @public\n * @static\n * @param {boolean} [flushResizeObserver=true]\n */\n public static initializeAllCards(flushResizeObserver = true): void {\n if (document.readyState === \"loading\") {\n if (!Card.onReadyScheduled) {\n Card.onReadyScheduled = true;\n document.addEventListener(\"DOMContentLoaded\", () => {\n Card.initializeAllCards(false);\n });\n }\n return;\n }\n\n if (flushResizeObserver) {\n // Trigger a recheck of observed cards to unobserve non-existent cards\n Card.shinyResizeObserver.flush();\n }\n\n const initSelector = `.${Card.attr.CLASS_CARD}[${Card.attr.ATTR_INIT}]`;\n if (!document.querySelector(initSelector)) {\n // no cards to initialize\n return;\n }\n\n const cards = document.querySelectorAll(initSelector);\n cards.forEach((card) => new Card(card as HTMLElement));\n }\n}\n\n// attach Sidebar class to window for global usage\n(window as any).bslib = (window as any).bslib || {};\n(window as any).bslib.Card = Card;\n\nexport { Card };\n", "import { InputBinding, registerBinding } from \"./_utils\";\nimport { ShinyResizeObserver } from \"./_shinyResizeObserver\";\n\n/**\n * Methods for programmatically toggling the state of the sidebar. These methods\n * describe the desired state of the sidebar: `\"close\"` and `\"open\"` transition\n * the sidebar to the desired state, unless the sidebar is already in that\n * state. `\"toggle\"` transitions the sidebar to the state opposite of its\n * current state.\n * @typedef {SidebarToggleMethod}\n */\ntype SidebarToggleMethod = \"close\" | \"open\" | \"toggle\";\n\n/**\n * Data received by the input binding's `receiveMessage` method.\n * @typedef {SidebarMessageData}\n */\ntype SidebarMessageData = {\n method: SidebarToggleMethod;\n};\n\n/**\n * The DOM elements that make up the sidebar. `main`, `sidebar`, and `toggle`\n * are all direct children of `container` (in that order).\n * @interface SidebarComponents\n * @typedef {SidebarComponents}\n */\ninterface SidebarComponents {\n /**\n * The `layout_sidebar()` parent container, with class\n * `Sidebar.classes.LAYOUT`.\n * @type {HTMLElement}\n */\n container: HTMLElement;\n /**\n * The main content area of the sidebar layout.\n * @type {HTMLElement}\n */\n main: HTMLElement;\n /**\n * The sidebar container of the sidebar layout.\n * @type {HTMLElement}\n */\n sidebar: HTMLElement;\n /**\n * The toggle button that is used to toggle the sidebar state.\n * @type {HTMLElement}\n */\n toggle: HTMLElement;\n}\n\n/**\n * The bslib sidebar component class. This class is only used for collapsible\n * sidebars.\n *\n * @class Sidebar\n * @typedef {Sidebar}\n */\nclass Sidebar {\n /**\n * The DOM elements that make up the sidebar, see `SidebarComponents`.\n * @private\n * @type {SidebarComponents}\n */\n private layout: SidebarComponents;\n\n /**\n * A Shiny-specific resize observer that ensures Shiny outputs in the main\n * content areas of the sidebar resize appropriately.\n * @private\n * @type {ShinyResizeObserver}\n * @static\n */\n private static shinyResizeObserver = new ShinyResizeObserver();\n\n /**\n * Creates an instance of a collapsible bslib Sidebar.\n * @constructor\n * @param {HTMLElement} container\n */\n constructor(container: HTMLElement) {\n Sidebar.instanceMap.set(container, this);\n this.layout = {\n container,\n main: container.querySelector(\":scope > .main\") as HTMLElement,\n sidebar: container.querySelector(\":scope > .sidebar\") as HTMLElement,\n toggle: container.querySelector(\n \":scope > .collapse-toggle\"\n ) as HTMLElement,\n } as SidebarComponents;\n\n const sideAccordion = this.layout.sidebar.querySelector(\n \":scope > .sidebar-content > .accordion\"\n );\n if (sideAccordion) {\n // Add `.has-accordion` class to `.sidebar-content` container\n sideAccordion?.parentElement?.classList.add(\"has-accordion\");\n sideAccordion.classList.add(\"accordion-flush\");\n }\n\n if (this.layout.toggle) {\n this._initEventListeners();\n this._initSidebarCounters();\n this._initDesktop();\n }\n\n // Start watching the main content area for size changes to ensure Shiny\n // outputs resize appropriately during sidebar transitions.\n Sidebar.shinyResizeObserver.observe(this.layout.main);\n\n container.removeAttribute(\"data-bslib-sidebar-init\");\n const initScript = container.querySelector(\n \":scope > script[data-bslib-sidebar-init]\"\n );\n if (initScript) {\n container.removeChild(initScript);\n }\n }\n\n /**\n * Read the current state of the sidebar. Note that, when calling this method,\n * the sidebar may be transitioning into the state returned by this method.\n *\n * @description\n * The sidebar state works as follows, starting from the open state. When the\n * sidebar is closed:\n * 1. We add both the `COLLAPSE` and `TRANSITIONING` classes to the sidebar.\n * 2. The sidebar collapse begins to animate. On desktop devices, and where it\n * is supported, we transition the `grid-template-columns` property of the\n * sidebar layout. On mobile, the sidebar is hidden immediately. In both\n * cases, the collapse icon rotates and we use this rotation to determine\n * when the transition is complete.\n * 3. If another sidebar state toggle is requested while closing the sidebar,\n * we remove the `COLLAPSE` class and the animation immediately starts to\n * reverse.\n * 4. When the `transition` is complete, we remove the `TRANSITIONING` class.\n * @readonly\n * @type {boolean}\n */\n get isClosed(): boolean {\n return this.layout.container.classList.contains(Sidebar.classes.COLLAPSE);\n }\n\n /**\n * Static classes related to the sidebar layout or state.\n * @public\n * @static\n * @readonly\n * @type {{ LAYOUT: string; COLLAPSE: string; TRANSITIONING: string; }}\n */\n public static readonly classes = {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n LAYOUT: \"bslib-sidebar-layout\",\n // eslint-disable-next-line @typescript-eslint/naming-convention\n COLLAPSE: \"sidebar-collapsed\",\n // eslint-disable-next-line @typescript-eslint/naming-convention\n TRANSITIONING: \"transitioning\",\n };\n\n /**\n * If sidebars are initialized before the DOM is ready, we re-schedule the\n * initialization to occur on DOMContentLoaded.\n * @private\n * @static\n * @type {boolean}\n */\n private static onReadyScheduled = false;\n /**\n * A map of initialized sidebars to their respective Sidebar instances.\n * @private\n * @static\n * @type {WeakMap}\n */\n private static instanceMap: WeakMap = new WeakMap();\n\n /**\n * Given a sidebar container, return the Sidebar instance associated with it.\n * @public\n * @static\n * @param {HTMLElement} el\n * @returns {(Sidebar | undefined)}\n */\n public static getInstance(el: HTMLElement): Sidebar | undefined {\n return Sidebar.instanceMap.get(el);\n }\n\n /**\n * Initialize all collapsible sidebars on the page.\n * @public\n * @static\n * @param {boolean} [flushResizeObserver=true] When `true`, we remove\n * non-existent elements from the ResizeObserver. This is required\n * periodically to prevent memory leaks. To avoid over-checking, we only flush\n * the ResizeObserver when initializing sidebars after page load.\n */\n public static initCollapsibleAll(flushResizeObserver = true): void {\n if (document.readyState === \"loading\") {\n if (!Sidebar.onReadyScheduled) {\n Sidebar.onReadyScheduled = true;\n document.addEventListener(\"DOMContentLoaded\", () => {\n Sidebar.initCollapsibleAll(false);\n });\n }\n return;\n }\n\n const initSelector = `.${Sidebar.classes.LAYOUT}[data-bslib-sidebar-init]`;\n if (!document.querySelector(initSelector)) {\n // no sidebars to initialize\n return;\n }\n\n if (flushResizeObserver) Sidebar.shinyResizeObserver.flush();\n\n const containers = document.querySelectorAll(initSelector);\n containers.forEach((container) => new Sidebar(container as HTMLElement));\n }\n\n /**\n * Initialize event listeners for the sidebar toggle button.\n * @private\n */\n private _initEventListeners(): void {\n const { toggle } = this.layout;\n\n toggle.addEventListener(\"click\", (ev) => {\n ev.preventDefault();\n this.toggle(\"toggle\");\n });\n\n // Remove the transitioning class when the transition ends. We watch the\n // collapse toggle icon because it's guaranteed to transition, whereas the\n // sidebar doesn't animate on mobile (or in browsers where animating\n // grid-template-columns is not supported).\n toggle\n .querySelector(\".collapse-icon\")\n ?.addEventListener(\"transitionend\", () => this._finalizeState());\n }\n\n /**\n * Initialize nested sidebar counters.\n *\n * @description\n * This function walks up the DOM tree, adding CSS variables to each direct\n * parent sidebar layout that count the layout's position in the stack of\n * nested layouts. We use these counters to keep the collapse toggles from\n * overlapping. Note that always-open sidebars that don't have collapse\n * toggles break the chain of nesting.\n * @private\n */\n private _initSidebarCounters(): void {\n const { container } = this.layout;\n\n const selectorChildLayouts =\n `.${Sidebar.classes.LAYOUT}` +\n \"> .main > \" +\n `.${Sidebar.classes.LAYOUT}:not([data-bslib-sidebar-open=\"always\"])`;\n\n const isInnermostLayout =\n container.querySelector(selectorChildLayouts) === null;\n\n if (!isInnermostLayout) {\n // There are sidebar layouts nested within this layout; defer to children\n return;\n }\n\n function nextSidebarParent(el: HTMLElement | null): HTMLElement | null {\n el = el ? el.parentElement : null;\n if (el && el.classList.contains(\"main\")) {\n // .bslib-sidebar-layout > .main > .bslib-sidebar-layout\n el = el.parentElement;\n }\n if (el && el.classList.contains(Sidebar.classes.LAYOUT)) {\n return el;\n }\n return null;\n }\n\n const layouts = [container];\n let parent = nextSidebarParent(container);\n\n while (parent) {\n // Add parent to front of layouts array, so we sort outer -> inner\n layouts.unshift(parent);\n parent = nextSidebarParent(parent);\n }\n\n const count = { left: 0, right: 0 };\n layouts.forEach(function (x: HTMLElement): void {\n const isRight = x.classList.contains(\"sidebar-right\");\n const thisCount = isRight ? count.right++ : count.left++;\n x.style.setProperty(\"--_js-toggle-count-this-side\", thisCount.toString());\n x.style.setProperty(\n \"--_js-toggle-count-max-side\",\n Math.max(count.right, count.left).toString()\n );\n });\n }\n\n /**\n * Initialize the sidebar's initial state when `open = \"desktop\"`.\n * @private\n */\n private _initDesktop(): void {\n const { container } = this.layout;\n // If sidebar is marked open='desktop'...\n if (container.dataset.bslibSidebarOpen?.trim() !== \"desktop\") {\n return;\n }\n\n // then close sidebar on mobile\n const initCollapsed = window\n .getComputedStyle(container)\n .getPropertyValue(\"--bslib-sidebar-js-init-collapsed\");\n\n if (initCollapsed.trim() === \"true\") {\n this.toggle(\"close\");\n }\n }\n\n /**\n * Toggle the sidebar's open/closed state.\n * @public\n * @param {SidebarToggleMethod | undefined} method Whether to `\"open\"`,\n * `\"close\"` or `\"toggle\"` the sidebar. If `.toggle()` is called without an\n * argument, it will toggle the sidebar's state.\n */\n public toggle(method: SidebarToggleMethod | undefined): void {\n if (typeof method === \"undefined\") {\n method = \"toggle\";\n }\n\n const { container, sidebar } = this.layout;\n const isClosed = this.isClosed;\n\n if ([\"open\", \"close\", \"toggle\"].indexOf(method) === -1) {\n throw new Error(`Unknown method ${method}`);\n }\n\n if (method === \"toggle\") {\n method = isClosed ? \"open\" : \"close\";\n }\n\n if ((isClosed && method === \"close\") || (!isClosed && method === \"open\")) {\n // nothing to do, sidebar is already in the desired state\n return;\n }\n\n if (method === \"open\") {\n // unhide sidebar immediately when opening,\n // otherwise the sidebar is hidden on transitionend\n sidebar.hidden = false;\n }\n\n // Add a transitioning class just before adding COLLAPSE_CLASS since we want\n // some of the transitioning styles to apply before the collapse state\n container.classList.add(Sidebar.classes.TRANSITIONING);\n container.classList.toggle(Sidebar.classes.COLLAPSE);\n }\n\n /**\n * When the sidebar open/close transition ends, finalize the sidebar's state.\n * @private\n */\n private _finalizeState(): void {\n const { container, sidebar, toggle } = this.layout;\n container.classList.remove(Sidebar.classes.TRANSITIONING);\n sidebar.hidden = this.isClosed;\n toggle.setAttribute(\"aria-expanded\", this.isClosed ? \"false\" : \"true\");\n\n // Send browser-native event with updated sidebar state\n const event = new CustomEvent(\"bslib.sidebar\", {\n bubbles: true,\n detail: { open: !this.isClosed },\n });\n sidebar.dispatchEvent(event);\n\n // Trigger Shiny input and output binding events\n $(sidebar).trigger(\"toggleCollapse.sidebarInputBinding\");\n $(sidebar).trigger(this.isClosed ? \"hidden\" : \"shown\");\n }\n}\n\n/**\n * A Shiny input binding for a sidebar.\n * @class SidebarInputBinding\n * @typedef {SidebarInputBinding}\n * @extends {InputBinding}\n */\nclass SidebarInputBinding extends InputBinding {\n find(scope: HTMLElement) {\n return $(scope).find(`.${Sidebar.classes.LAYOUT} > .bslib-sidebar-input`);\n }\n\n getValue(el: HTMLElement): boolean {\n const sb = Sidebar.getInstance(el.parentElement as HTMLElement);\n if (!sb) return false;\n return !sb.isClosed;\n }\n\n setValue(el: HTMLElement, value: boolean): void {\n const method = value ? \"open\" : \"close\";\n this.receiveMessage(el, { method });\n }\n\n subscribe(el: HTMLElement, callback: (x: boolean) => void) {\n $(el).on(\n \"toggleCollapse.sidebarInputBinding\",\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n function (event) {\n callback(true);\n }\n );\n }\n\n unsubscribe(el: HTMLElement) {\n $(el).off(\".sidebarInputBinding\");\n }\n\n receiveMessage(el: HTMLElement, data: SidebarMessageData) {\n const sb = Sidebar.getInstance(el.parentElement as HTMLElement);\n if (sb) sb.toggle(data.method);\n }\n}\n\nregisterBinding(SidebarInputBinding, \"sidebar\");\n\n// attach Sidebar class to window for global usage\n(window as any).bslib = (window as any).bslib || {};\n(window as any).bslib.Sidebar = Sidebar;\n", "import type { Handler as ShinyCustomMessageHandler } from \"rstudio-shiny/srcts/types/src/shiny/shinyapp\";\n\nexport function shinyAddCustomMessageHandlers(handlers: {\n [key: string]: ShinyCustomMessageHandler;\n}): void {\n if (!window.Shiny) {\n return;\n }\n\n for (const [name, handler] of Object.entries(handlers)) {\n Shiny.addCustomMessageHandler(name, handler);\n }\n}\n", "// ----------------------------------------------------------------------------\n// First, bring in non-webcomponent (legacy) components (they attach to the window)\n// ----------------------------------------------------------------------------\nimport \"./accordion\";\nimport \"./card\";\nimport \"./sidebar\";\n\n// ----------------------------------------------------------------------------\n// Register custom message handlers for Shiny\n// ----------------------------------------------------------------------------\nimport { InputBinding } from \"./_utils\";\nimport { shinyAddCustomMessageHandlers } from \"./_shinyAddCustomMessageHandlers\";\n\nconst bslibMessageHandlers = {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n \"bslib.toggle-input-binary\": (msg: any) => {\n // This handler was written for `toggle_switch()`, but could be used for any\n // binary Shiny input, e.g. checkbox.\n const el = document.getElementById(msg.id) as HTMLElement;\n if (!el) {\n console.warn(\"[bslib.toggle-input-binary] No element found\", msg);\n }\n\n const binding = $(el).data(\"shiny-input-binding\");\n if (!(binding instanceof InputBinding)) {\n console.warn(\"[bslib.toggle-input-binary] No input binding found\", msg);\n return;\n }\n\n let value = msg.value;\n if (typeof value === \"undefined\") {\n value = !binding.getValue(el);\n }\n binding.receiveMessage(el, { value });\n },\n};\n\nif (window.Shiny) {\n shinyAddCustomMessageHandlers(bslibMessageHandlers);\n}\n\n// ----------------------------------------------------------------------\n// Append the (global) SVG linearGradient to the body.\n// value_box() uses this (i.e., bslib---icon-gradient element) to apply a\n// gradient to the icon when bs_theme(preset=\"shiny\").\n// ----------------------------------------------------------------------\n\nfunction insertSvgGradient() {\n const temp = document.createElement(\"div\");\n temp.innerHTML = `\n `;\n document.body.appendChild(temp.children[0] as Node);\n}\n\nif (document.readyState === \"complete\") {\n insertSvgGradient();\n} else {\n document.addEventListener(\"DOMContentLoaded\", insertSvgGradient);\n}\n"],
- "mappings": "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",
+ "sourcesContent": ["import type { HtmlDep } from \"rstudio-shiny/srcts/types/src/shiny/render\";\n\nimport type { InputBinding as InputBindingType } from \"rstudio-shiny/srcts/types/src/bindings/input\";\n\n// Exclude undefined from T\ntype NotUndefined = T extends undefined ? never : T;\n\n// eslint-disable-next-line @typescript-eslint/naming-convention\nconst InputBinding = (\n window.Shiny ? Shiny.InputBinding : class {}\n) as typeof InputBindingType;\n\nfunction registerBinding(\n inputBindingClass: new () => InputBindingType,\n name: string\n): void {\n if (window.Shiny) {\n Shiny.inputBindings.register(new inputBindingClass(), \"bslib.\" + name);\n }\n}\n\n// Return true if the key exists on the object and the value is not undefined.\n//\n// This method is mainly used in input bindings' `receiveMessage` method.\n// Since we know that the values are sent by Shiny via `{jsonlite}`,\n// then we know that there are no `undefined` values. `null` is possible, but not `undefined`.\nfunction hasDefinedProperty<\n Prop extends keyof X,\n X extends { [key: string]: any }\n>(\n obj: X,\n prop: Prop\n): obj is X & { [key in NonNullable]: NotUndefined } {\n return (\n Object.prototype.hasOwnProperty.call(obj, prop) && obj[prop] !== undefined\n );\n}\n\n// TODO: Shiny should trigger resize events when the output\n// https://github.com/rstudio/shiny/pull/3682\nfunction doWindowResizeOnElementResize(el: HTMLElement): void {\n if ($(el).data(\"window-resize-observer\")) {\n return;\n }\n const resizeEvent = new Event(\"resize\");\n const ro = new ResizeObserver(() => {\n window.dispatchEvent(resizeEvent);\n });\n ro.observe(el);\n $(el).data(\"window-resize-observer\", ro);\n}\n\nfunction getAllFocusableChildren(el: HTMLElement): HTMLElement[] {\n // Cross-referenced with https://allyjs.io/data-tables/focusable.html\n const base = [\n \"a[href]\",\n \"area[href]\",\n \"button\",\n \"details summary\",\n \"input\",\n \"iframe\",\n \"select\",\n \"textarea\",\n '[contentEditable=\"\"]',\n '[contentEditable=\"true\"]',\n '[contentEditable=\"TRUE\"]',\n \"[tabindex]\",\n ];\n const modifiers = [':not([tabindex=\"-1\"])', \":not([disabled])\"];\n const selectors = base.map((b) => b + modifiers.join(\"\"));\n const focusable = el.querySelectorAll(selectors.join(\", \"));\n return Array.from(focusable) as HTMLElement[];\n}\n\nasync function shinyRenderContent(\n ...args: Parameters\n): ReturnType {\n if (!window.Shiny) {\n throw new Error(\"This function must be called in a Shiny app.\");\n }\n if (Shiny.renderContentAsync) {\n return await Shiny.renderContentAsync.apply(null, args);\n } else {\n return await Shiny.renderContent.apply(null, args);\n }\n}\n\nexport {\n InputBinding,\n registerBinding,\n hasDefinedProperty,\n doWindowResizeOnElementResize,\n getAllFocusableChildren,\n shinyRenderContent,\n};\nexport type { HtmlDep };\n", "import type { HtmlDep } from \"./_utils\";\nimport {\n InputBinding,\n registerBinding,\n hasDefinedProperty,\n shinyRenderContent,\n} from \"./_utils\";\n\ntype AccordionItem = {\n item: HTMLElement;\n value: string;\n isOpen: () => boolean;\n show: () => void;\n hide: () => void;\n};\n\ntype HTMLContent = {\n html: string;\n deps?: HtmlDep[];\n};\n\ntype SetMessage = {\n method: \"set\";\n values: string[];\n};\n\ntype OpenMessage = {\n method: \"open\";\n values: string[] | true;\n};\n\ntype CloseMessage = {\n method: \"close\";\n values: string[] | true;\n};\n\ntype InsertMessage = {\n method: \"insert\";\n panel: HTMLContent;\n target: string;\n position: \"after\" | \"before\";\n};\n\ntype RemoveMessage = {\n method: \"remove\";\n target: string[];\n};\n\ntype UpdateMessage = {\n method: \"update\";\n target: string;\n value: string;\n body: HTMLContent;\n title: HTMLContent;\n icon: HTMLContent;\n};\n\ntype MessageData =\n | CloseMessage\n | InsertMessage\n | OpenMessage\n | RemoveMessage\n | SetMessage\n | UpdateMessage;\n\nclass AccordionInputBinding extends InputBinding {\n find(scope: HTMLElement) {\n return $(scope).find(\".accordion.bslib-accordion-input\");\n }\n\n getValue(el: HTMLElement): string[] | null {\n const items = this._getItemInfo(el);\n const selected = items.filter((x) => x.isOpen()).map((x) => x.value);\n return selected.length === 0 ? null : selected;\n }\n\n subscribe(el: HTMLElement, callback: (x: boolean) => void) {\n $(el).on(\n \"shown.bs.collapse.accordionInputBinding hidden.bs.collapse.accordionInputBinding\",\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n function (event) {\n callback(true);\n }\n );\n }\n\n unsubscribe(el: HTMLElement) {\n $(el).off(\".accordionInputBinding\");\n }\n\n async receiveMessage(el: HTMLElement, data: MessageData) {\n const method = data.method;\n if (method === \"set\") {\n this._setItems(el, data);\n } else if (method === \"open\") {\n this._openItems(el, data);\n } else if (method === \"close\") {\n this._closeItems(el, data);\n } else if (method === \"remove\") {\n this._removeItem(el, data);\n } else if (method === \"insert\") {\n await this._insertItem(el, data);\n } else if (method === \"update\") {\n await this._updateItem(el, data);\n } else {\n throw new Error(`Method not yet implemented: ${method}`);\n }\n }\n\n protected _setItems(el: HTMLElement, data: SetMessage) {\n const items = this._getItemInfo(el);\n const vals = this._getValues(el, items, data.values);\n items.forEach((x) => {\n vals.indexOf(x.value) > -1 ? x.show() : x.hide();\n });\n }\n\n protected _openItems(el: HTMLElement, data: OpenMessage) {\n const items = this._getItemInfo(el);\n const vals = this._getValues(el, items, data.values);\n items.forEach((x) => {\n if (vals.indexOf(x.value) > -1) x.show();\n });\n }\n\n protected _closeItems(el: HTMLElement, data: CloseMessage) {\n const items = this._getItemInfo(el);\n const vals = this._getValues(el, items, data.values);\n items.forEach((x) => {\n if (vals.indexOf(x.value) > -1) x.hide();\n });\n }\n\n protected async _insertItem(el: HTMLElement, data: InsertMessage) {\n let targetItem = this._findItem(el, data.target);\n\n // If no target was specified, or the target was not found, then default\n // to the first or last item, depending on the position\n if (!targetItem) {\n targetItem = (\n data.position === \"before\" ? el.firstElementChild : el.lastElementChild\n ) as HTMLElement;\n }\n\n const panel = data.panel;\n\n // If there is still no targetItem, then there are no items in the accordion\n if (targetItem) {\n await shinyRenderContent(\n targetItem,\n panel,\n data.position === \"before\" ? \"beforeBegin\" : \"afterEnd\"\n );\n } else {\n await shinyRenderContent(el, panel);\n }\n\n // Need to add a reference to the parent id that makes autoclose to work\n if (this._isAutoClosing(el)) {\n const val = $(panel.html).attr(\"data-value\");\n $(el)\n .find(`[data-value=\"${val}\"] .accordion-collapse`)\n .attr(\"data-bs-parent\", \"#\" + el.id);\n }\n }\n\n protected _removeItem(el: HTMLElement, data: RemoveMessage) {\n const targetItems = this._getItemInfo(el).filter(\n (x) => data.target.indexOf(x.value) > -1\n );\n\n const unbindAll = Shiny?.unbindAll;\n\n targetItems.forEach((x) => {\n if (unbindAll) unbindAll(x.item);\n x.item.remove();\n });\n }\n\n protected async _updateItem(el: HTMLElement, data: UpdateMessage) {\n const target = this._findItem(el, data.target);\n\n if (!target) {\n throw new Error(\n `Unable to find an accordion_panel() with a value of ${data.target}`\n );\n }\n\n if (hasDefinedProperty(data, \"value\")) {\n target.dataset.value = data.value;\n }\n\n if (hasDefinedProperty(data, \"body\")) {\n const body = target.querySelector(\".accordion-body\") as HTMLElement; // always exists\n await shinyRenderContent(body, data.body);\n }\n\n const header = target.querySelector(\".accordion-header\") as HTMLElement; // always exists\n\n if (hasDefinedProperty(data, \"title\")) {\n const title = header.querySelector(\".accordion-title\") as HTMLElement; // always exists\n await shinyRenderContent(title, data.title);\n }\n\n if (hasDefinedProperty(data, \"icon\")) {\n const icon = header.querySelector(\n \".accordion-button > .accordion-icon\"\n ) as HTMLElement; // always exists\n await shinyRenderContent(icon, data.icon);\n }\n }\n\n protected _getItemInfo(el: HTMLElement): AccordionItem[] {\n const items = Array.from(\n el.querySelectorAll(\":scope > .accordion-item\")\n ) as HTMLElement[];\n return items.map((x) => this._getSingleItemInfo(x));\n }\n\n protected _getSingleItemInfo(x: HTMLElement): AccordionItem {\n const collapse = x.querySelector(\".accordion-collapse\") as HTMLElement;\n const isOpen = () => $(collapse).hasClass(\"show\");\n return {\n item: x,\n value: x.dataset.value as string,\n isOpen: isOpen,\n show: () => {\n if (!isOpen()) $(collapse).collapse(\"show\");\n },\n hide: () => {\n if (isOpen()) $(collapse).collapse(\"hide\");\n },\n };\n }\n\n protected _getValues(\n el: HTMLElement,\n items: AccordionItem[],\n values: string[] | true\n ): string[] {\n let vals = values !== true ? values : items.map((x) => x.value);\n const autoclose = this._isAutoClosing(el);\n if (autoclose) {\n vals = vals.slice(vals.length - 1, vals.length);\n }\n return vals;\n }\n\n protected _findItem(el: HTMLElement, value: string): HTMLElement | null {\n return el.querySelector(`[data-value=\"${value}\"]`);\n }\n\n protected _isAutoClosing(el: HTMLElement): boolean {\n return el.classList.contains(\"autoclose\");\n }\n}\n\nregisterBinding(AccordionInputBinding, \"accordion\");\n", "/**\n * A resize observer that ensures Shiny outputs resize during or just after\n * their parent container size changes. Useful, in particular, for sidebar\n * transitions or for full-screen card transitions.\n *\n * @class ShinyResizeObserver\n * @typedef {ShinyResizeObserver}\n */\nclass ShinyResizeObserver {\n /**\n * The actual ResizeObserver instance.\n * @private\n * @type {ResizeObserver}\n */\n private resizeObserver: ResizeObserver;\n /**\n * An array of elements that are currently being watched by the Resize\n * Observer.\n *\n * @details\n * We don't currently have lifecycle hooks that allow us to unobserve elements\n * when they are removed from the DOM. As a result, we need to manually check\n * that the elements we're watching still exist in the DOM. This array keeps\n * track of the elements we're watching so that we can check them later.\n * @private\n * @type {HTMLElement[]}\n */\n private resizeObserverEntries: HTMLElement[];\n\n /**\n * Watch containers for size changes and ensure that Shiny outputs and\n * htmlwidgets within resize appropriately.\n *\n * @details\n * The ShinyResizeObserver is used to watch the containers, such as Sidebars\n * and Cards for size changes, in particular when the sidebar state is toggled\n * or the card body is expanded full screen. It performs two primary tasks:\n *\n * 1. Dispatches a `resize` event on the window object. This is necessary to\n * ensure that Shiny outputs resize appropriately. In general, the window\n * resizing is throttled and the output update occurs when the transition\n * is complete.\n * 2. If an output with a resize method on the output binding is detected, we\n * directly call the `.onResize()` method of the binding. This ensures that\n * htmlwidgets transition smoothly. In static mode, htmlwidgets does this\n * already.\n *\n * @note\n * This resize observer also handles race conditions in some complex\n * fill-based layouts with multiple outputs (e.g., plotly), where shiny\n * initializes with the correct sizing, but in-between the 1st and last\n * renderValue(), the size of the output containers can change, meaning every\n * output but the 1st gets initialized with the wrong size during their\n * renderValue(). Then, after the render phase, shiny won't know to trigger a\n * resize since all the widgets will return to their original size (and thus,\n * Shiny thinks there isn't any resizing to do). The resize observer works\n * around this by ensuring that the output is resized whenever its container\n * size changes.\n * @constructor\n */\n constructor() {\n this.resizeObserverEntries = [];\n this.resizeObserver = new ResizeObserver((entries) => {\n const resizeEvent = new Event(\"resize\");\n window.dispatchEvent(resizeEvent);\n\n // the rest of this callback is only relevant in Shiny apps\n if (!window.Shiny) return;\n\n const resized = [] as HTMLElement[];\n\n for (const entry of entries) {\n if (!(entry.target instanceof HTMLElement)) continue;\n if (!entry.target.querySelector(\".shiny-bound-output\")) continue;\n\n entry.target\n .querySelectorAll(\".shiny-bound-output\")\n .forEach((el) => {\n if (resized.includes(el)) return;\n\n const { binding, onResize } = $(el).data(\"shinyOutputBinding\");\n if (!binding || !binding.resize) return;\n\n // if this output is owned by another observer, skip it\n const owner = (el as any).shinyResizeObserver;\n if (owner && owner !== this) return;\n // mark this output as owned by this shinyResizeObserver instance\n if (!owner) (el as any).shinyResizeObserver = this;\n\n // trigger immediate resizing of outputs with a resize method\n onResize(el);\n // only once per output and resize event\n resized.push(el);\n\n // set plot images to 100% width temporarily during the transition\n if (!el.classList.contains(\"shiny-plot-output\")) return;\n const img = el.querySelector(\n 'img:not([width=\"100%\"])'\n );\n if (img) img.setAttribute(\"width\", \"100%\");\n });\n }\n });\n }\n\n /**\n * Observe an element for size changes.\n * @param {HTMLElement} el - The element to observe.\n */\n observe(el: HTMLElement): void {\n this.resizeObserver.observe(el);\n this.resizeObserverEntries.push(el);\n }\n\n /**\n * Stop observing an element for size changes.\n * @param {HTMLElement} el - The element to stop observing.\n */\n unobserve(el: HTMLElement): void {\n const idxEl = this.resizeObserverEntries.indexOf(el);\n if (idxEl < 0) return;\n\n this.resizeObserver.unobserve(el);\n this.resizeObserverEntries.splice(idxEl, 1);\n }\n\n /**\n * This method checks that we're not continuing to watch elements that no\n * longer exist in the DOM. If any are found, we stop observing them and\n * remove them from our array of observed elements.\n *\n * @private\n * @static\n */\n flush(): void {\n this.resizeObserverEntries.forEach((el) => {\n if (!document.body.contains(el)) this.unobserve(el);\n });\n }\n}\n\nexport { ShinyResizeObserver };\n", "import { getAllFocusableChildren } from \"./_utils\";\nimport { ShinyResizeObserver } from \"./_shinyResizeObserver\";\n\n/**\n * The overlay element that is placed behind the card when expanded full screen.\n *\n * @interface CardFullScreenOverlay\n * @typedef {CardFullScreenOverlay}\n */\ninterface CardFullScreenOverlay {\n /**\n * The full screen overlay container.\n * @type {HTMLDivElement}\n */\n container: HTMLDivElement;\n /**\n * The anchor element used to close the full screen overlay.\n * @type {HTMLAnchorElement}\n */\n anchor: HTMLAnchorElement;\n}\n\n/**\n * The bslib card component class.\n *\n * @class Card\n * @typedef {Card}\n */\nclass Card {\n /**\n * The card container element.\n * @private\n * @type {HTMLElement}\n */\n private card: HTMLElement;\n /**\n * The card's full screen overlay element. We create this element once and add\n * and remove it from the DOM as needed (this simplifies focus management\n * while in full screen mode).\n * @private\n * @type {CardFullScreenOverlay}\n */\n private overlay: CardFullScreenOverlay;\n\n /**\n * Key bslib-specific classes and attributes used by the card component.\n * @private\n * @static\n * @type {{ ATTR_INIT: string; CLASS_CARD: string; CLASS_FULL_SCREEN: string; CLASS_HAS_FULL_SCREEN: string; CLASS_FULL_SCREEN_ENTER: string; CLASS_FULL_SCREEN_EXIT: string; ID_FULL_SCREEN_OVERLAY: string; }}\n */\n private static attr = {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n ATTR_INIT: \"data-bslib-card-init\",\n // eslint-disable-next-line @typescript-eslint/naming-convention\n CLASS_CARD: \"bslib-card\",\n // eslint-disable-next-line @typescript-eslint/naming-convention\n ATTR_FULL_SCREEN: \"data-full-screen\",\n // eslint-disable-next-line @typescript-eslint/naming-convention\n CLASS_HAS_FULL_SCREEN: \"bslib-has-full-screen\",\n // eslint-disable-next-line @typescript-eslint/naming-convention\n CLASS_FULL_SCREEN_ENTER: \"bslib-full-screen-enter\",\n // eslint-disable-next-line @typescript-eslint/naming-convention\n CLASS_FULL_SCREEN_EXIT: \"bslib-full-screen-exit\",\n // eslint-disable-next-line @typescript-eslint/naming-convention\n ID_FULL_SCREEN_OVERLAY: \"bslib-full-screen-overlay\",\n };\n\n /**\n * A Shiny-specific resize observer that ensures Shiny outputs in within the\n * card resize appropriately.\n * @private\n * @type {ShinyResizeObserver}\n * @static\n */\n private static shinyResizeObserver = new ShinyResizeObserver();\n\n /**\n * Creates an instance of a bslib Card component.\n *\n * @constructor\n * @param {HTMLElement} card\n */\n constructor(card: HTMLElement) {\n // remove initialization attribute and script\n card.removeAttribute(Card.attr.ATTR_INIT);\n card\n .querySelector(`script[${Card.attr.ATTR_INIT}]`)\n ?.remove();\n\n this.card = card;\n Card.instanceMap.set(card, this);\n\n // Let Shiny know to trigger resize when the card size changes\n // TODO: shiny could/should do this itself (rstudio/shiny#3682)\n Card.shinyResizeObserver.observe(this.card);\n\n this._addEventListeners();\n this.overlay = this._createOverlay();\n\n // bind event handler methods to this card instance\n this._exitFullScreenOnEscape = this._exitFullScreenOnEscape.bind(this);\n this._trapFocusExit = this._trapFocusExit.bind(this);\n }\n\n /**\n * Enter the card's full screen mode, either programmatically or via an event\n * handler. Full screen mode is activated by adding a class to the card that\n * positions it absolutely and expands it to fill the viewport. In addition,\n * we add a full screen overlay element behind the card and we trap focus in\n * the expanded card while in full screen mode.\n *\n * @param {?Event} [event]\n */\n enterFullScreen(event?: Event): void {\n if (event) event.preventDefault();\n\n document.addEventListener(\"keydown\", this._exitFullScreenOnEscape, false);\n\n // trap focus in the fullscreen container, listening for Tab key on the\n // capture phase so we have the best chance of preventing other handlers\n document.addEventListener(\"keydown\", this._trapFocusExit, true);\n\n this.card.setAttribute(Card.attr.ATTR_FULL_SCREEN, \"true\");\n document.body.classList.add(Card.attr.CLASS_HAS_FULL_SCREEN);\n this.card.insertAdjacentElement(\"beforebegin\", this.overlay.container);\n\n // Set initial focus on the card, if not already\n if (\n !this.card.contains(document.activeElement) ||\n document.activeElement?.classList.contains(\n Card.attr.CLASS_FULL_SCREEN_ENTER\n )\n ) {\n this.card.setAttribute(\"tabindex\", \"-1\");\n this.card.focus();\n }\n }\n\n /**\n * Exit full screen mode. This removes the full screen overlay element,\n * removes the full screen class from the card, and removes the keyboard event\n * listeners that were added when entering full screen mode.\n */\n exitFullScreen(): void {\n document.removeEventListener(\n \"keydown\",\n this._exitFullScreenOnEscape,\n false\n );\n document.removeEventListener(\"keydown\", this._trapFocusExit, true);\n\n // Remove overlay and remove full screen classes from card\n this.overlay.container.remove();\n this.card.setAttribute(Card.attr.ATTR_FULL_SCREEN, \"false\");\n this.card.removeAttribute(\"tabindex\");\n document.body.classList.remove(Card.attr.CLASS_HAS_FULL_SCREEN);\n }\n\n /**\n * Adds general card-specific event listeners.\n * @private\n */\n private _addEventListeners(): void {\n const btnFullScreen = this.card.querySelector(\n `:scope > * > .${Card.attr.CLASS_FULL_SCREEN_ENTER}`\n );\n if (!btnFullScreen) return;\n btnFullScreen.addEventListener(\"click\", (ev) => this.enterFullScreen(ev));\n }\n\n /**\n * An event handler to exit full screen mode when the Escape key is pressed.\n * @private\n * @param {KeyboardEvent} event\n */\n private _exitFullScreenOnEscape(event: KeyboardEvent): void {\n if (!(event.target instanceof HTMLElement)) return;\n // If the user is in the middle of a select input choice, don't exit\n const selOpenSelectInput = [\"select[open]\", \"input[aria-expanded='true']\"];\n if (event.target.matches(selOpenSelectInput.join(\", \"))) return;\n\n if (event.key === \"Escape\") {\n this.exitFullScreen();\n }\n }\n\n /**\n * An event handler to trap focus within the card when in full screen mode.\n *\n * @description\n * This keyboard event handler ensures that tab focus stays within the card\n * when in full screen mode. When the card is first expanded,\n * we move focus to the card element itself. If focus somehow leaves the card,\n * we returns focus to the card container.\n *\n * Within the card, we handle only tabbing from the close anchor or the last\n * focusable element and only when tab focus would have otherwise left the\n * card. In those cases, we cycle focus to the last focusable element or back\n * to the anchor. If the card doesn't have any focusable elements, we move\n * focus to the close anchor.\n *\n * @note\n * Because the card contents may change, we check for focusable elements\n * every time the handler is called.\n *\n * @private\n * @param {KeyboardEvent} event\n */\n private _trapFocusExit(event: KeyboardEvent): void {\n if (!(event instanceof KeyboardEvent)) return;\n if (event.key !== \"Tab\") return;\n\n const isFocusedContainer = event.target === this.card;\n const isFocusedAnchor = event.target === this.overlay.anchor;\n const isFocusedWithin = this.card.contains(event.target as Node);\n\n const stopEvent = () => {\n event.preventDefault();\n event.stopImmediatePropagation();\n };\n\n if (!(isFocusedWithin || isFocusedContainer || isFocusedAnchor)) {\n // If focus is outside the card, return to the card\n stopEvent();\n this.card.focus();\n return;\n }\n\n // Check focusables every time because the card contents may have changed\n // but exclude the full screen enter button from this list of elements\n const focusableElements = getAllFocusableChildren(this.card).filter(\n (el) => !el.classList.contains(Card.attr.CLASS_FULL_SCREEN_ENTER)\n );\n const hasFocusableElements = focusableElements.length > 0;\n\n // We need to handle five cases:\n // 1. The card has no focusable elements --> focus the anchor\n // 2. Focus is on the card container (do nothing, natural tab order)\n // 3. Focus is on the anchor and the user pressed Tab + Shift (backwards)\n // -> Move to the last focusable element (end of card)\n // 4. Focus is on the last focusable element and the user pressed Tab\n // (forwards) -> Move to the anchor (top of card)\n // 5. otherwise we don't interfere\n\n if (!hasFocusableElements) {\n // case 1\n stopEvent();\n this.overlay.anchor.focus();\n return;\n }\n\n // case 2\n if (isFocusedContainer) return;\n\n const lastFocusable = focusableElements[focusableElements.length - 1];\n const isFocusedLast = event.target === lastFocusable;\n\n if (isFocusedAnchor && event.shiftKey) {\n stopEvent();\n lastFocusable.focus();\n return;\n }\n\n if (isFocusedLast && !event.shiftKey) {\n stopEvent();\n this.overlay.anchor.focus();\n return;\n }\n }\n\n /**\n * Creates the full screen overlay.\n * @private\n * @returns {CardFullScreenOverlay}\n */\n private _createOverlay(): CardFullScreenOverlay {\n const container = document.createElement(\"div\");\n container.id = Card.attr.ID_FULL_SCREEN_OVERLAY;\n container.onclick = this.exitFullScreen.bind(this);\n\n const anchor = this._createOverlayCloseAnchor();\n container.appendChild(anchor);\n\n return { container, anchor };\n }\n\n /**\n * Creates the anchor element used to exit the full screen mode.\n * @private\n * @returns {HTMLAnchorElement}\n */\n private _createOverlayCloseAnchor(): HTMLAnchorElement {\n const anchor = document.createElement(\"a\");\n anchor.classList.add(Card.attr.CLASS_FULL_SCREEN_EXIT);\n anchor.tabIndex = 0;\n anchor.onclick = () => this.exitFullScreen();\n anchor.onkeydown = (ev) => {\n if (ev.key === \"Enter\" || ev.key === \" \") {\n this.exitFullScreen();\n }\n };\n anchor.innerHTML = this._overlayCloseHtml();\n\n return anchor;\n }\n\n /**\n * Returns the HTML for the close icon.\n * @private\n * @returns {string}\n */\n private _overlayCloseHtml(): string {\n return (\n \"Close \" +\n \"\"\n );\n }\n\n /**\n * The registry of card instances and their associated DOM elements.\n * @private\n * @static\n * @type {WeakMap}\n */\n private static instanceMap: WeakMap = new WeakMap();\n\n /**\n * Returns the card instance associated with the given element, if any.\n * @public\n * @static\n * @param {HTMLElement} el\n * @returns {(Card | undefined)}\n */\n public static getInstance(el: HTMLElement): Card | undefined {\n return Card.instanceMap.get(el);\n }\n\n /**\n * If cards are initialized before the DOM is ready, we re-schedule the\n * initialization to occur on DOMContentLoaded.\n * @private\n * @static\n * @type {boolean}\n */\n private static onReadyScheduled = false;\n\n /**\n * Initializes all cards that require initialization on the page, or schedules\n * initialization if the DOM is not yet ready.\n * @public\n * @static\n * @param {boolean} [flushResizeObserver=true]\n */\n public static initializeAllCards(flushResizeObserver = true): void {\n if (document.readyState === \"loading\") {\n if (!Card.onReadyScheduled) {\n Card.onReadyScheduled = true;\n document.addEventListener(\"DOMContentLoaded\", () => {\n Card.initializeAllCards(false);\n });\n }\n return;\n }\n\n if (flushResizeObserver) {\n // Trigger a recheck of observed cards to unobserve non-existent cards\n Card.shinyResizeObserver.flush();\n }\n\n const initSelector = `.${Card.attr.CLASS_CARD}[${Card.attr.ATTR_INIT}]`;\n if (!document.querySelector(initSelector)) {\n // no cards to initialize\n return;\n }\n\n const cards = document.querySelectorAll(initSelector);\n cards.forEach((card) => new Card(card as HTMLElement));\n }\n}\n\n// attach Sidebar class to window for global usage\n(window as any).bslib = (window as any).bslib || {};\n(window as any).bslib.Card = Card;\n\nexport { Card };\n", "import { InputBinding, registerBinding } from \"./_utils\";\nimport { ShinyResizeObserver } from \"./_shinyResizeObserver\";\n\n/**\n * Methods for programmatically toggling the state of the sidebar. These methods\n * describe the desired state of the sidebar: `\"close\"` and `\"open\"` transition\n * the sidebar to the desired state, unless the sidebar is already in that\n * state. `\"toggle\"` transitions the sidebar to the state opposite of its\n * current state.\n * @typedef {SidebarToggleMethod}\n */\ntype SidebarToggleMethod = \"close\" | \"open\" | \"toggle\";\n\n/**\n * Data received by the input binding's `receiveMessage` method.\n * @typedef {SidebarMessageData}\n */\ntype SidebarMessageData = {\n method: SidebarToggleMethod;\n};\n\n/**\n * The DOM elements that make up the sidebar. `main`, `sidebar`, and `toggle`\n * are all direct children of `container` (in that order).\n * @interface SidebarComponents\n * @typedef {SidebarComponents}\n */\ninterface SidebarComponents {\n /**\n * The `layout_sidebar()` parent container, with class\n * `Sidebar.classes.LAYOUT`.\n * @type {HTMLElement}\n */\n container: HTMLElement;\n /**\n * The main content area of the sidebar layout.\n * @type {HTMLElement}\n */\n main: HTMLElement;\n /**\n * The sidebar container of the sidebar layout.\n * @type {HTMLElement}\n */\n sidebar: HTMLElement;\n /**\n * The toggle button that is used to toggle the sidebar state.\n * @type {HTMLElement}\n */\n toggle: HTMLElement;\n}\n\n/**\n * The bslib sidebar component class. This class is only used for collapsible\n * sidebars.\n *\n * @class Sidebar\n * @typedef {Sidebar}\n */\nclass Sidebar {\n /**\n * The DOM elements that make up the sidebar, see `SidebarComponents`.\n * @private\n * @type {SidebarComponents}\n */\n private layout: SidebarComponents;\n\n /**\n * A Shiny-specific resize observer that ensures Shiny outputs in the main\n * content areas of the sidebar resize appropriately.\n * @private\n * @type {ShinyResizeObserver}\n * @static\n */\n private static shinyResizeObserver = new ShinyResizeObserver();\n\n /**\n * Creates an instance of a collapsible bslib Sidebar.\n * @constructor\n * @param {HTMLElement} container\n */\n constructor(container: HTMLElement) {\n Sidebar.instanceMap.set(container, this);\n this.layout = {\n container,\n main: container.querySelector(\":scope > .main\") as HTMLElement,\n sidebar: container.querySelector(\":scope > .sidebar\") as HTMLElement,\n toggle: container.querySelector(\n \":scope > .collapse-toggle\"\n ) as HTMLElement,\n } as SidebarComponents;\n\n const sideAccordion = this.layout.sidebar.querySelector(\n \":scope > .sidebar-content > .accordion\"\n );\n if (sideAccordion) {\n // Add `.has-accordion` class to `.sidebar-content` container\n sideAccordion?.parentElement?.classList.add(\"has-accordion\");\n sideAccordion.classList.add(\"accordion-flush\");\n }\n\n if (this.layout.toggle) {\n this._initEventListeners();\n this._initSidebarCounters();\n this._initDesktop();\n }\n\n // Start watching the main content area for size changes to ensure Shiny\n // outputs resize appropriately during sidebar transitions.\n Sidebar.shinyResizeObserver.observe(this.layout.main);\n\n container.removeAttribute(\"data-bslib-sidebar-init\");\n const initScript = container.querySelector(\n \":scope > script[data-bslib-sidebar-init]\"\n );\n if (initScript) {\n container.removeChild(initScript);\n }\n }\n\n /**\n * Read the current state of the sidebar. Note that, when calling this method,\n * the sidebar may be transitioning into the state returned by this method.\n *\n * @description\n * The sidebar state works as follows, starting from the open state. When the\n * sidebar is closed:\n * 1. We add both the `COLLAPSE` and `TRANSITIONING` classes to the sidebar.\n * 2. The sidebar collapse begins to animate. On desktop devices, and where it\n * is supported, we transition the `grid-template-columns` property of the\n * sidebar layout. On mobile, the sidebar is hidden immediately. In both\n * cases, the collapse icon rotates and we use this rotation to determine\n * when the transition is complete.\n * 3. If another sidebar state toggle is requested while closing the sidebar,\n * we remove the `COLLAPSE` class and the animation immediately starts to\n * reverse.\n * 4. When the `transition` is complete, we remove the `TRANSITIONING` class.\n * @readonly\n * @type {boolean}\n */\n get isClosed(): boolean {\n return this.layout.container.classList.contains(Sidebar.classes.COLLAPSE);\n }\n\n /**\n * Static classes related to the sidebar layout or state.\n * @public\n * @static\n * @readonly\n * @type {{ LAYOUT: string; COLLAPSE: string; TRANSITIONING: string; }}\n */\n public static readonly classes = {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n LAYOUT: \"bslib-sidebar-layout\",\n // eslint-disable-next-line @typescript-eslint/naming-convention\n COLLAPSE: \"sidebar-collapsed\",\n // eslint-disable-next-line @typescript-eslint/naming-convention\n TRANSITIONING: \"transitioning\",\n };\n\n /**\n * If sidebars are initialized before the DOM is ready, we re-schedule the\n * initialization to occur on DOMContentLoaded.\n * @private\n * @static\n * @type {boolean}\n */\n private static onReadyScheduled = false;\n /**\n * A map of initialized sidebars to their respective Sidebar instances.\n * @private\n * @static\n * @type {WeakMap}\n */\n private static instanceMap: WeakMap = new WeakMap();\n\n /**\n * Given a sidebar container, return the Sidebar instance associated with it.\n * @public\n * @static\n * @param {HTMLElement} el\n * @returns {(Sidebar | undefined)}\n */\n public static getInstance(el: HTMLElement): Sidebar | undefined {\n return Sidebar.instanceMap.get(el);\n }\n\n /**\n * Initialize all collapsible sidebars on the page.\n * @public\n * @static\n * @param {boolean} [flushResizeObserver=true] When `true`, we remove\n * non-existent elements from the ResizeObserver. This is required\n * periodically to prevent memory leaks. To avoid over-checking, we only flush\n * the ResizeObserver when initializing sidebars after page load.\n */\n public static initCollapsibleAll(flushResizeObserver = true): void {\n if (document.readyState === \"loading\") {\n if (!Sidebar.onReadyScheduled) {\n Sidebar.onReadyScheduled = true;\n document.addEventListener(\"DOMContentLoaded\", () => {\n Sidebar.initCollapsibleAll(false);\n });\n }\n return;\n }\n\n const initSelector = `.${Sidebar.classes.LAYOUT}[data-bslib-sidebar-init]`;\n if (!document.querySelector(initSelector)) {\n // no sidebars to initialize\n return;\n }\n\n if (flushResizeObserver) Sidebar.shinyResizeObserver.flush();\n\n const containers = document.querySelectorAll(initSelector);\n containers.forEach((container) => new Sidebar(container as HTMLElement));\n }\n\n /**\n * Initialize event listeners for the sidebar toggle button.\n * @private\n */\n private _initEventListeners(): void {\n const { toggle } = this.layout;\n\n toggle.addEventListener(\"click\", (ev) => {\n ev.preventDefault();\n this.toggle(\"toggle\");\n });\n\n // Remove the transitioning class when the transition ends. We watch the\n // collapse toggle icon because it's guaranteed to transition, whereas the\n // sidebar doesn't animate on mobile (or in browsers where animating\n // grid-template-columns is not supported).\n toggle\n .querySelector(\".collapse-icon\")\n ?.addEventListener(\"transitionend\", () => this._finalizeState());\n }\n\n /**\n * Initialize nested sidebar counters.\n *\n * @description\n * This function walks up the DOM tree, adding CSS variables to each direct\n * parent sidebar layout that count the layout's position in the stack of\n * nested layouts. We use these counters to keep the collapse toggles from\n * overlapping. Note that always-open sidebars that don't have collapse\n * toggles break the chain of nesting.\n * @private\n */\n private _initSidebarCounters(): void {\n const { container } = this.layout;\n\n const selectorChildLayouts =\n `.${Sidebar.classes.LAYOUT}` +\n \"> .main > \" +\n `.${Sidebar.classes.LAYOUT}:not([data-bslib-sidebar-open=\"always\"])`;\n\n const isInnermostLayout =\n container.querySelector(selectorChildLayouts) === null;\n\n if (!isInnermostLayout) {\n // There are sidebar layouts nested within this layout; defer to children\n return;\n }\n\n function nextSidebarParent(el: HTMLElement | null): HTMLElement | null {\n el = el ? el.parentElement : null;\n if (el && el.classList.contains(\"main\")) {\n // .bslib-sidebar-layout > .main > .bslib-sidebar-layout\n el = el.parentElement;\n }\n if (el && el.classList.contains(Sidebar.classes.LAYOUT)) {\n return el;\n }\n return null;\n }\n\n const layouts = [container];\n let parent = nextSidebarParent(container);\n\n while (parent) {\n // Add parent to front of layouts array, so we sort outer -> inner\n layouts.unshift(parent);\n parent = nextSidebarParent(parent);\n }\n\n const count = { left: 0, right: 0 };\n layouts.forEach(function (x: HTMLElement): void {\n const isRight = x.classList.contains(\"sidebar-right\");\n const thisCount = isRight ? count.right++ : count.left++;\n x.style.setProperty(\"--_js-toggle-count-this-side\", thisCount.toString());\n x.style.setProperty(\n \"--_js-toggle-count-max-side\",\n Math.max(count.right, count.left).toString()\n );\n });\n }\n\n /**\n * Initialize the sidebar's initial state when `open = \"desktop\"`.\n * @private\n */\n private _initDesktop(): void {\n const { container } = this.layout;\n // If sidebar is marked open='desktop'...\n if (container.dataset.bslibSidebarOpen?.trim() !== \"desktop\") {\n return;\n }\n\n // then close sidebar on mobile\n const initCollapsed = window\n .getComputedStyle(container)\n .getPropertyValue(\"--bslib-sidebar-js-init-collapsed\");\n\n if (initCollapsed.trim() === \"true\") {\n this.toggle(\"close\");\n }\n }\n\n /**\n * Toggle the sidebar's open/closed state.\n * @public\n * @param {SidebarToggleMethod | undefined} method Whether to `\"open\"`,\n * `\"close\"` or `\"toggle\"` the sidebar. If `.toggle()` is called without an\n * argument, it will toggle the sidebar's state.\n */\n public toggle(method: SidebarToggleMethod | undefined): void {\n if (typeof method === \"undefined\") {\n method = \"toggle\";\n }\n\n const { container, sidebar } = this.layout;\n const isClosed = this.isClosed;\n\n if ([\"open\", \"close\", \"toggle\"].indexOf(method) === -1) {\n throw new Error(`Unknown method ${method}`);\n }\n\n if (method === \"toggle\") {\n method = isClosed ? \"open\" : \"close\";\n }\n\n if ((isClosed && method === \"close\") || (!isClosed && method === \"open\")) {\n // nothing to do, sidebar is already in the desired state\n return;\n }\n\n if (method === \"open\") {\n // unhide sidebar immediately when opening,\n // otherwise the sidebar is hidden on transitionend\n sidebar.hidden = false;\n }\n\n // Add a transitioning class just before adding COLLAPSE_CLASS since we want\n // some of the transitioning styles to apply before the collapse state\n container.classList.add(Sidebar.classes.TRANSITIONING);\n container.classList.toggle(Sidebar.classes.COLLAPSE);\n }\n\n /**\n * When the sidebar open/close transition ends, finalize the sidebar's state.\n * @private\n */\n private _finalizeState(): void {\n const { container, sidebar, toggle } = this.layout;\n container.classList.remove(Sidebar.classes.TRANSITIONING);\n sidebar.hidden = this.isClosed;\n toggle.setAttribute(\"aria-expanded\", this.isClosed ? \"false\" : \"true\");\n\n // Send browser-native event with updated sidebar state\n const event = new CustomEvent(\"bslib.sidebar\", {\n bubbles: true,\n detail: { open: !this.isClosed },\n });\n sidebar.dispatchEvent(event);\n\n // Trigger Shiny input and output binding events\n $(sidebar).trigger(\"toggleCollapse.sidebarInputBinding\");\n $(sidebar).trigger(this.isClosed ? \"hidden\" : \"shown\");\n }\n}\n\n/**\n * A Shiny input binding for a sidebar.\n * @class SidebarInputBinding\n * @typedef {SidebarInputBinding}\n * @extends {InputBinding}\n */\nclass SidebarInputBinding extends InputBinding {\n find(scope: HTMLElement) {\n return $(scope).find(`.${Sidebar.classes.LAYOUT} > .bslib-sidebar-input`);\n }\n\n getValue(el: HTMLElement): boolean {\n const sb = Sidebar.getInstance(el.parentElement as HTMLElement);\n if (!sb) return false;\n return !sb.isClosed;\n }\n\n setValue(el: HTMLElement, value: boolean): void {\n const method = value ? \"open\" : \"close\";\n this.receiveMessage(el, { method });\n }\n\n subscribe(el: HTMLElement, callback: (x: boolean) => void) {\n $(el).on(\n \"toggleCollapse.sidebarInputBinding\",\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n function (event) {\n callback(true);\n }\n );\n }\n\n unsubscribe(el: HTMLElement) {\n $(el).off(\".sidebarInputBinding\");\n }\n\n receiveMessage(el: HTMLElement, data: SidebarMessageData) {\n const sb = Sidebar.getInstance(el.parentElement as HTMLElement);\n if (sb) sb.toggle(data.method);\n }\n}\n\nregisterBinding(SidebarInputBinding, \"sidebar\");\n\n// attach Sidebar class to window for global usage\n(window as any).bslib = (window as any).bslib || {};\n(window as any).bslib.Sidebar = Sidebar;\n", "import type { Handler as ShinyCustomMessageHandler } from \"rstudio-shiny/srcts/types/src/shiny/shinyapp\";\n\nexport function shinyAddCustomMessageHandlers(handlers: {\n [key: string]: ShinyCustomMessageHandler;\n}): void {\n if (!window.Shiny) {\n return;\n }\n\n for (const [name, handler] of Object.entries(handlers)) {\n Shiny.addCustomMessageHandler(name, handler);\n }\n}\n", "// ----------------------------------------------------------------------------\n// First, bring in non-webcomponent (legacy) components (they attach to the window)\n// ----------------------------------------------------------------------------\nimport \"./accordion\";\nimport \"./card\";\nimport \"./sidebar\";\n\n// ----------------------------------------------------------------------------\n// Register custom message handlers for Shiny\n// ----------------------------------------------------------------------------\nimport { InputBinding } from \"./_utils\";\nimport { shinyAddCustomMessageHandlers } from \"./_shinyAddCustomMessageHandlers\";\n\nconst bslibMessageHandlers = {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n \"bslib.toggle-input-binary\": async (msg: any) => {\n // This handler was written for `toggle_switch()`, but could be used for any\n // binary Shiny input, e.g. checkbox.\n const el = document.getElementById(msg.id) as HTMLElement;\n if (!el) {\n console.warn(\"[bslib.toggle-input-binary] No element found\", msg);\n }\n\n const binding = $(el).data(\"shiny-input-binding\");\n if (!(binding instanceof InputBinding)) {\n console.warn(\"[bslib.toggle-input-binary] No input binding found\", msg);\n return;\n }\n\n let value = msg.value;\n if (typeof value === \"undefined\") {\n value = !binding.getValue(el);\n }\n\n await binding.receiveMessage(el, { value });\n },\n};\n\nif (window.Shiny) {\n shinyAddCustomMessageHandlers(bslibMessageHandlers);\n}\n\n// ----------------------------------------------------------------------\n// Append the (global) SVG linearGradient to the body.\n// value_box() uses this (i.e., bslib---icon-gradient element) to apply a\n// gradient to the icon when bs_theme(preset=\"shiny\").\n// ----------------------------------------------------------------------\n\nfunction insertSvgGradient() {\n const temp = document.createElement(\"div\");\n temp.innerHTML = `\n `;\n document.body.appendChild(temp.children[0] as Node);\n}\n\nif (document.readyState === \"complete\") {\n insertSvgGradient();\n} else {\n document.addEventListener(\"DOMContentLoaded\", insertSvgGradient);\n}\n"],
+ "mappings": "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",
"names": []
}
diff --git a/inst/components/dist/components.min.js b/inst/components/dist/components.min.js
index a4e580aec..2b4007ebf 100644
--- a/inst/components/dist/components.min.js
+++ b/inst/components/dist/components.min.js
@@ -1,5 +1,5 @@
/*! bslib 0.5.1.9000 | (c) 2012-2023 RStudio, PBC. | License: MIT + file LICENSE */
-"use strict";(()=>{var h=window.Shiny?Shiny.InputBinding:class{};function g(a,e){window.Shiny&&Shiny.inputBindings.register(new a,"bslib."+e)}function b(a,e){return Object.prototype.hasOwnProperty.call(a,e)&&a[e]!==void 0}function L(a){let e=["a[href]","area[href]","button","details summary","input","iframe","select","textarea",'[contentEditable=""]','[contentEditable="true"]','[contentEditable="TRUE"]',"[tabindex]"],t=[':not([tabindex="-1"])',":not([disabled])"],n=e.map(i=>i+t.join("")),s=a.querySelectorAll(n.join(", "));return Array.from(s)}var y=class extends h{find(e){return $(e).find(".accordion.bslib-accordion-input")}getValue(e){let n=this._getItemInfo(e).filter(s=>s.isOpen()).map(s=>s.value);return n.length===0?null:n}subscribe(e,t){$(e).on("shown.bs.collapse.accordionInputBinding hidden.bs.collapse.accordionInputBinding",function(n){t(!0)})}unsubscribe(e){$(e).off(".accordionInputBinding")}receiveMessage(e,t){let n=t.method;if(n==="set")this._setItems(e,t);else if(n==="open")this._openItems(e,t);else if(n==="close")this._closeItems(e,t);else if(n==="remove")this._removeItem(e,t);else if(n==="insert")this._insertItem(e,t);else if(n==="update")this._updateItem(e,t);else throw new Error(`Method not yet implemented: ${n}`)}_setItems(e,t){let n=this._getItemInfo(e),s=this._getValues(e,n,t.values);n.forEach(i=>{s.indexOf(i.value)>-1?i.show():i.hide()})}_openItems(e,t){let n=this._getItemInfo(e),s=this._getValues(e,n,t.values);n.forEach(i=>{s.indexOf(i.value)>-1&&i.show()})}_closeItems(e,t){let n=this._getItemInfo(e),s=this._getValues(e,n,t.values);n.forEach(i=>{s.indexOf(i.value)>-1&&i.hide()})}_insertItem(e,t){let n=this._findItem(e,t.target);n||(n=t.position==="before"?e.firstElementChild:e.lastElementChild);let s=t.panel;if(n?Shiny.renderContent(n,s,t.position==="before"?"beforeBegin":"afterEnd"):Shiny.renderContent(e,s),this._isAutoClosing(e)){let i=$(s.html).attr("data-value");$(e).find(`[data-value="${i}"] .accordion-collapse`).attr("data-bs-parent","#"+e.id)}}_removeItem(e,t){let n=this._getItemInfo(e).filter(i=>t.target.indexOf(i.value)>-1),s=Shiny==null?void 0:Shiny.unbindAll;n.forEach(i=>{s&&s(i.item),i.item.remove()})}_updateItem(e,t){let n=this._findItem(e,t.target);if(!n)throw new Error(`Unable to find an accordion_panel() with a value of ${t.target}`);if(b(t,"value")&&(n.dataset.value=t.value),b(t,"body")){let i=n.querySelector(".accordion-body");Shiny.renderContent(i,t.body)}let s=n.querySelector(".accordion-header");if(b(t,"title")){let i=s.querySelector(".accordion-title");Shiny.renderContent(i,t.title)}if(b(t,"icon")){let i=s.querySelector(".accordion-button > .accordion-icon");Shiny.renderContent(i,t.icon)}}_getItemInfo(e){return Array.from(e.querySelectorAll(":scope > .accordion-item")).map(n=>this._getSingleItemInfo(n))}_getSingleItemInfo(e){let t=e.querySelector(".accordion-collapse"),n=()=>$(t).hasClass("show");return{item:e,value:e.dataset.value,isOpen:n,show:()=>{n()||$(t).collapse("show")},hide:()=>{n()&&$(t).collapse("hide")}}}_getValues(e,t,n){let s=n!==!0?n:t.map(c=>c.value);return this._isAutoClosing(e)&&(s=s.slice(s.length-1,s.length)),s}_findItem(e,t){return e.querySelector(`[data-value="${t}"]`)}_isAutoClosing(e){return e.classList.contains("autoclose")}};g(y,"accordion");var m=class{constructor(){this.resizeObserverEntries=[],this.resizeObserver=new ResizeObserver(e=>{let t=new Event("resize");if(window.dispatchEvent(t),!window.Shiny)return;let n=[];for(let s of e)s.target instanceof HTMLElement&&s.target.querySelector(".shiny-bound-output")&&s.target.querySelectorAll(".shiny-bound-output").forEach(i=>{if(n.includes(i))return;let{binding:c,onResize:u}=$(i).data("shinyOutputBinding");if(!c||!c.resize)return;let o=i.shinyResizeObserver;if(o&&o!==this||(o||(i.shinyResizeObserver=this),u(i),n.push(i),!i.classList.contains("shiny-plot-output")))return;let f=i.querySelector('img:not([width="100%"])');f&&f.setAttribute("width","100%")})})}observe(e){this.resizeObserver.observe(e),this.resizeObserverEntries.push(e)}unobserve(e){let t=this.resizeObserverEntries.indexOf(e);t<0||(this.resizeObserver.unobserve(e),this.resizeObserverEntries.splice(t,1))}flush(){this.resizeObserverEntries.forEach(e=>{document.body.contains(e)||this.unobserve(e)})}};var r=class{constructor(e){var t;e.removeAttribute(r.attr.ATTR_INIT),(t=e.querySelector(`script[${r.attr.ATTR_INIT}]`))==null||t.remove(),this.card=e,r.instanceMap.set(e,this),r.shinyResizeObserver.observe(this.card),this._addEventListeners(),this.overlay=this._createOverlay(),this._exitFullScreenOnEscape=this._exitFullScreenOnEscape.bind(this),this._trapFocusExit=this._trapFocusExit.bind(this)}enterFullScreen(e){var t;e&&e.preventDefault(),document.addEventListener("keydown",this._exitFullScreenOnEscape,!1),document.addEventListener("keydown",this._trapFocusExit,!0),this.card.setAttribute(r.attr.ATTR_FULL_SCREEN,"true"),document.body.classList.add(r.attr.CLASS_HAS_FULL_SCREEN),this.card.insertAdjacentElement("beforebegin",this.overlay.container),(!this.card.contains(document.activeElement)||(t=document.activeElement)!=null&&t.classList.contains(r.attr.CLASS_FULL_SCREEN_ENTER))&&(this.card.setAttribute("tabindex","-1"),this.card.focus())}exitFullScreen(){document.removeEventListener("keydown",this._exitFullScreenOnEscape,!1),document.removeEventListener("keydown",this._trapFocusExit,!0),this.overlay.container.remove(),this.card.setAttribute(r.attr.ATTR_FULL_SCREEN,"false"),this.card.removeAttribute("tabindex"),document.body.classList.remove(r.attr.CLASS_HAS_FULL_SCREEN)}_addEventListeners(){let e=this.card.querySelector(`:scope > * > .${r.attr.CLASS_FULL_SCREEN_ENTER}`);e&&e.addEventListener("click",t=>this.enterFullScreen(t))}_exitFullScreenOnEscape(e){if(!(e.target instanceof HTMLElement))return;let t=["select[open]","input[aria-expanded='true']"];e.target.matches(t.join(", "))||e.key==="Escape"&&this.exitFullScreen()}_trapFocusExit(e){if(!(e instanceof KeyboardEvent)||e.key!=="Tab")return;let t=e.target===this.card,n=e.target===this.overlay.anchor,s=this.card.contains(e.target),i=()=>{e.preventDefault(),e.stopImmediatePropagation()};if(!(s||t||n)){i(),this.card.focus();return}let c=L(this.card).filter(E=>!E.classList.contains(r.attr.CLASS_FULL_SCREEN_ENTER));if(!(c.length>0)){i(),this.overlay.anchor.focus();return}if(t)return;let o=c[c.length-1],f=e.target===o;if(n&&e.shiftKey){i(),o.focus();return}if(f&&!e.shiftKey){i(),this.overlay.anchor.focus();return}}_createOverlay(){let e=document.createElement("div");e.id=r.attr.ID_FULL_SCREEN_OVERLAY,e.onclick=this.exitFullScreen.bind(this);let t=this._createOverlayCloseAnchor();return e.appendChild(t),{container:e,anchor:t}}_createOverlayCloseAnchor(){let e=document.createElement("a");return e.classList.add(r.attr.CLASS_FULL_SCREEN_EXIT),e.tabIndex=0,e.onclick=()=>this.exitFullScreen(),e.onkeydown=t=>{(t.key==="Enter"||t.key===" ")&&this.exitFullScreen()},e.innerHTML=this._overlayCloseHtml(),e}_overlayCloseHtml(){return"Close "}static getInstance(e){return r.instanceMap.get(e)}static initializeAllCards(e=!0){if(document.readyState==="loading"){r.onReadyScheduled||(r.onReadyScheduled=!0,document.addEventListener("DOMContentLoaded",()=>{r.initializeAllCards(!1)}));return}e&&r.shinyResizeObserver.flush();let t=`.${r.attr.CLASS_CARD}[${r.attr.ATTR_INIT}]`;if(!document.querySelector(t))return;document.querySelectorAll(t).forEach(s=>new r(s))}},p=r;p.attr={ATTR_INIT:"data-bslib-card-init",CLASS_CARD:"bslib-card",ATTR_FULL_SCREEN:"data-full-screen",CLASS_HAS_FULL_SCREEN:"bslib-has-full-screen",CLASS_FULL_SCREEN_ENTER:"bslib-full-screen-enter",CLASS_FULL_SCREEN_EXIT:"bslib-full-screen-exit",ID_FULL_SCREEN_OVERLAY:"bslib-full-screen-overlay"},p.shinyResizeObserver=new m,p.instanceMap=new WeakMap,p.onReadyScheduled=!1;window.bslib=window.bslib||{};window.bslib.Card=p;var l=class{constructor(e){var s;l.instanceMap.set(e,this),this.layout={container:e,main:e.querySelector(":scope > .main"),sidebar:e.querySelector(":scope > .sidebar"),toggle:e.querySelector(":scope > .collapse-toggle")};let t=this.layout.sidebar.querySelector(":scope > .sidebar-content > .accordion");t&&((s=t==null?void 0:t.parentElement)==null||s.classList.add("has-accordion"),t.classList.add("accordion-flush")),this.layout.toggle&&(this._initEventListeners(),this._initSidebarCounters(),this._initDesktop()),l.shinyResizeObserver.observe(this.layout.main),e.removeAttribute("data-bslib-sidebar-init");let n=e.querySelector(":scope > script[data-bslib-sidebar-init]");n&&e.removeChild(n)}get isClosed(){return this.layout.container.classList.contains(l.classes.COLLAPSE)}static getInstance(e){return l.instanceMap.get(e)}static initCollapsibleAll(e=!0){if(document.readyState==="loading"){l.onReadyScheduled||(l.onReadyScheduled=!0,document.addEventListener("DOMContentLoaded",()=>{l.initCollapsibleAll(!1)}));return}let t=`.${l.classes.LAYOUT}[data-bslib-sidebar-init]`;if(!document.querySelector(t))return;e&&l.shinyResizeObserver.flush(),document.querySelectorAll(t).forEach(s=>new l(s))}_initEventListeners(){var t;let{toggle:e}=this.layout;e.addEventListener("click",n=>{n.preventDefault(),this.toggle("toggle")}),(t=e.querySelector(".collapse-icon"))==null||t.addEventListener("transitionend",()=>this._finalizeState())}_initSidebarCounters(){let{container:e}=this.layout,t=`.${l.classes.LAYOUT}> .main > .${l.classes.LAYOUT}:not([data-bslib-sidebar-open="always"])`;if(!(e.querySelector(t)===null))return;function s(o){return o=o?o.parentElement:null,o&&o.classList.contains("main")&&(o=o.parentElement),o&&o.classList.contains(l.classes.LAYOUT)?o:null}let i=[e],c=s(e);for(;c;)i.unshift(c),c=s(c);let u={left:0,right:0};i.forEach(function(o){let E=o.classList.contains("sidebar-right")?u.right++:u.left++;o.style.setProperty("--_js-toggle-count-this-side",E.toString()),o.style.setProperty("--_js-toggle-count-max-side",Math.max(u.right,u.left).toString())})}_initDesktop(){var n;let{container:e}=this.layout;if(((n=e.dataset.bslibSidebarOpen)==null?void 0:n.trim())!=="desktop")return;window.getComputedStyle(e).getPropertyValue("--bslib-sidebar-js-init-collapsed").trim()==="true"&&this.toggle("close")}toggle(e){typeof e=="undefined"&&(e="toggle");let{container:t,sidebar:n}=this.layout,s=this.isClosed;if(["open","close","toggle"].indexOf(e)===-1)throw new Error(`Unknown method ${e}`);e==="toggle"&&(e=s?"open":"close"),!(s&&e==="close"||!s&&e==="open")&&(e==="open"&&(n.hidden=!1),t.classList.add(l.classes.TRANSITIONING),t.classList.toggle(l.classes.COLLAPSE))}_finalizeState(){let{container:e,sidebar:t,toggle:n}=this.layout;e.classList.remove(l.classes.TRANSITIONING),t.hidden=this.isClosed,n.setAttribute("aria-expanded",this.isClosed?"false":"true");let s=new CustomEvent("bslib.sidebar",{bubbles:!0,detail:{open:!this.isClosed}});t.dispatchEvent(s),$(t).trigger("toggleCollapse.sidebarInputBinding"),$(t).trigger(this.isClosed?"hidden":"shown")}},d=l;d.shinyResizeObserver=new m,d.classes={LAYOUT:"bslib-sidebar-layout",COLLAPSE:"sidebar-collapsed",TRANSITIONING:"transitioning"},d.onReadyScheduled=!1,d.instanceMap=new WeakMap;var v=class extends h{find(e){return $(e).find(`.${d.classes.LAYOUT} > .bslib-sidebar-input`)}getValue(e){let t=d.getInstance(e.parentElement);return t?!t.isClosed:!1}setValue(e,t){let n=t?"open":"close";this.receiveMessage(e,{method:n})}subscribe(e,t){$(e).on("toggleCollapse.sidebarInputBinding",function(n){t(!0)})}unsubscribe(e){$(e).off(".sidebarInputBinding")}receiveMessage(e,t){let n=d.getInstance(e.parentElement);n&&n.toggle(t.method)}};g(v,"sidebar");window.bslib=window.bslib||{};window.bslib.Sidebar=d;function S(a){if(window.Shiny)for(let[e,t]of Object.entries(a))Shiny.addCustomMessageHandler(e,t)}var T={"bslib.toggle-input-binary":a=>{let e=document.getElementById(a.id);e||console.warn("[bslib.toggle-input-binary] No element found",a);let t=$(e).data("shiny-input-binding");if(!(t instanceof h)){console.warn("[bslib.toggle-input-binary] No input binding found",a);return}let n=a.value;typeof n=="undefined"&&(n=!t.getValue(e)),t.receiveMessage(e,{value:n})}};window.Shiny&&S(T);function M(){let a=document.createElement("div");a.innerHTML=`
+"use strict";(()=>{var f=(r,e)=>()=>(r&&(e=r(r=0)),e);var x=(r,e)=>()=>(e||r((e={exports:{}}).exports,e),e.exports);var h=(r,e,t)=>new Promise((n,s)=>{var i=o=>{try{d(t.next(o))}catch(p){s(p)}},c=o=>{try{d(t.throw(o))}catch(p){s(p)}},d=o=>o.done?n(o.value):Promise.resolve(o.value).then(i,c);d((t=t.apply(r,e)).next())});function L(r,e){window.Shiny&&Shiny.inputBindings.register(new r,"bslib."+e)}function E(r,e){return Object.prototype.hasOwnProperty.call(r,e)&&r[e]!==void 0}function w(r){let e=["a[href]","area[href]","button","details summary","input","iframe","select","textarea",'[contentEditable=""]','[contentEditable="true"]','[contentEditable="TRUE"]',"[tabindex]"],t=[':not([tabindex="-1"])',":not([disabled])"],n=e.map(i=>i+t.join("")),s=r.querySelectorAll(n.join(", "));return Array.from(s)}function g(...r){return h(this,null,function*(){if(!window.Shiny)throw new Error("This function must be called in a Shiny app.");return Shiny.renderContentAsync?yield Shiny.renderContentAsync.apply(null,r):yield Shiny.renderContent.apply(null,r)})}var b,v=f(()=>{"use strict";b=window.Shiny?Shiny.InputBinding:class{}});var M,H=f(()=>{"use strict";v();M=class extends b{find(e){return $(e).find(".accordion.bslib-accordion-input")}getValue(e){let n=this._getItemInfo(e).filter(s=>s.isOpen()).map(s=>s.value);return n.length===0?null:n}subscribe(e,t){$(e).on("shown.bs.collapse.accordionInputBinding hidden.bs.collapse.accordionInputBinding",function(n){t(!0)})}unsubscribe(e){$(e).off(".accordionInputBinding")}receiveMessage(e,t){return h(this,null,function*(){let n=t.method;if(n==="set")this._setItems(e,t);else if(n==="open")this._openItems(e,t);else if(n==="close")this._closeItems(e,t);else if(n==="remove")this._removeItem(e,t);else if(n==="insert")yield this._insertItem(e,t);else if(n==="update")yield this._updateItem(e,t);else throw new Error(`Method not yet implemented: ${n}`)})}_setItems(e,t){let n=this._getItemInfo(e),s=this._getValues(e,n,t.values);n.forEach(i=>{s.indexOf(i.value)>-1?i.show():i.hide()})}_openItems(e,t){let n=this._getItemInfo(e),s=this._getValues(e,n,t.values);n.forEach(i=>{s.indexOf(i.value)>-1&&i.show()})}_closeItems(e,t){let n=this._getItemInfo(e),s=this._getValues(e,n,t.values);n.forEach(i=>{s.indexOf(i.value)>-1&&i.hide()})}_insertItem(e,t){return h(this,null,function*(){let n=this._findItem(e,t.target);n||(n=t.position==="before"?e.firstElementChild:e.lastElementChild);let s=t.panel;if(n?yield g(n,s,t.position==="before"?"beforeBegin":"afterEnd"):yield g(e,s),this._isAutoClosing(e)){let i=$(s.html).attr("data-value");$(e).find(`[data-value="${i}"] .accordion-collapse`).attr("data-bs-parent","#"+e.id)}})}_removeItem(e,t){let n=this._getItemInfo(e).filter(i=>t.target.indexOf(i.value)>-1),s=Shiny==null?void 0:Shiny.unbindAll;n.forEach(i=>{s&&s(i.item),i.item.remove()})}_updateItem(e,t){return h(this,null,function*(){let n=this._findItem(e,t.target);if(!n)throw new Error(`Unable to find an accordion_panel() with a value of ${t.target}`);if(E(t,"value")&&(n.dataset.value=t.value),E(t,"body")){let i=n.querySelector(".accordion-body");yield g(i,t.body)}let s=n.querySelector(".accordion-header");if(E(t,"title")){let i=s.querySelector(".accordion-title");yield g(i,t.title)}if(E(t,"icon")){let i=s.querySelector(".accordion-button > .accordion-icon");yield g(i,t.icon)}})}_getItemInfo(e){return Array.from(e.querySelectorAll(":scope > .accordion-item")).map(n=>this._getSingleItemInfo(n))}_getSingleItemInfo(e){let t=e.querySelector(".accordion-collapse"),n=()=>$(t).hasClass("show");return{item:e,value:e.dataset.value,isOpen:n,show:()=>{n()||$(t).collapse("show")},hide:()=>{n()&&$(t).collapse("hide")}}}_getValues(e,t,n){let s=n!==!0?n:t.map(c=>c.value);return this._isAutoClosing(e)&&(s=s.slice(s.length-1,s.length)),s}_findItem(e,t){return e.querySelector(`[data-value="${t}"]`)}_isAutoClosing(e){return e.classList.contains("autoclose")}};L(M,"accordion")});var y,T=f(()=>{"use strict";y=class{constructor(){this.resizeObserverEntries=[],this.resizeObserver=new ResizeObserver(e=>{let t=new Event("resize");if(window.dispatchEvent(t),!window.Shiny)return;let n=[];for(let s of e)s.target instanceof HTMLElement&&s.target.querySelector(".shiny-bound-output")&&s.target.querySelectorAll(".shiny-bound-output").forEach(i=>{if(n.includes(i))return;let{binding:c,onResize:d}=$(i).data("shinyOutputBinding");if(!c||!c.resize)return;let o=i.shinyResizeObserver;if(o&&o!==this||(o||(i.shinyResizeObserver=this),d(i),n.push(i),!i.classList.contains("shiny-plot-output")))return;let p=i.querySelector('img:not([width="100%"])');p&&p.setAttribute("width","100%")})})}observe(e){this.resizeObserver.observe(e),this.resizeObserverEntries.push(e)}unobserve(e){let t=this.resizeObserverEntries.indexOf(e);t<0||(this.resizeObserver.unobserve(e),this.resizeObserverEntries.splice(t,1))}flush(){this.resizeObserverEntries.forEach(e=>{document.body.contains(e)||this.unobserve(e)})}}});var a,m,I=f(()=>{"use strict";v();T();a=class{constructor(e){var t;e.removeAttribute(a.attr.ATTR_INIT),(t=e.querySelector(`script[${a.attr.ATTR_INIT}]`))==null||t.remove(),this.card=e,a.instanceMap.set(e,this),a.shinyResizeObserver.observe(this.card),this._addEventListeners(),this.overlay=this._createOverlay(),this._exitFullScreenOnEscape=this._exitFullScreenOnEscape.bind(this),this._trapFocusExit=this._trapFocusExit.bind(this)}enterFullScreen(e){var t;e&&e.preventDefault(),document.addEventListener("keydown",this._exitFullScreenOnEscape,!1),document.addEventListener("keydown",this._trapFocusExit,!0),this.card.setAttribute(a.attr.ATTR_FULL_SCREEN,"true"),document.body.classList.add(a.attr.CLASS_HAS_FULL_SCREEN),this.card.insertAdjacentElement("beforebegin",this.overlay.container),(!this.card.contains(document.activeElement)||(t=document.activeElement)!=null&&t.classList.contains(a.attr.CLASS_FULL_SCREEN_ENTER))&&(this.card.setAttribute("tabindex","-1"),this.card.focus())}exitFullScreen(){document.removeEventListener("keydown",this._exitFullScreenOnEscape,!1),document.removeEventListener("keydown",this._trapFocusExit,!0),this.overlay.container.remove(),this.card.setAttribute(a.attr.ATTR_FULL_SCREEN,"false"),this.card.removeAttribute("tabindex"),document.body.classList.remove(a.attr.CLASS_HAS_FULL_SCREEN)}_addEventListeners(){let e=this.card.querySelector(`:scope > * > .${a.attr.CLASS_FULL_SCREEN_ENTER}`);e&&e.addEventListener("click",t=>this.enterFullScreen(t))}_exitFullScreenOnEscape(e){if(!(e.target instanceof HTMLElement))return;let t=["select[open]","input[aria-expanded='true']"];e.target.matches(t.join(", "))||e.key==="Escape"&&this.exitFullScreen()}_trapFocusExit(e){if(!(e instanceof KeyboardEvent)||e.key!=="Tab")return;let t=e.target===this.card,n=e.target===this.overlay.anchor,s=this.card.contains(e.target),i=()=>{e.preventDefault(),e.stopImmediatePropagation()};if(!(s||t||n)){i(),this.card.focus();return}let c=w(this.card).filter(S=>!S.classList.contains(a.attr.CLASS_FULL_SCREEN_ENTER));if(!(c.length>0)){i(),this.overlay.anchor.focus();return}if(t)return;let o=c[c.length-1],p=e.target===o;if(n&&e.shiftKey){i(),o.focus();return}if(p&&!e.shiftKey){i(),this.overlay.anchor.focus();return}}_createOverlay(){let e=document.createElement("div");e.id=a.attr.ID_FULL_SCREEN_OVERLAY,e.onclick=this.exitFullScreen.bind(this);let t=this._createOverlayCloseAnchor();return e.appendChild(t),{container:e,anchor:t}}_createOverlayCloseAnchor(){let e=document.createElement("a");return e.classList.add(a.attr.CLASS_FULL_SCREEN_EXIT),e.tabIndex=0,e.onclick=()=>this.exitFullScreen(),e.onkeydown=t=>{(t.key==="Enter"||t.key===" ")&&this.exitFullScreen()},e.innerHTML=this._overlayCloseHtml(),e}_overlayCloseHtml(){return"Close "}static getInstance(e){return a.instanceMap.get(e)}static initializeAllCards(e=!0){if(document.readyState==="loading"){a.onReadyScheduled||(a.onReadyScheduled=!0,document.addEventListener("DOMContentLoaded",()=>{a.initializeAllCards(!1)}));return}e&&a.shinyResizeObserver.flush();let t=`.${a.attr.CLASS_CARD}[${a.attr.ATTR_INIT}]`;if(!document.querySelector(t))return;document.querySelectorAll(t).forEach(s=>new a(s))}},m=a;m.attr={ATTR_INIT:"data-bslib-card-init",CLASS_CARD:"bslib-card",ATTR_FULL_SCREEN:"data-full-screen",CLASS_HAS_FULL_SCREEN:"bslib-has-full-screen",CLASS_FULL_SCREEN_ENTER:"bslib-full-screen-enter",CLASS_FULL_SCREEN_EXIT:"bslib-full-screen-exit",ID_FULL_SCREEN_OVERLAY:"bslib-full-screen-overlay"},m.shinyResizeObserver=new y,m.instanceMap=new WeakMap,m.onReadyScheduled=!1;window.bslib=window.bslib||{};window.bslib.Card=m});var l,u,C,A=f(()=>{"use strict";v();T();l=class{constructor(e){var s;l.instanceMap.set(e,this),this.layout={container:e,main:e.querySelector(":scope > .main"),sidebar:e.querySelector(":scope > .sidebar"),toggle:e.querySelector(":scope > .collapse-toggle")};let t=this.layout.sidebar.querySelector(":scope > .sidebar-content > .accordion");t&&((s=t==null?void 0:t.parentElement)==null||s.classList.add("has-accordion"),t.classList.add("accordion-flush")),this.layout.toggle&&(this._initEventListeners(),this._initSidebarCounters(),this._initDesktop()),l.shinyResizeObserver.observe(this.layout.main),e.removeAttribute("data-bslib-sidebar-init");let n=e.querySelector(":scope > script[data-bslib-sidebar-init]");n&&e.removeChild(n)}get isClosed(){return this.layout.container.classList.contains(l.classes.COLLAPSE)}static getInstance(e){return l.instanceMap.get(e)}static initCollapsibleAll(e=!0){if(document.readyState==="loading"){l.onReadyScheduled||(l.onReadyScheduled=!0,document.addEventListener("DOMContentLoaded",()=>{l.initCollapsibleAll(!1)}));return}let t=`.${l.classes.LAYOUT}[data-bslib-sidebar-init]`;if(!document.querySelector(t))return;e&&l.shinyResizeObserver.flush(),document.querySelectorAll(t).forEach(s=>new l(s))}_initEventListeners(){var t;let{toggle:e}=this.layout;e.addEventListener("click",n=>{n.preventDefault(),this.toggle("toggle")}),(t=e.querySelector(".collapse-icon"))==null||t.addEventListener("transitionend",()=>this._finalizeState())}_initSidebarCounters(){let{container:e}=this.layout,t=`.${l.classes.LAYOUT}> .main > .${l.classes.LAYOUT}:not([data-bslib-sidebar-open="always"])`;if(!(e.querySelector(t)===null))return;function s(o){return o=o?o.parentElement:null,o&&o.classList.contains("main")&&(o=o.parentElement),o&&o.classList.contains(l.classes.LAYOUT)?o:null}let i=[e],c=s(e);for(;c;)i.unshift(c),c=s(c);let d={left:0,right:0};i.forEach(function(o){let S=o.classList.contains("sidebar-right")?d.right++:d.left++;o.style.setProperty("--_js-toggle-count-this-side",S.toString()),o.style.setProperty("--_js-toggle-count-max-side",Math.max(d.right,d.left).toString())})}_initDesktop(){var n;let{container:e}=this.layout;if(((n=e.dataset.bslibSidebarOpen)==null?void 0:n.trim())!=="desktop")return;window.getComputedStyle(e).getPropertyValue("--bslib-sidebar-js-init-collapsed").trim()==="true"&&this.toggle("close")}toggle(e){typeof e=="undefined"&&(e="toggle");let{container:t,sidebar:n}=this.layout,s=this.isClosed;if(["open","close","toggle"].indexOf(e)===-1)throw new Error(`Unknown method ${e}`);e==="toggle"&&(e=s?"open":"close"),!(s&&e==="close"||!s&&e==="open")&&(e==="open"&&(n.hidden=!1),t.classList.add(l.classes.TRANSITIONING),t.classList.toggle(l.classes.COLLAPSE))}_finalizeState(){let{container:e,sidebar:t,toggle:n}=this.layout;e.classList.remove(l.classes.TRANSITIONING),t.hidden=this.isClosed,n.setAttribute("aria-expanded",this.isClosed?"false":"true");let s=new CustomEvent("bslib.sidebar",{bubbles:!0,detail:{open:!this.isClosed}});t.dispatchEvent(s),$(t).trigger("toggleCollapse.sidebarInputBinding"),$(t).trigger(this.isClosed?"hidden":"shown")}},u=l;u.shinyResizeObserver=new y,u.classes={LAYOUT:"bslib-sidebar-layout",COLLAPSE:"sidebar-collapsed",TRANSITIONING:"transitioning"},u.onReadyScheduled=!1,u.instanceMap=new WeakMap;C=class extends b{find(e){return $(e).find(`.${u.classes.LAYOUT} > .bslib-sidebar-input`)}getValue(e){let t=u.getInstance(e.parentElement);return t?!t.isClosed:!1}setValue(e,t){let n=t?"open":"close";this.receiveMessage(e,{method:n})}subscribe(e,t){$(e).on("toggleCollapse.sidebarInputBinding",function(n){t(!0)})}unsubscribe(e){$(e).off(".sidebarInputBinding")}receiveMessage(e,t){let n=u.getInstance(e.parentElement);n&&n.toggle(t.method)}};L(C,"sidebar");window.bslib=window.bslib||{};window.bslib.Sidebar=u});function O(r){if(window.Shiny)for(let[e,t]of Object.entries(r))Shiny.addCustomMessageHandler(e,t)}var _=f(()=>{"use strict"});var z=x(F=>{H();I();A();v();_();var N={"bslib.toggle-input-binary":r=>h(F,null,function*(){let e=document.getElementById(r.id);e||console.warn("[bslib.toggle-input-binary] No element found",r);let t=$(e).data("shiny-input-binding");if(!(t instanceof b)){console.warn("[bslib.toggle-input-binary] No input binding found",r);return}let n=r.value;typeof n=="undefined"&&(n=!t.getValue(e)),yield t.receiveMessage(e,{value:n})})};window.Shiny&&O(N);function R(){let r=document.createElement("div");r.innerHTML=`
`,document.body.appendChild(a.children[0])}document.readyState==="complete"?M():document.addEventListener("DOMContentLoaded",M);})();
+ `,document.body.appendChild(r.children[0])}document.readyState==="complete"?R():document.addEventListener("DOMContentLoaded",R)});z();})();
//# sourceMappingURL=components.min.js.map
diff --git a/inst/components/dist/components.min.js.map b/inst/components/dist/components.min.js.map
index 823a316ac..f7e7a530d 100644
--- a/inst/components/dist/components.min.js.map
+++ b/inst/components/dist/components.min.js.map
@@ -1,7 +1,7 @@
{
"version": 3,
"sources": ["../../../srcts/src/components/_utils.ts", "../../../srcts/src/components/accordion.ts", "../../../srcts/src/components/_shinyResizeObserver.ts", "../../../srcts/src/components/card.ts", "../../../srcts/src/components/sidebar.ts", "../../../srcts/src/components/_shinyAddCustomMessageHandlers.ts", "../../../srcts/src/components/index.ts"],
- "sourcesContent": ["import type { HtmlDep } from \"rstudio-shiny/srcts/types/src/shiny/render\";\n\nimport type { InputBinding as InputBindingType } from \"rstudio-shiny/srcts/types/src/bindings/input\";\n\n// Exclude undefined from T\ntype NotUndefined = T extends undefined ? never : T;\n\n// eslint-disable-next-line @typescript-eslint/naming-convention\nconst InputBinding = (\n window.Shiny ? Shiny.InputBinding : class {}\n) as typeof InputBindingType;\n\nfunction registerBinding(\n inputBindingClass: new () => InputBindingType,\n name: string\n): void {\n if (window.Shiny) {\n Shiny.inputBindings.register(new inputBindingClass(), \"bslib.\" + name);\n }\n}\n\n// Return true if the key exists on the object and the value is not undefined.\n//\n// This method is mainly used in input bindings' `receiveMessage` method.\n// Since we know that the values are sent by Shiny via `{jsonlite}`,\n// then we know that there are no `undefined` values. `null` is possible, but not `undefined`.\nfunction hasDefinedProperty<\n Prop extends keyof X,\n X extends { [key: string]: any }\n>(\n obj: X,\n prop: Prop\n): obj is X & { [key in NonNullable]: NotUndefined } {\n return (\n Object.prototype.hasOwnProperty.call(obj, prop) && obj[prop] !== undefined\n );\n}\n\n// TODO: Shiny should trigger resize events when the output\n// https://github.com/rstudio/shiny/pull/3682\nfunction doWindowResizeOnElementResize(el: HTMLElement): void {\n if ($(el).data(\"window-resize-observer\")) {\n return;\n }\n const resizeEvent = new Event(\"resize\");\n const ro = new ResizeObserver(() => {\n window.dispatchEvent(resizeEvent);\n });\n ro.observe(el);\n $(el).data(\"window-resize-observer\", ro);\n}\n\nfunction getAllFocusableChildren(el: HTMLElement): HTMLElement[] {\n // Cross-referenced with https://allyjs.io/data-tables/focusable.html\n const base = [\n \"a[href]\",\n \"area[href]\",\n \"button\",\n \"details summary\",\n \"input\",\n \"iframe\",\n \"select\",\n \"textarea\",\n '[contentEditable=\"\"]',\n '[contentEditable=\"true\"]',\n '[contentEditable=\"TRUE\"]',\n \"[tabindex]\",\n ];\n const modifiers = [':not([tabindex=\"-1\"])', \":not([disabled])\"];\n const selectors = base.map((b) => b + modifiers.join(\"\"));\n const focusable = el.querySelectorAll(selectors.join(\", \"));\n return Array.from(focusable) as HTMLElement[];\n}\n\nexport {\n InputBinding,\n registerBinding,\n hasDefinedProperty,\n doWindowResizeOnElementResize,\n getAllFocusableChildren,\n};\nexport type { HtmlDep };\n", "import type { HtmlDep } from \"./_utils\";\nimport { InputBinding, registerBinding, hasDefinedProperty } from \"./_utils\";\n\ntype AccordionItem = {\n item: HTMLElement;\n value: string;\n isOpen: () => boolean;\n show: () => void;\n hide: () => void;\n};\n\ntype HTMLContent = {\n html: string;\n deps?: HtmlDep[];\n};\n\ntype SetMessage = {\n method: \"set\";\n values: string[];\n};\n\ntype OpenMessage = {\n method: \"open\";\n values: string[] | true;\n};\n\ntype CloseMessage = {\n method: \"close\";\n values: string[] | true;\n};\n\ntype InsertMessage = {\n method: \"insert\";\n panel: HTMLContent;\n target: string;\n position: \"after\" | \"before\";\n};\n\ntype RemoveMessage = {\n method: \"remove\";\n target: string[];\n};\n\ntype UpdateMessage = {\n method: \"update\";\n target: string;\n value: string;\n body: HTMLContent;\n title: HTMLContent;\n icon: HTMLContent;\n};\n\ntype MessageData =\n | CloseMessage\n | InsertMessage\n | OpenMessage\n | RemoveMessage\n | SetMessage\n | UpdateMessage;\n\nclass AccordionInputBinding extends InputBinding {\n find(scope: HTMLElement) {\n return $(scope).find(\".accordion.bslib-accordion-input\");\n }\n\n getValue(el: HTMLElement): string[] | null {\n const items = this._getItemInfo(el);\n const selected = items.filter((x) => x.isOpen()).map((x) => x.value);\n return selected.length === 0 ? null : selected;\n }\n\n subscribe(el: HTMLElement, callback: (x: boolean) => void) {\n $(el).on(\n \"shown.bs.collapse.accordionInputBinding hidden.bs.collapse.accordionInputBinding\",\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n function (event) {\n callback(true);\n }\n );\n }\n\n unsubscribe(el: HTMLElement) {\n $(el).off(\".accordionInputBinding\");\n }\n\n receiveMessage(el: HTMLElement, data: MessageData) {\n const method = data.method;\n if (method === \"set\") {\n this._setItems(el, data);\n } else if (method === \"open\") {\n this._openItems(el, data);\n } else if (method === \"close\") {\n this._closeItems(el, data);\n } else if (method === \"remove\") {\n this._removeItem(el, data);\n } else if (method === \"insert\") {\n this._insertItem(el, data);\n } else if (method === \"update\") {\n this._updateItem(el, data);\n } else {\n throw new Error(`Method not yet implemented: ${method}`);\n }\n }\n\n protected _setItems(el: HTMLElement, data: SetMessage) {\n const items = this._getItemInfo(el);\n const vals = this._getValues(el, items, data.values);\n items.forEach((x) => {\n vals.indexOf(x.value) > -1 ? x.show() : x.hide();\n });\n }\n\n protected _openItems(el: HTMLElement, data: OpenMessage) {\n const items = this._getItemInfo(el);\n const vals = this._getValues(el, items, data.values);\n items.forEach((x) => {\n if (vals.indexOf(x.value) > -1) x.show();\n });\n }\n\n protected _closeItems(el: HTMLElement, data: CloseMessage) {\n const items = this._getItemInfo(el);\n const vals = this._getValues(el, items, data.values);\n items.forEach((x) => {\n if (vals.indexOf(x.value) > -1) x.hide();\n });\n }\n\n protected _insertItem(el: HTMLElement, data: InsertMessage) {\n let targetItem = this._findItem(el, data.target);\n\n // If no target was specified, or the target was not found, then default\n // to the first or last item, depending on the position\n if (!targetItem) {\n targetItem = (\n data.position === \"before\" ? el.firstElementChild : el.lastElementChild\n ) as HTMLElement;\n }\n\n const panel = data.panel;\n\n // If there is still no targetItem, then there are no items in the accordion\n if (targetItem) {\n Shiny.renderContent(\n targetItem,\n panel,\n data.position === \"before\" ? \"beforeBegin\" : \"afterEnd\"\n );\n } else {\n Shiny.renderContent(el, panel);\n }\n\n // Need to add a reference to the parent id that makes autoclose to work\n if (this._isAutoClosing(el)) {\n const val = $(panel.html).attr(\"data-value\");\n $(el)\n .find(`[data-value=\"${val}\"] .accordion-collapse`)\n .attr(\"data-bs-parent\", \"#\" + el.id);\n }\n }\n\n protected _removeItem(el: HTMLElement, data: RemoveMessage) {\n const targetItems = this._getItemInfo(el).filter(\n (x) => data.target.indexOf(x.value) > -1\n );\n\n const unbindAll = Shiny?.unbindAll;\n\n targetItems.forEach((x) => {\n if (unbindAll) unbindAll(x.item);\n x.item.remove();\n });\n }\n\n protected _updateItem(el: HTMLElement, data: UpdateMessage) {\n const target = this._findItem(el, data.target);\n\n if (!target) {\n throw new Error(\n `Unable to find an accordion_panel() with a value of ${data.target}`\n );\n }\n\n if (hasDefinedProperty(data, \"value\")) {\n target.dataset.value = data.value;\n }\n\n if (hasDefinedProperty(data, \"body\")) {\n const body = target.querySelector(\".accordion-body\") as HTMLElement; // always exists\n Shiny.renderContent(body, data.body);\n }\n\n const header = target.querySelector(\".accordion-header\") as HTMLElement; // always exists\n\n if (hasDefinedProperty(data, \"title\")) {\n const title = header.querySelector(\".accordion-title\") as HTMLElement; // always exists\n Shiny.renderContent(title, data.title);\n }\n\n if (hasDefinedProperty(data, \"icon\")) {\n const icon = header.querySelector(\n \".accordion-button > .accordion-icon\"\n ) as HTMLElement; // always exists\n Shiny.renderContent(icon, data.icon);\n }\n }\n\n protected _getItemInfo(el: HTMLElement): AccordionItem[] {\n const items = Array.from(\n el.querySelectorAll(\":scope > .accordion-item\")\n ) as HTMLElement[];\n return items.map((x) => this._getSingleItemInfo(x));\n }\n\n protected _getSingleItemInfo(x: HTMLElement): AccordionItem {\n const collapse = x.querySelector(\".accordion-collapse\") as HTMLElement;\n const isOpen = () => $(collapse).hasClass(\"show\");\n return {\n item: x,\n value: x.dataset.value as string,\n isOpen: isOpen,\n show: () => {\n if (!isOpen()) $(collapse).collapse(\"show\");\n },\n hide: () => {\n if (isOpen()) $(collapse).collapse(\"hide\");\n },\n };\n }\n\n protected _getValues(\n el: HTMLElement,\n items: AccordionItem[],\n values: string[] | true\n ): string[] {\n let vals = values !== true ? values : items.map((x) => x.value);\n const autoclose = this._isAutoClosing(el);\n if (autoclose) {\n vals = vals.slice(vals.length - 1, vals.length);\n }\n return vals;\n }\n\n protected _findItem(el: HTMLElement, value: string): HTMLElement | null {\n return el.querySelector(`[data-value=\"${value}\"]`);\n }\n\n protected _isAutoClosing(el: HTMLElement): boolean {\n return el.classList.contains(\"autoclose\");\n }\n}\n\nregisterBinding(AccordionInputBinding, \"accordion\");\n", "/**\n * A resize observer that ensures Shiny outputs resize during or just after\n * their parent container size changes. Useful, in particular, for sidebar\n * transitions or for full-screen card transitions.\n *\n * @class ShinyResizeObserver\n * @typedef {ShinyResizeObserver}\n */\nclass ShinyResizeObserver {\n /**\n * The actual ResizeObserver instance.\n * @private\n * @type {ResizeObserver}\n */\n private resizeObserver: ResizeObserver;\n /**\n * An array of elements that are currently being watched by the Resize\n * Observer.\n *\n * @details\n * We don't currently have lifecycle hooks that allow us to unobserve elements\n * when they are removed from the DOM. As a result, we need to manually check\n * that the elements we're watching still exist in the DOM. This array keeps\n * track of the elements we're watching so that we can check them later.\n * @private\n * @type {HTMLElement[]}\n */\n private resizeObserverEntries: HTMLElement[];\n\n /**\n * Watch containers for size changes and ensure that Shiny outputs and\n * htmlwidgets within resize appropriately.\n *\n * @details\n * The ShinyResizeObserver is used to watch the containers, such as Sidebars\n * and Cards for size changes, in particular when the sidebar state is toggled\n * or the card body is expanded full screen. It performs two primary tasks:\n *\n * 1. Dispatches a `resize` event on the window object. This is necessary to\n * ensure that Shiny outputs resize appropriately. In general, the window\n * resizing is throttled and the output update occurs when the transition\n * is complete.\n * 2. If an output with a resize method on the output binding is detected, we\n * directly call the `.onResize()` method of the binding. This ensures that\n * htmlwidgets transition smoothly. In static mode, htmlwidgets does this\n * already.\n *\n * @note\n * This resize observer also handles race conditions in some complex\n * fill-based layouts with multiple outputs (e.g., plotly), where shiny\n * initializes with the correct sizing, but in-between the 1st and last\n * renderValue(), the size of the output containers can change, meaning every\n * output but the 1st gets initialized with the wrong size during their\n * renderValue(). Then, after the render phase, shiny won't know to trigger a\n * resize since all the widgets will return to their original size (and thus,\n * Shiny thinks there isn't any resizing to do). The resize observer works\n * around this by ensuring that the output is resized whenever its container\n * size changes.\n * @constructor\n */\n constructor() {\n this.resizeObserverEntries = [];\n this.resizeObserver = new ResizeObserver((entries) => {\n const resizeEvent = new Event(\"resize\");\n window.dispatchEvent(resizeEvent);\n\n // the rest of this callback is only relevant in Shiny apps\n if (!window.Shiny) return;\n\n const resized = [] as HTMLElement[];\n\n for (const entry of entries) {\n if (!(entry.target instanceof HTMLElement)) continue;\n if (!entry.target.querySelector(\".shiny-bound-output\")) continue;\n\n entry.target\n .querySelectorAll(\".shiny-bound-output\")\n .forEach((el) => {\n if (resized.includes(el)) return;\n\n const { binding, onResize } = $(el).data(\"shinyOutputBinding\");\n if (!binding || !binding.resize) return;\n\n // if this output is owned by another observer, skip it\n const owner = (el as any).shinyResizeObserver;\n if (owner && owner !== this) return;\n // mark this output as owned by this shinyResizeObserver instance\n if (!owner) (el as any).shinyResizeObserver = this;\n\n // trigger immediate resizing of outputs with a resize method\n onResize(el);\n // only once per output and resize event\n resized.push(el);\n\n // set plot images to 100% width temporarily during the transition\n if (!el.classList.contains(\"shiny-plot-output\")) return;\n const img = el.querySelector(\n 'img:not([width=\"100%\"])'\n );\n if (img) img.setAttribute(\"width\", \"100%\");\n });\n }\n });\n }\n\n /**\n * Observe an element for size changes.\n * @param {HTMLElement} el - The element to observe.\n */\n observe(el: HTMLElement): void {\n this.resizeObserver.observe(el);\n this.resizeObserverEntries.push(el);\n }\n\n /**\n * Stop observing an element for size changes.\n * @param {HTMLElement} el - The element to stop observing.\n */\n unobserve(el: HTMLElement): void {\n const idxEl = this.resizeObserverEntries.indexOf(el);\n if (idxEl < 0) return;\n\n this.resizeObserver.unobserve(el);\n this.resizeObserverEntries.splice(idxEl, 1);\n }\n\n /**\n * This method checks that we're not continuing to watch elements that no\n * longer exist in the DOM. If any are found, we stop observing them and\n * remove them from our array of observed elements.\n *\n * @private\n * @static\n */\n flush(): void {\n this.resizeObserverEntries.forEach((el) => {\n if (!document.body.contains(el)) this.unobserve(el);\n });\n }\n}\n\nexport { ShinyResizeObserver };\n", "import { getAllFocusableChildren } from \"./_utils\";\nimport { ShinyResizeObserver } from \"./_shinyResizeObserver\";\n\n/**\n * The overlay element that is placed behind the card when expanded full screen.\n *\n * @interface CardFullScreenOverlay\n * @typedef {CardFullScreenOverlay}\n */\ninterface CardFullScreenOverlay {\n /**\n * The full screen overlay container.\n * @type {HTMLDivElement}\n */\n container: HTMLDivElement;\n /**\n * The anchor element used to close the full screen overlay.\n * @type {HTMLAnchorElement}\n */\n anchor: HTMLAnchorElement;\n}\n\n/**\n * The bslib card component class.\n *\n * @class Card\n * @typedef {Card}\n */\nclass Card {\n /**\n * The card container element.\n * @private\n * @type {HTMLElement}\n */\n private card: HTMLElement;\n /**\n * The card's full screen overlay element. We create this element once and add\n * and remove it from the DOM as needed (this simplifies focus management\n * while in full screen mode).\n * @private\n * @type {CardFullScreenOverlay}\n */\n private overlay: CardFullScreenOverlay;\n\n /**\n * Key bslib-specific classes and attributes used by the card component.\n * @private\n * @static\n * @type {{ ATTR_INIT: string; CLASS_CARD: string; CLASS_FULL_SCREEN: string; CLASS_HAS_FULL_SCREEN: string; CLASS_FULL_SCREEN_ENTER: string; CLASS_FULL_SCREEN_EXIT: string; ID_FULL_SCREEN_OVERLAY: string; }}\n */\n private static attr = {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n ATTR_INIT: \"data-bslib-card-init\",\n // eslint-disable-next-line @typescript-eslint/naming-convention\n CLASS_CARD: \"bslib-card\",\n // eslint-disable-next-line @typescript-eslint/naming-convention\n ATTR_FULL_SCREEN: \"data-full-screen\",\n // eslint-disable-next-line @typescript-eslint/naming-convention\n CLASS_HAS_FULL_SCREEN: \"bslib-has-full-screen\",\n // eslint-disable-next-line @typescript-eslint/naming-convention\n CLASS_FULL_SCREEN_ENTER: \"bslib-full-screen-enter\",\n // eslint-disable-next-line @typescript-eslint/naming-convention\n CLASS_FULL_SCREEN_EXIT: \"bslib-full-screen-exit\",\n // eslint-disable-next-line @typescript-eslint/naming-convention\n ID_FULL_SCREEN_OVERLAY: \"bslib-full-screen-overlay\",\n };\n\n /**\n * A Shiny-specific resize observer that ensures Shiny outputs in within the\n * card resize appropriately.\n * @private\n * @type {ShinyResizeObserver}\n * @static\n */\n private static shinyResizeObserver = new ShinyResizeObserver();\n\n /**\n * Creates an instance of a bslib Card component.\n *\n * @constructor\n * @param {HTMLElement} card\n */\n constructor(card: HTMLElement) {\n // remove initialization attribute and script\n card.removeAttribute(Card.attr.ATTR_INIT);\n card\n .querySelector(`script[${Card.attr.ATTR_INIT}]`)\n ?.remove();\n\n this.card = card;\n Card.instanceMap.set(card, this);\n\n // Let Shiny know to trigger resize when the card size changes\n // TODO: shiny could/should do this itself (rstudio/shiny#3682)\n Card.shinyResizeObserver.observe(this.card);\n\n this._addEventListeners();\n this.overlay = this._createOverlay();\n\n // bind event handler methods to this card instance\n this._exitFullScreenOnEscape = this._exitFullScreenOnEscape.bind(this);\n this._trapFocusExit = this._trapFocusExit.bind(this);\n }\n\n /**\n * Enter the card's full screen mode, either programmatically or via an event\n * handler. Full screen mode is activated by adding a class to the card that\n * positions it absolutely and expands it to fill the viewport. In addition,\n * we add a full screen overlay element behind the card and we trap focus in\n * the expanded card while in full screen mode.\n *\n * @param {?Event} [event]\n */\n enterFullScreen(event?: Event): void {\n if (event) event.preventDefault();\n\n document.addEventListener(\"keydown\", this._exitFullScreenOnEscape, false);\n\n // trap focus in the fullscreen container, listening for Tab key on the\n // capture phase so we have the best chance of preventing other handlers\n document.addEventListener(\"keydown\", this._trapFocusExit, true);\n\n this.card.setAttribute(Card.attr.ATTR_FULL_SCREEN, \"true\");\n document.body.classList.add(Card.attr.CLASS_HAS_FULL_SCREEN);\n this.card.insertAdjacentElement(\"beforebegin\", this.overlay.container);\n\n // Set initial focus on the card, if not already\n if (\n !this.card.contains(document.activeElement) ||\n document.activeElement?.classList.contains(\n Card.attr.CLASS_FULL_SCREEN_ENTER\n )\n ) {\n this.card.setAttribute(\"tabindex\", \"-1\");\n this.card.focus();\n }\n }\n\n /**\n * Exit full screen mode. This removes the full screen overlay element,\n * removes the full screen class from the card, and removes the keyboard event\n * listeners that were added when entering full screen mode.\n */\n exitFullScreen(): void {\n document.removeEventListener(\n \"keydown\",\n this._exitFullScreenOnEscape,\n false\n );\n document.removeEventListener(\"keydown\", this._trapFocusExit, true);\n\n // Remove overlay and remove full screen classes from card\n this.overlay.container.remove();\n this.card.setAttribute(Card.attr.ATTR_FULL_SCREEN, \"false\");\n this.card.removeAttribute(\"tabindex\");\n document.body.classList.remove(Card.attr.CLASS_HAS_FULL_SCREEN);\n }\n\n /**\n * Adds general card-specific event listeners.\n * @private\n */\n private _addEventListeners(): void {\n const btnFullScreen = this.card.querySelector(\n `:scope > * > .${Card.attr.CLASS_FULL_SCREEN_ENTER}`\n );\n if (!btnFullScreen) return;\n btnFullScreen.addEventListener(\"click\", (ev) => this.enterFullScreen(ev));\n }\n\n /**\n * An event handler to exit full screen mode when the Escape key is pressed.\n * @private\n * @param {KeyboardEvent} event\n */\n private _exitFullScreenOnEscape(event: KeyboardEvent): void {\n if (!(event.target instanceof HTMLElement)) return;\n // If the user is in the middle of a select input choice, don't exit\n const selOpenSelectInput = [\"select[open]\", \"input[aria-expanded='true']\"];\n if (event.target.matches(selOpenSelectInput.join(\", \"))) return;\n\n if (event.key === \"Escape\") {\n this.exitFullScreen();\n }\n }\n\n /**\n * An event handler to trap focus within the card when in full screen mode.\n *\n * @description\n * This keyboard event handler ensures that tab focus stays within the card\n * when in full screen mode. When the card is first expanded,\n * we move focus to the card element itself. If focus somehow leaves the card,\n * we returns focus to the card container.\n *\n * Within the card, we handle only tabbing from the close anchor or the last\n * focusable element and only when tab focus would have otherwise left the\n * card. In those cases, we cycle focus to the last focusable element or back\n * to the anchor. If the card doesn't have any focusable elements, we move\n * focus to the close anchor.\n *\n * @note\n * Because the card contents may change, we check for focusable elements\n * every time the handler is called.\n *\n * @private\n * @param {KeyboardEvent} event\n */\n private _trapFocusExit(event: KeyboardEvent): void {\n if (!(event instanceof KeyboardEvent)) return;\n if (event.key !== \"Tab\") return;\n\n const isFocusedContainer = event.target === this.card;\n const isFocusedAnchor = event.target === this.overlay.anchor;\n const isFocusedWithin = this.card.contains(event.target as Node);\n\n const stopEvent = () => {\n event.preventDefault();\n event.stopImmediatePropagation();\n };\n\n if (!(isFocusedWithin || isFocusedContainer || isFocusedAnchor)) {\n // If focus is outside the card, return to the card\n stopEvent();\n this.card.focus();\n return;\n }\n\n // Check focusables every time because the card contents may have changed\n // but exclude the full screen enter button from this list of elements\n const focusableElements = getAllFocusableChildren(this.card).filter(\n (el) => !el.classList.contains(Card.attr.CLASS_FULL_SCREEN_ENTER)\n );\n const hasFocusableElements = focusableElements.length > 0;\n\n // We need to handle five cases:\n // 1. The card has no focusable elements --> focus the anchor\n // 2. Focus is on the card container (do nothing, natural tab order)\n // 3. Focus is on the anchor and the user pressed Tab + Shift (backwards)\n // -> Move to the last focusable element (end of card)\n // 4. Focus is on the last focusable element and the user pressed Tab\n // (forwards) -> Move to the anchor (top of card)\n // 5. otherwise we don't interfere\n\n if (!hasFocusableElements) {\n // case 1\n stopEvent();\n this.overlay.anchor.focus();\n return;\n }\n\n // case 2\n if (isFocusedContainer) return;\n\n const lastFocusable = focusableElements[focusableElements.length - 1];\n const isFocusedLast = event.target === lastFocusable;\n\n if (isFocusedAnchor && event.shiftKey) {\n stopEvent();\n lastFocusable.focus();\n return;\n }\n\n if (isFocusedLast && !event.shiftKey) {\n stopEvent();\n this.overlay.anchor.focus();\n return;\n }\n }\n\n /**\n * Creates the full screen overlay.\n * @private\n * @returns {CardFullScreenOverlay}\n */\n private _createOverlay(): CardFullScreenOverlay {\n const container = document.createElement(\"div\");\n container.id = Card.attr.ID_FULL_SCREEN_OVERLAY;\n container.onclick = this.exitFullScreen.bind(this);\n\n const anchor = this._createOverlayCloseAnchor();\n container.appendChild(anchor);\n\n return { container, anchor };\n }\n\n /**\n * Creates the anchor element used to exit the full screen mode.\n * @private\n * @returns {HTMLAnchorElement}\n */\n private _createOverlayCloseAnchor(): HTMLAnchorElement {\n const anchor = document.createElement(\"a\");\n anchor.classList.add(Card.attr.CLASS_FULL_SCREEN_EXIT);\n anchor.tabIndex = 0;\n anchor.onclick = () => this.exitFullScreen();\n anchor.onkeydown = (ev) => {\n if (ev.key === \"Enter\" || ev.key === \" \") {\n this.exitFullScreen();\n }\n };\n anchor.innerHTML = this._overlayCloseHtml();\n\n return anchor;\n }\n\n /**\n * Returns the HTML for the close icon.\n * @private\n * @returns {string}\n */\n private _overlayCloseHtml(): string {\n return (\n \"Close \" +\n \"\"\n );\n }\n\n /**\n * The registry of card instances and their associated DOM elements.\n * @private\n * @static\n * @type {WeakMap}\n */\n private static instanceMap: WeakMap = new WeakMap();\n\n /**\n * Returns the card instance associated with the given element, if any.\n * @public\n * @static\n * @param {HTMLElement} el\n * @returns {(Card | undefined)}\n */\n public static getInstance(el: HTMLElement): Card | undefined {\n return Card.instanceMap.get(el);\n }\n\n /**\n * If cards are initialized before the DOM is ready, we re-schedule the\n * initialization to occur on DOMContentLoaded.\n * @private\n * @static\n * @type {boolean}\n */\n private static onReadyScheduled = false;\n\n /**\n * Initializes all cards that require initialization on the page, or schedules\n * initialization if the DOM is not yet ready.\n * @public\n * @static\n * @param {boolean} [flushResizeObserver=true]\n */\n public static initializeAllCards(flushResizeObserver = true): void {\n if (document.readyState === \"loading\") {\n if (!Card.onReadyScheduled) {\n Card.onReadyScheduled = true;\n document.addEventListener(\"DOMContentLoaded\", () => {\n Card.initializeAllCards(false);\n });\n }\n return;\n }\n\n if (flushResizeObserver) {\n // Trigger a recheck of observed cards to unobserve non-existent cards\n Card.shinyResizeObserver.flush();\n }\n\n const initSelector = `.${Card.attr.CLASS_CARD}[${Card.attr.ATTR_INIT}]`;\n if (!document.querySelector(initSelector)) {\n // no cards to initialize\n return;\n }\n\n const cards = document.querySelectorAll(initSelector);\n cards.forEach((card) => new Card(card as HTMLElement));\n }\n}\n\n// attach Sidebar class to window for global usage\n(window as any).bslib = (window as any).bslib || {};\n(window as any).bslib.Card = Card;\n\nexport { Card };\n", "import { InputBinding, registerBinding } from \"./_utils\";\nimport { ShinyResizeObserver } from \"./_shinyResizeObserver\";\n\n/**\n * Methods for programmatically toggling the state of the sidebar. These methods\n * describe the desired state of the sidebar: `\"close\"` and `\"open\"` transition\n * the sidebar to the desired state, unless the sidebar is already in that\n * state. `\"toggle\"` transitions the sidebar to the state opposite of its\n * current state.\n * @typedef {SidebarToggleMethod}\n */\ntype SidebarToggleMethod = \"close\" | \"open\" | \"toggle\";\n\n/**\n * Data received by the input binding's `receiveMessage` method.\n * @typedef {SidebarMessageData}\n */\ntype SidebarMessageData = {\n method: SidebarToggleMethod;\n};\n\n/**\n * The DOM elements that make up the sidebar. `main`, `sidebar`, and `toggle`\n * are all direct children of `container` (in that order).\n * @interface SidebarComponents\n * @typedef {SidebarComponents}\n */\ninterface SidebarComponents {\n /**\n * The `layout_sidebar()` parent container, with class\n * `Sidebar.classes.LAYOUT`.\n * @type {HTMLElement}\n */\n container: HTMLElement;\n /**\n * The main content area of the sidebar layout.\n * @type {HTMLElement}\n */\n main: HTMLElement;\n /**\n * The sidebar container of the sidebar layout.\n * @type {HTMLElement}\n */\n sidebar: HTMLElement;\n /**\n * The toggle button that is used to toggle the sidebar state.\n * @type {HTMLElement}\n */\n toggle: HTMLElement;\n}\n\n/**\n * The bslib sidebar component class. This class is only used for collapsible\n * sidebars.\n *\n * @class Sidebar\n * @typedef {Sidebar}\n */\nclass Sidebar {\n /**\n * The DOM elements that make up the sidebar, see `SidebarComponents`.\n * @private\n * @type {SidebarComponents}\n */\n private layout: SidebarComponents;\n\n /**\n * A Shiny-specific resize observer that ensures Shiny outputs in the main\n * content areas of the sidebar resize appropriately.\n * @private\n * @type {ShinyResizeObserver}\n * @static\n */\n private static shinyResizeObserver = new ShinyResizeObserver();\n\n /**\n * Creates an instance of a collapsible bslib Sidebar.\n * @constructor\n * @param {HTMLElement} container\n */\n constructor(container: HTMLElement) {\n Sidebar.instanceMap.set(container, this);\n this.layout = {\n container,\n main: container.querySelector(\":scope > .main\") as HTMLElement,\n sidebar: container.querySelector(\":scope > .sidebar\") as HTMLElement,\n toggle: container.querySelector(\n \":scope > .collapse-toggle\"\n ) as HTMLElement,\n } as SidebarComponents;\n\n const sideAccordion = this.layout.sidebar.querySelector(\n \":scope > .sidebar-content > .accordion\"\n );\n if (sideAccordion) {\n // Add `.has-accordion` class to `.sidebar-content` container\n sideAccordion?.parentElement?.classList.add(\"has-accordion\");\n sideAccordion.classList.add(\"accordion-flush\");\n }\n\n if (this.layout.toggle) {\n this._initEventListeners();\n this._initSidebarCounters();\n this._initDesktop();\n }\n\n // Start watching the main content area for size changes to ensure Shiny\n // outputs resize appropriately during sidebar transitions.\n Sidebar.shinyResizeObserver.observe(this.layout.main);\n\n container.removeAttribute(\"data-bslib-sidebar-init\");\n const initScript = container.querySelector(\n \":scope > script[data-bslib-sidebar-init]\"\n );\n if (initScript) {\n container.removeChild(initScript);\n }\n }\n\n /**\n * Read the current state of the sidebar. Note that, when calling this method,\n * the sidebar may be transitioning into the state returned by this method.\n *\n * @description\n * The sidebar state works as follows, starting from the open state. When the\n * sidebar is closed:\n * 1. We add both the `COLLAPSE` and `TRANSITIONING` classes to the sidebar.\n * 2. The sidebar collapse begins to animate. On desktop devices, and where it\n * is supported, we transition the `grid-template-columns` property of the\n * sidebar layout. On mobile, the sidebar is hidden immediately. In both\n * cases, the collapse icon rotates and we use this rotation to determine\n * when the transition is complete.\n * 3. If another sidebar state toggle is requested while closing the sidebar,\n * we remove the `COLLAPSE` class and the animation immediately starts to\n * reverse.\n * 4. When the `transition` is complete, we remove the `TRANSITIONING` class.\n * @readonly\n * @type {boolean}\n */\n get isClosed(): boolean {\n return this.layout.container.classList.contains(Sidebar.classes.COLLAPSE);\n }\n\n /**\n * Static classes related to the sidebar layout or state.\n * @public\n * @static\n * @readonly\n * @type {{ LAYOUT: string; COLLAPSE: string; TRANSITIONING: string; }}\n */\n public static readonly classes = {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n LAYOUT: \"bslib-sidebar-layout\",\n // eslint-disable-next-line @typescript-eslint/naming-convention\n COLLAPSE: \"sidebar-collapsed\",\n // eslint-disable-next-line @typescript-eslint/naming-convention\n TRANSITIONING: \"transitioning\",\n };\n\n /**\n * If sidebars are initialized before the DOM is ready, we re-schedule the\n * initialization to occur on DOMContentLoaded.\n * @private\n * @static\n * @type {boolean}\n */\n private static onReadyScheduled = false;\n /**\n * A map of initialized sidebars to their respective Sidebar instances.\n * @private\n * @static\n * @type {WeakMap}\n */\n private static instanceMap: WeakMap = new WeakMap();\n\n /**\n * Given a sidebar container, return the Sidebar instance associated with it.\n * @public\n * @static\n * @param {HTMLElement} el\n * @returns {(Sidebar | undefined)}\n */\n public static getInstance(el: HTMLElement): Sidebar | undefined {\n return Sidebar.instanceMap.get(el);\n }\n\n /**\n * Initialize all collapsible sidebars on the page.\n * @public\n * @static\n * @param {boolean} [flushResizeObserver=true] When `true`, we remove\n * non-existent elements from the ResizeObserver. This is required\n * periodically to prevent memory leaks. To avoid over-checking, we only flush\n * the ResizeObserver when initializing sidebars after page load.\n */\n public static initCollapsibleAll(flushResizeObserver = true): void {\n if (document.readyState === \"loading\") {\n if (!Sidebar.onReadyScheduled) {\n Sidebar.onReadyScheduled = true;\n document.addEventListener(\"DOMContentLoaded\", () => {\n Sidebar.initCollapsibleAll(false);\n });\n }\n return;\n }\n\n const initSelector = `.${Sidebar.classes.LAYOUT}[data-bslib-sidebar-init]`;\n if (!document.querySelector(initSelector)) {\n // no sidebars to initialize\n return;\n }\n\n if (flushResizeObserver) Sidebar.shinyResizeObserver.flush();\n\n const containers = document.querySelectorAll(initSelector);\n containers.forEach((container) => new Sidebar(container as HTMLElement));\n }\n\n /**\n * Initialize event listeners for the sidebar toggle button.\n * @private\n */\n private _initEventListeners(): void {\n const { toggle } = this.layout;\n\n toggle.addEventListener(\"click\", (ev) => {\n ev.preventDefault();\n this.toggle(\"toggle\");\n });\n\n // Remove the transitioning class when the transition ends. We watch the\n // collapse toggle icon because it's guaranteed to transition, whereas the\n // sidebar doesn't animate on mobile (or in browsers where animating\n // grid-template-columns is not supported).\n toggle\n .querySelector(\".collapse-icon\")\n ?.addEventListener(\"transitionend\", () => this._finalizeState());\n }\n\n /**\n * Initialize nested sidebar counters.\n *\n * @description\n * This function walks up the DOM tree, adding CSS variables to each direct\n * parent sidebar layout that count the layout's position in the stack of\n * nested layouts. We use these counters to keep the collapse toggles from\n * overlapping. Note that always-open sidebars that don't have collapse\n * toggles break the chain of nesting.\n * @private\n */\n private _initSidebarCounters(): void {\n const { container } = this.layout;\n\n const selectorChildLayouts =\n `.${Sidebar.classes.LAYOUT}` +\n \"> .main > \" +\n `.${Sidebar.classes.LAYOUT}:not([data-bslib-sidebar-open=\"always\"])`;\n\n const isInnermostLayout =\n container.querySelector(selectorChildLayouts) === null;\n\n if (!isInnermostLayout) {\n // There are sidebar layouts nested within this layout; defer to children\n return;\n }\n\n function nextSidebarParent(el: HTMLElement | null): HTMLElement | null {\n el = el ? el.parentElement : null;\n if (el && el.classList.contains(\"main\")) {\n // .bslib-sidebar-layout > .main > .bslib-sidebar-layout\n el = el.parentElement;\n }\n if (el && el.classList.contains(Sidebar.classes.LAYOUT)) {\n return el;\n }\n return null;\n }\n\n const layouts = [container];\n let parent = nextSidebarParent(container);\n\n while (parent) {\n // Add parent to front of layouts array, so we sort outer -> inner\n layouts.unshift(parent);\n parent = nextSidebarParent(parent);\n }\n\n const count = { left: 0, right: 0 };\n layouts.forEach(function (x: HTMLElement): void {\n const isRight = x.classList.contains(\"sidebar-right\");\n const thisCount = isRight ? count.right++ : count.left++;\n x.style.setProperty(\"--_js-toggle-count-this-side\", thisCount.toString());\n x.style.setProperty(\n \"--_js-toggle-count-max-side\",\n Math.max(count.right, count.left).toString()\n );\n });\n }\n\n /**\n * Initialize the sidebar's initial state when `open = \"desktop\"`.\n * @private\n */\n private _initDesktop(): void {\n const { container } = this.layout;\n // If sidebar is marked open='desktop'...\n if (container.dataset.bslibSidebarOpen?.trim() !== \"desktop\") {\n return;\n }\n\n // then close sidebar on mobile\n const initCollapsed = window\n .getComputedStyle(container)\n .getPropertyValue(\"--bslib-sidebar-js-init-collapsed\");\n\n if (initCollapsed.trim() === \"true\") {\n this.toggle(\"close\");\n }\n }\n\n /**\n * Toggle the sidebar's open/closed state.\n * @public\n * @param {SidebarToggleMethod | undefined} method Whether to `\"open\"`,\n * `\"close\"` or `\"toggle\"` the sidebar. If `.toggle()` is called without an\n * argument, it will toggle the sidebar's state.\n */\n public toggle(method: SidebarToggleMethod | undefined): void {\n if (typeof method === \"undefined\") {\n method = \"toggle\";\n }\n\n const { container, sidebar } = this.layout;\n const isClosed = this.isClosed;\n\n if ([\"open\", \"close\", \"toggle\"].indexOf(method) === -1) {\n throw new Error(`Unknown method ${method}`);\n }\n\n if (method === \"toggle\") {\n method = isClosed ? \"open\" : \"close\";\n }\n\n if ((isClosed && method === \"close\") || (!isClosed && method === \"open\")) {\n // nothing to do, sidebar is already in the desired state\n return;\n }\n\n if (method === \"open\") {\n // unhide sidebar immediately when opening,\n // otherwise the sidebar is hidden on transitionend\n sidebar.hidden = false;\n }\n\n // Add a transitioning class just before adding COLLAPSE_CLASS since we want\n // some of the transitioning styles to apply before the collapse state\n container.classList.add(Sidebar.classes.TRANSITIONING);\n container.classList.toggle(Sidebar.classes.COLLAPSE);\n }\n\n /**\n * When the sidebar open/close transition ends, finalize the sidebar's state.\n * @private\n */\n private _finalizeState(): void {\n const { container, sidebar, toggle } = this.layout;\n container.classList.remove(Sidebar.classes.TRANSITIONING);\n sidebar.hidden = this.isClosed;\n toggle.setAttribute(\"aria-expanded\", this.isClosed ? \"false\" : \"true\");\n\n // Send browser-native event with updated sidebar state\n const event = new CustomEvent(\"bslib.sidebar\", {\n bubbles: true,\n detail: { open: !this.isClosed },\n });\n sidebar.dispatchEvent(event);\n\n // Trigger Shiny input and output binding events\n $(sidebar).trigger(\"toggleCollapse.sidebarInputBinding\");\n $(sidebar).trigger(this.isClosed ? \"hidden\" : \"shown\");\n }\n}\n\n/**\n * A Shiny input binding for a sidebar.\n * @class SidebarInputBinding\n * @typedef {SidebarInputBinding}\n * @extends {InputBinding}\n */\nclass SidebarInputBinding extends InputBinding {\n find(scope: HTMLElement) {\n return $(scope).find(`.${Sidebar.classes.LAYOUT} > .bslib-sidebar-input`);\n }\n\n getValue(el: HTMLElement): boolean {\n const sb = Sidebar.getInstance(el.parentElement as HTMLElement);\n if (!sb) return false;\n return !sb.isClosed;\n }\n\n setValue(el: HTMLElement, value: boolean): void {\n const method = value ? \"open\" : \"close\";\n this.receiveMessage(el, { method });\n }\n\n subscribe(el: HTMLElement, callback: (x: boolean) => void) {\n $(el).on(\n \"toggleCollapse.sidebarInputBinding\",\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n function (event) {\n callback(true);\n }\n );\n }\n\n unsubscribe(el: HTMLElement) {\n $(el).off(\".sidebarInputBinding\");\n }\n\n receiveMessage(el: HTMLElement, data: SidebarMessageData) {\n const sb = Sidebar.getInstance(el.parentElement as HTMLElement);\n if (sb) sb.toggle(data.method);\n }\n}\n\nregisterBinding(SidebarInputBinding, \"sidebar\");\n\n// attach Sidebar class to window for global usage\n(window as any).bslib = (window as any).bslib || {};\n(window as any).bslib.Sidebar = Sidebar;\n", "import type { Handler as ShinyCustomMessageHandler } from \"rstudio-shiny/srcts/types/src/shiny/shinyapp\";\n\nexport function shinyAddCustomMessageHandlers(handlers: {\n [key: string]: ShinyCustomMessageHandler;\n}): void {\n if (!window.Shiny) {\n return;\n }\n\n for (const [name, handler] of Object.entries(handlers)) {\n Shiny.addCustomMessageHandler(name, handler);\n }\n}\n", "// ----------------------------------------------------------------------------\n// First, bring in non-webcomponent (legacy) components (they attach to the window)\n// ----------------------------------------------------------------------------\nimport \"./accordion\";\nimport \"./card\";\nimport \"./sidebar\";\n\n// ----------------------------------------------------------------------------\n// Register custom message handlers for Shiny\n// ----------------------------------------------------------------------------\nimport { InputBinding } from \"./_utils\";\nimport { shinyAddCustomMessageHandlers } from \"./_shinyAddCustomMessageHandlers\";\n\nconst bslibMessageHandlers = {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n \"bslib.toggle-input-binary\": (msg: any) => {\n // This handler was written for `toggle_switch()`, but could be used for any\n // binary Shiny input, e.g. checkbox.\n const el = document.getElementById(msg.id) as HTMLElement;\n if (!el) {\n console.warn(\"[bslib.toggle-input-binary] No element found\", msg);\n }\n\n const binding = $(el).data(\"shiny-input-binding\");\n if (!(binding instanceof InputBinding)) {\n console.warn(\"[bslib.toggle-input-binary] No input binding found\", msg);\n return;\n }\n\n let value = msg.value;\n if (typeof value === \"undefined\") {\n value = !binding.getValue(el);\n }\n binding.receiveMessage(el, { value });\n },\n};\n\nif (window.Shiny) {\n shinyAddCustomMessageHandlers(bslibMessageHandlers);\n}\n\n// ----------------------------------------------------------------------\n// Append the (global) SVG linearGradient to the body.\n// value_box() uses this (i.e., bslib---icon-gradient element) to apply a\n// gradient to the icon when bs_theme(preset=\"shiny\").\n// ----------------------------------------------------------------------\n\nfunction insertSvgGradient() {\n const temp = document.createElement(\"div\");\n temp.innerHTML = `\n `;\n document.body.appendChild(temp.children[0] as Node);\n}\n\nif (document.readyState === \"complete\") {\n insertSvgGradient();\n} else {\n document.addEventListener(\"DOMContentLoaded\", insertSvgGradient);\n}\n"],
- "mappings": ";mBAQA,IAAMA,EACJ,OAAO,MAAQ,MAAM,aAAe,KAAM,CAAC,EAG7C,SAASC,EACPC,EACAC,EACM,CACF,OAAO,OACT,MAAM,cAAc,SAAS,IAAID,EAAqB,SAAWC,CAAI,CAEzE,CAOA,SAASC,EAIPC,EACAC,EACiE,CACjE,OACE,OAAO,UAAU,eAAe,KAAKD,EAAKC,CAAI,GAAKD,EAAIC,CAAI,IAAM,MAErE,CAgBA,SAASC,EAAwBC,EAAgC,CAE/D,IAAMC,EAAO,CACX,UACA,aACA,SACA,kBACA,QACA,SACA,SACA,WACA,uBACA,2BACA,2BACA,YACF,EACMC,EAAY,CAAC,wBAAyB,kBAAkB,EACxDC,EAAYF,EAAK,IAAKG,GAAMA,EAAIF,EAAU,KAAK,EAAE,CAAC,EAClDG,EAAYL,EAAG,iBAAiBG,EAAU,KAAK,IAAI,CAAC,EAC1D,OAAO,MAAM,KAAKE,CAAS,CAC7B,CCZA,IAAMC,EAAN,cAAoCC,CAAa,CAC/C,KAAKC,EAAoB,CACvB,OAAO,EAAEA,CAAK,EAAE,KAAK,kCAAkC,CACzD,CAEA,SAASC,EAAkC,CAEzC,IAAMC,EADQ,KAAK,aAAaD,CAAE,EACX,OAAQE,GAAMA,EAAE,OAAO,CAAC,EAAE,IAAKA,GAAMA,EAAE,KAAK,EACnE,OAAOD,EAAS,SAAW,EAAI,KAAOA,CACxC,CAEA,UAAUD,EAAiBG,EAAgC,CACzD,EAAEH,CAAE,EAAE,GACJ,mFAEA,SAAUI,EAAO,CACfD,EAAS,EAAI,CACf,CACF,CACF,CAEA,YAAYH,EAAiB,CAC3B,EAAEA,CAAE,EAAE,IAAI,wBAAwB,CACpC,CAEA,eAAeA,EAAiBK,EAAmB,CACjD,IAAMC,EAASD,EAAK,OACpB,GAAIC,IAAW,MACb,KAAK,UAAUN,EAAIK,CAAI,UACdC,IAAW,OACpB,KAAK,WAAWN,EAAIK,CAAI,UACfC,IAAW,QACpB,KAAK,YAAYN,EAAIK,CAAI,UAChBC,IAAW,SACpB,KAAK,YAAYN,EAAIK,CAAI,UAChBC,IAAW,SACpB,KAAK,YAAYN,EAAIK,CAAI,UAChBC,IAAW,SACpB,KAAK,YAAYN,EAAIK,CAAI,MAEzB,OAAM,IAAI,MAAM,+BAA+BC,GAAQ,CAE3D,CAEU,UAAUN,EAAiBK,EAAkB,CACrD,IAAME,EAAQ,KAAK,aAAaP,CAAE,EAC5BQ,EAAO,KAAK,WAAWR,EAAIO,EAAOF,EAAK,MAAM,EACnDE,EAAM,QAASL,GAAM,CACnBM,EAAK,QAAQN,EAAE,KAAK,EAAI,GAAKA,EAAE,KAAK,EAAIA,EAAE,KAAK,CACjD,CAAC,CACH,CAEU,WAAWF,EAAiBK,EAAmB,CACvD,IAAME,EAAQ,KAAK,aAAaP,CAAE,EAC5BQ,EAAO,KAAK,WAAWR,EAAIO,EAAOF,EAAK,MAAM,EACnDE,EAAM,QAASL,GAAM,CACfM,EAAK,QAAQN,EAAE,KAAK,EAAI,IAAIA,EAAE,KAAK,CACzC,CAAC,CACH,CAEU,YAAYF,EAAiBK,EAAoB,CACzD,IAAME,EAAQ,KAAK,aAAaP,CAAE,EAC5BQ,EAAO,KAAK,WAAWR,EAAIO,EAAOF,EAAK,MAAM,EACnDE,EAAM,QAASL,GAAM,CACfM,EAAK,QAAQN,EAAE,KAAK,EAAI,IAAIA,EAAE,KAAK,CACzC,CAAC,CACH,CAEU,YAAYF,EAAiBK,EAAqB,CAC1D,IAAII,EAAa,KAAK,UAAUT,EAAIK,EAAK,MAAM,EAI1CI,IACHA,EACEJ,EAAK,WAAa,SAAWL,EAAG,kBAAoBA,EAAG,kBAI3D,IAAMU,EAAQL,EAAK,MAcnB,GAXII,EACF,MAAM,cACJA,EACAC,EACAL,EAAK,WAAa,SAAW,cAAgB,UAC/C,EAEA,MAAM,cAAcL,EAAIU,CAAK,EAI3B,KAAK,eAAeV,CAAE,EAAG,CAC3B,IAAMW,EAAM,EAAED,EAAM,IAAI,EAAE,KAAK,YAAY,EAC3C,EAAEV,CAAE,EACD,KAAK,gBAAgBW,yBAA2B,EAChD,KAAK,iBAAkB,IAAMX,EAAG,EAAE,CACvC,CACF,CAEU,YAAYA,EAAiBK,EAAqB,CAC1D,IAAMO,EAAc,KAAK,aAAaZ,CAAE,EAAE,OACvCE,GAAMG,EAAK,OAAO,QAAQH,EAAE,KAAK,EAAI,EACxC,EAEMW,EAAY,yBAAO,UAEzBD,EAAY,QAASV,GAAM,CACrBW,GAAWA,EAAUX,EAAE,IAAI,EAC/BA,EAAE,KAAK,OAAO,CAChB,CAAC,CACH,CAEU,YAAYF,EAAiBK,EAAqB,CAC1D,IAAMS,EAAS,KAAK,UAAUd,EAAIK,EAAK,MAAM,EAE7C,GAAI,CAACS,EACH,MAAM,IAAI,MACR,uDAAuDT,EAAK,QAC9D,EAOF,GAJIU,EAAmBV,EAAM,OAAO,IAClCS,EAAO,QAAQ,MAAQT,EAAK,OAG1BU,EAAmBV,EAAM,MAAM,EAAG,CACpC,IAAMW,EAAOF,EAAO,cAAc,iBAAiB,EACnD,MAAM,cAAcE,EAAMX,EAAK,IAAI,CACrC,CAEA,IAAMY,EAASH,EAAO,cAAc,mBAAmB,EAEvD,GAAIC,EAAmBV,EAAM,OAAO,EAAG,CACrC,IAAMa,EAAQD,EAAO,cAAc,kBAAkB,EACrD,MAAM,cAAcC,EAAOb,EAAK,KAAK,CACvC,CAEA,GAAIU,EAAmBV,EAAM,MAAM,EAAG,CACpC,IAAMc,EAAOF,EAAO,cAClB,qCACF,EACA,MAAM,cAAcE,EAAMd,EAAK,IAAI,CACrC,CACF,CAEU,aAAaL,EAAkC,CAIvD,OAHc,MAAM,KAClBA,EAAG,iBAAiB,0BAA0B,CAChD,EACa,IAAKE,GAAM,KAAK,mBAAmBA,CAAC,CAAC,CACpD,CAEU,mBAAmBA,EAA+B,CAC1D,IAAMkB,EAAWlB,EAAE,cAAc,qBAAqB,EAChDmB,EAAS,IAAM,EAAED,CAAQ,EAAE,SAAS,MAAM,EAChD,MAAO,CACL,KAAMlB,EACN,MAAOA,EAAE,QAAQ,MACjB,OAAQmB,EACR,KAAM,IAAM,CACLA,EAAO,GAAG,EAAED,CAAQ,EAAE,SAAS,MAAM,CAC5C,EACA,KAAM,IAAM,CACNC,EAAO,GAAG,EAAED,CAAQ,EAAE,SAAS,MAAM,CAC3C,CACF,CACF,CAEU,WACRpB,EACAO,EACAe,EACU,CACV,IAAId,EAAOc,IAAW,GAAOA,EAASf,EAAM,IAAKL,GAAMA,EAAE,KAAK,EAE9D,OADkB,KAAK,eAAeF,CAAE,IAEtCQ,EAAOA,EAAK,MAAMA,EAAK,OAAS,EAAGA,EAAK,MAAM,GAEzCA,CACT,CAEU,UAAUR,EAAiBuB,EAAmC,CACtE,OAAOvB,EAAG,cAAc,gBAAgBuB,KAAS,CACnD,CAEU,eAAevB,EAA0B,CACjD,OAAOA,EAAG,UAAU,SAAS,WAAW,CAC1C,CACF,EAEAwB,EAAgB3B,EAAuB,WAAW,ECpPlD,IAAM4B,EAAN,KAA0B,CAoDxB,aAAc,CACZ,KAAK,sBAAwB,CAAC,EAC9B,KAAK,eAAiB,IAAI,eAAgBC,GAAY,CACpD,IAAMC,EAAc,IAAI,MAAM,QAAQ,EAItC,GAHA,OAAO,cAAcA,CAAW,EAG5B,CAAC,OAAO,MAAO,OAEnB,IAAMC,EAAU,CAAC,EAEjB,QAAWC,KAASH,EACZG,EAAM,kBAAkB,aACzBA,EAAM,OAAO,cAAc,qBAAqB,GAErDA,EAAM,OACH,iBAA8B,qBAAqB,EACnD,QAASC,GAAO,CACf,GAAIF,EAAQ,SAASE,CAAE,EAAG,OAE1B,GAAM,CAAE,QAAAC,EAAS,SAAAC,CAAS,EAAI,EAAEF,CAAE,EAAE,KAAK,oBAAoB,EAC7D,GAAI,CAACC,GAAW,CAACA,EAAQ,OAAQ,OAGjC,IAAME,EAASH,EAAW,oBAW1B,GAVIG,GAASA,IAAU,OAElBA,IAAQH,EAAW,oBAAsB,MAG9CE,EAASF,CAAE,EAEXF,EAAQ,KAAKE,CAAE,EAGX,CAACA,EAAG,UAAU,SAAS,mBAAmB,GAAG,OACjD,IAAMI,EAAMJ,EAAG,cACb,yBACF,EACII,GAAKA,EAAI,aAAa,QAAS,MAAM,CAC3C,CAAC,CAEP,CAAC,CACH,CAMA,QAAQJ,EAAuB,CAC7B,KAAK,eAAe,QAAQA,CAAE,EAC9B,KAAK,sBAAsB,KAAKA,CAAE,CACpC,CAMA,UAAUA,EAAuB,CAC/B,IAAMK,EAAQ,KAAK,sBAAsB,QAAQL,CAAE,EAC/CK,EAAQ,IAEZ,KAAK,eAAe,UAAUL,CAAE,EAChC,KAAK,sBAAsB,OAAOK,EAAO,CAAC,EAC5C,CAUA,OAAc,CACZ,KAAK,sBAAsB,QAASL,GAAO,CACpC,SAAS,KAAK,SAASA,CAAE,GAAG,KAAK,UAAUA,CAAE,CACpD,CAAC,CACH,CACF,EC/GA,IAAMM,EAAN,KAAW,CAsDT,YAAYC,EAAmB,CAlFjC,IAAAC,EAoFID,EAAK,gBAAgBD,EAAK,KAAK,SAAS,GACxCE,EAAAD,EACG,cAAiC,UAAUD,EAAK,KAAK,YAAY,IADpE,MAAAE,EAEI,SAEJ,KAAK,KAAOD,EACZD,EAAK,YAAY,IAAIC,EAAM,IAAI,EAI/BD,EAAK,oBAAoB,QAAQ,KAAK,IAAI,EAE1C,KAAK,mBAAmB,EACxB,KAAK,QAAU,KAAK,eAAe,EAGnC,KAAK,wBAA0B,KAAK,wBAAwB,KAAK,IAAI,EACrE,KAAK,eAAiB,KAAK,eAAe,KAAK,IAAI,CACrD,CAWA,gBAAgBG,EAAqB,CAjHvC,IAAAD,EAkHQC,GAAOA,EAAM,eAAe,EAEhC,SAAS,iBAAiB,UAAW,KAAK,wBAAyB,EAAK,EAIxE,SAAS,iBAAiB,UAAW,KAAK,eAAgB,EAAI,EAE9D,KAAK,KAAK,aAAaH,EAAK,KAAK,iBAAkB,MAAM,EACzD,SAAS,KAAK,UAAU,IAAIA,EAAK,KAAK,qBAAqB,EAC3D,KAAK,KAAK,sBAAsB,cAAe,KAAK,QAAQ,SAAS,GAInE,CAAC,KAAK,KAAK,SAAS,SAAS,aAAa,IAC1CE,EAAA,SAAS,gBAAT,MAAAA,EAAwB,UAAU,SAChCF,EAAK,KAAK,4BAGZ,KAAK,KAAK,aAAa,WAAY,IAAI,EACvC,KAAK,KAAK,MAAM,EAEpB,CAOA,gBAAuB,CACrB,SAAS,oBACP,UACA,KAAK,wBACL,EACF,EACA,SAAS,oBAAoB,UAAW,KAAK,eAAgB,EAAI,EAGjE,KAAK,QAAQ,UAAU,OAAO,EAC9B,KAAK,KAAK,aAAaA,EAAK,KAAK,iBAAkB,OAAO,EAC1D,KAAK,KAAK,gBAAgB,UAAU,EACpC,SAAS,KAAK,UAAU,OAAOA,EAAK,KAAK,qBAAqB,CAChE,CAMQ,oBAA2B,CACjC,IAAMI,EAAgB,KAAK,KAAK,cAC9B,iBAAiBJ,EAAK,KAAK,yBAC7B,EACKI,GACLA,EAAc,iBAAiB,QAAUC,GAAO,KAAK,gBAAgBA,CAAE,CAAC,CAC1E,CAOQ,wBAAwBF,EAA4B,CAC1D,GAAI,EAAEA,EAAM,kBAAkB,aAAc,OAE5C,IAAMG,EAAqB,CAAC,eAAgB,6BAA6B,EACrEH,EAAM,OAAO,QAAQG,EAAmB,KAAK,IAAI,CAAC,GAElDH,EAAM,MAAQ,UAChB,KAAK,eAAe,CAExB,CAwBQ,eAAeA,EAA4B,CAEjD,GADI,EAAEA,aAAiB,gBACnBA,EAAM,MAAQ,MAAO,OAEzB,IAAMI,EAAqBJ,EAAM,SAAW,KAAK,KAC3CK,EAAkBL,EAAM,SAAW,KAAK,QAAQ,OAChDM,EAAkB,KAAK,KAAK,SAASN,EAAM,MAAc,EAEzDO,EAAY,IAAM,CACtBP,EAAM,eAAe,EACrBA,EAAM,yBAAyB,CACjC,EAEA,GAAI,EAAEM,GAAmBF,GAAsBC,GAAkB,CAE/DE,EAAU,EACV,KAAK,KAAK,MAAM,EAChB,MACF,CAIA,IAAMC,EAAoBC,EAAwB,KAAK,IAAI,EAAE,OAC1DC,GAAO,CAACA,EAAG,UAAU,SAASb,EAAK,KAAK,uBAAuB,CAClE,EAYA,GAAI,EAXyBW,EAAkB,OAAS,GAW7B,CAEzBD,EAAU,EACV,KAAK,QAAQ,OAAO,MAAM,EAC1B,MACF,CAGA,GAAIH,EAAoB,OAExB,IAAMO,EAAgBH,EAAkBA,EAAkB,OAAS,CAAC,EAC9DI,EAAgBZ,EAAM,SAAWW,EAEvC,GAAIN,GAAmBL,EAAM,SAAU,CACrCO,EAAU,EACVI,EAAc,MAAM,EACpB,MACF,CAEA,GAAIC,GAAiB,CAACZ,EAAM,SAAU,CACpCO,EAAU,EACV,KAAK,QAAQ,OAAO,MAAM,EAC1B,MACF,CACF,CAOQ,gBAAwC,CAC9C,IAAMM,EAAY,SAAS,cAAc,KAAK,EAC9CA,EAAU,GAAKhB,EAAK,KAAK,uBACzBgB,EAAU,QAAU,KAAK,eAAe,KAAK,IAAI,EAEjD,IAAMC,EAAS,KAAK,0BAA0B,EAC9C,OAAAD,EAAU,YAAYC,CAAM,EAErB,CAAE,UAAAD,EAAW,OAAAC,CAAO,CAC7B,CAOQ,2BAA+C,CACrD,IAAMA,EAAS,SAAS,cAAc,GAAG,EACzC,OAAAA,EAAO,UAAU,IAAIjB,EAAK,KAAK,sBAAsB,EACrDiB,EAAO,SAAW,EAClBA,EAAO,QAAU,IAAM,KAAK,eAAe,EAC3CA,EAAO,UAAaZ,GAAO,EACrBA,EAAG,MAAQ,SAAWA,EAAG,MAAQ,MACnC,KAAK,eAAe,CAExB,EACAY,EAAO,UAAY,KAAK,kBAAkB,EAEnCA,CACT,CAOQ,mBAA4B,CAClC,MACE,iSAOJ,CAiBA,OAAc,YAAYJ,EAAmC,CAC3D,OAAOb,EAAK,YAAY,IAAIa,CAAE,CAChC,CAkBA,OAAc,mBAAmBK,EAAsB,GAAY,CACjE,GAAI,SAAS,aAAe,UAAW,CAChClB,EAAK,mBACRA,EAAK,iBAAmB,GACxB,SAAS,iBAAiB,mBAAoB,IAAM,CAClDA,EAAK,mBAAmB,EAAK,CAC/B,CAAC,GAEH,MACF,CAEIkB,GAEFlB,EAAK,oBAAoB,MAAM,EAGjC,IAAMmB,EAAe,IAAInB,EAAK,KAAK,cAAcA,EAAK,KAAK,aAC3D,GAAI,CAAC,SAAS,cAAcmB,CAAY,EAEtC,OAGY,SAAS,iBAAiBA,CAAY,EAC9C,QAASlB,GAAS,IAAID,EAAKC,CAAmB,CAAC,CACvD,CACF,EAlWMmB,EAANpB,EAAMoB,EAsBW,KAAO,CAEpB,UAAW,uBAEX,WAAY,aAEZ,iBAAkB,mBAElB,sBAAuB,wBAEvB,wBAAyB,0BAEzB,uBAAwB,yBAExB,uBAAwB,2BAC1B,EArCIA,EA8CW,oBAAsB,IAAIC,EA9CrCD,EA4SW,YAA0C,IAAI,QA5SzDA,EAgUW,iBAAmB,GAqCnC,OAAe,MAAS,OAAe,OAAS,CAAC,EACjD,OAAe,MAAM,KAAOA,ECxU7B,IAAME,EAAN,KAAc,CAsBZ,YAAYC,EAAwB,CAhFtC,IAAAC,EAiFIF,EAAQ,YAAY,IAAIC,EAAW,IAAI,EACvC,KAAK,OAAS,CACZ,UAAAA,EACA,KAAMA,EAAU,cAAc,gBAAgB,EAC9C,QAASA,EAAU,cAAc,mBAAmB,EACpD,OAAQA,EAAU,cAChB,2BACF,CACF,EAEA,IAAME,EAAgB,KAAK,OAAO,QAAQ,cACxC,wCACF,EACIA,KAEFD,EAAAC,GAAA,YAAAA,EAAe,gBAAf,MAAAD,EAA8B,UAAU,IAAI,iBAC5CC,EAAc,UAAU,IAAI,iBAAiB,GAG3C,KAAK,OAAO,SACd,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC1B,KAAK,aAAa,GAKpBH,EAAQ,oBAAoB,QAAQ,KAAK,OAAO,IAAI,EAEpDC,EAAU,gBAAgB,yBAAyB,EACnD,IAAMG,EAAaH,EAAU,cAC3B,0CACF,EACIG,GACFH,EAAU,YAAYG,CAAU,CAEpC,CAsBA,IAAI,UAAoB,CACtB,OAAO,KAAK,OAAO,UAAU,UAAU,SAASJ,EAAQ,QAAQ,QAAQ,CAC1E,CAyCA,OAAc,YAAYK,EAAsC,CAC9D,OAAOL,EAAQ,YAAY,IAAIK,CAAE,CACnC,CAWA,OAAc,mBAAmBC,EAAsB,GAAY,CACjE,GAAI,SAAS,aAAe,UAAW,CAChCN,EAAQ,mBACXA,EAAQ,iBAAmB,GAC3B,SAAS,iBAAiB,mBAAoB,IAAM,CAClDA,EAAQ,mBAAmB,EAAK,CAClC,CAAC,GAEH,MACF,CAEA,IAAMO,EAAe,IAAIP,EAAQ,QAAQ,kCACzC,GAAI,CAAC,SAAS,cAAcO,CAAY,EAEtC,OAGED,GAAqBN,EAAQ,oBAAoB,MAAM,EAExC,SAAS,iBAAiBO,CAAY,EAC9C,QAASN,GAAc,IAAID,EAAQC,CAAwB,CAAC,CACzE,CAMQ,qBAA4B,CA9NtC,IAAAC,EA+NI,GAAM,CAAE,OAAAM,CAAO,EAAI,KAAK,OAExBA,EAAO,iBAAiB,QAAUC,GAAO,CACvCA,EAAG,eAAe,EAClB,KAAK,OAAO,QAAQ,CACtB,CAAC,GAMDP,EAAAM,EACG,cAAc,gBAAgB,IADjC,MAAAN,EAEI,iBAAiB,gBAAiB,IAAM,KAAK,eAAe,EAClE,CAaQ,sBAA6B,CACnC,GAAM,CAAE,UAAAD,CAAU,EAAI,KAAK,OAErBS,EACJ,IAAIV,EAAQ,QAAQ,oBAEhBA,EAAQ,QAAQ,iDAKtB,GAAI,EAFFC,EAAU,cAAcS,CAAoB,IAAM,MAIlD,OAGF,SAASC,EAAkBN,EAA4C,CAMrE,OALAA,EAAKA,EAAKA,EAAG,cAAgB,KACzBA,GAAMA,EAAG,UAAU,SAAS,MAAM,IAEpCA,EAAKA,EAAG,eAENA,GAAMA,EAAG,UAAU,SAASL,EAAQ,QAAQ,MAAM,EAC7CK,EAEF,IACT,CAEA,IAAMO,EAAU,CAACX,CAAS,EACtBY,EAASF,EAAkBV,CAAS,EAExC,KAAOY,GAELD,EAAQ,QAAQC,CAAM,EACtBA,EAASF,EAAkBE,CAAM,EAGnC,IAAMC,EAAQ,CAAE,KAAM,EAAG,MAAO,CAAE,EAClCF,EAAQ,QAAQ,SAAUG,EAAsB,CAE9C,IAAMC,EADUD,EAAE,UAAU,SAAS,eAAe,EACxBD,EAAM,QAAUA,EAAM,OAClDC,EAAE,MAAM,YAAY,+BAAgCC,EAAU,SAAS,CAAC,EACxED,EAAE,MAAM,YACN,8BACA,KAAK,IAAID,EAAM,MAAOA,EAAM,IAAI,EAAE,SAAS,CAC7C,CACF,CAAC,CACH,CAMQ,cAAqB,CA/S/B,IAAAZ,EAgTI,GAAM,CAAE,UAAAD,CAAU,EAAI,KAAK,OAE3B,KAAIC,EAAAD,EAAU,QAAQ,mBAAlB,YAAAC,EAAoC,UAAW,UACjD,OAIoB,OACnB,iBAAiBD,CAAS,EAC1B,iBAAiB,mCAAmC,EAErC,KAAK,IAAM,QAC3B,KAAK,OAAO,OAAO,CAEvB,CASO,OAAOgB,EAA+C,CACvD,OAAOA,GAAW,cACpBA,EAAS,UAGX,GAAM,CAAE,UAAAhB,EAAW,QAAAiB,CAAQ,EAAI,KAAK,OAC9BC,EAAW,KAAK,SAEtB,GAAI,CAAC,OAAQ,QAAS,QAAQ,EAAE,QAAQF,CAAM,IAAM,GAClD,MAAM,IAAI,MAAM,kBAAkBA,GAAQ,EAGxCA,IAAW,WACbA,EAASE,EAAW,OAAS,SAG1B,EAAAA,GAAYF,IAAW,SAAa,CAACE,GAAYF,IAAW,UAK7DA,IAAW,SAGbC,EAAQ,OAAS,IAKnBjB,EAAU,UAAU,IAAID,EAAQ,QAAQ,aAAa,EACrDC,EAAU,UAAU,OAAOD,EAAQ,QAAQ,QAAQ,EACrD,CAMQ,gBAAuB,CAC7B,GAAM,CAAE,UAAAC,EAAW,QAAAiB,EAAS,OAAAV,CAAO,EAAI,KAAK,OAC5CP,EAAU,UAAU,OAAOD,EAAQ,QAAQ,aAAa,EACxDkB,EAAQ,OAAS,KAAK,SACtBV,EAAO,aAAa,gBAAiB,KAAK,SAAW,QAAU,MAAM,EAGrE,IAAMY,EAAQ,IAAI,YAAY,gBAAiB,CAC7C,QAAS,GACT,OAAQ,CAAE,KAAM,CAAC,KAAK,QAAS,CACjC,CAAC,EACDF,EAAQ,cAAcE,CAAK,EAG3B,EAAEF,CAAO,EAAE,QAAQ,oCAAoC,EACvD,EAAEA,CAAO,EAAE,QAAQ,KAAK,SAAW,SAAW,OAAO,CACvD,CACF,EAnUMG,EAANrB,EAAMqB,EAeW,oBAAsB,IAAIC,EAfrCD,EA4FmB,QAAU,CAE/B,OAAQ,uBAER,SAAU,oBAEV,cAAe,eACjB,EAnGIA,EA4GW,iBAAmB,GA5G9BA,EAmHW,YAA6C,IAAI,QAwNlE,IAAME,EAAN,cAAkCC,CAAa,CAC7C,KAAKC,EAAoB,CACvB,OAAO,EAAEA,CAAK,EAAE,KAAK,IAAIJ,EAAQ,QAAQ,+BAA+B,CAC1E,CAEA,SAAShB,EAA0B,CACjC,IAAMqB,EAAKL,EAAQ,YAAYhB,EAAG,aAA4B,EAC9D,OAAKqB,EACE,CAACA,EAAG,SADK,EAElB,CAEA,SAASrB,EAAiBsB,EAAsB,CAC9C,IAAMV,EAASU,EAAQ,OAAS,QAChC,KAAK,eAAetB,EAAI,CAAE,OAAAY,CAAO,CAAC,CACpC,CAEA,UAAUZ,EAAiBuB,EAAgC,CACzD,EAAEvB,CAAE,EAAE,GACJ,qCAEA,SAAUe,EAAO,CACfQ,EAAS,EAAI,CACf,CACF,CACF,CAEA,YAAYvB,EAAiB,CAC3B,EAAEA,CAAE,EAAE,IAAI,sBAAsB,CAClC,CAEA,eAAeA,EAAiBwB,EAA0B,CACxD,IAAMH,EAAKL,EAAQ,YAAYhB,EAAG,aAA4B,EAC1DqB,GAAIA,EAAG,OAAOG,EAAK,MAAM,CAC/B,CACF,EAEAC,EAAgBP,EAAqB,SAAS,EAG7C,OAAe,MAAS,OAAe,OAAS,CAAC,EACjD,OAAe,MAAM,QAAUF,EC3azB,SAASU,EAA8BC,EAErC,CACP,GAAK,OAAO,MAIZ,OAAW,CAACC,EAAMC,CAAO,IAAK,OAAO,QAAQF,CAAQ,EACnD,MAAM,wBAAwBC,EAAMC,CAAO,CAE/C,CCCA,IAAMC,EAAuB,CAE3B,4BAA8BC,GAAa,CAGzC,IAAMC,EAAK,SAAS,eAAeD,EAAI,EAAE,EACpCC,GACH,QAAQ,KAAK,+CAAgDD,CAAG,EAGlE,IAAME,EAAU,EAAED,CAAE,EAAE,KAAK,qBAAqB,EAChD,GAAI,EAAEC,aAAmBC,GAAe,CACtC,QAAQ,KAAK,qDAAsDH,CAAG,EACtE,MACF,CAEA,IAAII,EAAQJ,EAAI,MACZ,OAAOI,GAAU,cACnBA,EAAQ,CAACF,EAAQ,SAASD,CAAE,GAE9BC,EAAQ,eAAeD,EAAI,CAAE,MAAAG,CAAM,CAAC,CACtC,CACF,EAEI,OAAO,OACTC,EAA8BN,CAAoB,EASpD,SAASO,GAAoB,CAC3B,IAAMC,EAAO,SAAS,cAAc,KAAK,EACzCA,EAAK,UAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAajB,SAAS,KAAK,YAAYA,EAAK,SAAS,CAAC,CAAS,CACpD,CAEI,SAAS,aAAe,WAC1BD,EAAkB,EAElB,SAAS,iBAAiB,mBAAoBA,CAAiB",
- "names": ["InputBinding", "registerBinding", "inputBindingClass", "name", "hasDefinedProperty", "obj", "prop", "getAllFocusableChildren", "el", "base", "modifiers", "selectors", "b", "focusable", "AccordionInputBinding", "InputBinding", "scope", "el", "selected", "x", "callback", "event", "data", "method", "items", "vals", "targetItem", "panel", "val", "targetItems", "unbindAll", "target", "hasDefinedProperty", "body", "header", "title", "icon", "collapse", "isOpen", "values", "value", "registerBinding", "ShinyResizeObserver", "entries", "resizeEvent", "resized", "entry", "el", "binding", "onResize", "owner", "img", "idxEl", "_Card", "card", "_a", "event", "btnFullScreen", "ev", "selOpenSelectInput", "isFocusedContainer", "isFocusedAnchor", "isFocusedWithin", "stopEvent", "focusableElements", "getAllFocusableChildren", "el", "lastFocusable", "isFocusedLast", "container", "anchor", "flushResizeObserver", "initSelector", "Card", "ShinyResizeObserver", "_Sidebar", "container", "_a", "sideAccordion", "initScript", "el", "flushResizeObserver", "initSelector", "toggle", "ev", "selectorChildLayouts", "nextSidebarParent", "layouts", "parent", "count", "x", "thisCount", "method", "sidebar", "isClosed", "event", "Sidebar", "ShinyResizeObserver", "SidebarInputBinding", "InputBinding", "scope", "sb", "value", "callback", "data", "registerBinding", "shinyAddCustomMessageHandlers", "handlers", "name", "handler", "bslibMessageHandlers", "msg", "el", "binding", "InputBinding", "value", "shinyAddCustomMessageHandlers", "insertSvgGradient", "temp"]
+ "sourcesContent": ["import type { HtmlDep } from \"rstudio-shiny/srcts/types/src/shiny/render\";\n\nimport type { InputBinding as InputBindingType } from \"rstudio-shiny/srcts/types/src/bindings/input\";\n\n// Exclude undefined from T\ntype NotUndefined = T extends undefined ? never : T;\n\n// eslint-disable-next-line @typescript-eslint/naming-convention\nconst InputBinding = (\n window.Shiny ? Shiny.InputBinding : class {}\n) as typeof InputBindingType;\n\nfunction registerBinding(\n inputBindingClass: new () => InputBindingType,\n name: string\n): void {\n if (window.Shiny) {\n Shiny.inputBindings.register(new inputBindingClass(), \"bslib.\" + name);\n }\n}\n\n// Return true if the key exists on the object and the value is not undefined.\n//\n// This method is mainly used in input bindings' `receiveMessage` method.\n// Since we know that the values are sent by Shiny via `{jsonlite}`,\n// then we know that there are no `undefined` values. `null` is possible, but not `undefined`.\nfunction hasDefinedProperty<\n Prop extends keyof X,\n X extends { [key: string]: any }\n>(\n obj: X,\n prop: Prop\n): obj is X & { [key in NonNullable]: NotUndefined } {\n return (\n Object.prototype.hasOwnProperty.call(obj, prop) && obj[prop] !== undefined\n );\n}\n\n// TODO: Shiny should trigger resize events when the output\n// https://github.com/rstudio/shiny/pull/3682\nfunction doWindowResizeOnElementResize(el: HTMLElement): void {\n if ($(el).data(\"window-resize-observer\")) {\n return;\n }\n const resizeEvent = new Event(\"resize\");\n const ro = new ResizeObserver(() => {\n window.dispatchEvent(resizeEvent);\n });\n ro.observe(el);\n $(el).data(\"window-resize-observer\", ro);\n}\n\nfunction getAllFocusableChildren(el: HTMLElement): HTMLElement[] {\n // Cross-referenced with https://allyjs.io/data-tables/focusable.html\n const base = [\n \"a[href]\",\n \"area[href]\",\n \"button\",\n \"details summary\",\n \"input\",\n \"iframe\",\n \"select\",\n \"textarea\",\n '[contentEditable=\"\"]',\n '[contentEditable=\"true\"]',\n '[contentEditable=\"TRUE\"]',\n \"[tabindex]\",\n ];\n const modifiers = [':not([tabindex=\"-1\"])', \":not([disabled])\"];\n const selectors = base.map((b) => b + modifiers.join(\"\"));\n const focusable = el.querySelectorAll(selectors.join(\", \"));\n return Array.from(focusable) as HTMLElement[];\n}\n\nasync function shinyRenderContent(\n ...args: Parameters\n): ReturnType {\n if (!window.Shiny) {\n throw new Error(\"This function must be called in a Shiny app.\");\n }\n if (Shiny.renderContentAsync) {\n return await Shiny.renderContentAsync.apply(null, args);\n } else {\n return await Shiny.renderContent.apply(null, args);\n }\n}\n\nexport {\n InputBinding,\n registerBinding,\n hasDefinedProperty,\n doWindowResizeOnElementResize,\n getAllFocusableChildren,\n shinyRenderContent,\n};\nexport type { HtmlDep };\n", "import type { HtmlDep } from \"./_utils\";\nimport {\n InputBinding,\n registerBinding,\n hasDefinedProperty,\n shinyRenderContent,\n} from \"./_utils\";\n\ntype AccordionItem = {\n item: HTMLElement;\n value: string;\n isOpen: () => boolean;\n show: () => void;\n hide: () => void;\n};\n\ntype HTMLContent = {\n html: string;\n deps?: HtmlDep[];\n};\n\ntype SetMessage = {\n method: \"set\";\n values: string[];\n};\n\ntype OpenMessage = {\n method: \"open\";\n values: string[] | true;\n};\n\ntype CloseMessage = {\n method: \"close\";\n values: string[] | true;\n};\n\ntype InsertMessage = {\n method: \"insert\";\n panel: HTMLContent;\n target: string;\n position: \"after\" | \"before\";\n};\n\ntype RemoveMessage = {\n method: \"remove\";\n target: string[];\n};\n\ntype UpdateMessage = {\n method: \"update\";\n target: string;\n value: string;\n body: HTMLContent;\n title: HTMLContent;\n icon: HTMLContent;\n};\n\ntype MessageData =\n | CloseMessage\n | InsertMessage\n | OpenMessage\n | RemoveMessage\n | SetMessage\n | UpdateMessage;\n\nclass AccordionInputBinding extends InputBinding {\n find(scope: HTMLElement) {\n return $(scope).find(\".accordion.bslib-accordion-input\");\n }\n\n getValue(el: HTMLElement): string[] | null {\n const items = this._getItemInfo(el);\n const selected = items.filter((x) => x.isOpen()).map((x) => x.value);\n return selected.length === 0 ? null : selected;\n }\n\n subscribe(el: HTMLElement, callback: (x: boolean) => void) {\n $(el).on(\n \"shown.bs.collapse.accordionInputBinding hidden.bs.collapse.accordionInputBinding\",\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n function (event) {\n callback(true);\n }\n );\n }\n\n unsubscribe(el: HTMLElement) {\n $(el).off(\".accordionInputBinding\");\n }\n\n async receiveMessage(el: HTMLElement, data: MessageData) {\n const method = data.method;\n if (method === \"set\") {\n this._setItems(el, data);\n } else if (method === \"open\") {\n this._openItems(el, data);\n } else if (method === \"close\") {\n this._closeItems(el, data);\n } else if (method === \"remove\") {\n this._removeItem(el, data);\n } else if (method === \"insert\") {\n await this._insertItem(el, data);\n } else if (method === \"update\") {\n await this._updateItem(el, data);\n } else {\n throw new Error(`Method not yet implemented: ${method}`);\n }\n }\n\n protected _setItems(el: HTMLElement, data: SetMessage) {\n const items = this._getItemInfo(el);\n const vals = this._getValues(el, items, data.values);\n items.forEach((x) => {\n vals.indexOf(x.value) > -1 ? x.show() : x.hide();\n });\n }\n\n protected _openItems(el: HTMLElement, data: OpenMessage) {\n const items = this._getItemInfo(el);\n const vals = this._getValues(el, items, data.values);\n items.forEach((x) => {\n if (vals.indexOf(x.value) > -1) x.show();\n });\n }\n\n protected _closeItems(el: HTMLElement, data: CloseMessage) {\n const items = this._getItemInfo(el);\n const vals = this._getValues(el, items, data.values);\n items.forEach((x) => {\n if (vals.indexOf(x.value) > -1) x.hide();\n });\n }\n\n protected async _insertItem(el: HTMLElement, data: InsertMessage) {\n let targetItem = this._findItem(el, data.target);\n\n // If no target was specified, or the target was not found, then default\n // to the first or last item, depending on the position\n if (!targetItem) {\n targetItem = (\n data.position === \"before\" ? el.firstElementChild : el.lastElementChild\n ) as HTMLElement;\n }\n\n const panel = data.panel;\n\n // If there is still no targetItem, then there are no items in the accordion\n if (targetItem) {\n await shinyRenderContent(\n targetItem,\n panel,\n data.position === \"before\" ? \"beforeBegin\" : \"afterEnd\"\n );\n } else {\n await shinyRenderContent(el, panel);\n }\n\n // Need to add a reference to the parent id that makes autoclose to work\n if (this._isAutoClosing(el)) {\n const val = $(panel.html).attr(\"data-value\");\n $(el)\n .find(`[data-value=\"${val}\"] .accordion-collapse`)\n .attr(\"data-bs-parent\", \"#\" + el.id);\n }\n }\n\n protected _removeItem(el: HTMLElement, data: RemoveMessage) {\n const targetItems = this._getItemInfo(el).filter(\n (x) => data.target.indexOf(x.value) > -1\n );\n\n const unbindAll = Shiny?.unbindAll;\n\n targetItems.forEach((x) => {\n if (unbindAll) unbindAll(x.item);\n x.item.remove();\n });\n }\n\n protected async _updateItem(el: HTMLElement, data: UpdateMessage) {\n const target = this._findItem(el, data.target);\n\n if (!target) {\n throw new Error(\n `Unable to find an accordion_panel() with a value of ${data.target}`\n );\n }\n\n if (hasDefinedProperty(data, \"value\")) {\n target.dataset.value = data.value;\n }\n\n if (hasDefinedProperty(data, \"body\")) {\n const body = target.querySelector(\".accordion-body\") as HTMLElement; // always exists\n await shinyRenderContent(body, data.body);\n }\n\n const header = target.querySelector(\".accordion-header\") as HTMLElement; // always exists\n\n if (hasDefinedProperty(data, \"title\")) {\n const title = header.querySelector(\".accordion-title\") as HTMLElement; // always exists\n await shinyRenderContent(title, data.title);\n }\n\n if (hasDefinedProperty(data, \"icon\")) {\n const icon = header.querySelector(\n \".accordion-button > .accordion-icon\"\n ) as HTMLElement; // always exists\n await shinyRenderContent(icon, data.icon);\n }\n }\n\n protected _getItemInfo(el: HTMLElement): AccordionItem[] {\n const items = Array.from(\n el.querySelectorAll(\":scope > .accordion-item\")\n ) as HTMLElement[];\n return items.map((x) => this._getSingleItemInfo(x));\n }\n\n protected _getSingleItemInfo(x: HTMLElement): AccordionItem {\n const collapse = x.querySelector(\".accordion-collapse\") as HTMLElement;\n const isOpen = () => $(collapse).hasClass(\"show\");\n return {\n item: x,\n value: x.dataset.value as string,\n isOpen: isOpen,\n show: () => {\n if (!isOpen()) $(collapse).collapse(\"show\");\n },\n hide: () => {\n if (isOpen()) $(collapse).collapse(\"hide\");\n },\n };\n }\n\n protected _getValues(\n el: HTMLElement,\n items: AccordionItem[],\n values: string[] | true\n ): string[] {\n let vals = values !== true ? values : items.map((x) => x.value);\n const autoclose = this._isAutoClosing(el);\n if (autoclose) {\n vals = vals.slice(vals.length - 1, vals.length);\n }\n return vals;\n }\n\n protected _findItem(el: HTMLElement, value: string): HTMLElement | null {\n return el.querySelector(`[data-value=\"${value}\"]`);\n }\n\n protected _isAutoClosing(el: HTMLElement): boolean {\n return el.classList.contains(\"autoclose\");\n }\n}\n\nregisterBinding(AccordionInputBinding, \"accordion\");\n", "/**\n * A resize observer that ensures Shiny outputs resize during or just after\n * their parent container size changes. Useful, in particular, for sidebar\n * transitions or for full-screen card transitions.\n *\n * @class ShinyResizeObserver\n * @typedef {ShinyResizeObserver}\n */\nclass ShinyResizeObserver {\n /**\n * The actual ResizeObserver instance.\n * @private\n * @type {ResizeObserver}\n */\n private resizeObserver: ResizeObserver;\n /**\n * An array of elements that are currently being watched by the Resize\n * Observer.\n *\n * @details\n * We don't currently have lifecycle hooks that allow us to unobserve elements\n * when they are removed from the DOM. As a result, we need to manually check\n * that the elements we're watching still exist in the DOM. This array keeps\n * track of the elements we're watching so that we can check them later.\n * @private\n * @type {HTMLElement[]}\n */\n private resizeObserverEntries: HTMLElement[];\n\n /**\n * Watch containers for size changes and ensure that Shiny outputs and\n * htmlwidgets within resize appropriately.\n *\n * @details\n * The ShinyResizeObserver is used to watch the containers, such as Sidebars\n * and Cards for size changes, in particular when the sidebar state is toggled\n * or the card body is expanded full screen. It performs two primary tasks:\n *\n * 1. Dispatches a `resize` event on the window object. This is necessary to\n * ensure that Shiny outputs resize appropriately. In general, the window\n * resizing is throttled and the output update occurs when the transition\n * is complete.\n * 2. If an output with a resize method on the output binding is detected, we\n * directly call the `.onResize()` method of the binding. This ensures that\n * htmlwidgets transition smoothly. In static mode, htmlwidgets does this\n * already.\n *\n * @note\n * This resize observer also handles race conditions in some complex\n * fill-based layouts with multiple outputs (e.g., plotly), where shiny\n * initializes with the correct sizing, but in-between the 1st and last\n * renderValue(), the size of the output containers can change, meaning every\n * output but the 1st gets initialized with the wrong size during their\n * renderValue(). Then, after the render phase, shiny won't know to trigger a\n * resize since all the widgets will return to their original size (and thus,\n * Shiny thinks there isn't any resizing to do). The resize observer works\n * around this by ensuring that the output is resized whenever its container\n * size changes.\n * @constructor\n */\n constructor() {\n this.resizeObserverEntries = [];\n this.resizeObserver = new ResizeObserver((entries) => {\n const resizeEvent = new Event(\"resize\");\n window.dispatchEvent(resizeEvent);\n\n // the rest of this callback is only relevant in Shiny apps\n if (!window.Shiny) return;\n\n const resized = [] as HTMLElement[];\n\n for (const entry of entries) {\n if (!(entry.target instanceof HTMLElement)) continue;\n if (!entry.target.querySelector(\".shiny-bound-output\")) continue;\n\n entry.target\n .querySelectorAll(\".shiny-bound-output\")\n .forEach((el) => {\n if (resized.includes(el)) return;\n\n const { binding, onResize } = $(el).data(\"shinyOutputBinding\");\n if (!binding || !binding.resize) return;\n\n // if this output is owned by another observer, skip it\n const owner = (el as any).shinyResizeObserver;\n if (owner && owner !== this) return;\n // mark this output as owned by this shinyResizeObserver instance\n if (!owner) (el as any).shinyResizeObserver = this;\n\n // trigger immediate resizing of outputs with a resize method\n onResize(el);\n // only once per output and resize event\n resized.push(el);\n\n // set plot images to 100% width temporarily during the transition\n if (!el.classList.contains(\"shiny-plot-output\")) return;\n const img = el.querySelector(\n 'img:not([width=\"100%\"])'\n );\n if (img) img.setAttribute(\"width\", \"100%\");\n });\n }\n });\n }\n\n /**\n * Observe an element for size changes.\n * @param {HTMLElement} el - The element to observe.\n */\n observe(el: HTMLElement): void {\n this.resizeObserver.observe(el);\n this.resizeObserverEntries.push(el);\n }\n\n /**\n * Stop observing an element for size changes.\n * @param {HTMLElement} el - The element to stop observing.\n */\n unobserve(el: HTMLElement): void {\n const idxEl = this.resizeObserverEntries.indexOf(el);\n if (idxEl < 0) return;\n\n this.resizeObserver.unobserve(el);\n this.resizeObserverEntries.splice(idxEl, 1);\n }\n\n /**\n * This method checks that we're not continuing to watch elements that no\n * longer exist in the DOM. If any are found, we stop observing them and\n * remove them from our array of observed elements.\n *\n * @private\n * @static\n */\n flush(): void {\n this.resizeObserverEntries.forEach((el) => {\n if (!document.body.contains(el)) this.unobserve(el);\n });\n }\n}\n\nexport { ShinyResizeObserver };\n", "import { getAllFocusableChildren } from \"./_utils\";\nimport { ShinyResizeObserver } from \"./_shinyResizeObserver\";\n\n/**\n * The overlay element that is placed behind the card when expanded full screen.\n *\n * @interface CardFullScreenOverlay\n * @typedef {CardFullScreenOverlay}\n */\ninterface CardFullScreenOverlay {\n /**\n * The full screen overlay container.\n * @type {HTMLDivElement}\n */\n container: HTMLDivElement;\n /**\n * The anchor element used to close the full screen overlay.\n * @type {HTMLAnchorElement}\n */\n anchor: HTMLAnchorElement;\n}\n\n/**\n * The bslib card component class.\n *\n * @class Card\n * @typedef {Card}\n */\nclass Card {\n /**\n * The card container element.\n * @private\n * @type {HTMLElement}\n */\n private card: HTMLElement;\n /**\n * The card's full screen overlay element. We create this element once and add\n * and remove it from the DOM as needed (this simplifies focus management\n * while in full screen mode).\n * @private\n * @type {CardFullScreenOverlay}\n */\n private overlay: CardFullScreenOverlay;\n\n /**\n * Key bslib-specific classes and attributes used by the card component.\n * @private\n * @static\n * @type {{ ATTR_INIT: string; CLASS_CARD: string; CLASS_FULL_SCREEN: string; CLASS_HAS_FULL_SCREEN: string; CLASS_FULL_SCREEN_ENTER: string; CLASS_FULL_SCREEN_EXIT: string; ID_FULL_SCREEN_OVERLAY: string; }}\n */\n private static attr = {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n ATTR_INIT: \"data-bslib-card-init\",\n // eslint-disable-next-line @typescript-eslint/naming-convention\n CLASS_CARD: \"bslib-card\",\n // eslint-disable-next-line @typescript-eslint/naming-convention\n ATTR_FULL_SCREEN: \"data-full-screen\",\n // eslint-disable-next-line @typescript-eslint/naming-convention\n CLASS_HAS_FULL_SCREEN: \"bslib-has-full-screen\",\n // eslint-disable-next-line @typescript-eslint/naming-convention\n CLASS_FULL_SCREEN_ENTER: \"bslib-full-screen-enter\",\n // eslint-disable-next-line @typescript-eslint/naming-convention\n CLASS_FULL_SCREEN_EXIT: \"bslib-full-screen-exit\",\n // eslint-disable-next-line @typescript-eslint/naming-convention\n ID_FULL_SCREEN_OVERLAY: \"bslib-full-screen-overlay\",\n };\n\n /**\n * A Shiny-specific resize observer that ensures Shiny outputs in within the\n * card resize appropriately.\n * @private\n * @type {ShinyResizeObserver}\n * @static\n */\n private static shinyResizeObserver = new ShinyResizeObserver();\n\n /**\n * Creates an instance of a bslib Card component.\n *\n * @constructor\n * @param {HTMLElement} card\n */\n constructor(card: HTMLElement) {\n // remove initialization attribute and script\n card.removeAttribute(Card.attr.ATTR_INIT);\n card\n .querySelector(`script[${Card.attr.ATTR_INIT}]`)\n ?.remove();\n\n this.card = card;\n Card.instanceMap.set(card, this);\n\n // Let Shiny know to trigger resize when the card size changes\n // TODO: shiny could/should do this itself (rstudio/shiny#3682)\n Card.shinyResizeObserver.observe(this.card);\n\n this._addEventListeners();\n this.overlay = this._createOverlay();\n\n // bind event handler methods to this card instance\n this._exitFullScreenOnEscape = this._exitFullScreenOnEscape.bind(this);\n this._trapFocusExit = this._trapFocusExit.bind(this);\n }\n\n /**\n * Enter the card's full screen mode, either programmatically or via an event\n * handler. Full screen mode is activated by adding a class to the card that\n * positions it absolutely and expands it to fill the viewport. In addition,\n * we add a full screen overlay element behind the card and we trap focus in\n * the expanded card while in full screen mode.\n *\n * @param {?Event} [event]\n */\n enterFullScreen(event?: Event): void {\n if (event) event.preventDefault();\n\n document.addEventListener(\"keydown\", this._exitFullScreenOnEscape, false);\n\n // trap focus in the fullscreen container, listening for Tab key on the\n // capture phase so we have the best chance of preventing other handlers\n document.addEventListener(\"keydown\", this._trapFocusExit, true);\n\n this.card.setAttribute(Card.attr.ATTR_FULL_SCREEN, \"true\");\n document.body.classList.add(Card.attr.CLASS_HAS_FULL_SCREEN);\n this.card.insertAdjacentElement(\"beforebegin\", this.overlay.container);\n\n // Set initial focus on the card, if not already\n if (\n !this.card.contains(document.activeElement) ||\n document.activeElement?.classList.contains(\n Card.attr.CLASS_FULL_SCREEN_ENTER\n )\n ) {\n this.card.setAttribute(\"tabindex\", \"-1\");\n this.card.focus();\n }\n }\n\n /**\n * Exit full screen mode. This removes the full screen overlay element,\n * removes the full screen class from the card, and removes the keyboard event\n * listeners that were added when entering full screen mode.\n */\n exitFullScreen(): void {\n document.removeEventListener(\n \"keydown\",\n this._exitFullScreenOnEscape,\n false\n );\n document.removeEventListener(\"keydown\", this._trapFocusExit, true);\n\n // Remove overlay and remove full screen classes from card\n this.overlay.container.remove();\n this.card.setAttribute(Card.attr.ATTR_FULL_SCREEN, \"false\");\n this.card.removeAttribute(\"tabindex\");\n document.body.classList.remove(Card.attr.CLASS_HAS_FULL_SCREEN);\n }\n\n /**\n * Adds general card-specific event listeners.\n * @private\n */\n private _addEventListeners(): void {\n const btnFullScreen = this.card.querySelector(\n `:scope > * > .${Card.attr.CLASS_FULL_SCREEN_ENTER}`\n );\n if (!btnFullScreen) return;\n btnFullScreen.addEventListener(\"click\", (ev) => this.enterFullScreen(ev));\n }\n\n /**\n * An event handler to exit full screen mode when the Escape key is pressed.\n * @private\n * @param {KeyboardEvent} event\n */\n private _exitFullScreenOnEscape(event: KeyboardEvent): void {\n if (!(event.target instanceof HTMLElement)) return;\n // If the user is in the middle of a select input choice, don't exit\n const selOpenSelectInput = [\"select[open]\", \"input[aria-expanded='true']\"];\n if (event.target.matches(selOpenSelectInput.join(\", \"))) return;\n\n if (event.key === \"Escape\") {\n this.exitFullScreen();\n }\n }\n\n /**\n * An event handler to trap focus within the card when in full screen mode.\n *\n * @description\n * This keyboard event handler ensures that tab focus stays within the card\n * when in full screen mode. When the card is first expanded,\n * we move focus to the card element itself. If focus somehow leaves the card,\n * we returns focus to the card container.\n *\n * Within the card, we handle only tabbing from the close anchor or the last\n * focusable element and only when tab focus would have otherwise left the\n * card. In those cases, we cycle focus to the last focusable element or back\n * to the anchor. If the card doesn't have any focusable elements, we move\n * focus to the close anchor.\n *\n * @note\n * Because the card contents may change, we check for focusable elements\n * every time the handler is called.\n *\n * @private\n * @param {KeyboardEvent} event\n */\n private _trapFocusExit(event: KeyboardEvent): void {\n if (!(event instanceof KeyboardEvent)) return;\n if (event.key !== \"Tab\") return;\n\n const isFocusedContainer = event.target === this.card;\n const isFocusedAnchor = event.target === this.overlay.anchor;\n const isFocusedWithin = this.card.contains(event.target as Node);\n\n const stopEvent = () => {\n event.preventDefault();\n event.stopImmediatePropagation();\n };\n\n if (!(isFocusedWithin || isFocusedContainer || isFocusedAnchor)) {\n // If focus is outside the card, return to the card\n stopEvent();\n this.card.focus();\n return;\n }\n\n // Check focusables every time because the card contents may have changed\n // but exclude the full screen enter button from this list of elements\n const focusableElements = getAllFocusableChildren(this.card).filter(\n (el) => !el.classList.contains(Card.attr.CLASS_FULL_SCREEN_ENTER)\n );\n const hasFocusableElements = focusableElements.length > 0;\n\n // We need to handle five cases:\n // 1. The card has no focusable elements --> focus the anchor\n // 2. Focus is on the card container (do nothing, natural tab order)\n // 3. Focus is on the anchor and the user pressed Tab + Shift (backwards)\n // -> Move to the last focusable element (end of card)\n // 4. Focus is on the last focusable element and the user pressed Tab\n // (forwards) -> Move to the anchor (top of card)\n // 5. otherwise we don't interfere\n\n if (!hasFocusableElements) {\n // case 1\n stopEvent();\n this.overlay.anchor.focus();\n return;\n }\n\n // case 2\n if (isFocusedContainer) return;\n\n const lastFocusable = focusableElements[focusableElements.length - 1];\n const isFocusedLast = event.target === lastFocusable;\n\n if (isFocusedAnchor && event.shiftKey) {\n stopEvent();\n lastFocusable.focus();\n return;\n }\n\n if (isFocusedLast && !event.shiftKey) {\n stopEvent();\n this.overlay.anchor.focus();\n return;\n }\n }\n\n /**\n * Creates the full screen overlay.\n * @private\n * @returns {CardFullScreenOverlay}\n */\n private _createOverlay(): CardFullScreenOverlay {\n const container = document.createElement(\"div\");\n container.id = Card.attr.ID_FULL_SCREEN_OVERLAY;\n container.onclick = this.exitFullScreen.bind(this);\n\n const anchor = this._createOverlayCloseAnchor();\n container.appendChild(anchor);\n\n return { container, anchor };\n }\n\n /**\n * Creates the anchor element used to exit the full screen mode.\n * @private\n * @returns {HTMLAnchorElement}\n */\n private _createOverlayCloseAnchor(): HTMLAnchorElement {\n const anchor = document.createElement(\"a\");\n anchor.classList.add(Card.attr.CLASS_FULL_SCREEN_EXIT);\n anchor.tabIndex = 0;\n anchor.onclick = () => this.exitFullScreen();\n anchor.onkeydown = (ev) => {\n if (ev.key === \"Enter\" || ev.key === \" \") {\n this.exitFullScreen();\n }\n };\n anchor.innerHTML = this._overlayCloseHtml();\n\n return anchor;\n }\n\n /**\n * Returns the HTML for the close icon.\n * @private\n * @returns {string}\n */\n private _overlayCloseHtml(): string {\n return (\n \"Close \" +\n \"\"\n );\n }\n\n /**\n * The registry of card instances and their associated DOM elements.\n * @private\n * @static\n * @type {WeakMap}\n */\n private static instanceMap: WeakMap = new WeakMap();\n\n /**\n * Returns the card instance associated with the given element, if any.\n * @public\n * @static\n * @param {HTMLElement} el\n * @returns {(Card | undefined)}\n */\n public static getInstance(el: HTMLElement): Card | undefined {\n return Card.instanceMap.get(el);\n }\n\n /**\n * If cards are initialized before the DOM is ready, we re-schedule the\n * initialization to occur on DOMContentLoaded.\n * @private\n * @static\n * @type {boolean}\n */\n private static onReadyScheduled = false;\n\n /**\n * Initializes all cards that require initialization on the page, or schedules\n * initialization if the DOM is not yet ready.\n * @public\n * @static\n * @param {boolean} [flushResizeObserver=true]\n */\n public static initializeAllCards(flushResizeObserver = true): void {\n if (document.readyState === \"loading\") {\n if (!Card.onReadyScheduled) {\n Card.onReadyScheduled = true;\n document.addEventListener(\"DOMContentLoaded\", () => {\n Card.initializeAllCards(false);\n });\n }\n return;\n }\n\n if (flushResizeObserver) {\n // Trigger a recheck of observed cards to unobserve non-existent cards\n Card.shinyResizeObserver.flush();\n }\n\n const initSelector = `.${Card.attr.CLASS_CARD}[${Card.attr.ATTR_INIT}]`;\n if (!document.querySelector(initSelector)) {\n // no cards to initialize\n return;\n }\n\n const cards = document.querySelectorAll(initSelector);\n cards.forEach((card) => new Card(card as HTMLElement));\n }\n}\n\n// attach Sidebar class to window for global usage\n(window as any).bslib = (window as any).bslib || {};\n(window as any).bslib.Card = Card;\n\nexport { Card };\n", "import { InputBinding, registerBinding } from \"./_utils\";\nimport { ShinyResizeObserver } from \"./_shinyResizeObserver\";\n\n/**\n * Methods for programmatically toggling the state of the sidebar. These methods\n * describe the desired state of the sidebar: `\"close\"` and `\"open\"` transition\n * the sidebar to the desired state, unless the sidebar is already in that\n * state. `\"toggle\"` transitions the sidebar to the state opposite of its\n * current state.\n * @typedef {SidebarToggleMethod}\n */\ntype SidebarToggleMethod = \"close\" | \"open\" | \"toggle\";\n\n/**\n * Data received by the input binding's `receiveMessage` method.\n * @typedef {SidebarMessageData}\n */\ntype SidebarMessageData = {\n method: SidebarToggleMethod;\n};\n\n/**\n * The DOM elements that make up the sidebar. `main`, `sidebar`, and `toggle`\n * are all direct children of `container` (in that order).\n * @interface SidebarComponents\n * @typedef {SidebarComponents}\n */\ninterface SidebarComponents {\n /**\n * The `layout_sidebar()` parent container, with class\n * `Sidebar.classes.LAYOUT`.\n * @type {HTMLElement}\n */\n container: HTMLElement;\n /**\n * The main content area of the sidebar layout.\n * @type {HTMLElement}\n */\n main: HTMLElement;\n /**\n * The sidebar container of the sidebar layout.\n * @type {HTMLElement}\n */\n sidebar: HTMLElement;\n /**\n * The toggle button that is used to toggle the sidebar state.\n * @type {HTMLElement}\n */\n toggle: HTMLElement;\n}\n\n/**\n * The bslib sidebar component class. This class is only used for collapsible\n * sidebars.\n *\n * @class Sidebar\n * @typedef {Sidebar}\n */\nclass Sidebar {\n /**\n * The DOM elements that make up the sidebar, see `SidebarComponents`.\n * @private\n * @type {SidebarComponents}\n */\n private layout: SidebarComponents;\n\n /**\n * A Shiny-specific resize observer that ensures Shiny outputs in the main\n * content areas of the sidebar resize appropriately.\n * @private\n * @type {ShinyResizeObserver}\n * @static\n */\n private static shinyResizeObserver = new ShinyResizeObserver();\n\n /**\n * Creates an instance of a collapsible bslib Sidebar.\n * @constructor\n * @param {HTMLElement} container\n */\n constructor(container: HTMLElement) {\n Sidebar.instanceMap.set(container, this);\n this.layout = {\n container,\n main: container.querySelector(\":scope > .main\") as HTMLElement,\n sidebar: container.querySelector(\":scope > .sidebar\") as HTMLElement,\n toggle: container.querySelector(\n \":scope > .collapse-toggle\"\n ) as HTMLElement,\n } as SidebarComponents;\n\n const sideAccordion = this.layout.sidebar.querySelector(\n \":scope > .sidebar-content > .accordion\"\n );\n if (sideAccordion) {\n // Add `.has-accordion` class to `.sidebar-content` container\n sideAccordion?.parentElement?.classList.add(\"has-accordion\");\n sideAccordion.classList.add(\"accordion-flush\");\n }\n\n if (this.layout.toggle) {\n this._initEventListeners();\n this._initSidebarCounters();\n this._initDesktop();\n }\n\n // Start watching the main content area for size changes to ensure Shiny\n // outputs resize appropriately during sidebar transitions.\n Sidebar.shinyResizeObserver.observe(this.layout.main);\n\n container.removeAttribute(\"data-bslib-sidebar-init\");\n const initScript = container.querySelector(\n \":scope > script[data-bslib-sidebar-init]\"\n );\n if (initScript) {\n container.removeChild(initScript);\n }\n }\n\n /**\n * Read the current state of the sidebar. Note that, when calling this method,\n * the sidebar may be transitioning into the state returned by this method.\n *\n * @description\n * The sidebar state works as follows, starting from the open state. When the\n * sidebar is closed:\n * 1. We add both the `COLLAPSE` and `TRANSITIONING` classes to the sidebar.\n * 2. The sidebar collapse begins to animate. On desktop devices, and where it\n * is supported, we transition the `grid-template-columns` property of the\n * sidebar layout. On mobile, the sidebar is hidden immediately. In both\n * cases, the collapse icon rotates and we use this rotation to determine\n * when the transition is complete.\n * 3. If another sidebar state toggle is requested while closing the sidebar,\n * we remove the `COLLAPSE` class and the animation immediately starts to\n * reverse.\n * 4. When the `transition` is complete, we remove the `TRANSITIONING` class.\n * @readonly\n * @type {boolean}\n */\n get isClosed(): boolean {\n return this.layout.container.classList.contains(Sidebar.classes.COLLAPSE);\n }\n\n /**\n * Static classes related to the sidebar layout or state.\n * @public\n * @static\n * @readonly\n * @type {{ LAYOUT: string; COLLAPSE: string; TRANSITIONING: string; }}\n */\n public static readonly classes = {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n LAYOUT: \"bslib-sidebar-layout\",\n // eslint-disable-next-line @typescript-eslint/naming-convention\n COLLAPSE: \"sidebar-collapsed\",\n // eslint-disable-next-line @typescript-eslint/naming-convention\n TRANSITIONING: \"transitioning\",\n };\n\n /**\n * If sidebars are initialized before the DOM is ready, we re-schedule the\n * initialization to occur on DOMContentLoaded.\n * @private\n * @static\n * @type {boolean}\n */\n private static onReadyScheduled = false;\n /**\n * A map of initialized sidebars to their respective Sidebar instances.\n * @private\n * @static\n * @type {WeakMap}\n */\n private static instanceMap: WeakMap = new WeakMap();\n\n /**\n * Given a sidebar container, return the Sidebar instance associated with it.\n * @public\n * @static\n * @param {HTMLElement} el\n * @returns {(Sidebar | undefined)}\n */\n public static getInstance(el: HTMLElement): Sidebar | undefined {\n return Sidebar.instanceMap.get(el);\n }\n\n /**\n * Initialize all collapsible sidebars on the page.\n * @public\n * @static\n * @param {boolean} [flushResizeObserver=true] When `true`, we remove\n * non-existent elements from the ResizeObserver. This is required\n * periodically to prevent memory leaks. To avoid over-checking, we only flush\n * the ResizeObserver when initializing sidebars after page load.\n */\n public static initCollapsibleAll(flushResizeObserver = true): void {\n if (document.readyState === \"loading\") {\n if (!Sidebar.onReadyScheduled) {\n Sidebar.onReadyScheduled = true;\n document.addEventListener(\"DOMContentLoaded\", () => {\n Sidebar.initCollapsibleAll(false);\n });\n }\n return;\n }\n\n const initSelector = `.${Sidebar.classes.LAYOUT}[data-bslib-sidebar-init]`;\n if (!document.querySelector(initSelector)) {\n // no sidebars to initialize\n return;\n }\n\n if (flushResizeObserver) Sidebar.shinyResizeObserver.flush();\n\n const containers = document.querySelectorAll(initSelector);\n containers.forEach((container) => new Sidebar(container as HTMLElement));\n }\n\n /**\n * Initialize event listeners for the sidebar toggle button.\n * @private\n */\n private _initEventListeners(): void {\n const { toggle } = this.layout;\n\n toggle.addEventListener(\"click\", (ev) => {\n ev.preventDefault();\n this.toggle(\"toggle\");\n });\n\n // Remove the transitioning class when the transition ends. We watch the\n // collapse toggle icon because it's guaranteed to transition, whereas the\n // sidebar doesn't animate on mobile (or in browsers where animating\n // grid-template-columns is not supported).\n toggle\n .querySelector(\".collapse-icon\")\n ?.addEventListener(\"transitionend\", () => this._finalizeState());\n }\n\n /**\n * Initialize nested sidebar counters.\n *\n * @description\n * This function walks up the DOM tree, adding CSS variables to each direct\n * parent sidebar layout that count the layout's position in the stack of\n * nested layouts. We use these counters to keep the collapse toggles from\n * overlapping. Note that always-open sidebars that don't have collapse\n * toggles break the chain of nesting.\n * @private\n */\n private _initSidebarCounters(): void {\n const { container } = this.layout;\n\n const selectorChildLayouts =\n `.${Sidebar.classes.LAYOUT}` +\n \"> .main > \" +\n `.${Sidebar.classes.LAYOUT}:not([data-bslib-sidebar-open=\"always\"])`;\n\n const isInnermostLayout =\n container.querySelector(selectorChildLayouts) === null;\n\n if (!isInnermostLayout) {\n // There are sidebar layouts nested within this layout; defer to children\n return;\n }\n\n function nextSidebarParent(el: HTMLElement | null): HTMLElement | null {\n el = el ? el.parentElement : null;\n if (el && el.classList.contains(\"main\")) {\n // .bslib-sidebar-layout > .main > .bslib-sidebar-layout\n el = el.parentElement;\n }\n if (el && el.classList.contains(Sidebar.classes.LAYOUT)) {\n return el;\n }\n return null;\n }\n\n const layouts = [container];\n let parent = nextSidebarParent(container);\n\n while (parent) {\n // Add parent to front of layouts array, so we sort outer -> inner\n layouts.unshift(parent);\n parent = nextSidebarParent(parent);\n }\n\n const count = { left: 0, right: 0 };\n layouts.forEach(function (x: HTMLElement): void {\n const isRight = x.classList.contains(\"sidebar-right\");\n const thisCount = isRight ? count.right++ : count.left++;\n x.style.setProperty(\"--_js-toggle-count-this-side\", thisCount.toString());\n x.style.setProperty(\n \"--_js-toggle-count-max-side\",\n Math.max(count.right, count.left).toString()\n );\n });\n }\n\n /**\n * Initialize the sidebar's initial state when `open = \"desktop\"`.\n * @private\n */\n private _initDesktop(): void {\n const { container } = this.layout;\n // If sidebar is marked open='desktop'...\n if (container.dataset.bslibSidebarOpen?.trim() !== \"desktop\") {\n return;\n }\n\n // then close sidebar on mobile\n const initCollapsed = window\n .getComputedStyle(container)\n .getPropertyValue(\"--bslib-sidebar-js-init-collapsed\");\n\n if (initCollapsed.trim() === \"true\") {\n this.toggle(\"close\");\n }\n }\n\n /**\n * Toggle the sidebar's open/closed state.\n * @public\n * @param {SidebarToggleMethod | undefined} method Whether to `\"open\"`,\n * `\"close\"` or `\"toggle\"` the sidebar. If `.toggle()` is called without an\n * argument, it will toggle the sidebar's state.\n */\n public toggle(method: SidebarToggleMethod | undefined): void {\n if (typeof method === \"undefined\") {\n method = \"toggle\";\n }\n\n const { container, sidebar } = this.layout;\n const isClosed = this.isClosed;\n\n if ([\"open\", \"close\", \"toggle\"].indexOf(method) === -1) {\n throw new Error(`Unknown method ${method}`);\n }\n\n if (method === \"toggle\") {\n method = isClosed ? \"open\" : \"close\";\n }\n\n if ((isClosed && method === \"close\") || (!isClosed && method === \"open\")) {\n // nothing to do, sidebar is already in the desired state\n return;\n }\n\n if (method === \"open\") {\n // unhide sidebar immediately when opening,\n // otherwise the sidebar is hidden on transitionend\n sidebar.hidden = false;\n }\n\n // Add a transitioning class just before adding COLLAPSE_CLASS since we want\n // some of the transitioning styles to apply before the collapse state\n container.classList.add(Sidebar.classes.TRANSITIONING);\n container.classList.toggle(Sidebar.classes.COLLAPSE);\n }\n\n /**\n * When the sidebar open/close transition ends, finalize the sidebar's state.\n * @private\n */\n private _finalizeState(): void {\n const { container, sidebar, toggle } = this.layout;\n container.classList.remove(Sidebar.classes.TRANSITIONING);\n sidebar.hidden = this.isClosed;\n toggle.setAttribute(\"aria-expanded\", this.isClosed ? \"false\" : \"true\");\n\n // Send browser-native event with updated sidebar state\n const event = new CustomEvent(\"bslib.sidebar\", {\n bubbles: true,\n detail: { open: !this.isClosed },\n });\n sidebar.dispatchEvent(event);\n\n // Trigger Shiny input and output binding events\n $(sidebar).trigger(\"toggleCollapse.sidebarInputBinding\");\n $(sidebar).trigger(this.isClosed ? \"hidden\" : \"shown\");\n }\n}\n\n/**\n * A Shiny input binding for a sidebar.\n * @class SidebarInputBinding\n * @typedef {SidebarInputBinding}\n * @extends {InputBinding}\n */\nclass SidebarInputBinding extends InputBinding {\n find(scope: HTMLElement) {\n return $(scope).find(`.${Sidebar.classes.LAYOUT} > .bslib-sidebar-input`);\n }\n\n getValue(el: HTMLElement): boolean {\n const sb = Sidebar.getInstance(el.parentElement as HTMLElement);\n if (!sb) return false;\n return !sb.isClosed;\n }\n\n setValue(el: HTMLElement, value: boolean): void {\n const method = value ? \"open\" : \"close\";\n this.receiveMessage(el, { method });\n }\n\n subscribe(el: HTMLElement, callback: (x: boolean) => void) {\n $(el).on(\n \"toggleCollapse.sidebarInputBinding\",\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n function (event) {\n callback(true);\n }\n );\n }\n\n unsubscribe(el: HTMLElement) {\n $(el).off(\".sidebarInputBinding\");\n }\n\n receiveMessage(el: HTMLElement, data: SidebarMessageData) {\n const sb = Sidebar.getInstance(el.parentElement as HTMLElement);\n if (sb) sb.toggle(data.method);\n }\n}\n\nregisterBinding(SidebarInputBinding, \"sidebar\");\n\n// attach Sidebar class to window for global usage\n(window as any).bslib = (window as any).bslib || {};\n(window as any).bslib.Sidebar = Sidebar;\n", "import type { Handler as ShinyCustomMessageHandler } from \"rstudio-shiny/srcts/types/src/shiny/shinyapp\";\n\nexport function shinyAddCustomMessageHandlers(handlers: {\n [key: string]: ShinyCustomMessageHandler;\n}): void {\n if (!window.Shiny) {\n return;\n }\n\n for (const [name, handler] of Object.entries(handlers)) {\n Shiny.addCustomMessageHandler(name, handler);\n }\n}\n", "// ----------------------------------------------------------------------------\n// First, bring in non-webcomponent (legacy) components (they attach to the window)\n// ----------------------------------------------------------------------------\nimport \"./accordion\";\nimport \"./card\";\nimport \"./sidebar\";\n\n// ----------------------------------------------------------------------------\n// Register custom message handlers for Shiny\n// ----------------------------------------------------------------------------\nimport { InputBinding } from \"./_utils\";\nimport { shinyAddCustomMessageHandlers } from \"./_shinyAddCustomMessageHandlers\";\n\nconst bslibMessageHandlers = {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n \"bslib.toggle-input-binary\": async (msg: any) => {\n // This handler was written for `toggle_switch()`, but could be used for any\n // binary Shiny input, e.g. checkbox.\n const el = document.getElementById(msg.id) as HTMLElement;\n if (!el) {\n console.warn(\"[bslib.toggle-input-binary] No element found\", msg);\n }\n\n const binding = $(el).data(\"shiny-input-binding\");\n if (!(binding instanceof InputBinding)) {\n console.warn(\"[bslib.toggle-input-binary] No input binding found\", msg);\n return;\n }\n\n let value = msg.value;\n if (typeof value === \"undefined\") {\n value = !binding.getValue(el);\n }\n\n await binding.receiveMessage(el, { value });\n },\n};\n\nif (window.Shiny) {\n shinyAddCustomMessageHandlers(bslibMessageHandlers);\n}\n\n// ----------------------------------------------------------------------\n// Append the (global) SVG linearGradient to the body.\n// value_box() uses this (i.e., bslib---icon-gradient element) to apply a\n// gradient to the icon when bs_theme(preset=\"shiny\").\n// ----------------------------------------------------------------------\n\nfunction insertSvgGradient() {\n const temp = document.createElement(\"div\");\n temp.innerHTML = `\n `;\n document.body.appendChild(temp.children[0] as Node);\n}\n\nif (document.readyState === \"complete\") {\n insertSvgGradient();\n} else {\n document.addEventListener(\"DOMContentLoaded\", insertSvgGradient);\n}\n"],
+ "mappings": "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",
+ "names": ["registerBinding", "inputBindingClass", "name", "hasDefinedProperty", "obj", "prop", "getAllFocusableChildren", "el", "base", "modifiers", "selectors", "b", "focusable", "shinyRenderContent", "args", "__async", "InputBinding", "init_utils", "__esmMin", "AccordionInputBinding", "init_accordion", "__esmMin", "init_utils", "InputBinding", "scope", "el", "selected", "x", "callback", "event", "data", "__async", "method", "items", "vals", "targetItem", "panel", "shinyRenderContent", "val", "targetItems", "unbindAll", "target", "hasDefinedProperty", "body", "header", "title", "icon", "collapse", "isOpen", "values", "value", "registerBinding", "ShinyResizeObserver", "init_shinyResizeObserver", "__esmMin", "entries", "resizeEvent", "resized", "entry", "el", "binding", "onResize", "owner", "img", "idxEl", "_Card", "Card", "init_card", "__esmMin", "init_utils", "init_shinyResizeObserver", "card", "_a", "event", "btnFullScreen", "ev", "selOpenSelectInput", "isFocusedContainer", "isFocusedAnchor", "isFocusedWithin", "stopEvent", "focusableElements", "getAllFocusableChildren", "el", "lastFocusable", "isFocusedLast", "container", "anchor", "flushResizeObserver", "initSelector", "ShinyResizeObserver", "_Sidebar", "Sidebar", "SidebarInputBinding", "init_sidebar", "__esmMin", "init_utils", "init_shinyResizeObserver", "container", "_a", "sideAccordion", "initScript", "el", "flushResizeObserver", "initSelector", "toggle", "ev", "selectorChildLayouts", "nextSidebarParent", "layouts", "parent", "count", "x", "thisCount", "method", "sidebar", "isClosed", "event", "ShinyResizeObserver", "InputBinding", "scope", "sb", "value", "callback", "data", "registerBinding", "shinyAddCustomMessageHandlers", "handlers", "name", "handler", "init_shinyAddCustomMessageHandlers", "__esmMin", "require_components", "__commonJSMin", "exports", "init_accordion", "init_card", "init_sidebar", "init_utils", "init_shinyAddCustomMessageHandlers", "bslibMessageHandlers", "msg", "__async", "el", "binding", "InputBinding", "value", "shinyAddCustomMessageHandlers", "insertSvgGradient", "temp"]
}
diff --git a/package.json b/package.json
index 456682ca3..4ee4d20ac 100644
--- a/package.json
+++ b/package.json
@@ -7,7 +7,7 @@
"devDependencies": {
"@types/bootstrap": "5.2.2",
"@types/node": "^18.11.18",
- "@types/rstudio-shiny": "https://github.com/rstudio/shiny#v1.7.4",
+ "@types/rstudio-shiny": "https://github.com/rstudio/shiny#main",
"@typescript-eslint/eslint-plugin": "^5.48.1",
"@typescript-eslint/parser": "^5.48.1",
"esbuild": "^0.16.14",
diff --git a/srcts/src/components/_utils.ts b/srcts/src/components/_utils.ts
index c9d445631..edd7db72e 100644
--- a/srcts/src/components/_utils.ts
+++ b/srcts/src/components/_utils.ts
@@ -72,11 +72,25 @@ function getAllFocusableChildren(el: HTMLElement): HTMLElement[] {
return Array.from(focusable) as HTMLElement[];
}
+async function shinyRenderContent(
+ ...args: Parameters
+): ReturnType {
+ if (!window.Shiny) {
+ throw new Error("This function must be called in a Shiny app.");
+ }
+ if (Shiny.renderContentAsync) {
+ return await Shiny.renderContentAsync.apply(null, args);
+ } else {
+ return await Shiny.renderContent.apply(null, args);
+ }
+}
+
export {
InputBinding,
registerBinding,
hasDefinedProperty,
doWindowResizeOnElementResize,
getAllFocusableChildren,
+ shinyRenderContent,
};
export type { HtmlDep };
diff --git a/srcts/src/components/accordion.ts b/srcts/src/components/accordion.ts
index 593463aa8..0d12f7245 100644
--- a/srcts/src/components/accordion.ts
+++ b/srcts/src/components/accordion.ts
@@ -1,5 +1,10 @@
import type { HtmlDep } from "./_utils";
-import { InputBinding, registerBinding, hasDefinedProperty } from "./_utils";
+import {
+ InputBinding,
+ registerBinding,
+ hasDefinedProperty,
+ shinyRenderContent,
+} from "./_utils";
type AccordionItem = {
item: HTMLElement;
@@ -83,7 +88,7 @@ class AccordionInputBinding extends InputBinding {
$(el).off(".accordionInputBinding");
}
- receiveMessage(el: HTMLElement, data: MessageData) {
+ async receiveMessage(el: HTMLElement, data: MessageData) {
const method = data.method;
if (method === "set") {
this._setItems(el, data);
@@ -94,9 +99,9 @@ class AccordionInputBinding extends InputBinding {
} else if (method === "remove") {
this._removeItem(el, data);
} else if (method === "insert") {
- this._insertItem(el, data);
+ await this._insertItem(el, data);
} else if (method === "update") {
- this._updateItem(el, data);
+ await this._updateItem(el, data);
} else {
throw new Error(`Method not yet implemented: ${method}`);
}
@@ -126,7 +131,7 @@ class AccordionInputBinding extends InputBinding {
});
}
- protected _insertItem(el: HTMLElement, data: InsertMessage) {
+ protected async _insertItem(el: HTMLElement, data: InsertMessage) {
let targetItem = this._findItem(el, data.target);
// If no target was specified, or the target was not found, then default
@@ -141,13 +146,13 @@ class AccordionInputBinding extends InputBinding {
// If there is still no targetItem, then there are no items in the accordion
if (targetItem) {
- Shiny.renderContent(
+ await shinyRenderContent(
targetItem,
panel,
data.position === "before" ? "beforeBegin" : "afterEnd"
);
} else {
- Shiny.renderContent(el, panel);
+ await shinyRenderContent(el, panel);
}
// Need to add a reference to the parent id that makes autoclose to work
@@ -172,7 +177,7 @@ class AccordionInputBinding extends InputBinding {
});
}
- protected _updateItem(el: HTMLElement, data: UpdateMessage) {
+ protected async _updateItem(el: HTMLElement, data: UpdateMessage) {
const target = this._findItem(el, data.target);
if (!target) {
@@ -187,21 +192,21 @@ class AccordionInputBinding extends InputBinding {
if (hasDefinedProperty(data, "body")) {
const body = target.querySelector(".accordion-body") as HTMLElement; // always exists
- Shiny.renderContent(body, data.body);
+ await shinyRenderContent(body, data.body);
}
const header = target.querySelector(".accordion-header") as HTMLElement; // always exists
if (hasDefinedProperty(data, "title")) {
const title = header.querySelector(".accordion-title") as HTMLElement; // always exists
- Shiny.renderContent(title, data.title);
+ await shinyRenderContent(title, data.title);
}
if (hasDefinedProperty(data, "icon")) {
const icon = header.querySelector(
".accordion-button > .accordion-icon"
) as HTMLElement; // always exists
- Shiny.renderContent(icon, data.icon);
+ await shinyRenderContent(icon, data.icon);
}
}
diff --git a/srcts/src/components/index.ts b/srcts/src/components/index.ts
index b589d2357..3aa09e41a 100644
--- a/srcts/src/components/index.ts
+++ b/srcts/src/components/index.ts
@@ -13,7 +13,7 @@ import { shinyAddCustomMessageHandlers } from "./_shinyAddCustomMessageHandlers"
const bslibMessageHandlers = {
// eslint-disable-next-line @typescript-eslint/naming-convention
- "bslib.toggle-input-binary": (msg: any) => {
+ "bslib.toggle-input-binary": async (msg: any) => {
// This handler was written for `toggle_switch()`, but could be used for any
// binary Shiny input, e.g. checkbox.
const el = document.getElementById(msg.id) as HTMLElement;
@@ -31,7 +31,8 @@ const bslibMessageHandlers = {
if (typeof value === "undefined") {
value = !binding.getValue(el);
}
- binding.receiveMessage(el, { value });
+
+ await binding.receiveMessage(el, { value });
},
};
diff --git a/yarn.lock b/yarn.lock
index da41f0d3b..6ea13431f 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -312,9 +312,9 @@
resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301"
integrity sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==
-"@types/rstudio-shiny@https://github.com/rstudio/shiny#v1.7.4":
- version "1.7.4"
- resolved "https://github.com/rstudio/shiny#6176f03ad0a706bfdf265ff23bd5ea7d90802a06"
+"@types/rstudio-shiny@https://github.com/rstudio/shiny#main":
+ version "1.7.5-alpha.9001"
+ resolved "https://github.com/rstudio/shiny#56878ebbaa92e1abf7136c8da8795fa71aa20a79"
dependencies:
"@types/bootstrap" "3.4.0"
"@types/bootstrap-datepicker" "0.0.14"