| /*! |
| * Bootstrap v6.0.0-alpha1 (https://getbootstrap.com/) |
| * Copyright 2011-2026 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) |
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
| */ |
| //#region js/src/dom/data.ts |
| /** |
| * -------------------------------------------------------------------------- |
| * Bootstrap dom/data.ts |
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
| * -------------------------------------------------------------------------- |
| */ |
| /** |
| * Constants |
| */ |
| const elementMap = /* @__PURE__ */ new Map(); |
| var data_default = { |
| set(element, key, instance) { |
| if (!elementMap.has(element)) elementMap.set(element, /* @__PURE__ */ new Map()); |
| const instanceMap = elementMap.get(element); |
| if (!instanceMap.has(key) && instanceMap.size !== 0) { |
| console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${[...instanceMap.keys()][0]}.`); |
| return; |
| } |
| instanceMap.set(key, instance); |
| }, |
| get(element, key) { |
| if (element && elementMap.has(element)) return elementMap.get(element).get(key) || null; |
| return null; |
| }, |
| getAny(element) { |
| if (element && elementMap.has(element)) return elementMap.get(element).values().next().value || null; |
| return null; |
| }, |
| remove(element, key) { |
| if (!elementMap.has(element)) return; |
| const instanceMap = elementMap.get(element); |
| instanceMap.delete(key); |
| if (instanceMap.size === 0) elementMap.delete(element); |
| } |
| }; |
| //#endregion |
| //#region js/src/dom/event-handler.ts |
| /** |
| * Constants |
| */ |
| const namespaceRegex = /[^.]*(?=\..*)\.|.*/; |
| const stripNameRegex = /\..*/; |
| const stripUidRegex = /::\d+$/; |
| const eventRegistry = {}; |
| let uidEvent = 1; |
| const customEvents = { |
| mouseenter: "mouseover", |
| mouseleave: "mouseout" |
| }; |
| const nativeEvents = /* @__PURE__ */ new Set([ |
| "click", |
| "dblclick", |
| "mouseup", |
| "mousedown", |
| "contextmenu", |
| "mousewheel", |
| "DOMMouseScroll", |
| "mouseover", |
| "mouseout", |
| "mousemove", |
| "selectstart", |
| "selectend", |
| "keydown", |
| "keypress", |
| "keyup", |
| "orientationchange", |
| "touchstart", |
| "touchmove", |
| "touchend", |
| "touchcancel", |
| "pointerdown", |
| "pointermove", |
| "pointerup", |
| "pointerleave", |
| "pointercancel", |
| "gesturestart", |
| "gesturechange", |
| "gestureend", |
| "focus", |
| "blur", |
| "change", |
| "reset", |
| "select", |
| "submit", |
| "focusin", |
| "focusout", |
| "load", |
| "unload", |
| "beforeunload", |
| "resize", |
| "move", |
| "DOMContentLoaded", |
| "readystatechange", |
| "error", |
| "abort", |
| "scroll", |
| "scrollend" |
| ]); |
| /** |
| * Private methods |
| */ |
| function makeEventUid(element, uid) { |
| return uid && `${uid}::${uidEvent++}` || element.uidEvent || uidEvent++; |
| } |
| function getElementEvents(element) { |
| const uid = makeEventUid(element); |
| element.uidEvent = uid; |
| eventRegistry[uid] = eventRegistry[uid] || {}; |
| return eventRegistry[uid]; |
| } |
| function isMouseEventWithinTarget(event) { |
| const { delegateTarget, relatedTarget } = event; |
| return Boolean(relatedTarget && delegateTarget.contains(relatedTarget)); |
| } |
| function bootstrapHandler(element, fn, handlerTypeEvent) { |
| const isCustomMouseEvent = handlerTypeEvent in customEvents; |
| return function handler(event) { |
| const bootstrapEvent = hydrateObj(event, { delegateTarget: element }); |
| if (isCustomMouseEvent && isMouseEventWithinTarget(bootstrapEvent)) return; |
| if (handler.oneOff) EventHandler.off(element, handlerTypeEvent, fn); |
| return fn.apply(element, [bootstrapEvent]); |
| }; |
| } |
| function bootstrapDelegationHandler(element, selector, fn, handlerTypeEvent) { |
| const isCustomMouseEvent = handlerTypeEvent in customEvents; |
| return function handler(event) { |
| const domElements = element.querySelectorAll(selector); |
| for (let { target } = event; target && target !== this; target = target.parentNode) for (const domElement of domElements) { |
| if (domElement !== target) continue; |
| const bootstrapEvent = hydrateObj(event, { delegateTarget: target }); |
| if (isCustomMouseEvent && isMouseEventWithinTarget(bootstrapEvent)) return; |
| if (handler.oneOff) EventHandler.off(element, handlerTypeEvent, selector, fn); |
| return fn.apply(target, [bootstrapEvent]); |
| } |
| }; |
| } |
| function findHandler(events, callable, handlerTypeEvent, delegationSelector = null) { |
| return Object.values(events).find((event) => event.callable === callable && event.handlerTypeEvent === handlerTypeEvent && event.delegationSelector === delegationSelector); |
| } |
| function normalizeParameters(originalTypeEvent, handler, delegationFunction) { |
| const isDelegated = typeof handler === "string"; |
| const callable = isDelegated ? delegationFunction : handler || delegationFunction; |
| const baseTypeEvent = originalTypeEvent.replace(stripNameRegex, ""); |
| let typeEvent = customEvents[baseTypeEvent] || baseTypeEvent; |
| if (!nativeEvents.has(typeEvent)) typeEvent = originalTypeEvent; |
| const handlerTypeEvent = baseTypeEvent in customEvents ? baseTypeEvent : typeEvent; |
| return { |
| isDelegated, |
| callable, |
| typeEvent, |
| handlerTypeEvent |
| }; |
| } |
| function addHandler(element, originalTypeEvent, handler, delegationFunction, oneOff) { |
| if (typeof originalTypeEvent !== "string" || !element) return; |
| const { isDelegated, callable, typeEvent, handlerTypeEvent } = normalizeParameters(originalTypeEvent, handler, delegationFunction); |
| const events = getElementEvents(element); |
| const handlers = events[typeEvent] || (events[typeEvent] = {}); |
| const previousFunction = findHandler(handlers, callable, handlerTypeEvent, isDelegated ? handler : null); |
| if (previousFunction) { |
| previousFunction.oneOff = previousFunction.oneOff && oneOff; |
| return; |
| } |
| const uid = makeEventUid(callable, originalTypeEvent.replace(namespaceRegex, "")); |
| const fn = isDelegated ? bootstrapDelegationHandler(element, handler, callable, handlerTypeEvent) : bootstrapHandler(element, callable, handlerTypeEvent); |
| fn.delegationSelector = isDelegated ? handler : null; |
| fn.callable = callable; |
| fn.handlerTypeEvent = handlerTypeEvent; |
| fn.oneOff = oneOff; |
| fn.uidEvent = uid; |
| handlers[uid] = fn; |
| element.addEventListener(typeEvent, fn, isDelegated); |
| } |
| function removeHandler(element, events, typeEvent, handler) { |
| element.removeEventListener(typeEvent, handler, Boolean(handler.delegationSelector)); |
| delete events[typeEvent][handler.uidEvent]; |
| } |
| function removeNamespacedHandlers(element, events, typeEvent, namespace) { |
| const storeElementEvent = events[typeEvent] || {}; |
| for (const [handlerKey, event] of Object.entries(storeElementEvent)) if (handlerKey.includes(namespace)) removeHandler(element, events, typeEvent, event); |
| } |
| function trigger(element, event, args) { |
| if (typeof event !== "string" || !element) return null; |
| const evt = hydrateObj(new Event(event, { |
| bubbles: true, |
| cancelable: true |
| }), args); |
| element.dispatchEvent(evt); |
| return evt; |
| } |
| const EventHandler = { |
| on(element, event, handler, delegationFunction) { |
| addHandler(element, event, handler, delegationFunction, false); |
| }, |
| one(element, event, handler, delegationFunction) { |
| addHandler(element, event, handler, delegationFunction, true); |
| }, |
| off(element, originalTypeEvent, handler, delegationFunction) { |
| if (typeof originalTypeEvent !== "string" || !element) return; |
| const { isDelegated, callable, typeEvent, handlerTypeEvent } = normalizeParameters(originalTypeEvent, handler, delegationFunction); |
| const inNamespace = typeEvent !== originalTypeEvent && handlerTypeEvent !== originalTypeEvent; |
| const events = getElementEvents(element); |
| const storeElementEvent = events[typeEvent] || {}; |
| const isNamespace = originalTypeEvent.startsWith("."); |
| if (typeof callable !== "undefined") { |
| if (!Object.keys(storeElementEvent).length) return; |
| const fn = findHandler(storeElementEvent, callable, handlerTypeEvent, isDelegated ? handler : null); |
| if (fn) removeHandler(element, events, typeEvent, fn); |
| return; |
| } |
| if (isNamespace) for (const elementEvent of Object.keys(events)) removeNamespacedHandlers(element, events, elementEvent, originalTypeEvent.slice(1)); |
| for (const [keyHandlers, event] of Object.entries(storeElementEvent)) { |
| const handlerKey = keyHandlers.replace(stripUidRegex, ""); |
| if (event.handlerTypeEvent === handlerTypeEvent && (!inNamespace || originalTypeEvent.includes(handlerKey))) removeHandler(element, events, typeEvent, event); |
| } |
| }, |
| trigger |
| }; |
| function hydrateObj(obj, meta = {}) { |
| for (const [key, value] of Object.entries(meta)) try { |
| obj[key] = value; |
| } catch { |
| Object.defineProperty(obj, key, { |
| configurable: true, |
| get() { |
| return value; |
| } |
| }); |
| } |
| return obj; |
| } |
| //#endregion |
| //#region js/src/dom/manipulator.ts |
| /** |
| * -------------------------------------------------------------------------- |
| * Bootstrap dom/manipulator.ts |
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
| * -------------------------------------------------------------------------- |
| */ |
| function normalizeData(value) { |
| if (value === "true") return true; |
| if (value === "false") return false; |
| if (value === Number(value).toString()) return Number(value); |
| if (value === "" || value === "null") return null; |
| if (typeof value !== "string") return value; |
| try { |
| return JSON.parse(decodeURIComponent(value)); |
| } catch { |
| return value; |
| } |
| } |
| function normalizeDataKey(key) { |
| return key.replace(/[A-Z]/g, (chr) => `-${chr.toLowerCase()}`); |
| } |
| const Manipulator = { |
| setDataAttribute(element, key, value) { |
| element.setAttribute(`data-bs-${normalizeDataKey(key)}`, value); |
| }, |
| removeDataAttribute(element, key) { |
| element.removeAttribute(`data-bs-${normalizeDataKey(key)}`); |
| }, |
| getDataAttributes(element) { |
| if (!element) return {}; |
| const attributes = {}; |
| const bsKeys = Object.keys(element.dataset).filter((key) => key.startsWith("bs") && !key.startsWith("bsConfig")); |
| for (const key of bsKeys) { |
| let pureKey = key.replace(/^bs/, ""); |
| pureKey = pureKey.charAt(0).toLowerCase() + pureKey.slice(1); |
| attributes[pureKey] = normalizeData(element.dataset[key]); |
| } |
| return attributes; |
| }, |
| getDataAttribute(element, key) { |
| return normalizeData(element.getAttribute(`data-bs-${normalizeDataKey(key)}`)); |
| } |
| }; |
| //#endregion |
| //#region js/src/util/index.ts |
| /** |
| * -------------------------------------------------------------------------- |
| * Bootstrap util/index.ts |
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
| * -------------------------------------------------------------------------- |
| */ |
| const MAX_UID = 1e6; |
| const MILLISECONDS_MULTIPLIER = 1e3; |
| const TRANSITION_END = "transitionend"; |
| /** |
| * Properly escape IDs selectors to handle weird IDs |
| */ |
| const parseSelector = (selector) => { |
| if (selector && window.CSS && window.CSS.escape) selector = selector.replace(/#([^\s"#']+)/g, (match, id) => `#${CSS.escape(id)}`); |
| return selector; |
| }; |
| const toType = (object) => { |
| if (object === null || object === void 0) return `${object}`; |
| return Object.prototype.toString.call(object).match(/\s([a-z]+)/i)[1].toLowerCase(); |
| }; |
| /** |
| * Public Util API |
| */ |
| const getUID = (prefix) => { |
| do |
| prefix += Math.floor(Math.random() * MAX_UID); |
| while (document.getElementById(prefix)); |
| return prefix; |
| }; |
| const getTransitionDurationFromElement = (element) => { |
| if (!element) return 0; |
| let { transitionDuration, transitionDelay } = window.getComputedStyle(element); |
| if (!Number.parseFloat(transitionDuration) && !Number.parseFloat(transitionDelay)) return 0; |
| transitionDuration = transitionDuration.split(",")[0]; |
| transitionDelay = transitionDelay.split(",")[0]; |
| return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER; |
| }; |
| const triggerTransitionEnd = (element) => { |
| element.dispatchEvent(new Event(TRANSITION_END)); |
| }; |
| const isElement$1 = (object) => { |
| if (!object || typeof object !== "object") return false; |
| return typeof object.nodeType !== "undefined"; |
| }; |
| const getElement = (object) => { |
| if (isElement$1(object)) return object; |
| if (typeof object === "string" && object.length > 0) return document.querySelector(parseSelector(object)); |
| return null; |
| }; |
| const isVisible = (element) => { |
| if (!isElement$1(element) || element.getClientRects().length === 0) return false; |
| const elementIsVisible = getComputedStyle(element).getPropertyValue("visibility") === "visible"; |
| const closedDetails = element.closest("details:not([open])"); |
| if (!closedDetails) return elementIsVisible; |
| if (closedDetails !== element) { |
| const summary = element.closest("summary"); |
| if (summary && summary.parentNode !== closedDetails) return false; |
| if (summary === null) return false; |
| } |
| return elementIsVisible; |
| }; |
| const isDisabled = (element) => { |
| if (!element || element.nodeType !== Node.ELEMENT_NODE) return true; |
| if (element.classList.contains("disabled")) return true; |
| const disableableElement = element; |
| if (typeof disableableElement.disabled !== "undefined") return disableableElement.disabled; |
| return element.hasAttribute("disabled") && element.getAttribute("disabled") !== "false"; |
| }; |
| const setAriaAttribute = (element, name, value) => { |
| element.setAttribute(name, String(value)); |
| }; |
| const findShadowRoot = (element) => { |
| if (!document.documentElement.attachShadow) return null; |
| if (typeof element.getRootNode === "function") { |
| const root = element.getRootNode(); |
| return root instanceof ShadowRoot ? root : null; |
| } |
| if (element instanceof ShadowRoot) return element; |
| if (!element.parentNode) return null; |
| return findShadowRoot(element.parentNode); |
| }; |
| const noop = () => {}; |
| const isRTL$1 = () => document.documentElement.dir === "rtl"; |
| const execute = (possibleCallback, args = [], defaultValue = possibleCallback) => { |
| return typeof possibleCallback === "function" ? possibleCallback.call(...args) : defaultValue; |
| }; |
| const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => { |
| if (!waitForTransition) { |
| execute(callback); |
| return; |
| } |
| const emulatedDuration = getTransitionDurationFromElement(transitionElement) + 5; |
| let called = false; |
| const handler = ({ target }) => { |
| if (target !== transitionElement) return; |
| called = true; |
| transitionElement.removeEventListener(TRANSITION_END, handler); |
| execute(callback); |
| }; |
| transitionElement.addEventListener(TRANSITION_END, handler); |
| setTimeout(() => { |
| if (!called) triggerTransitionEnd(transitionElement); |
| }, emulatedDuration); |
| }; |
| /** |
| * Return the previous/next element of a list. |
| * |
| * @param list The list of elements |
| * @param activeElement The active element |
| * @param shouldGetNext Choose to get next or previous element |
| * @param isCycleAllowed |
| * @return The proper element |
| */ |
| const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => { |
| const listLength = list.length; |
| let index = list.indexOf(activeElement); |
| if (index === -1) return !shouldGetNext && isCycleAllowed ? list[listLength - 1] : list[0]; |
| index += shouldGetNext ? 1 : -1; |
| if (isCycleAllowed) index = (index + listLength) % listLength; |
| return list[Math.max(0, Math.min(index, listLength - 1))]; |
| }; |
| //#endregion |
| //#region js/src/util/config.ts |
| /** |
| * -------------------------------------------------------------------------- |
| * Bootstrap util/config.ts |
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
| * -------------------------------------------------------------------------- |
| */ |
| /** |
| * Class definition |
| */ |
| var Config = class { |
| static get Default() { |
| return {}; |
| } |
| static get DefaultType() { |
| return {}; |
| } |
| static get NAME() { |
| throw new Error("You have to implement the static method \"NAME\", for each component!"); |
| } |
| _getConfig(config) { |
| config = this._mergeConfigObj(config); |
| config = this._configAfterMerge(config); |
| this._typeCheckConfig(config); |
| return config; |
| } |
| _configAfterMerge(config) { |
| return config; |
| } |
| _mergeConfigObj(config, element) { |
| const jsonConfig = isElement$1(element) ? Manipulator.getDataAttribute(element, "config") : {}; |
| return { |
| ...this.constructor.Default, |
| ...typeof jsonConfig === "object" ? jsonConfig : {}, |
| ...isElement$1(element) ? Manipulator.getDataAttributes(element) : {}, |
| ...typeof config === "object" ? config : {} |
| }; |
| } |
| _typeCheckConfig(config, configTypes = this.constructor.DefaultType) { |
| for (const [property, expectedTypes] of Object.entries(configTypes)) { |
| const value = config[property]; |
| const valueType = isElement$1(value) ? "element" : toType(value); |
| if (!new RegExp(expectedTypes).test(valueType)) throw new TypeError(`${this.constructor.NAME.toUpperCase()}: Option "${property}" provided type "${valueType}" but expected type "${expectedTypes}".`); |
| } |
| } |
| }; |
| //#endregion |
| //#region js/src/base-component.ts |
| /** |
| * -------------------------------------------------------------------------- |
| * Bootstrap base-component.ts |
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
| * -------------------------------------------------------------------------- |
| */ |
| /** |
| * Constants |
| */ |
| const VERSION = "6.0.0-alpha1"; |
| /** |
| * Class definition |
| */ |
| var BaseComponent = class extends Config { |
| constructor(element, config) { |
| super(); |
| element = getElement(element); |
| if (!element) return; |
| this._element = element; |
| this._config = this._getConfig(config); |
| const existingInstance = data_default.get(this._element, this.constructor.DATA_KEY); |
| if (existingInstance) existingInstance.dispose(); |
| data_default.set(this._element, this.constructor.DATA_KEY, this); |
| } |
| dispose() { |
| data_default.remove(this._element, this.constructor.DATA_KEY); |
| EventHandler.off(this._element, this.constructor.EVENT_KEY); |
| for (const propertyName of Object.getOwnPropertyNames(this)) this[propertyName] = null; |
| } |
| _queueCallback(callback, element, isAnimated = true) { |
| return new Promise((resolve) => { |
| executeAfterTransition(() => { |
| if (this._element) callback(); |
| resolve(); |
| }, element, isAnimated); |
| }); |
| } |
| _getConfig(config) { |
| config = this._mergeConfigObj(config, this._element); |
| config = this._configAfterMerge(config); |
| this._typeCheckConfig(config); |
| return config; |
| } |
| static getInstance(element) { |
| return data_default.get(getElement(element), this.DATA_KEY); |
| } |
| static getOrCreateInstance(element, config = {}) { |
| return this.getInstance(element) || new this(element, typeof config === "object" ? config : null); |
| } |
| static get VERSION() { |
| return VERSION; |
| } |
| static get DATA_KEY() { |
| return `bs.${this.NAME}`; |
| } |
| static get EVENT_KEY() { |
| return `.${this.DATA_KEY}`; |
| } |
| static eventName(name) { |
| return `${name}${this.EVENT_KEY}`; |
| } |
| }; |
| //#endregion |
| //#region js/src/dom/selector-engine.ts |
| /** |
| * -------------------------------------------------------------------------- |
| * Bootstrap dom/selector-engine.ts |
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
| * -------------------------------------------------------------------------- |
| */ |
| const getSelector = (element) => { |
| let selector = element.getAttribute("data-bs-target"); |
| if (!selector || selector === "#") { |
| let hrefAttribute = element.getAttribute("href"); |
| if (!hrefAttribute || !hrefAttribute.includes("#") && !hrefAttribute.startsWith(".")) return null; |
| if (hrefAttribute.includes("#") && !hrefAttribute.startsWith("#")) hrefAttribute = `#${hrefAttribute.split("#")[1]}`; |
| selector = hrefAttribute && hrefAttribute !== "#" ? hrefAttribute.trim() : null; |
| } |
| return selector ? selector.split(",").map((sel) => parseSelector(sel)).join(",") : null; |
| }; |
| const SelectorEngine = { |
| find(selector, element = document.documentElement) { |
| return [...Element.prototype.querySelectorAll.call(element, selector)]; |
| }, |
| findOne(selector, element = document.documentElement) { |
| return Element.prototype.querySelector.call(element, selector); |
| }, |
| parents(element, selector) { |
| const parents = []; |
| let ancestor = element.parentNode.closest(selector); |
| while (ancestor) { |
| parents.push(ancestor); |
| ancestor = ancestor.parentNode.closest(selector); |
| } |
| return parents; |
| }, |
| closest(element, selector) { |
| return Element.prototype.closest.call(element, selector); |
| }, |
| prev(element, selector) { |
| let previous = element.previousElementSibling; |
| while (previous) { |
| if (previous.matches(selector)) return [previous]; |
| previous = previous.previousElementSibling; |
| } |
| return []; |
| }, |
| next(element, selector) { |
| let next = element.nextElementSibling; |
| while (next) { |
| if (next.matches(selector)) return [next]; |
| next = next.nextElementSibling; |
| } |
| return []; |
| }, |
| getSelectorFromElement(element) { |
| const selector = getSelector(element); |
| if (selector) return SelectorEngine.findOne(selector) ? selector : null; |
| return null; |
| }, |
| getElementFromSelector(element) { |
| const selector = getSelector(element); |
| return selector ? SelectorEngine.findOne(selector) : null; |
| }, |
| getMultipleElementsFromSelector(element) { |
| const selector = getSelector(element); |
| return selector ? SelectorEngine.find(selector) : []; |
| } |
| }; |
| //#endregion |
| //#region js/src/util/component-functions.ts |
| const enableDismissTrigger = (component, method = "hide") => { |
| const clickEvent = `click.dismiss${component.EVENT_KEY}`; |
| const name = component.NAME; |
| EventHandler.on(document, clickEvent, `[data-bs-dismiss="${name}"]`, function(event) { |
| if (["A", "AREA"].includes(this.tagName)) event.preventDefault(); |
| if (isDisabled(this)) return; |
| const target = SelectorEngine.getElementFromSelector(this) || this.closest(`.${name}, [class*=":${name}"]`); |
| component.getOrCreateInstance(target)[method](); |
| }); |
| }; |
| const eventActionOnPlugin = (Plugin, onEvent, stringSelector, method, callback = null) => { |
| eventAction(`${onEvent}.${Plugin.NAME}`, stringSelector, (data) => { |
| const instances = data.targets.filter(Boolean).map((element) => Plugin.getOrCreateInstance(element)); |
| if (typeof callback === "function") callback({ |
| ...data, |
| instances |
| }); |
| for (const instance of instances) instance[method](); |
| }); |
| }; |
| const eventAction = (onEvent, stringSelector, callback) => { |
| const selector = `${stringSelector}:not(.disabled):not(:disabled)`; |
| EventHandler.on(document, onEvent, selector, function(event) { |
| if (["A", "AREA"].includes(this.tagName)) event.preventDefault(); |
| const selector = SelectorEngine.getSelectorFromElement(this); |
| callback({ |
| targets: selector ? SelectorEngine.find(selector) : [this], |
| event |
| }); |
| }); |
| }; |
| //#endregion |
| //#region js/src/alert.ts |
| /** |
| * -------------------------------------------------------------------------- |
| * Bootstrap alert.ts |
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
| * -------------------------------------------------------------------------- |
| */ |
| /** |
| * Constants |
| */ |
| const NAME$21 = "alert"; |
| const EVENT_KEY$18 = `.bs.alert`; |
| const EVENT_CLOSE = `close${EVENT_KEY$18}`; |
| const EVENT_CLOSED = `closed${EVENT_KEY$18}`; |
| const CLASS_NAME_HIDING = "hiding"; |
| const CLASS_NAME_SHOW$6 = "show"; |
| /** |
| * Class definition |
| */ |
| var Alert = class extends BaseComponent { |
| static get NAME() { |
| return NAME$21; |
| } |
| async close() { |
| if (EventHandler.trigger(this._element, EVENT_CLOSE).defaultPrevented) return; |
| this._element.classList.remove(CLASS_NAME_SHOW$6); |
| this._element.classList.add(CLASS_NAME_HIDING); |
| const isAnimated = getTransitionDurationFromElement(this._element) > 0; |
| await this._queueCallback(() => this._destroyElement(), this._element, isAnimated); |
| } |
| _destroyElement() { |
| this._element.remove(); |
| EventHandler.trigger(this._element, EVENT_CLOSED); |
| this.dispose(); |
| } |
| }; |
| /** |
| * Data API implementation |
| */ |
| enableDismissTrigger(Alert, "close"); |
| //#endregion |
| //#region js/src/button.ts |
| /** |
| * -------------------------------------------------------------------------- |
| * Bootstrap button.ts |
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
| * -------------------------------------------------------------------------- |
| */ |
| /** |
| * Constants |
| */ |
| const NAME$20 = "button"; |
| const EVENT_KEY$17 = `.bs.button`; |
| const DATA_API_KEY$12 = ".data-api"; |
| const CLASS_NAME_ACTIVE$4 = "active"; |
| const SELECTOR_DATA_TOGGLE$10 = "[data-bs-toggle=\"button\"]"; |
| const EVENT_CLICK_DATA_API$8 = `click${EVENT_KEY$17}${DATA_API_KEY$12}`; |
| const EVENT_DOM_CONTENT_LOADED$1 = `DOMContentLoaded${EVENT_KEY$17}${DATA_API_KEY$12}`; |
| /** |
| * Class definition |
| */ |
| var Button = class extends BaseComponent { |
| static get NAME() { |
| return NAME$20; |
| } |
| toggle() { |
| setAriaAttribute(this._element, "aria-pressed", this._element.classList.toggle(CLASS_NAME_ACTIVE$4)); |
| } |
| }; |
| /** |
| * Data API implementation |
| */ |
| EventHandler.on(document, EVENT_CLICK_DATA_API$8, SELECTOR_DATA_TOGGLE$10, (event) => { |
| event.preventDefault(); |
| const button = event.target.closest(SELECTOR_DATA_TOGGLE$10); |
| Button.getOrCreateInstance(button).toggle(); |
| }); |
| EventHandler.on(document, EVENT_DOM_CONTENT_LOADED$1, () => { |
| for (const element of SelectorEngine.find(SELECTOR_DATA_TOGGLE$10)) if (!element.hasAttribute("aria-pressed")) setAriaAttribute(element, "aria-pressed", element.classList.contains(CLASS_NAME_ACTIVE$4)); |
| }); |
| //#endregion |
| //#region js/src/carousel.ts |
| /** |
| * -------------------------------------------------------------------------- |
| * Bootstrap carousel.ts |
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
| * -------------------------------------------------------------------------- |
| */ |
| /** |
| * Constants |
| */ |
| const NAME$19 = "carousel"; |
| const EVENT_KEY$16 = `.bs.carousel`; |
| const DATA_API_KEY$11 = ".data-api"; |
| const ARROW_LEFT_KEY$2 = "ArrowLeft"; |
| const ARROW_RIGHT_KEY$2 = "ArrowRight"; |
| const DIRECTION_LEFT = "left"; |
| const DIRECTION_RIGHT = "right"; |
| const EVENT_SLIDE = `slide${EVENT_KEY$16}`; |
| const EVENT_SLID = `slid${EVENT_KEY$16}`; |
| const EVENT_KEYDOWN$2 = `keydown${EVENT_KEY$16}`; |
| const EVENT_MOUSEENTER$2 = `mouseenter${EVENT_KEY$16}`; |
| const EVENT_MOUSELEAVE$1 = `mouseleave${EVENT_KEY$16}`; |
| const EVENT_POINTERDOWN$1 = `pointerdown${EVENT_KEY$16}`; |
| const EVENT_LOAD_DATA_API$3 = `load${EVENT_KEY$16}${DATA_API_KEY$11}`; |
| const EVENT_CLICK_DATA_API$7 = `click${EVENT_KEY$16}${DATA_API_KEY$11}`; |
| const CLASS_NAME_CAROUSEL = "carousel"; |
| const CLASS_NAME_ACTIVE$3 = "active"; |
| const CLASS_NAME_FADE = "carousel-fade"; |
| const CLASS_NAME_CENTER = "carousel-center"; |
| const CLASS_NAME_AUTO = "carousel-auto"; |
| const CLASS_NAME_CLONE = "carousel-item-clone"; |
| const CLASS_NAME_PAUSED = "paused"; |
| const CLASS_NAME_PLAYING = "carousel-playing"; |
| const PROPERTY_INTERVAL = "--bs-carousel-interval"; |
| const SCROLL_DURATION = 300; |
| const ACTIVE_RATIO_TOLERANCE = .05; |
| const SELECTOR_ACTIVE = ".active"; |
| const SELECTOR_ITEM = `.carousel-item:not(.${CLASS_NAME_CLONE})`; |
| const SELECTOR_ACTIVE_ITEM = SELECTOR_ACTIVE + SELECTOR_ITEM; |
| const SELECTOR_INNER$1 = ".carousel-inner"; |
| const SELECTOR_INDICATORS = ".carousel-indicators"; |
| const SELECTOR_PLAY_PAUSE = ".carousel-control-play-pause"; |
| const SELECTOR_DATA_SLIDE = "[data-bs-slide], [data-bs-slide-to]"; |
| const SELECTOR_DATA_SLIDE_PREV = "[data-bs-slide=\"prev\"]"; |
| const SELECTOR_DATA_SLIDE_NEXT = "[data-bs-slide=\"next\"]"; |
| const SELECTOR_DATA_AUTOPLAY = "[data-bs-autoplay=\"true\"]"; |
| const KEY_TO_DIRECTION = { |
| [ARROW_LEFT_KEY$2]: DIRECTION_RIGHT, |
| [ARROW_RIGHT_KEY$2]: DIRECTION_LEFT |
| }; |
| const ENDS_STOP = "stop"; |
| const ENDS_WRAP = "wrap"; |
| const ENDS_LOOP = "loop"; |
| const Default$18 = { |
| autoplay: false, |
| ends: ENDS_LOOP, |
| interval: 5e3, |
| keyboard: true, |
| pause: "hover" |
| }; |
| const DefaultType$18 = { |
| autoplay: "boolean", |
| ends: "string", |
| interval: "number", |
| keyboard: "boolean", |
| pause: "(string|boolean)" |
| }; |
| const easeInOutCubic = (progress) => progress < .5 ? 4 * progress * progress * progress : 1 - (-2 * progress + 2) ** 3 / 2; |
| /** |
| * Class definition |
| */ |
| var Carousel = class extends BaseComponent { |
| constructor(element, config) { |
| super(element, config); |
| this._viewport = SelectorEngine.findOne(SELECTOR_INNER$1, this._element) || this._element; |
| this._indicatorsElement = SelectorEngine.findOne(SELECTOR_INDICATORS, this._element); |
| this._playPauseElement = SelectorEngine.findOne(SELECTOR_PLAY_PAUSE, this._element); |
| this._prevControls = SelectorEngine.find(SELECTOR_DATA_SLIDE_PREV, this._element); |
| this._nextControls = SelectorEngine.find(SELECTOR_DATA_SLIDE_NEXT, this._element); |
| this._interval = null; |
| this._observer = null; |
| this._scrollFrame = null; |
| this._looping = false; |
| this._visibility = /* @__PURE__ */ new Map(); |
| this._playing = this._config.autoplay; |
| this._activeIndex = this._initialActiveIndex(); |
| this._addEventListeners(); |
| this._observeItems(); |
| this._refreshActiveState(); |
| if (this._playing) this.cycle(); |
| this._updatePlayPauseControl(); |
| } |
| static get Default() { |
| return Default$18; |
| } |
| static get DefaultType() { |
| return DefaultType$18; |
| } |
| static get NAME() { |
| return NAME$19; |
| } |
| next() { |
| this.to(this._navIndex() + 1); |
| } |
| nextWhenVisible() { |
| if (document.visibilityState === "visible" && isVisible(this._element)) this.next(); |
| } |
| prev() { |
| this.to(this._navIndex() - 1); |
| } |
| pause() { |
| this._clearInterval(); |
| this._element.classList.remove(CLASS_NAME_PLAYING); |
| } |
| cycle() { |
| this._clearInterval(); |
| this._scheduleAutoplay(); |
| this._element.classList.add(CLASS_NAME_PLAYING); |
| } |
| to(index) { |
| if (this._looping) return; |
| const items = this._getItems(); |
| const rawIndex = Number.parseInt(index, 10); |
| if (this._config.ends === ENDS_LOOP && !this._prefersReducedMotion() && this._canLoop()) { |
| if (rawIndex > items.length - 1) { |
| this._loopTransition(true); |
| return; |
| } |
| if (rawIndex < 0) { |
| this._loopTransition(false); |
| return; |
| } |
| } |
| const targetIndex = this._normalizeIndex(rawIndex, items.length); |
| const currentIndex = this._navIndex(); |
| if (targetIndex === null || targetIndex === currentIndex) return; |
| if (EventHandler.trigger(this._element, EVENT_SLIDE, { |
| relatedTarget: items[targetIndex], |
| direction: this._direction(currentIndex, targetIndex), |
| from: currentIndex, |
| to: targetIndex |
| }).defaultPrevented) return; |
| if (this._isFade()) { |
| this._fadeTo(targetIndex); |
| return; |
| } |
| this._scrollToIndex(targetIndex); |
| } |
| dispose() { |
| this._clearInterval(); |
| if (this._observer) this._observer.disconnect(); |
| if (this._scrollFrame !== null) cancelAnimationFrame(this._scrollFrame); |
| for (const clone of SelectorEngine.find(`.${CLASS_NAME_CLONE}`, this._viewport)) clone.remove(); |
| this._viewport.style.scrollSnapType = ""; |
| EventHandler.off(this._viewport, EVENT_KEY$16); |
| super.dispose(); |
| } |
| _configAfterMerge(config) { |
| if (![ |
| ENDS_STOP, |
| ENDS_WRAP, |
| ENDS_LOOP |
| ].includes(config.ends)) config.ends = Default$18.ends; |
| return config; |
| } |
| _initialActiveIndex() { |
| const active = SelectorEngine.findOne(SELECTOR_ACTIVE_ITEM, this._element); |
| const index = active ? this._getItems().indexOf(active) : 0; |
| return Math.max(index, 0); |
| } |
| _addEventListeners() { |
| if (this._config.keyboard) EventHandler.on(this._element, EVENT_KEYDOWN$2, (event) => this._keydown(event)); |
| if (this._config.pause === "hover") { |
| EventHandler.on(this._element, EVENT_MOUSEENTER$2, () => this.pause()); |
| EventHandler.on(this._element, EVENT_MOUSELEAVE$1, () => this._maybeEnableCycle()); |
| } |
| EventHandler.on(this._viewport, EVENT_POINTERDOWN$1, () => this._pauseFromInteraction()); |
| } |
| _keydown(event) { |
| if (/input|textarea/i.test(event.target.tagName)) return; |
| const direction = KEY_TO_DIRECTION[event.key]; |
| if (direction) { |
| event.preventDefault(); |
| this._pauseFromInteraction(); |
| if (direction === DIRECTION_RIGHT) this.prev(); |
| else this.next(); |
| } |
| } |
| _observeItems() { |
| if (this._isFade() || typeof IntersectionObserver === "undefined") return; |
| this._observer = new IntersectionObserver((entries) => this._handleIntersection(entries), { |
| root: this._viewport, |
| threshold: [ |
| 0, |
| .25, |
| .5, |
| .75, |
| 1 |
| ] |
| }); |
| for (const item of this._getItems()) this._observer.observe(item); |
| } |
| _handleIntersection(entries) { |
| if (this._looping) return; |
| for (const entry of entries) this._visibility.set(entry.target, entry.isIntersecting ? entry.intersectionRatio : 0); |
| const ratios = this._getItems().map((item) => this._visibility.get(item) ?? 0); |
| const maxRatio = Math.max(...ratios); |
| let bestIndex = this._activeIndex; |
| if (maxRatio > 0) bestIndex = ratios.findIndex((ratio) => ratio >= maxRatio - ACTIVE_RATIO_TOLERANCE); |
| this._setActive(bestIndex); |
| this._updateEndControls(); |
| } |
| _navIndex() { |
| if (this._isFade() || this._viewport.scrollWidth - this._viewport.clientWidth <= 0) return this._activeIndex; |
| let index = this._activeIndex; |
| let smallestDelta = Number.POSITIVE_INFINITY; |
| for (const [itemIndex, item] of this._getItems().entries()) { |
| const delta = Math.abs(this._scrollDelta(item)); |
| if (delta < smallestDelta) { |
| smallestDelta = delta; |
| index = itemIndex; |
| } |
| } |
| return index; |
| } |
| _scrollToIndex(index) { |
| const item = this._getItems()[index]; |
| if (!item) return; |
| const left = this._scrollDelta(item); |
| if (Math.abs(left) < 1) return; |
| const targetLeft = this._viewport.scrollLeft + left; |
| this._viewport.style.scrollSnapType = "none"; |
| this._animateScroll(targetLeft, () => { |
| this._viewport.style.scrollSnapType = ""; |
| if (!this._observer) this._setActive(index); |
| this._updateEndControls(); |
| }); |
| } |
| _animateScroll(targetLeft, onComplete) { |
| if (this._scrollFrame !== null) { |
| cancelAnimationFrame(this._scrollFrame); |
| this._scrollFrame = null; |
| } |
| const startLeft = this._viewport.scrollLeft; |
| const distance = targetLeft - startLeft; |
| if (this._prefersReducedMotion() || typeof requestAnimationFrame === "undefined") { |
| this._viewport.scrollTo({ |
| left: targetLeft, |
| behavior: "instant" |
| }); |
| onComplete(); |
| return; |
| } |
| let startTime = null; |
| const step = (now) => { |
| if (startTime === null) startTime = now; |
| const progress = Math.min((now - startTime) / SCROLL_DURATION, 1); |
| this._viewport.scrollTo({ |
| left: startLeft + distance * easeInOutCubic(progress), |
| behavior: "instant" |
| }); |
| if (progress < 1) { |
| this._scrollFrame = requestAnimationFrame(step); |
| return; |
| } |
| this._viewport.scrollTo({ |
| left: targetLeft, |
| behavior: "instant" |
| }); |
| this._scrollFrame = null; |
| onComplete(); |
| }; |
| this._scrollFrame = requestAnimationFrame(step); |
| } |
| _scrollDelta(element) { |
| const viewportRect = this._viewport.getBoundingClientRect(); |
| const rect = element.getBoundingClientRect(); |
| if (this._element.classList.contains(CLASS_NAME_CENTER)) return rect.left + rect.width / 2 - (viewportRect.left + viewportRect.width / 2); |
| const padStart = Number.parseFloat(getComputedStyle(this._viewport).scrollPaddingInlineStart) || 0; |
| return isRTL$1() ? rect.right - (viewportRect.right - padStart) : rect.left - (viewportRect.left + padStart); |
| } |
| _loopTransition(isNext) { |
| const items = this._getItems(); |
| const last = items.length - 1; |
| const fromIndex = this._activeIndex; |
| const toIndex = isNext ? 0 : last; |
| const direction = this._loopDirection(isNext); |
| if (EventHandler.trigger(this._element, EVENT_SLIDE, { |
| relatedTarget: items[toIndex], |
| direction, |
| from: fromIndex, |
| to: toIndex |
| }).defaultPrevented) return; |
| this._looping = true; |
| const clone = (isNext ? items[0] : items[last]).cloneNode(true); |
| clone.classList.add(CLASS_NAME_CLONE); |
| clone.classList.remove(CLASS_NAME_ACTIVE$3); |
| clone.removeAttribute("id"); |
| for (const node of SelectorEngine.find("[id]", clone)) node.removeAttribute("id"); |
| clone.setAttribute("aria-hidden", "true"); |
| clone.inert = true; |
| this._viewport.style.scrollSnapType = "none"; |
| if (isNext) this._viewport.append(clone); |
| else { |
| this._viewport.prepend(clone); |
| this._jumpScroll(this._scrollDelta(items[fromIndex])); |
| } |
| this._animateScroll(this._viewport.scrollLeft + this._scrollDelta(clone), () => { |
| clone.remove(); |
| this._jumpScroll(this._scrollDelta(items[toIndex])); |
| this._activeIndex = toIndex; |
| this._refreshActiveState(); |
| EventHandler.trigger(this._element, EVENT_SLID, { |
| relatedTarget: items[toIndex], |
| direction, |
| from: fromIndex, |
| to: toIndex |
| }); |
| this._viewport.style.scrollSnapType = ""; |
| this._looping = false; |
| }); |
| } |
| _loopDirection(isNext) { |
| if (isRTL$1()) return isNext ? DIRECTION_RIGHT : DIRECTION_LEFT; |
| return isNext ? DIRECTION_LEFT : DIRECTION_RIGHT; |
| } |
| _jumpScroll(delta) { |
| this._viewport.style.scrollSnapType = "none"; |
| this._viewport.scrollBy({ |
| left: delta, |
| top: 0, |
| behavior: "instant" |
| }); |
| } |
| _fadeTo(index) { |
| this._setActive(index); |
| } |
| _setActive(index) { |
| const items = this._getItems(); |
| if (index === this._activeIndex || !items[index]) return; |
| const from = this._activeIndex; |
| this._activeIndex = index; |
| this._refreshActiveState(); |
| EventHandler.trigger(this._element, EVENT_SLID, { |
| relatedTarget: items[index], |
| direction: this._direction(from, index), |
| from, |
| to: index |
| }); |
| } |
| _refreshActiveState() { |
| const items = this._getItems(); |
| for (const [index, item] of items.entries()) item.classList.toggle(CLASS_NAME_ACTIVE$3, index === this._activeIndex); |
| this._setActiveIndicatorElement(this._activeIndex); |
| this._updateEndControls(); |
| } |
| _updateEndControls() { |
| if (this._config.ends !== ENDS_STOP) return; |
| const viewport = this._viewport; |
| const maxScroll = viewport.scrollWidth - viewport.clientWidth; |
| let atStart; |
| let atEnd; |
| if (maxScroll > 0) { |
| const progress = Math.abs(viewport.scrollLeft); |
| atStart = progress <= 1; |
| atEnd = progress >= maxScroll - 1; |
| } else { |
| const last = this._getItems().length - 1; |
| atStart = this._activeIndex <= 0; |
| atEnd = this._activeIndex >= last; |
| } |
| this._setControlsDisabled(this._prevControls, atStart); |
| this._setControlsDisabled(this._nextControls, atEnd); |
| } |
| _setControlsDisabled(controls, disabled) { |
| for (const control of controls) { |
| if (disabled && control === document.activeElement) ((controls === this._prevControls ? this._nextControls : this._prevControls)[0] ?? this._viewport).focus({ preventScroll: true }); |
| control.disabled = disabled; |
| } |
| } |
| _setActiveIndicatorElement(index) { |
| if (!this._indicatorsElement) return; |
| const active = SelectorEngine.findOne(SELECTOR_ACTIVE, this._indicatorsElement); |
| if (active) { |
| active.classList.remove(CLASS_NAME_ACTIVE$3); |
| active.removeAttribute("aria-current"); |
| } |
| const newActive = SelectorEngine.findOne(`[data-bs-slide-to="${index}"]`, this._indicatorsElement); |
| if (newActive) { |
| newActive.classList.add(CLASS_NAME_ACTIVE$3); |
| newActive.setAttribute("aria-current", "true"); |
| } |
| } |
| _normalizeIndex(index, length) { |
| if (Number.isNaN(index) || length === 0) return null; |
| if (index < 0) return this._wrapsAround() ? length - 1 : null; |
| if (index > length - 1) return this._wrapsAround() ? 0 : null; |
| return index; |
| } |
| _wrapsAround() { |
| return this._config.ends === ENDS_WRAP || this._config.ends === ENDS_LOOP; |
| } |
| _canLoop() { |
| if (this._isFade() || this._getItems().length < 2) return false; |
| const styles = getComputedStyle(this._element); |
| const num = (name) => Number.parseFloat(styles.getPropertyValue(name)) || 0; |
| return (num("--bs-carousel-items") || 1) === 1 && num("--bs-carousel-items-peek") === 0 && !this._element.classList.contains(CLASS_NAME_CENTER) && !this._element.classList.contains(CLASS_NAME_AUTO); |
| } |
| _direction(from, to) { |
| const isNext = to > from; |
| if (isRTL$1()) return isNext ? DIRECTION_RIGHT : DIRECTION_LEFT; |
| return isNext ? DIRECTION_LEFT : DIRECTION_RIGHT; |
| } |
| _scheduleAutoplay(index = this._activeIndex) { |
| const interval = this._itemInterval(index); |
| this._element.style.setProperty(PROPERTY_INTERVAL, `${interval}ms`); |
| this._interval = setTimeout(() => { |
| const upcoming = this._upcomingIndex(); |
| this.nextWhenVisible(); |
| if (upcoming === null) { |
| this.pause(); |
| return; |
| } |
| this._scheduleAutoplay(upcoming); |
| }, interval); |
| } |
| _upcomingIndex() { |
| return this._normalizeIndex(this._navIndex() + 1, this._getItems().length); |
| } |
| _itemInterval(index = this._activeIndex) { |
| const item = this._getItems()[index]; |
| const interval = item ? Number.parseInt(item.getAttribute("data-bs-interval"), 10) : NaN; |
| return Number.isNaN(interval) ? this._config.interval : interval; |
| } |
| _maybeEnableCycle() { |
| if (!this._playing) return; |
| this.cycle(); |
| } |
| _pauseFromInteraction() { |
| this._playing = false; |
| this.pause(); |
| this._updatePlayPauseControl(); |
| } |
| _togglePlayPause() { |
| if (this._playing) { |
| this._pauseFromInteraction(); |
| return; |
| } |
| this._playing = true; |
| this.cycle(); |
| this._updatePlayPauseControl(); |
| } |
| _updatePlayPauseControl() { |
| if (!this._playPauseElement) return; |
| this._playPauseElement.classList.toggle(CLASS_NAME_PAUSED, !this._playing); |
| const label = this._playPauseElement.getAttribute(this._playing ? "data-bs-pause-label" : "data-bs-play-label"); |
| if (label) this._playPauseElement.setAttribute("aria-label", label); |
| } |
| _isFade() { |
| return this._element.classList.contains(CLASS_NAME_FADE); |
| } |
| _prefersReducedMotion() { |
| return typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches; |
| } |
| _getItems() { |
| return SelectorEngine.find(SELECTOR_ITEM, this._element); |
| } |
| _clearInterval() { |
| if (this._interval) { |
| clearTimeout(this._interval); |
| this._interval = null; |
| } |
| } |
| }; |
| /** |
| * Data API implementation |
| */ |
| EventHandler.on(document, EVENT_CLICK_DATA_API$7, SELECTOR_DATA_SLIDE, function(event) { |
| const target = SelectorEngine.getElementFromSelector(this); |
| if (!target || !target.classList.contains(CLASS_NAME_CAROUSEL)) return; |
| event.preventDefault(); |
| const carousel = Carousel.getOrCreateInstance(target); |
| carousel._pauseFromInteraction(); |
| const slideIndex = this.getAttribute("data-bs-slide-to"); |
| if (slideIndex) { |
| carousel.to(slideIndex); |
| return; |
| } |
| if (Manipulator.getDataAttribute(this, "slide") === "next") { |
| carousel.next(); |
| return; |
| } |
| carousel.prev(); |
| }); |
| EventHandler.on(document, EVENT_CLICK_DATA_API$7, SELECTOR_PLAY_PAUSE, function(event) { |
| const target = SelectorEngine.getElementFromSelector(this); |
| if (!target || !target.classList.contains(CLASS_NAME_CAROUSEL)) return; |
| event.preventDefault(); |
| Carousel.getOrCreateInstance(target)._togglePlayPause(); |
| }); |
| EventHandler.on(window, EVENT_LOAD_DATA_API$3, () => { |
| const carousels = SelectorEngine.find(SELECTOR_DATA_AUTOPLAY); |
| for (const carousel of carousels) Carousel.getOrCreateInstance(carousel); |
| }); |
| //#endregion |
| //#region js/src/collapse.ts |
| /** |
| * -------------------------------------------------------------------------- |
| * Bootstrap collapse.ts |
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
| * -------------------------------------------------------------------------- |
| */ |
| /** |
| * Constants |
| */ |
| const NAME$18 = "collapse"; |
| const EVENT_KEY$15 = `.bs.collapse`; |
| const DATA_API_KEY$10 = ".data-api"; |
| const EVENT_SHOW$7 = `show${EVENT_KEY$15}`; |
| const EVENT_SHOWN$6 = `shown${EVENT_KEY$15}`; |
| const EVENT_HIDE$6 = `hide${EVENT_KEY$15}`; |
| const EVENT_HIDDEN$8 = `hidden${EVENT_KEY$15}`; |
| const EVENT_CLICK_DATA_API$6 = `click${EVENT_KEY$15}${DATA_API_KEY$10}`; |
| const CLASS_NAME_SHOW$5 = "show"; |
| const CLASS_NAME_COLLAPSE = "collapse"; |
| const CLASS_NAME_DEEPER_CHILDREN = `:scope .${CLASS_NAME_COLLAPSE} .${CLASS_NAME_COLLAPSE}`; |
| const SELECTOR_ACTIVES = ".collapse.show"; |
| const SELECTOR_DATA_TOGGLE$9 = "[data-bs-toggle=\"collapse\"]"; |
| const Default$17 = { parent: null }; |
| const DefaultType$17 = { parent: "(null|element)" }; |
| /** |
| * Class definition |
| */ |
| var Collapse = class Collapse extends BaseComponent { |
| constructor(element, config) { |
| super(element, config); |
| this._isTransitioning = false; |
| this._triggerArray = []; |
| const toggleList = SelectorEngine.find(SELECTOR_DATA_TOGGLE$9); |
| for (const elem of toggleList) { |
| const selector = SelectorEngine.getSelectorFromElement(elem); |
| const filterElement = SelectorEngine.find(selector).filter((foundElement) => foundElement === this._element); |
| if (selector !== null && filterElement.length) this._triggerArray.push(elem); |
| } |
| this._initializeChildren(); |
| if (!this._config.parent) this._setAriaExpanded(this._triggerArray, this._isShown()); |
| } |
| static get Default() { |
| return Default$17; |
| } |
| static get DefaultType() { |
| return DefaultType$17; |
| } |
| static get NAME() { |
| return NAME$18; |
| } |
| toggle() { |
| return this._isShown() ? this.hide() : this.show(); |
| } |
| async show() { |
| if (this._isTransitioning || this._isShown()) return; |
| let activeChildren = []; |
| if (this._config.parent) activeChildren = this._getFirstLevelChildren(SELECTOR_ACTIVES).filter((element) => element !== this._element && !this._sharesTrigger(element)).map((element) => Collapse.getOrCreateInstance(element)); |
| if (activeChildren.length && activeChildren[0]._isTransitioning) return; |
| if (EventHandler.trigger(this._element, EVENT_SHOW$7).defaultPrevented) return; |
| for (const activeInstance of activeChildren) activeInstance.hide(); |
| this._element.classList.add(CLASS_NAME_SHOW$5); |
| this._setAriaExpanded(this._triggerArray, true); |
| this._isTransitioning = true; |
| const complete = () => { |
| this._isTransitioning = false; |
| EventHandler.trigger(this._element, EVENT_SHOWN$6); |
| }; |
| await this._queueCallback(complete, this._element, this._isAnimated()); |
| } |
| async hide() { |
| if (this._isTransitioning || !this._isShown()) return; |
| if (EventHandler.trigger(this._element, EVENT_HIDE$6).defaultPrevented) return; |
| this._element.classList.remove(CLASS_NAME_SHOW$5); |
| for (const trigger of this._triggerArray) { |
| const element = SelectorEngine.getElementFromSelector(trigger); |
| if (element && !this._isShown(element)) this._setAriaExpanded([trigger], false); |
| } |
| this._isTransitioning = true; |
| const complete = () => { |
| this._isTransitioning = false; |
| EventHandler.trigger(this._element, EVENT_HIDDEN$8); |
| }; |
| await this._queueCallback(complete, this._element, this._isAnimated()); |
| } |
| _isShown(element = this._element) { |
| return element.classList.contains(CLASS_NAME_SHOW$5); |
| } |
| _isAnimated() { |
| return getTransitionDurationFromElement(this._element) > 0; |
| } |
| _sharesTrigger(element) { |
| return this._triggerArray.some((trigger) => SelectorEngine.getMultipleElementsFromSelector(trigger).includes(element)); |
| } |
| _configAfterMerge(config) { |
| config.parent = getElement(config.parent); |
| return config; |
| } |
| _initializeChildren() { |
| if (!this._config.parent) return; |
| const children = this._getFirstLevelChildren(SELECTOR_DATA_TOGGLE$9); |
| for (const element of children) { |
| const selected = SelectorEngine.getElementFromSelector(element); |
| if (selected) this._setAriaExpanded([element], this._isShown(selected)); |
| } |
| } |
| _getFirstLevelChildren(selector) { |
| const children = SelectorEngine.find(CLASS_NAME_DEEPER_CHILDREN, this._config.parent); |
| return SelectorEngine.find(selector, this._config.parent).filter((element) => !children.includes(element)); |
| } |
| _setAriaExpanded(triggerArray, isOpen) { |
| if (!triggerArray.length) return; |
| for (const element of triggerArray) setAriaAttribute(element, "aria-expanded", isOpen); |
| } |
| }; |
| /** |
| * Data API implementation |
| */ |
| EventHandler.on(document, EVENT_CLICK_DATA_API$6, SELECTOR_DATA_TOGGLE$9, function(event) { |
| if (event.target.tagName === "A" || event.delegateTarget && event.delegateTarget.tagName === "A") event.preventDefault(); |
| for (const element of SelectorEngine.getMultipleElementsFromSelector(this)) Collapse.getOrCreateInstance(element).toggle(); |
| }); |
| //#endregion |
| //#region node_modules/@floating-ui/utils/dist/floating-ui.utils.mjs |
| const min = Math.min; |
| const max = Math.max; |
| const round = Math.round; |
| const floor = Math.floor; |
| const createCoords = (v) => ({ |
| x: v, |
| y: v |
| }); |
| const oppositeSideMap = { |
| left: "right", |
| right: "left", |
| bottom: "top", |
| top: "bottom" |
| }; |
| function clamp(start, value, end) { |
| return max(start, min(value, end)); |
| } |
| function evaluate(value, param) { |
| return typeof value === "function" ? value(param) : value; |
| } |
| function getSide(placement) { |
| return placement.split("-")[0]; |
| } |
| function getAlignment(placement) { |
| return placement.split("-")[1]; |
| } |
| function getOppositeAxis(axis) { |
| return axis === "x" ? "y" : "x"; |
| } |
| function getAxisLength(axis) { |
| return axis === "y" ? "height" : "width"; |
| } |
| function getSideAxis(placement) { |
| const firstChar = placement[0]; |
| return firstChar === "t" || firstChar === "b" ? "y" : "x"; |
| } |
| function getAlignmentAxis(placement) { |
| return getOppositeAxis(getSideAxis(placement)); |
| } |
| function getAlignmentSides(placement, rects, rtl) { |
| if (rtl === void 0) rtl = false; |
| const alignment = getAlignment(placement); |
| const alignmentAxis = getAlignmentAxis(placement); |
| const length = getAxisLength(alignmentAxis); |
| let mainAlignmentSide = alignmentAxis === "x" ? alignment === (rtl ? "end" : "start") ? "right" : "left" : alignment === "start" ? "bottom" : "top"; |
| if (rects.reference[length] > rects.floating[length]) mainAlignmentSide = getOppositePlacement(mainAlignmentSide); |
| return [mainAlignmentSide, getOppositePlacement(mainAlignmentSide)]; |
| } |
| function getExpandedPlacements(placement) { |
| const oppositePlacement = getOppositePlacement(placement); |
| return [ |
| getOppositeAlignmentPlacement(placement), |
| oppositePlacement, |
| getOppositeAlignmentPlacement(oppositePlacement) |
| ]; |
| } |
| function getOppositeAlignmentPlacement(placement) { |
| return placement.includes("start") ? placement.replace("start", "end") : placement.replace("end", "start"); |
| } |
| const lrPlacement = ["left", "right"]; |
| const rlPlacement = ["right", "left"]; |
| const tbPlacement = ["top", "bottom"]; |
| const btPlacement = ["bottom", "top"]; |
| function getSideList(side, isStart, rtl) { |
| switch (side) { |
| case "top": |
| case "bottom": |
| if (rtl) return isStart ? rlPlacement : lrPlacement; |
| return isStart ? lrPlacement : rlPlacement; |
| case "left": |
| case "right": return isStart ? tbPlacement : btPlacement; |
| default: return []; |
| } |
| } |
| function getOppositeAxisPlacements(placement, flipAlignment, direction, rtl) { |
| const alignment = getAlignment(placement); |
| let list = getSideList(getSide(placement), direction === "start", rtl); |
| if (alignment) { |
| list = list.map((side) => side + "-" + alignment); |
| if (flipAlignment) list = list.concat(list.map(getOppositeAlignmentPlacement)); |
| } |
| return list; |
| } |
| function getOppositePlacement(placement) { |
| const side = getSide(placement); |
| return oppositeSideMap[side] + placement.slice(side.length); |
| } |
| function expandPaddingObject(padding) { |
| return { |
| top: 0, |
| right: 0, |
| bottom: 0, |
| left: 0, |
| ...padding |
| }; |
| } |
| function getPaddingObject(padding) { |
| return typeof padding !== "number" ? expandPaddingObject(padding) : { |
| top: padding, |
| right: padding, |
| bottom: padding, |
| left: padding |
| }; |
| } |
| function rectToClientRect(rect) { |
| const { x, y, width, height } = rect; |
| return { |
| width, |
| height, |
| top: y, |
| left: x, |
| right: x + width, |
| bottom: y + height, |
| x, |
| y |
| }; |
| } |
| //#endregion |
| //#region node_modules/@floating-ui/core/dist/floating-ui.core.mjs |
| function computeCoordsFromPlacement(_ref, placement, rtl) { |
| let { reference, floating } = _ref; |
| const sideAxis = getSideAxis(placement); |
| const alignmentAxis = getAlignmentAxis(placement); |
| const alignLength = getAxisLength(alignmentAxis); |
| const side = getSide(placement); |
| const isVertical = sideAxis === "y"; |
| const commonX = reference.x + reference.width / 2 - floating.width / 2; |
| const commonY = reference.y + reference.height / 2 - floating.height / 2; |
| const commonAlign = reference[alignLength] / 2 - floating[alignLength] / 2; |
| let coords; |
| switch (side) { |
| case "top": |
| coords = { |
| x: commonX, |
| y: reference.y - floating.height |
| }; |
| break; |
| case "bottom": |
| coords = { |
| x: commonX, |
| y: reference.y + reference.height |
| }; |
| break; |
| case "right": |
| coords = { |
| x: reference.x + reference.width, |
| y: commonY |
| }; |
| break; |
| case "left": |
| coords = { |
| x: reference.x - floating.width, |
| y: commonY |
| }; |
| break; |
| default: coords = { |
| x: reference.x, |
| y: reference.y |
| }; |
| } |
| switch (getAlignment(placement)) { |
| case "start": |
| coords[alignmentAxis] -= commonAlign * (rtl && isVertical ? -1 : 1); |
| break; |
| case "end": |
| coords[alignmentAxis] += commonAlign * (rtl && isVertical ? -1 : 1); |
| break; |
| } |
| return coords; |
| } |
| /** |
| * Resolves with an object of overflow side offsets that determine how much the |
| * element is overflowing a given clipping boundary on each side. |
| * - positive = overflowing the boundary by that number of pixels |
| * - negative = how many pixels left before it will overflow |
| * - 0 = lies flush with the boundary |
| * @see https://floating-ui.com/docs/detectOverflow |
| */ |
| async function detectOverflow(state, options) { |
| var _await$platform$isEle; |
| if (options === void 0) options = {}; |
| const { x, y, platform, rects, elements, strategy } = state; |
| const { boundary = "clippingAncestors", rootBoundary = "viewport", elementContext = "floating", altBoundary = false, padding = 0 } = evaluate(options, state); |
| const paddingObject = getPaddingObject(padding); |
| const element = elements[altBoundary ? elementContext === "floating" ? "reference" : "floating" : elementContext]; |
| const clippingClientRect = rectToClientRect(await platform.getClippingRect({ |
| element: ((_await$platform$isEle = await (platform.isElement == null ? void 0 : platform.isElement(element))) != null ? _await$platform$isEle : true) ? element : element.contextElement || await (platform.getDocumentElement == null ? void 0 : platform.getDocumentElement(elements.floating)), |
| boundary, |
| rootBoundary, |
| strategy |
| })); |
| const rect = elementContext === "floating" ? { |
| x, |
| y, |
| width: rects.floating.width, |
| height: rects.floating.height |
| } : rects.reference; |
| const offsetParent = await (platform.getOffsetParent == null ? void 0 : platform.getOffsetParent(elements.floating)); |
| const offsetScale = await (platform.isElement == null ? void 0 : platform.isElement(offsetParent)) ? await (platform.getScale == null ? void 0 : platform.getScale(offsetParent)) || { |
| x: 1, |
| y: 1 |
| } : { |
| x: 1, |
| y: 1 |
| }; |
| const elementClientRect = rectToClientRect(platform.convertOffsetParentRelativeRectToViewportRelativeRect ? await platform.convertOffsetParentRelativeRectToViewportRelativeRect({ |
| elements, |
| rect, |
| offsetParent, |
| strategy |
| }) : rect); |
| return { |
| top: (clippingClientRect.top - elementClientRect.top + paddingObject.top) / offsetScale.y, |
| bottom: (elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom) / offsetScale.y, |
| left: (clippingClientRect.left - elementClientRect.left + paddingObject.left) / offsetScale.x, |
| right: (elementClientRect.right - clippingClientRect.right + paddingObject.right) / offsetScale.x |
| }; |
| } |
| const MAX_RESET_COUNT = 50; |
| /** |
| * Computes the `x` and `y` coordinates that will place the floating element |
| * next to a given reference element. |
| * |
| * This export does not have any `platform` interface logic. You will need to |
| * write one for the platform you are using Floating UI with. |
| */ |
| const computePosition$1 = async (reference, floating, config) => { |
| const { placement = "bottom", strategy = "absolute", middleware = [], platform } = config; |
| const platformWithDetectOverflow = platform.detectOverflow ? platform : { |
| ...platform, |
| detectOverflow |
| }; |
| const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(floating)); |
| let rects = await platform.getElementRects({ |
| reference, |
| floating, |
| strategy |
| }); |
| let { x, y } = computeCoordsFromPlacement(rects, placement, rtl); |
| let statefulPlacement = placement; |
| let resetCount = 0; |
| const middlewareData = {}; |
| for (let i = 0; i < middleware.length; i++) { |
| const currentMiddleware = middleware[i]; |
| if (!currentMiddleware) continue; |
| const { name, fn } = currentMiddleware; |
| const { x: nextX, y: nextY, data, reset } = await fn({ |
| x, |
| y, |
| initialPlacement: placement, |
| placement: statefulPlacement, |
| strategy, |
| middlewareData, |
| rects, |
| platform: platformWithDetectOverflow, |
| elements: { |
| reference, |
| floating |
| } |
| }); |
| x = nextX != null ? nextX : x; |
| y = nextY != null ? nextY : y; |
| middlewareData[name] = { |
| ...middlewareData[name], |
| ...data |
| }; |
| if (reset && resetCount < MAX_RESET_COUNT) { |
| resetCount++; |
| if (typeof reset === "object") { |
| if (reset.placement) statefulPlacement = reset.placement; |
| if (reset.rects) rects = reset.rects === true ? await platform.getElementRects({ |
| reference, |
| floating, |
| strategy |
| }) : reset.rects; |
| ({x, y} = computeCoordsFromPlacement(rects, statefulPlacement, rtl)); |
| } |
| i = -1; |
| } |
| } |
| return { |
| x, |
| y, |
| placement: statefulPlacement, |
| strategy, |
| middlewareData |
| }; |
| }; |
| /** |
| * Provides data to position an inner element of the floating element so that it |
| * appears centered to the reference element. |
| * @see https://floating-ui.com/docs/arrow |
| */ |
| const arrow$1 = (options) => ({ |
| name: "arrow", |
| options, |
| async fn(state) { |
| const { x, y, placement, rects, platform, elements, middlewareData } = state; |
| const { element, padding = 0 } = evaluate(options, state) || {}; |
| if (element == null) return {}; |
| const paddingObject = getPaddingObject(padding); |
| const coords = { |
| x, |
| y |
| }; |
| const axis = getAlignmentAxis(placement); |
| const length = getAxisLength(axis); |
| const arrowDimensions = await platform.getDimensions(element); |
| const isYAxis = axis === "y"; |
| const minProp = isYAxis ? "top" : "left"; |
| const maxProp = isYAxis ? "bottom" : "right"; |
| const clientProp = isYAxis ? "clientHeight" : "clientWidth"; |
| const endDiff = rects.reference[length] + rects.reference[axis] - coords[axis] - rects.floating[length]; |
| const startDiff = coords[axis] - rects.reference[axis]; |
| const arrowOffsetParent = await (platform.getOffsetParent == null ? void 0 : platform.getOffsetParent(element)); |
| let clientSize = arrowOffsetParent ? arrowOffsetParent[clientProp] : 0; |
| if (!clientSize || !await (platform.isElement == null ? void 0 : platform.isElement(arrowOffsetParent))) clientSize = elements.floating[clientProp] || rects.floating[length]; |
| const centerToReference = endDiff / 2 - startDiff / 2; |
| const largestPossiblePadding = clientSize / 2 - arrowDimensions[length] / 2 - 1; |
| const minPadding = min(paddingObject[minProp], largestPossiblePadding); |
| const maxPadding = min(paddingObject[maxProp], largestPossiblePadding); |
| const min$1 = minPadding; |
| const max = clientSize - arrowDimensions[length] - maxPadding; |
| const center = clientSize / 2 - arrowDimensions[length] / 2 + centerToReference; |
| const offset = clamp(min$1, center, max); |
| const shouldAddOffset = !middlewareData.arrow && getAlignment(placement) != null && center !== offset && rects.reference[length] / 2 - (center < min$1 ? minPadding : maxPadding) - arrowDimensions[length] / 2 < 0; |
| const alignmentOffset = shouldAddOffset ? center < min$1 ? center - min$1 : center - max : 0; |
| return { |
| [axis]: coords[axis] + alignmentOffset, |
| data: { |
| [axis]: offset, |
| centerOffset: center - offset - alignmentOffset, |
| ...shouldAddOffset && { alignmentOffset } |
| }, |
| reset: shouldAddOffset |
| }; |
| } |
| }); |
| /** |
| * Optimizes the visibility of the floating element by flipping the `placement` |
| * in order to keep it in view when the preferred placement(s) will overflow the |
| * clipping boundary. Alternative to `autoPlacement`. |
| * @see https://floating-ui.com/docs/flip |
| */ |
| const flip$1 = function(options) { |
| if (options === void 0) options = {}; |
| return { |
| name: "flip", |
| options, |
| async fn(state) { |
| var _middlewareData$arrow, _middlewareData$flip; |
| const { placement, middlewareData, rects, initialPlacement, platform, elements } = state; |
| const { mainAxis: checkMainAxis = true, crossAxis: checkCrossAxis = true, fallbackPlacements: specifiedFallbackPlacements, fallbackStrategy = "bestFit", fallbackAxisSideDirection = "none", flipAlignment = true, ...detectOverflowOptions } = evaluate(options, state); |
| if ((_middlewareData$arrow = middlewareData.arrow) != null && _middlewareData$arrow.alignmentOffset) return {}; |
| const side = getSide(placement); |
| const initialSideAxis = getSideAxis(initialPlacement); |
| const isBasePlacement = getSide(initialPlacement) === initialPlacement; |
| const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating)); |
| const fallbackPlacements = specifiedFallbackPlacements || (isBasePlacement || !flipAlignment ? [getOppositePlacement(initialPlacement)] : getExpandedPlacements(initialPlacement)); |
| const hasFallbackAxisSideDirection = fallbackAxisSideDirection !== "none"; |
| if (!specifiedFallbackPlacements && hasFallbackAxisSideDirection) fallbackPlacements.push(...getOppositeAxisPlacements(initialPlacement, flipAlignment, fallbackAxisSideDirection, rtl)); |
| const placements = [initialPlacement, ...fallbackPlacements]; |
| const overflow = await platform.detectOverflow(state, detectOverflowOptions); |
| const overflows = []; |
| let overflowsData = ((_middlewareData$flip = middlewareData.flip) == null ? void 0 : _middlewareData$flip.overflows) || []; |
| if (checkMainAxis) overflows.push(overflow[side]); |
| if (checkCrossAxis) { |
| const sides = getAlignmentSides(placement, rects, rtl); |
| overflows.push(overflow[sides[0]], overflow[sides[1]]); |
| } |
| overflowsData = [...overflowsData, { |
| placement, |
| overflows |
| }]; |
| if (!overflows.every((side) => side <= 0)) { |
| var _middlewareData$flip2, _overflowsData$filter; |
| const nextIndex = (((_middlewareData$flip2 = middlewareData.flip) == null ? void 0 : _middlewareData$flip2.index) || 0) + 1; |
| const nextPlacement = placements[nextIndex]; |
| if (nextPlacement) { |
| if (!(checkCrossAxis === "alignment" ? initialSideAxis !== getSideAxis(nextPlacement) : false) || overflowsData.every((d) => getSideAxis(d.placement) === initialSideAxis ? d.overflows[0] > 0 : true)) return { |
| data: { |
| index: nextIndex, |
| overflows: overflowsData |
| }, |
| reset: { placement: nextPlacement } |
| }; |
| } |
| let resetPlacement = (_overflowsData$filter = overflowsData.filter((d) => d.overflows[0] <= 0).sort((a, b) => a.overflows[1] - b.overflows[1])[0]) == null ? void 0 : _overflowsData$filter.placement; |
| if (!resetPlacement) switch (fallbackStrategy) { |
| case "bestFit": { |
| var _overflowsData$filter2; |
| const placement = (_overflowsData$filter2 = overflowsData.filter((d) => { |
| if (hasFallbackAxisSideDirection) { |
| const currentSideAxis = getSideAxis(d.placement); |
| return currentSideAxis === initialSideAxis || currentSideAxis === "y"; |
| } |
| return true; |
| }).map((d) => [d.placement, d.overflows.filter((overflow) => overflow > 0).reduce((acc, overflow) => acc + overflow, 0)]).sort((a, b) => a[1] - b[1])[0]) == null ? void 0 : _overflowsData$filter2[0]; |
| if (placement) resetPlacement = placement; |
| break; |
| } |
| case "initialPlacement": |
| resetPlacement = initialPlacement; |
| break; |
| } |
| if (placement !== resetPlacement) return { reset: { placement: resetPlacement } }; |
| } |
| return {}; |
| } |
| }; |
| }; |
| const originSides = /*#__PURE__*/ new Set(["left", "top"]); |
| async function convertValueToCoords(state, options) { |
| const { placement, platform, elements } = state; |
| const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating)); |
| const side = getSide(placement); |
| const alignment = getAlignment(placement); |
| const isVertical = getSideAxis(placement) === "y"; |
| const mainAxisMulti = originSides.has(side) ? -1 : 1; |
| const crossAxisMulti = rtl && isVertical ? -1 : 1; |
| const rawValue = evaluate(options, state); |
| let { mainAxis, crossAxis, alignmentAxis } = typeof rawValue === "number" ? { |
| mainAxis: rawValue, |
| crossAxis: 0, |
| alignmentAxis: null |
| } : { |
| mainAxis: rawValue.mainAxis || 0, |
| crossAxis: rawValue.crossAxis || 0, |
| alignmentAxis: rawValue.alignmentAxis |
| }; |
| if (alignment && typeof alignmentAxis === "number") crossAxis = alignment === "end" ? alignmentAxis * -1 : alignmentAxis; |
| return isVertical ? { |
| x: crossAxis * crossAxisMulti, |
| y: mainAxis * mainAxisMulti |
| } : { |
| x: mainAxis * mainAxisMulti, |
| y: crossAxis * crossAxisMulti |
| }; |
| } |
| /** |
| * Modifies the placement by translating the floating element along the |
| * specified axes. |
| * A number (shorthand for `mainAxis` or distance), or an axes configuration |
| * object may be passed. |
| * @see https://floating-ui.com/docs/offset |
| */ |
| const offset$1 = function(options) { |
| if (options === void 0) options = 0; |
| return { |
| name: "offset", |
| options, |
| async fn(state) { |
| var _middlewareData$offse, _middlewareData$arrow; |
| const { x, y, placement, middlewareData } = state; |
| const diffCoords = await convertValueToCoords(state, options); |
| if (placement === ((_middlewareData$offse = middlewareData.offset) == null ? void 0 : _middlewareData$offse.placement) && (_middlewareData$arrow = middlewareData.arrow) != null && _middlewareData$arrow.alignmentOffset) return {}; |
| return { |
| x: x + diffCoords.x, |
| y: y + diffCoords.y, |
| data: { |
| ...diffCoords, |
| placement |
| } |
| }; |
| } |
| }; |
| }; |
| /** |
| * Optimizes the visibility of the floating element by shifting it in order to |
| * keep it in view when it will overflow the clipping boundary. |
| * @see https://floating-ui.com/docs/shift |
| */ |
| const shift$1 = function(options) { |
| if (options === void 0) options = {}; |
| return { |
| name: "shift", |
| options, |
| async fn(state) { |
| const { x, y, placement, platform } = state; |
| const { mainAxis: checkMainAxis = true, crossAxis: checkCrossAxis = false, limiter = { fn: (_ref) => { |
| let { x, y } = _ref; |
| return { |
| x, |
| y |
| }; |
| } }, ...detectOverflowOptions } = evaluate(options, state); |
| const coords = { |
| x, |
| y |
| }; |
| const overflow = await platform.detectOverflow(state, detectOverflowOptions); |
| const crossAxis = getSideAxis(getSide(placement)); |
| const mainAxis = getOppositeAxis(crossAxis); |
| let mainAxisCoord = coords[mainAxis]; |
| let crossAxisCoord = coords[crossAxis]; |
| if (checkMainAxis) { |
| const minSide = mainAxis === "y" ? "top" : "left"; |
| const maxSide = mainAxis === "y" ? "bottom" : "right"; |
| const min = mainAxisCoord + overflow[minSide]; |
| const max = mainAxisCoord - overflow[maxSide]; |
| mainAxisCoord = clamp(min, mainAxisCoord, max); |
| } |
| if (checkCrossAxis) { |
| const minSide = crossAxis === "y" ? "top" : "left"; |
| const maxSide = crossAxis === "y" ? "bottom" : "right"; |
| const min = crossAxisCoord + overflow[minSide]; |
| const max = crossAxisCoord - overflow[maxSide]; |
| crossAxisCoord = clamp(min, crossAxisCoord, max); |
| } |
| const limitedCoords = limiter.fn({ |
| ...state, |
| [mainAxis]: mainAxisCoord, |
| [crossAxis]: crossAxisCoord |
| }); |
| return { |
| ...limitedCoords, |
| data: { |
| x: limitedCoords.x - x, |
| y: limitedCoords.y - y, |
| enabled: { |
| [mainAxis]: checkMainAxis, |
| [crossAxis]: checkCrossAxis |
| } |
| } |
| }; |
| } |
| }; |
| }; |
| //#endregion |
| //#region node_modules/@floating-ui/utils/dist/floating-ui.utils.dom.mjs |
| function hasWindow() { |
| return typeof window !== "undefined"; |
| } |
| function getNodeName(node) { |
| if (isNode(node)) return (node.nodeName || "").toLowerCase(); |
| return "#document"; |
| } |
| function getWindow(node) { |
| var _node$ownerDocument; |
| return (node == null || (_node$ownerDocument = node.ownerDocument) == null ? void 0 : _node$ownerDocument.defaultView) || window; |
| } |
| function getDocumentElement(node) { |
| var _ref; |
| return (_ref = (isNode(node) ? node.ownerDocument : node.document) || window.document) == null ? void 0 : _ref.documentElement; |
| } |
| function isNode(value) { |
| if (!hasWindow()) return false; |
| return value instanceof Node || value instanceof getWindow(value).Node; |
| } |
| function isElement(value) { |
| if (!hasWindow()) return false; |
| return value instanceof Element || value instanceof getWindow(value).Element; |
| } |
| function isHTMLElement(value) { |
| if (!hasWindow()) return false; |
| return value instanceof HTMLElement || value instanceof getWindow(value).HTMLElement; |
| } |
| function isShadowRoot(value) { |
| if (!hasWindow() || typeof ShadowRoot === "undefined") return false; |
| return value instanceof ShadowRoot || value instanceof getWindow(value).ShadowRoot; |
| } |
| function isOverflowElement(element) { |
| const { overflow, overflowX, overflowY, display } = getComputedStyle$1(element); |
| return /auto|scroll|overlay|hidden|clip/.test(overflow + overflowY + overflowX) && display !== "inline" && display !== "contents"; |
| } |
| function isTableElement(element) { |
| return /^(table|td|th)$/.test(getNodeName(element)); |
| } |
| function isTopLayer(element) { |
| try { |
| if (element.matches(":popover-open")) return true; |
| } catch (_e) {} |
| try { |
| return element.matches(":modal"); |
| } catch (_e) { |
| return false; |
| } |
| } |
| const willChangeRe = /transform|translate|scale|rotate|perspective|filter/; |
| const containRe = /paint|layout|strict|content/; |
| const isNotNone = (value) => !!value && value !== "none"; |
| let isWebKitValue; |
| function isContainingBlock(elementOrCss) { |
| const css = isElement(elementOrCss) ? getComputedStyle$1(elementOrCss) : elementOrCss; |
| return isNotNone(css.transform) || isNotNone(css.translate) || isNotNone(css.scale) || isNotNone(css.rotate) || isNotNone(css.perspective) || !isWebKit() && (isNotNone(css.backdropFilter) || isNotNone(css.filter)) || willChangeRe.test(css.willChange || "") || containRe.test(css.contain || ""); |
| } |
| function getContainingBlock(element) { |
| let currentNode = getParentNode(element); |
| while (isHTMLElement(currentNode) && !isLastTraversableNode(currentNode)) { |
| if (isContainingBlock(currentNode)) return currentNode; |
| else if (isTopLayer(currentNode)) return null; |
| currentNode = getParentNode(currentNode); |
| } |
| return null; |
| } |
| function isWebKit() { |
| if (isWebKitValue == null) isWebKitValue = typeof CSS !== "undefined" && CSS.supports && CSS.supports("-webkit-backdrop-filter", "none"); |
| return isWebKitValue; |
| } |
| function isLastTraversableNode(node) { |
| return /^(html|body|#document)$/.test(getNodeName(node)); |
| } |
| function getComputedStyle$1(element) { |
| return getWindow(element).getComputedStyle(element); |
| } |
| function getNodeScroll(element) { |
| if (isElement(element)) return { |
| scrollLeft: element.scrollLeft, |
| scrollTop: element.scrollTop |
| }; |
| return { |
| scrollLeft: element.scrollX, |
| scrollTop: element.scrollY |
| }; |
| } |
| function getParentNode(node) { |
| if (getNodeName(node) === "html") return node; |
| const result = node.assignedSlot || node.parentNode || isShadowRoot(node) && node.host || getDocumentElement(node); |
| return isShadowRoot(result) ? result.host : result; |
| } |
| function getNearestOverflowAncestor(node) { |
| const parentNode = getParentNode(node); |
| if (isLastTraversableNode(parentNode)) return node.ownerDocument ? node.ownerDocument.body : node.body; |
| if (isHTMLElement(parentNode) && isOverflowElement(parentNode)) return parentNode; |
| return getNearestOverflowAncestor(parentNode); |
| } |
| function getOverflowAncestors(node, list, traverseIframes) { |
| var _node$ownerDocument2; |
| if (list === void 0) list = []; |
| if (traverseIframes === void 0) traverseIframes = true; |
| const scrollableAncestor = getNearestOverflowAncestor(node); |
| const isBody = scrollableAncestor === ((_node$ownerDocument2 = node.ownerDocument) == null ? void 0 : _node$ownerDocument2.body); |
| const win = getWindow(scrollableAncestor); |
| if (isBody) { |
| const frameElement = getFrameElement(win); |
| return list.concat(win, win.visualViewport || [], isOverflowElement(scrollableAncestor) ? scrollableAncestor : [], frameElement && traverseIframes ? getOverflowAncestors(frameElement) : []); |
| } else return list.concat(scrollableAncestor, getOverflowAncestors(scrollableAncestor, [], traverseIframes)); |
| } |
| function getFrameElement(win) { |
| return win.parent && Object.getPrototypeOf(win.parent) ? win.frameElement : null; |
| } |
| //#endregion |
| //#region node_modules/@floating-ui/dom/dist/floating-ui.dom.mjs |
| function getCssDimensions(element) { |
| const css = getComputedStyle$1(element); |
| let width = parseFloat(css.width) || 0; |
| let height = parseFloat(css.height) || 0; |
| const hasOffset = isHTMLElement(element); |
| const offsetWidth = hasOffset ? element.offsetWidth : width; |
| const offsetHeight = hasOffset ? element.offsetHeight : height; |
| const shouldFallback = round(width) !== offsetWidth || round(height) !== offsetHeight; |
| if (shouldFallback) { |
| width = offsetWidth; |
| height = offsetHeight; |
| } |
| return { |
| width, |
| height, |
| $: shouldFallback |
| }; |
| } |
| function unwrapElement(element) { |
| return !isElement(element) ? element.contextElement : element; |
| } |
| function getScale(element) { |
| const domElement = unwrapElement(element); |
| if (!isHTMLElement(domElement)) return createCoords(1); |
| const rect = domElement.getBoundingClientRect(); |
| const { width, height, $ } = getCssDimensions(domElement); |
| let x = ($ ? round(rect.width) : rect.width) / width; |
| let y = ($ ? round(rect.height) : rect.height) / height; |
| if (!x || !Number.isFinite(x)) x = 1; |
| if (!y || !Number.isFinite(y)) y = 1; |
| return { |
| x, |
| y |
| }; |
| } |
| const noOffsets = /*#__PURE__*/ createCoords(0); |
| function getVisualOffsets(element) { |
| const win = getWindow(element); |
| if (!isWebKit() || !win.visualViewport) return noOffsets; |
| return { |
| x: win.visualViewport.offsetLeft, |
| y: win.visualViewport.offsetTop |
| }; |
| } |
| function shouldAddVisualOffsets(element, isFixed, floatingOffsetParent) { |
| if (isFixed === void 0) isFixed = false; |
| if (!floatingOffsetParent || isFixed && floatingOffsetParent !== getWindow(element)) return false; |
| return isFixed; |
| } |
| function getBoundingClientRect(element, includeScale, isFixedStrategy, offsetParent) { |
| if (includeScale === void 0) includeScale = false; |
| if (isFixedStrategy === void 0) isFixedStrategy = false; |
| const clientRect = element.getBoundingClientRect(); |
| const domElement = unwrapElement(element); |
| let scale = createCoords(1); |
| if (includeScale) if (offsetParent) { |
| if (isElement(offsetParent)) scale = getScale(offsetParent); |
| } else scale = getScale(element); |
| const visualOffsets = shouldAddVisualOffsets(domElement, isFixedStrategy, offsetParent) ? getVisualOffsets(domElement) : createCoords(0); |
| let x = (clientRect.left + visualOffsets.x) / scale.x; |
| let y = (clientRect.top + visualOffsets.y) / scale.y; |
| let width = clientRect.width / scale.x; |
| let height = clientRect.height / scale.y; |
| if (domElement) { |
| const win = getWindow(domElement); |
| const offsetWin = offsetParent && isElement(offsetParent) ? getWindow(offsetParent) : offsetParent; |
| let currentWin = win; |
| let currentIFrame = getFrameElement(currentWin); |
| while (currentIFrame && offsetParent && offsetWin !== currentWin) { |
| const iframeScale = getScale(currentIFrame); |
| const iframeRect = currentIFrame.getBoundingClientRect(); |
| const css = getComputedStyle$1(currentIFrame); |
| const left = iframeRect.left + (currentIFrame.clientLeft + parseFloat(css.paddingLeft)) * iframeScale.x; |
| const top = iframeRect.top + (currentIFrame.clientTop + parseFloat(css.paddingTop)) * iframeScale.y; |
| x *= iframeScale.x; |
| y *= iframeScale.y; |
| width *= iframeScale.x; |
| height *= iframeScale.y; |
| x += left; |
| y += top; |
| currentWin = getWindow(currentIFrame); |
| currentIFrame = getFrameElement(currentWin); |
| } |
| } |
| return rectToClientRect({ |
| width, |
| height, |
| x, |
| y |
| }); |
| } |
| function getWindowScrollBarX(element, rect) { |
| const leftScroll = getNodeScroll(element).scrollLeft; |
| if (!rect) return getBoundingClientRect(getDocumentElement(element)).left + leftScroll; |
| return rect.left + leftScroll; |
| } |
| function getHTMLOffset(documentElement, scroll) { |
| const htmlRect = documentElement.getBoundingClientRect(); |
| return { |
| x: htmlRect.left + scroll.scrollLeft - getWindowScrollBarX(documentElement, htmlRect), |
| y: htmlRect.top + scroll.scrollTop |
| }; |
| } |
| function convertOffsetParentRelativeRectToViewportRelativeRect(_ref) { |
| let { elements, rect, offsetParent, strategy } = _ref; |
| const isFixed = strategy === "fixed"; |
| const documentElement = getDocumentElement(offsetParent); |
| const topLayer = elements ? isTopLayer(elements.floating) : false; |
| if (offsetParent === documentElement || topLayer && isFixed) return rect; |
| let scroll = { |
| scrollLeft: 0, |
| scrollTop: 0 |
| }; |
| let scale = createCoords(1); |
| const offsets = createCoords(0); |
| const isOffsetParentAnElement = isHTMLElement(offsetParent); |
| if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) { |
| if (getNodeName(offsetParent) !== "body" || isOverflowElement(documentElement)) scroll = getNodeScroll(offsetParent); |
| if (isOffsetParentAnElement) { |
| const offsetRect = getBoundingClientRect(offsetParent); |
| scale = getScale(offsetParent); |
| offsets.x = offsetRect.x + offsetParent.clientLeft; |
| offsets.y = offsetRect.y + offsetParent.clientTop; |
| } |
| } |
| const htmlOffset = documentElement && !isOffsetParentAnElement && !isFixed ? getHTMLOffset(documentElement, scroll) : createCoords(0); |
| return { |
| width: rect.width * scale.x, |
| height: rect.height * scale.y, |
| x: rect.x * scale.x - scroll.scrollLeft * scale.x + offsets.x + htmlOffset.x, |
| y: rect.y * scale.y - scroll.scrollTop * scale.y + offsets.y + htmlOffset.y |
| }; |
| } |
| function getClientRects(element) { |
| return Array.from(element.getClientRects()); |
| } |
| function getDocumentRect(element) { |
| const html = getDocumentElement(element); |
| const scroll = getNodeScroll(element); |
| const body = element.ownerDocument.body; |
| const width = max(html.scrollWidth, html.clientWidth, body.scrollWidth, body.clientWidth); |
| const height = max(html.scrollHeight, html.clientHeight, body.scrollHeight, body.clientHeight); |
| let x = -scroll.scrollLeft + getWindowScrollBarX(element); |
| const y = -scroll.scrollTop; |
| if (getComputedStyle$1(body).direction === "rtl") x += max(html.clientWidth, body.clientWidth) - width; |
| return { |
| width, |
| height, |
| x, |
| y |
| }; |
| } |
| const SCROLLBAR_MAX = 25; |
| function getViewportRect(element, strategy) { |
| const win = getWindow(element); |
| const html = getDocumentElement(element); |
| const visualViewport = win.visualViewport; |
| let width = html.clientWidth; |
| let height = html.clientHeight; |
| let x = 0; |
| let y = 0; |
| if (visualViewport) { |
| width = visualViewport.width; |
| height = visualViewport.height; |
| const visualViewportBased = isWebKit(); |
| if (!visualViewportBased || visualViewportBased && strategy === "fixed") { |
| x = visualViewport.offsetLeft; |
| y = visualViewport.offsetTop; |
| } |
| } |
| const windowScrollbarX = getWindowScrollBarX(html); |
| if (windowScrollbarX <= 0) { |
| const doc = html.ownerDocument; |
| const body = doc.body; |
| const bodyStyles = getComputedStyle(body); |
| const bodyMarginInline = doc.compatMode === "CSS1Compat" ? parseFloat(bodyStyles.marginLeft) + parseFloat(bodyStyles.marginRight) || 0 : 0; |
| const clippingStableScrollbarWidth = Math.abs(html.clientWidth - body.clientWidth - bodyMarginInline); |
| if (clippingStableScrollbarWidth <= SCROLLBAR_MAX) width -= clippingStableScrollbarWidth; |
| } else if (windowScrollbarX <= SCROLLBAR_MAX) width += windowScrollbarX; |
| return { |
| width, |
| height, |
| x, |
| y |
| }; |
| } |
| function getInnerBoundingClientRect(element, strategy) { |
| const clientRect = getBoundingClientRect(element, true, strategy === "fixed"); |
| const top = clientRect.top + element.clientTop; |
| const left = clientRect.left + element.clientLeft; |
| const scale = isHTMLElement(element) ? getScale(element) : createCoords(1); |
| return { |
| width: element.clientWidth * scale.x, |
| height: element.clientHeight * scale.y, |
| x: left * scale.x, |
| y: top * scale.y |
| }; |
| } |
| function getClientRectFromClippingAncestor(element, clippingAncestor, strategy) { |
| let rect; |
| if (clippingAncestor === "viewport") rect = getViewportRect(element, strategy); |
| else if (clippingAncestor === "document") rect = getDocumentRect(getDocumentElement(element)); |
| else if (isElement(clippingAncestor)) rect = getInnerBoundingClientRect(clippingAncestor, strategy); |
| else { |
| const visualOffsets = getVisualOffsets(element); |
| rect = { |
| x: clippingAncestor.x - visualOffsets.x, |
| y: clippingAncestor.y - visualOffsets.y, |
| width: clippingAncestor.width, |
| height: clippingAncestor.height |
| }; |
| } |
| return rectToClientRect(rect); |
| } |
| function hasFixedPositionAncestor(element, stopNode) { |
| const parentNode = getParentNode(element); |
| if (parentNode === stopNode || !isElement(parentNode) || isLastTraversableNode(parentNode)) return false; |
| return getComputedStyle$1(parentNode).position === "fixed" || hasFixedPositionAncestor(parentNode, stopNode); |
| } |
| function getClippingElementAncestors(element, cache) { |
| const cachedResult = cache.get(element); |
| if (cachedResult) return cachedResult; |
| let result = getOverflowAncestors(element, [], false).filter((el) => isElement(el) && getNodeName(el) !== "body"); |
| let currentContainingBlockComputedStyle = null; |
| const elementIsFixed = getComputedStyle$1(element).position === "fixed"; |
| let currentNode = elementIsFixed ? getParentNode(element) : element; |
| while (isElement(currentNode) && !isLastTraversableNode(currentNode)) { |
| const computedStyle = getComputedStyle$1(currentNode); |
| const currentNodeIsContaining = isContainingBlock(currentNode); |
| if (!currentNodeIsContaining && computedStyle.position === "fixed") currentContainingBlockComputedStyle = null; |
| if (elementIsFixed ? !currentNodeIsContaining && !currentContainingBlockComputedStyle : !currentNodeIsContaining && computedStyle.position === "static" && !!currentContainingBlockComputedStyle && (currentContainingBlockComputedStyle.position === "absolute" || currentContainingBlockComputedStyle.position === "fixed") || isOverflowElement(currentNode) && !currentNodeIsContaining && hasFixedPositionAncestor(element, currentNode)) result = result.filter((ancestor) => ancestor !== currentNode); |
| else currentContainingBlockComputedStyle = computedStyle; |
| currentNode = getParentNode(currentNode); |
| } |
| cache.set(element, result); |
| return result; |
| } |
| function getClippingRect(_ref) { |
| let { element, boundary, rootBoundary, strategy } = _ref; |
| const clippingAncestors = [...boundary === "clippingAncestors" ? isTopLayer(element) ? [] : getClippingElementAncestors(element, this._c) : [].concat(boundary), rootBoundary]; |
| const firstRect = getClientRectFromClippingAncestor(element, clippingAncestors[0], strategy); |
| let top = firstRect.top; |
| let right = firstRect.right; |
| let bottom = firstRect.bottom; |
| let left = firstRect.left; |
| for (let i = 1; i < clippingAncestors.length; i++) { |
| const rect = getClientRectFromClippingAncestor(element, clippingAncestors[i], strategy); |
| top = max(rect.top, top); |
| right = min(rect.right, right); |
| bottom = min(rect.bottom, bottom); |
| left = max(rect.left, left); |
| } |
| return { |
| width: right - left, |
| height: bottom - top, |
| x: left, |
| y: top |
| }; |
| } |
| function getDimensions(element) { |
| const { width, height } = getCssDimensions(element); |
| return { |
| width, |
| height |
| }; |
| } |
| function getRectRelativeToOffsetParent(element, offsetParent, strategy) { |
| const isOffsetParentAnElement = isHTMLElement(offsetParent); |
| const documentElement = getDocumentElement(offsetParent); |
| const isFixed = strategy === "fixed"; |
| const rect = getBoundingClientRect(element, true, isFixed, offsetParent); |
| let scroll = { |
| scrollLeft: 0, |
| scrollTop: 0 |
| }; |
| const offsets = createCoords(0); |
| function setLeftRTLScrollbarOffset() { |
| offsets.x = getWindowScrollBarX(documentElement); |
| } |
| if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) { |
| if (getNodeName(offsetParent) !== "body" || isOverflowElement(documentElement)) scroll = getNodeScroll(offsetParent); |
| if (isOffsetParentAnElement) { |
| const offsetRect = getBoundingClientRect(offsetParent, true, isFixed, offsetParent); |
| offsets.x = offsetRect.x + offsetParent.clientLeft; |
| offsets.y = offsetRect.y + offsetParent.clientTop; |
| } else if (documentElement) setLeftRTLScrollbarOffset(); |
| } |
| if (isFixed && !isOffsetParentAnElement && documentElement) setLeftRTLScrollbarOffset(); |
| const htmlOffset = documentElement && !isOffsetParentAnElement && !isFixed ? getHTMLOffset(documentElement, scroll) : createCoords(0); |
| return { |
| x: rect.left + scroll.scrollLeft - offsets.x - htmlOffset.x, |
| y: rect.top + scroll.scrollTop - offsets.y - htmlOffset.y, |
| width: rect.width, |
| height: rect.height |
| }; |
| } |
| function isStaticPositioned(element) { |
| return getComputedStyle$1(element).position === "static"; |
| } |
| function getTrueOffsetParent(element, polyfill) { |
| if (!isHTMLElement(element) || getComputedStyle$1(element).position === "fixed") return null; |
| if (polyfill) return polyfill(element); |
| let rawOffsetParent = element.offsetParent; |
| if (getDocumentElement(element) === rawOffsetParent) rawOffsetParent = rawOffsetParent.ownerDocument.body; |
| return rawOffsetParent; |
| } |
| function getOffsetParent(element, polyfill) { |
| const win = getWindow(element); |
| if (isTopLayer(element)) return win; |
| if (!isHTMLElement(element)) { |
| let svgOffsetParent = getParentNode(element); |
| while (svgOffsetParent && !isLastTraversableNode(svgOffsetParent)) { |
| if (isElement(svgOffsetParent) && !isStaticPositioned(svgOffsetParent)) return svgOffsetParent; |
| svgOffsetParent = getParentNode(svgOffsetParent); |
| } |
| return win; |
| } |
| let offsetParent = getTrueOffsetParent(element, polyfill); |
| while (offsetParent && isTableElement(offsetParent) && isStaticPositioned(offsetParent)) offsetParent = getTrueOffsetParent(offsetParent, polyfill); |
| if (offsetParent && isLastTraversableNode(offsetParent) && isStaticPositioned(offsetParent) && !isContainingBlock(offsetParent)) return win; |
| return offsetParent || getContainingBlock(element) || win; |
| } |
| const getElementRects = async function(data) { |
| const getOffsetParentFn = this.getOffsetParent || getOffsetParent; |
| const getDimensionsFn = this.getDimensions; |
| const floatingDimensions = await getDimensionsFn(data.floating); |
| return { |
| reference: getRectRelativeToOffsetParent(data.reference, await getOffsetParentFn(data.floating), data.strategy), |
| floating: { |
| x: 0, |
| y: 0, |
| width: floatingDimensions.width, |
| height: floatingDimensions.height |
| } |
| }; |
| }; |
| function isRTL(element) { |
| return getComputedStyle$1(element).direction === "rtl"; |
| } |
| const platform = { |
| convertOffsetParentRelativeRectToViewportRelativeRect, |
| getDocumentElement, |
| getClippingRect, |
| getOffsetParent, |
| getElementRects, |
| getClientRects, |
| getDimensions, |
| getScale, |
| isElement, |
| isRTL |
| }; |
| function rectsAreEqual(a, b) { |
| return a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height; |
| } |
| function observeMove(element, onMove) { |
| let io = null; |
| let timeoutId; |
| const root = getDocumentElement(element); |
| function cleanup() { |
| var _io; |
| clearTimeout(timeoutId); |
| (_io = io) == null || _io.disconnect(); |
| io = null; |
| } |
| function refresh(skip, threshold) { |
| if (skip === void 0) skip = false; |
| if (threshold === void 0) threshold = 1; |
| cleanup(); |
| const elementRectForRootMargin = element.getBoundingClientRect(); |
| const { left, top, width, height } = elementRectForRootMargin; |
| if (!skip) onMove(); |
| if (!width || !height) return; |
| const insetTop = floor(top); |
| const insetRight = floor(root.clientWidth - (left + width)); |
| const insetBottom = floor(root.clientHeight - (top + height)); |
| const insetLeft = floor(left); |
| const options = { |
| rootMargin: -insetTop + "px " + -insetRight + "px " + -insetBottom + "px " + -insetLeft + "px", |
| threshold: max(0, min(1, threshold)) || 1 |
| }; |
| let isFirstUpdate = true; |
| function handleObserve(entries) { |
| const ratio = entries[0].intersectionRatio; |
| if (ratio !== threshold) { |
| if (!isFirstUpdate) return refresh(); |
| if (!ratio) timeoutId = setTimeout(() => { |
| refresh(false, 1e-7); |
| }, 1e3); |
| else refresh(false, ratio); |
| } |
| if (ratio === 1 && !rectsAreEqual(elementRectForRootMargin, element.getBoundingClientRect())) refresh(); |
| isFirstUpdate = false; |
| } |
| try { |
| io = new IntersectionObserver(handleObserve, { |
| ...options, |
| root: root.ownerDocument |
| }); |
| } catch (_e) { |
| io = new IntersectionObserver(handleObserve, options); |
| } |
| io.observe(element); |
| } |
| refresh(true); |
| return cleanup; |
| } |
| /** |
| * Automatically updates the position of the floating element when necessary. |
| * Should only be called when the floating element is mounted on the DOM or |
| * visible on the screen. |
| * @returns cleanup function that should be invoked when the floating element is |
| * removed from the DOM or hidden from the screen. |
| * @see https://floating-ui.com/docs/autoUpdate |
| */ |
| function autoUpdate(reference, floating, update, options) { |
| if (options === void 0) options = {}; |
| const { ancestorScroll = true, ancestorResize = true, elementResize = typeof ResizeObserver === "function", layoutShift = typeof IntersectionObserver === "function", animationFrame = false } = options; |
| const referenceEl = unwrapElement(reference); |
| const ancestors = ancestorScroll || ancestorResize ? [...referenceEl ? getOverflowAncestors(referenceEl) : [], ...floating ? getOverflowAncestors(floating) : []] : []; |
| ancestors.forEach((ancestor) => { |
| ancestorScroll && ancestor.addEventListener("scroll", update, { passive: true }); |
| ancestorResize && ancestor.addEventListener("resize", update); |
| }); |
| const cleanupIo = referenceEl && layoutShift ? observeMove(referenceEl, update) : null; |
| let reobserveFrame = -1; |
| let resizeObserver = null; |
| if (elementResize) { |
| resizeObserver = new ResizeObserver((_ref) => { |
| let [firstEntry] = _ref; |
| if (firstEntry && firstEntry.target === referenceEl && resizeObserver && floating) { |
| resizeObserver.unobserve(floating); |
| cancelAnimationFrame(reobserveFrame); |
| reobserveFrame = requestAnimationFrame(() => { |
| var _resizeObserver; |
| (_resizeObserver = resizeObserver) == null || _resizeObserver.observe(floating); |
| }); |
| } |
| update(); |
| }); |
| if (referenceEl && !animationFrame) resizeObserver.observe(referenceEl); |
| if (floating) resizeObserver.observe(floating); |
| } |
| let frameId; |
| let prevRefRect = animationFrame ? getBoundingClientRect(reference) : null; |
| if (animationFrame) frameLoop(); |
| function frameLoop() { |
| const nextRefRect = getBoundingClientRect(reference); |
| if (prevRefRect && !rectsAreEqual(prevRefRect, nextRefRect)) update(); |
| prevRefRect = nextRefRect; |
| frameId = requestAnimationFrame(frameLoop); |
| } |
| update(); |
| return () => { |
| var _resizeObserver2; |
| ancestors.forEach((ancestor) => { |
| ancestorScroll && ancestor.removeEventListener("scroll", update); |
| ancestorResize && ancestor.removeEventListener("resize", update); |
| }); |
| cleanupIo?.(); |
| (_resizeObserver2 = resizeObserver) == null || _resizeObserver2.disconnect(); |
| resizeObserver = null; |
| if (animationFrame) cancelAnimationFrame(frameId); |
| }; |
| } |
| /** |
| * Modifies the placement by translating the floating element along the |
| * specified axes. |
| * A number (shorthand for `mainAxis` or distance), or an axes configuration |
| * object may be passed. |
| * @see https://floating-ui.com/docs/offset |
| */ |
| const offset = offset$1; |
| /** |
| * Optimizes the visibility of the floating element by shifting it in order to |
| * keep it in view when it will overflow the clipping boundary. |
| * @see https://floating-ui.com/docs/shift |
| */ |
| const shift = shift$1; |
| /** |
| * Optimizes the visibility of the floating element by flipping the `placement` |
| * in order to keep it in view when the preferred placement(s) will overflow the |
| * clipping boundary. Alternative to `autoPlacement`. |
| * @see https://floating-ui.com/docs/flip |
| */ |
| const flip = flip$1; |
| /** |
| * Provides data to position an inner element of the floating element so that it |
| * appears centered to the reference element. |
| * @see https://floating-ui.com/docs/arrow |
| */ |
| const arrow = arrow$1; |
| /** |
| * Computes the `x` and `y` coordinates that will place the floating element |
| * next to a given reference element. |
| */ |
| const computePosition = (reference, floating, options) => { |
| const cache = /* @__PURE__ */ new Map(); |
| const mergedOptions = { |
| platform, |
| ...options |
| }; |
| const platformWithCache = { |
| ...mergedOptions.platform, |
| _c: cache |
| }; |
| return computePosition$1(reference, floating, { |
| ...mergedOptions, |
| platform: platformWithCache |
| }); |
| }; |
| //#endregion |
| //#region js/src/util/floating-ui.ts |
| /** |
| * Breakpoints for responsive placement (matches SCSS $breakpoints) |
| */ |
| const BREAKPOINTS = { |
| sm: 576, |
| md: 768, |
| lg: 1024, |
| xl: 1280, |
| "2xl": 1536 |
| }; |
| /** |
| * Parse a placement string that may contain responsive prefixes |
| * Example: "bottom-start md:top-end lg:right" returns { xs: 'bottom-start', md: 'top-end', lg: 'right' } |
| * |
| * @param placementString - The placement string to parse |
| * @param defaultPlacement - The default placement to use for xs/base |
| * @returns Object with breakpoint keys and placement values, or null if not responsive |
| */ |
| const parseResponsivePlacement = (placementString, defaultPlacement = "bottom") => { |
| if (!placementString || !placementString.includes(":")) return null; |
| const parts = placementString.split(/\s+/); |
| const placements = { xs: defaultPlacement }; |
| for (const part of parts) if (part.includes(":")) { |
| const [breakpoint, placement] = part.split(":"); |
| if (BREAKPOINTS[breakpoint] !== void 0) placements[breakpoint] = placement; |
| } else placements.xs = part; |
| return placements; |
| }; |
| /** |
| * Get the active placement for the current viewport width |
| * |
| * @param responsivePlacements - Object with breakpoint keys and placement values |
| * @param defaultPlacement - Fallback placement |
| * @returns The active placement for current viewport |
| */ |
| const getResponsivePlacement = (responsivePlacements, defaultPlacement = "bottom") => { |
| if (!responsivePlacements) return defaultPlacement; |
| const viewportWidth = window.innerWidth; |
| let activePlacement = responsivePlacements.xs || defaultPlacement; |
| for (const breakpoint of [ |
| "sm", |
| "md", |
| "lg", |
| "xl", |
| "2xl" |
| ]) if (viewportWidth >= BREAKPOINTS[breakpoint] && responsivePlacements[breakpoint]) activePlacement = responsivePlacements[breakpoint]; |
| return activePlacement; |
| }; |
| /** |
| * Create media query listeners for responsive placement changes |
| * |
| * @param callback - Callback to run when breakpoint changes |
| * @returns Array of { mql, handler } objects for cleanup |
| */ |
| const createBreakpointListeners = (callback) => { |
| const listeners = []; |
| for (const breakpoint of Object.keys(BREAKPOINTS)) { |
| const minWidth = BREAKPOINTS[breakpoint]; |
| const mql = window.matchMedia(`(min-width: ${minWidth}px)`); |
| mql.addEventListener("change", callback); |
| listeners.push({ |
| mql, |
| handler: callback |
| }); |
| } |
| return listeners; |
| }; |
| /** |
| * Clean up media query listeners |
| * |
| * @param listeners - Array of { mql, handler } objects |
| */ |
| const disposeBreakpointListeners = (listeners) => { |
| for (const { mql, handler } of listeners) mql.removeEventListener("change", handler); |
| }; |
| /** |
| * Normalize an offset value into Floating UI's offset shape. |
| * A `[skidding, distance]` array becomes `{ mainAxis: distance, crossAxis: skidding }`; |
| * numbers and axis objects pass through unchanged. |
| */ |
| const toFloatingOffset = (value) => { |
| return Array.isArray(value) ? { |
| mainAxis: value[1] || 0, |
| crossAxis: value[0] || 0 |
| } : value; |
| }; |
| //#endregion |
| //#region js/src/menu.ts |
| /** |
| * -------------------------------------------------------------------------- |
| * Bootstrap menu.ts |
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
| * -------------------------------------------------------------------------- |
| */ |
| /** |
| * Constants |
| */ |
| const NAME$17 = "menu"; |
| const EVENT_KEY$14 = `.bs.menu`; |
| const DATA_API_KEY$9 = ".data-api"; |
| const ESCAPE_KEY$2 = "Escape"; |
| const TAB_KEY$1 = "Tab"; |
| const ARROW_UP_KEY$2 = "ArrowUp"; |
| const ARROW_DOWN_KEY$2 = "ArrowDown"; |
| const ARROW_LEFT_KEY$1 = "ArrowLeft"; |
| const ARROW_RIGHT_KEY$1 = "ArrowRight"; |
| const HOME_KEY$2 = "Home"; |
| const END_KEY$2 = "End"; |
| const ENTER_KEY$1 = "Enter"; |
| const SPACE_KEY$1 = " "; |
| const RIGHT_MOUSE_BUTTON = 2; |
| const SUBMENU_CLOSE_DELAY = 100; |
| const EVENT_HIDE$5 = `hide${EVENT_KEY$14}`; |
| const EVENT_HIDDEN$7 = `hidden${EVENT_KEY$14}`; |
| const EVENT_SHOW$6 = `show${EVENT_KEY$14}`; |
| const EVENT_SHOWN$5 = `shown${EVENT_KEY$14}`; |
| const EVENT_CLICK_DATA_API$5 = `click${EVENT_KEY$14}${DATA_API_KEY$9}`; |
| const EVENT_KEYDOWN_DATA_API = `keydown${EVENT_KEY$14}${DATA_API_KEY$9}`; |
| const EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY$14}${DATA_API_KEY$9}`; |
| const CLASS_NAME_SHOW$4 = "show"; |
| const SELECTOR_DATA_TOGGLE$8 = "[data-bs-toggle=\"menu\"]:not(.disabled):not(:disabled)"; |
| const SELECTOR_MENU$2 = ".menu"; |
| const SELECTOR_SUBMENU = ".submenu"; |
| const SELECTOR_SUBMENU_TOGGLE = ".submenu > .menu-item"; |
| const SELECTOR_NAVBAR_NAV = ".navbar-nav"; |
| const SELECTOR_VISIBLE_ITEMS$1 = ".menu-item:not(.disabled):not(:disabled)"; |
| const DEFAULT_PLACEMENT = "bottom-start"; |
| const SUBMENU_PLACEMENT = "end-start"; |
| const resolveLogicalPlacement = (placement) => { |
| if (isRTL$1()) return placement.replace(/^start(?=-|$)/, "right").replace(/^end(?=-|$)/, "left"); |
| return placement.replace(/^start(?=-|$)/, "left").replace(/^end(?=-|$)/, "right"); |
| }; |
| const triangleSign = (p1, p2, p3) => (p1.x - p3.x) * (p2.y - p3.y) - (p2.x - p3.x) * (p1.y - p3.y); |
| const Default$16 = { |
| autoClose: true, |
| boundary: "clippingParents", |
| container: false, |
| display: "dynamic", |
| offset: [0, 2], |
| floatingConfig: null, |
| menu: null, |
| placement: DEFAULT_PLACEMENT, |
| reference: "toggle", |
| strategy: "absolute", |
| submenuTrigger: "both", |
| submenuDelay: SUBMENU_CLOSE_DELAY |
| }; |
| const DefaultType$16 = { |
| autoClose: "(boolean|string)", |
| boundary: "(string|element)", |
| container: "(string|element|boolean)", |
| display: "string", |
| offset: "(array|string|function)", |
| floatingConfig: "(null|object|function)", |
| menu: "(null|element)", |
| placement: "string", |
| reference: "(string|element|object)", |
| strategy: "string", |
| submenuTrigger: "string", |
| submenuDelay: "number" |
| }; |
| /** |
| * Class definition |
| */ |
| var Menu = class Menu extends BaseComponent { |
| static _openInstances = /* @__PURE__ */ new Set(); |
| constructor(element, config) { |
| if (typeof computePosition === "undefined") throw new TypeError("Bootstrap's menus require Floating UI (https://floating-ui.com)"); |
| super(element, config); |
| this._floatingCleanup = null; |
| this._mediaQueryListeners = []; |
| this._responsivePlacements = null; |
| this._parent = this._element.parentNode; |
| this._openSubmenus = /* @__PURE__ */ new Map(); |
| this._submenuCloseTimeouts = /* @__PURE__ */ new Map(); |
| this._hoverIntentData = null; |
| this._menu = this._config.menu || this._findMenu(); |
| if (!this._config.menu && this._menu) this._parent = this._findWrapper(this._menu); |
| this._isSubmenu = this._parent.classList?.contains("submenu"); |
| this._menuOriginalParent = this._menu?.parentNode; |
| this._parseResponsivePlacements(); |
| this._setupSubmenuListeners(); |
| this._initSubmenuTriggers(); |
| } |
| static get Default() { |
| return Default$16; |
| } |
| static get DefaultType() { |
| return DefaultType$16; |
| } |
| static get NAME() { |
| return NAME$17; |
| } |
| toggle() { |
| return this._isShown() ? this.hide() : this.show(); |
| } |
| async show() { |
| if (isDisabled(this._element) || this._isShown()) return; |
| const relatedTarget = { relatedTarget: this._element }; |
| if (EventHandler.trigger(this._element, EVENT_SHOW$6, relatedTarget).defaultPrevented) return; |
| this._moveMenuToContainer(); |
| this._createFloating(); |
| if ("ontouchstart" in document.documentElement && !this._parent.closest(SELECTOR_NAVBAR_NAV)) for (const element of document.body.children) EventHandler.on(element, "mouseover", noop); |
| this._element.focus({ focusVisible: false }); |
| this._element.setAttribute("aria-expanded", "true"); |
| this._menu.classList.add(CLASS_NAME_SHOW$4); |
| this._element.classList.add(CLASS_NAME_SHOW$4); |
| if (this._parent) this._parent.classList.add(CLASS_NAME_SHOW$4); |
| Menu._openInstances.add(this); |
| await this._queueCallback(() => { |
| if (this._isShown()) EventHandler.trigger(this._element, EVENT_SHOWN$5, relatedTarget); |
| }, this._menu, this._isAnimated()); |
| } |
| async hide() { |
| if (isDisabled(this._element) || !this._isShown()) return; |
| const relatedTarget = { relatedTarget: this._element }; |
| await this._completeHide(relatedTarget); |
| } |
| dispose() { |
| this._disposeFloating(); |
| this._restoreMenuToOriginalParent(); |
| this._disposeMediaQueryListeners(); |
| this._closeAllSubmenus(); |
| this._clearAllSubmenuTimeouts(); |
| Menu._openInstances.delete(this); |
| super.dispose(); |
| } |
| update() { |
| if (this._floatingCleanup) this._updateFloatingPosition(); |
| } |
| _findMenu() { |
| const wrapper = SelectorEngine.closest(this._element, `:has(${SELECTOR_MENU$2})`); |
| return SelectorEngine.next(this._element, SELECTOR_MENU$2)[0] || SelectorEngine.prev(this._element, SELECTOR_MENU$2)[0] || SelectorEngine.findOne(SELECTOR_MENU$2, wrapper || this._parent); |
| } |
| _findWrapper(menu) { |
| let wrapper = this._element.parentNode; |
| while (wrapper instanceof Element && !wrapper.contains(menu)) wrapper = wrapper.parentNode; |
| return wrapper instanceof Element ? wrapper : this._element.parentNode; |
| } |
| async _completeHide(relatedTarget) { |
| if (EventHandler.trigger(this._element, EVENT_HIDE$5, relatedTarget).defaultPrevented) return; |
| this._closeAllSubmenus(); |
| if ("ontouchstart" in document.documentElement) for (const element of document.body.children) EventHandler.off(element, "mouseover", noop); |
| this._menu.classList.remove(CLASS_NAME_SHOW$4); |
| this._element.classList.remove(CLASS_NAME_SHOW$4); |
| if (this._parent) this._parent.classList.remove(CLASS_NAME_SHOW$4); |
| this._element.setAttribute("aria-expanded", "false"); |
| Menu._openInstances.delete(this); |
| await this._queueCallback(() => { |
| if (this._isShown()) return; |
| this._disposeFloating(); |
| this._restoreMenuToOriginalParent(); |
| Manipulator.removeDataAttribute(this._menu, "placement"); |
| Manipulator.removeDataAttribute(this._menu, "display"); |
| EventHandler.trigger(this._element, EVENT_HIDDEN$7, relatedTarget); |
| }, this._menu, this._isAnimated()); |
| } |
| _getConfig(config) { |
| config = super._getConfig(config); |
| if (typeof config.reference === "object" && !isElement$1(config.reference) && typeof config.reference.getBoundingClientRect !== "function") throw new TypeError(`${NAME$17.toUpperCase()}: Option "reference" provided type "object" without a required "getBoundingClientRect" method.`); |
| return config; |
| } |
| _createFloating() { |
| if (this._config.display === "static") { |
| Manipulator.setDataAttribute(this._menu, "display", "static"); |
| return; |
| } |
| let referenceElement = this._element; |
| if (this._config.reference === "parent") referenceElement = this._parent; |
| else if (isElement$1(this._config.reference)) referenceElement = getElement(this._config.reference); |
| else if (typeof this._config.reference === "object") referenceElement = this._config.reference; |
| this._updateFloatingPosition(referenceElement); |
| this._floatingCleanup = autoUpdate(referenceElement, this._menu, () => this._updateFloatingPosition(referenceElement)); |
| } |
| async _updateFloatingPosition(referenceElement = null) { |
| if (!this._menu) return; |
| if (!referenceElement) if (this._config.reference === "parent") referenceElement = this._parent; |
| else if (isElement$1(this._config.reference)) referenceElement = getElement(this._config.reference); |
| else if (typeof this._config.reference === "object") referenceElement = this._config.reference; |
| else referenceElement = this._element; |
| const placement = this._getPlacement(); |
| const middleware = this._getFloatingMiddleware(); |
| const floatingConfig = this._getFloatingConfig(placement, middleware); |
| await this._applyFloatingPosition(referenceElement, this._menu, floatingConfig.placement, floatingConfig.middleware, floatingConfig.strategy); |
| } |
| _isShown() { |
| return this._menu.classList.contains(CLASS_NAME_SHOW$4); |
| } |
| _isAnimated() { |
| return getTransitionDurationFromElement(this._menu) > 0; |
| } |
| _getPlacement() { |
| const placement = this._responsivePlacements ? getResponsivePlacement(this._responsivePlacements, DEFAULT_PLACEMENT) : this._config.placement; |
| return resolveLogicalPlacement(placement); |
| } |
| _parseResponsivePlacements() { |
| this._responsivePlacements = parseResponsivePlacement(this._config.placement, DEFAULT_PLACEMENT); |
| if (this._responsivePlacements) this._setupMediaQueryListeners(); |
| } |
| _setupMediaQueryListeners() { |
| this._disposeMediaQueryListeners(); |
| this._mediaQueryListeners = createBreakpointListeners(() => { |
| if (this._isShown()) this._updateFloatingPosition(); |
| }); |
| } |
| _disposeMediaQueryListeners() { |
| disposeBreakpointListeners(this._mediaQueryListeners); |
| this._mediaQueryListeners = []; |
| } |
| _getOffset() { |
| const { offset: offsetConfig } = this._config; |
| if (typeof offsetConfig === "string") return offsetConfig.split(",").map((value) => Number.parseInt(value, 10)); |
| if (typeof offsetConfig === "function") return ({ placement, rects }) => { |
| return toFloatingOffset(offsetConfig({ |
| placement, |
| reference: rects.reference, |
| floating: rects.floating |
| }, this._element)); |
| }; |
| return offsetConfig; |
| } |
| _getFloatingMiddleware() { |
| const offsetValue = this._getOffset(); |
| return [ |
| offset(typeof offsetValue === "function" ? offsetValue : toFloatingOffset(offsetValue)), |
| flip({ |
| fallbackPlacements: this._getFallbackPlacements(), |
| fallbackStrategy: "initialPlacement" |
| }), |
| shift({ boundary: this._config.boundary === "clippingParents" ? "clippingAncestors" : this._config.boundary }) |
| ]; |
| } |
| _getFallbackPlacements() { |
| return { |
| bottom: [ |
| "top", |
| "bottom-start", |
| "bottom-end", |
| "top-start", |
| "top-end" |
| ], |
| "bottom-start": [ |
| "top-start", |
| "bottom-end", |
| "top-end" |
| ], |
| "bottom-end": [ |
| "top-end", |
| "bottom-start", |
| "top-start" |
| ], |
| top: [ |
| "bottom", |
| "top-start", |
| "top-end", |
| "bottom-start", |
| "bottom-end" |
| ], |
| "top-start": [ |
| "bottom-start", |
| "top-end", |
| "bottom-end" |
| ], |
| "top-end": [ |
| "bottom-end", |
| "top-start", |
| "bottom-start" |
| ], |
| right: [ |
| "left", |
| "right-start", |
| "right-end", |
| "left-start", |
| "left-end" |
| ], |
| "right-start": [ |
| "left-start", |
| "right-end", |
| "left-end", |
| "top-start", |
| "bottom-start" |
| ], |
| "right-end": [ |
| "left-end", |
| "right-start", |
| "left-start", |
| "top-end", |
| "bottom-end" |
| ], |
| left: [ |
| "right", |
| "left-start", |
| "left-end", |
| "right-start", |
| "right-end" |
| ], |
| "left-start": [ |
| "right-start", |
| "left-end", |
| "right-end", |
| "top-start", |
| "bottom-start" |
| ], |
| "left-end": [ |
| "right-end", |
| "left-start", |
| "right-start", |
| "top-end", |
| "bottom-end" |
| ] |
| }[this._getPlacement()] || [ |
| "top", |
| "bottom", |
| "right", |
| "left" |
| ]; |
| } |
| _getFloatingConfig(placement, middleware) { |
| const defaultConfig = { |
| placement, |
| middleware, |
| strategy: this._config.strategy |
| }; |
| return { |
| ...defaultConfig, |
| ...execute(this._config.floatingConfig, [void 0, defaultConfig]) |
| }; |
| } |
| _disposeFloating() { |
| if (this._floatingCleanup) { |
| this._floatingCleanup(); |
| this._floatingCleanup = null; |
| } |
| } |
| _getContainer() { |
| const { container } = this._config; |
| if (container === false) return null; |
| return container === true ? document.body : getElement(container); |
| } |
| _moveMenuToContainer() { |
| const container = this._getContainer(); |
| if (!container || !this._menu) return; |
| if (this._menu.parentNode !== container) container.append(this._menu); |
| } |
| _restoreMenuToOriginalParent() { |
| if (!this._menuOriginalParent || !this._menu) return; |
| if (this._menu.parentNode !== this._menuOriginalParent) this._menuOriginalParent.append(this._menu); |
| } |
| async _applyFloatingPosition(reference, floating, placement, middleware, strategy = "absolute") { |
| if (!floating.isConnected) return null; |
| const { x, y, placement: finalPlacement } = await computePosition(reference, floating, { |
| placement, |
| middleware, |
| strategy |
| }); |
| if (!floating.isConnected) return null; |
| Object.assign(floating.style, { |
| position: strategy, |
| left: `${x}px`, |
| top: `${y}px`, |
| margin: "0" |
| }); |
| Manipulator.setDataAttribute(floating, "placement", finalPlacement); |
| return finalPlacement; |
| } |
| _setupSubmenuListeners() { |
| if (this._config.submenuTrigger === "hover" || this._config.submenuTrigger === "both") { |
| EventHandler.on(this._menu, "mouseenter", SELECTOR_SUBMENU_TOGGLE, (event) => { |
| this._onSubmenuTriggerEnter(event); |
| }); |
| EventHandler.on(this._menu, "mouseleave", SELECTOR_SUBMENU, (event) => { |
| this._onSubmenuLeave(event); |
| }); |
| EventHandler.on(this._menu, "mousemove", (event) => { |
| this._trackMousePosition(event); |
| }); |
| } |
| if (this._config.submenuTrigger === "click" || this._config.submenuTrigger === "both") EventHandler.on(this._menu, "click", SELECTOR_SUBMENU_TOGGLE, (event) => { |
| this._onSubmenuTriggerClick(event); |
| }); |
| } |
| _onSubmenuTriggerEnter(event) { |
| const trigger = event.target.closest(SELECTOR_SUBMENU_TOGGLE); |
| if (!trigger) return; |
| const submenuWrapper = trigger.closest(SELECTOR_SUBMENU); |
| const submenu = SelectorEngine.findOne(SELECTOR_MENU$2, submenuWrapper); |
| if (!submenu) return; |
| this._cancelSubmenuCloseTimeout(submenu); |
| this._closeSiblingSubmenus(submenuWrapper); |
| this._openSubmenu(trigger, submenu, submenuWrapper); |
| } |
| _onSubmenuLeave(event) { |
| const submenuWrapper = event.target.closest(SELECTOR_SUBMENU); |
| const submenu = SelectorEngine.findOne(SELECTOR_MENU$2, submenuWrapper); |
| if (!submenu || !this._openSubmenus.has(submenu)) return; |
| if (this._isMovingTowardSubmenu(event, submenu)) return; |
| this._scheduleSubmenuClose(submenu, submenuWrapper); |
| } |
| _onSubmenuTriggerClick(event) { |
| const trigger = event.target.closest(SELECTOR_SUBMENU_TOGGLE); |
| if (!trigger) return; |
| event.preventDefault(); |
| event.stopPropagation(); |
| const submenuWrapper = trigger.closest(SELECTOR_SUBMENU); |
| const submenu = SelectorEngine.findOne(SELECTOR_MENU$2, submenuWrapper); |
| if (!submenu) return; |
| if (this._openSubmenus.has(submenu)) this._closeSubmenu(submenu, submenuWrapper); |
| else { |
| this._closeSiblingSubmenus(submenuWrapper); |
| this._openSubmenu(trigger, submenu, submenuWrapper); |
| } |
| } |
| _initSubmenuTriggers() { |
| if (!this._menu) return; |
| for (const trigger of SelectorEngine.find(SELECTOR_SUBMENU_TOGGLE, this._menu)) { |
| if (!SelectorEngine.findOne(SELECTOR_MENU$2, trigger.parentElement)) continue; |
| trigger.setAttribute("aria-haspopup", "true"); |
| if (!trigger.hasAttribute("aria-expanded")) trigger.setAttribute("aria-expanded", "false"); |
| } |
| } |
| _openSubmenu(trigger, submenu, submenuWrapper) { |
| if (this._openSubmenus.has(submenu)) return; |
| trigger.setAttribute("aria-expanded", "true"); |
| trigger.setAttribute("aria-haspopup", "true"); |
| submenu.style.opacity = "0"; |
| submenu.classList.add(CLASS_NAME_SHOW$4); |
| submenuWrapper.classList.add(CLASS_NAME_SHOW$4); |
| const cleanup = this._createSubmenuFloating(trigger, submenu, submenuWrapper); |
| this._openSubmenus.set(submenu, cleanup); |
| EventHandler.on(submenu, "mouseenter", () => { |
| this._cancelSubmenuCloseTimeout(submenu); |
| }); |
| } |
| _closeSubmenu(submenu, submenuWrapper) { |
| if (!this._openSubmenus.has(submenu)) return; |
| const nestedSubmenus = SelectorEngine.find(`${SELECTOR_SUBMENU} ${SELECTOR_MENU$2}.${CLASS_NAME_SHOW$4}`, submenu); |
| for (const nested of nestedSubmenus) { |
| const nestedWrapper = nested.closest(SELECTOR_SUBMENU); |
| this._closeSubmenu(nested, nestedWrapper); |
| } |
| const trigger = SelectorEngine.findOne(SELECTOR_SUBMENU_TOGGLE, submenuWrapper); |
| const cleanup = this._openSubmenus.get(submenu); |
| if (cleanup) cleanup(); |
| this._openSubmenus.delete(submenu); |
| EventHandler.off(submenu, "mouseenter"); |
| if (trigger) trigger.setAttribute("aria-expanded", "false"); |
| submenu.classList.remove(CLASS_NAME_SHOW$4); |
| submenuWrapper.classList.remove(CLASS_NAME_SHOW$4); |
| submenu.style.opacity = ""; |
| } |
| _closeAllSubmenus() { |
| for (const [submenu] of this._openSubmenus) { |
| const submenuWrapper = submenu.closest(SELECTOR_SUBMENU); |
| this._closeSubmenu(submenu, submenuWrapper); |
| } |
| } |
| _closeSiblingSubmenus(currentSubmenuWrapper) { |
| const parent = currentSubmenuWrapper.parentNode; |
| const siblingSubmenus = SelectorEngine.find(`${SELECTOR_SUBMENU} > ${SELECTOR_MENU$2}.${CLASS_NAME_SHOW$4}`, parent); |
| for (const siblingMenu of siblingSubmenus) { |
| const siblingWrapper = siblingMenu.closest(SELECTOR_SUBMENU); |
| if (siblingWrapper !== currentSubmenuWrapper) this._closeSubmenu(siblingMenu, siblingWrapper); |
| } |
| } |
| _createSubmenuFloating(trigger, submenu, submenuWrapper) { |
| const referenceElement = submenuWrapper; |
| const placement = resolveLogicalPlacement(SUBMENU_PLACEMENT); |
| const middleware = [ |
| offset({ |
| mainAxis: 0, |
| crossAxis: -4 |
| }), |
| flip({ fallbackPlacements: [ |
| resolveLogicalPlacement("start-start"), |
| resolveLogicalPlacement("end-end"), |
| resolveLogicalPlacement("start-end") |
| ] }), |
| shift({ padding: 8 }) |
| ]; |
| const updatePosition = () => this._applyFloatingPosition(referenceElement, submenu, placement, middleware).then((finalPlacement) => { |
| submenu.style.opacity = ""; |
| return finalPlacement; |
| }); |
| updatePosition(); |
| return autoUpdate(referenceElement, submenu, updatePosition); |
| } |
| _scheduleSubmenuClose(submenu, submenuWrapper) { |
| this._cancelSubmenuCloseTimeout(submenu); |
| const timeoutId = setTimeout(() => { |
| this._closeSubmenu(submenu, submenuWrapper); |
| this._submenuCloseTimeouts.delete(submenu); |
| }, this._config.submenuDelay); |
| this._submenuCloseTimeouts.set(submenu, timeoutId); |
| } |
| _cancelSubmenuCloseTimeout(submenu) { |
| const timeoutId = this._submenuCloseTimeouts.get(submenu); |
| if (timeoutId) { |
| clearTimeout(timeoutId); |
| this._submenuCloseTimeouts.delete(submenu); |
| } |
| } |
| _clearAllSubmenuTimeouts() { |
| for (const timeoutId of this._submenuCloseTimeouts.values()) clearTimeout(timeoutId); |
| this._submenuCloseTimeouts.clear(); |
| } |
| _trackMousePosition(event) { |
| this._hoverIntentData = { |
| x: event.clientX, |
| y: event.clientY, |
| timestamp: Date.now() |
| }; |
| } |
| _isMovingTowardSubmenu(event, submenu) { |
| if (!this._hoverIntentData) return false; |
| const submenuRect = submenu.getBoundingClientRect(); |
| const currentPos = { |
| x: event.clientX, |
| y: event.clientY |
| }; |
| const lastPos = { |
| x: this._hoverIntentData.x, |
| y: this._hoverIntentData.y |
| }; |
| const targetX = isRTL$1() ? submenuRect.right : submenuRect.left; |
| const topCorner = { |
| x: targetX, |
| y: submenuRect.top |
| }; |
| const bottomCorner = { |
| x: targetX, |
| y: submenuRect.bottom |
| }; |
| return this._pointInTriangle(currentPos, lastPos, topCorner, bottomCorner); |
| } |
| _pointInTriangle(point, v1, v2, v3) { |
| const d1 = triangleSign(point, v1, v2); |
| const d2 = triangleSign(point, v2, v3); |
| const d3 = triangleSign(point, v3, v1); |
| return !((d1 < 0 || d2 < 0 || d3 < 0) && (d1 > 0 || d2 > 0 || d3 > 0)); |
| } |
| _getItemsInMenu(menu) { |
| return SelectorEngine.find(`:scope > ${SELECTOR_VISIBLE_ITEMS$1}, :scope > ${SELECTOR_SUBMENU} > ${SELECTOR_VISIBLE_ITEMS$1}`, menu).filter((element) => isVisible(element)); |
| } |
| _selectMenuItem({ key, target }) { |
| const currentMenu = target.closest(SELECTOR_MENU$2) || this._menu; |
| const items = this._getItemsInMenu(currentMenu); |
| if (!items.length) return; |
| const nextItem = getNextActiveElement(items, target, key === ARROW_DOWN_KEY$2, !items.includes(target)); |
| nextItem.focus(); |
| this._closeUnrelatedSubmenus(currentMenu, nextItem); |
| } |
| _closeUnrelatedSubmenus(currentMenu, focusedElement) { |
| for (const [submenu] of this._openSubmenus) { |
| const submenuWrapper = submenu.closest(SELECTOR_SUBMENU); |
| if (!submenuWrapper || submenuWrapper.parentElement !== currentMenu || submenuWrapper.contains(focusedElement)) continue; |
| this._closeSubmenu(submenu, submenuWrapper); |
| } |
| } |
| _handleSubmenuKeydown(event) { |
| const { key, target } = event; |
| const isRtl = isRTL$1(); |
| const enterKey = isRtl ? ARROW_LEFT_KEY$1 : ARROW_RIGHT_KEY$1; |
| const exitKey = isRtl ? ARROW_RIGHT_KEY$1 : ARROW_LEFT_KEY$1; |
| const submenuWrapper = target.closest(SELECTOR_SUBMENU); |
| const isSubmenuToggle = target.matches(SELECTOR_SUBMENU_TOGGLE); |
| if ((key === ENTER_KEY$1 || key === SPACE_KEY$1 || key === enterKey) && submenuWrapper && isSubmenuToggle) { |
| event.preventDefault(); |
| event.stopPropagation(); |
| const submenu = SelectorEngine.findOne(SELECTOR_MENU$2, submenuWrapper); |
| if (submenu) { |
| this._closeSiblingSubmenus(submenuWrapper); |
| this._openSubmenu(target, submenu, submenuWrapper); |
| requestAnimationFrame(() => { |
| const firstItem = SelectorEngine.findOne(SELECTOR_VISIBLE_ITEMS$1, submenu); |
| if (firstItem) firstItem.focus(); |
| }); |
| } |
| return true; |
| } |
| if (key === exitKey) { |
| const currentMenu = target.closest(SELECTOR_MENU$2); |
| const parentSubmenuWrapper = currentMenu?.closest(SELECTOR_SUBMENU); |
| if (parentSubmenuWrapper) { |
| event.preventDefault(); |
| event.stopPropagation(); |
| const parentTrigger = SelectorEngine.findOne(SELECTOR_SUBMENU_TOGGLE, parentSubmenuWrapper); |
| this._closeSubmenu(currentMenu, parentSubmenuWrapper); |
| if (parentTrigger) parentTrigger.focus(); |
| return true; |
| } |
| } |
| if (key === HOME_KEY$2 || key === END_KEY$2) { |
| event.preventDefault(); |
| event.stopPropagation(); |
| const currentMenu = target.closest(SELECTOR_MENU$2); |
| const items = this._getItemsInMenu(currentMenu); |
| if (items.length) { |
| const targetItem = key === HOME_KEY$2 ? items[0] : items.at(-1); |
| targetItem.focus(); |
| this._closeUnrelatedSubmenus(currentMenu, targetItem); |
| } |
| return true; |
| } |
| return false; |
| } |
| static clearMenus(event) { |
| if (event.button === RIGHT_MOUSE_BUTTON || event.type === "keyup" && event.key !== TAB_KEY$1) return; |
| for (const instance of Menu._openInstances) { |
| if (instance._config.autoClose === false) continue; |
| const composedPath = event.composedPath(); |
| const isMenuTarget = composedPath.includes(instance._menu); |
| if (composedPath.includes(instance._element) || instance._config.autoClose === "inside" && !isMenuTarget || instance._config.autoClose === "outside" && isMenuTarget) continue; |
| const formAncestor = event.target.closest?.("form"); |
| const isInsideMenuForm = Boolean(formAncestor) && instance._menu.contains(formAncestor); |
| if (instance._menu.contains(event.target) && (event.type === "keyup" && event.key === TAB_KEY$1 || /input|select|option|textarea|form/i.test(event.target.tagName) || isInsideMenuForm)) continue; |
| const relatedTarget = { relatedTarget: instance._element }; |
| if (event.type === "click") relatedTarget.clickEvent = event; |
| instance._completeHide(relatedTarget); |
| } |
| } |
| static _getToggleFromKeydownContext(element, event) { |
| if (element.matches(SELECTOR_DATA_TOGGLE$8)) return element; |
| for (const instance of Menu._openInstances) if (instance._element === event.target || instance._menu?.contains(event.target)) return instance._element; |
| return SelectorEngine.prev(element, SELECTOR_DATA_TOGGLE$8)[0] || SelectorEngine.next(element, SELECTOR_DATA_TOGGLE$8)[0] || SelectorEngine.findOne(SELECTOR_DATA_TOGGLE$8, event.delegateTarget.parentNode); |
| } |
| static dataApiKeydownHandler(event) { |
| const isInput = /input|textarea/i.test(event.target.tagName) || event.target.isContentEditable; |
| const isEscapeEvent = event.key === ESCAPE_KEY$2; |
| const isUpOrDownEvent = [ARROW_UP_KEY$2, ARROW_DOWN_KEY$2].includes(event.key); |
| const isLeftOrRightEvent = [ARROW_LEFT_KEY$1, ARROW_RIGHT_KEY$1].includes(event.key); |
| const isHomeOrEndEvent = [HOME_KEY$2, END_KEY$2].includes(event.key); |
| const isEnterOrSpaceEvent = [ENTER_KEY$1, SPACE_KEY$1].includes(event.key); |
| const isSubmenuTrigger = event.target.matches(SELECTOR_SUBMENU_TOGGLE); |
| if (!isUpOrDownEvent && !isEscapeEvent && !isLeftOrRightEvent && !isHomeOrEndEvent && !(isEnterOrSpaceEvent && isSubmenuTrigger)) return; |
| if (isInput && !isEscapeEvent) return; |
| const getToggleButton = Menu._getToggleFromKeydownContext(this, event); |
| if (!getToggleButton) return; |
| const instance = Menu.getOrCreateInstance(getToggleButton); |
| if ((isLeftOrRightEvent || isHomeOrEndEvent || isEnterOrSpaceEvent && isSubmenuTrigger) && instance._handleSubmenuKeydown(event)) return; |
| if (isUpOrDownEvent) { |
| event.preventDefault(); |
| event.stopPropagation(); |
| instance.show(); |
| instance._selectMenuItem(event); |
| return; |
| } |
| if (isEscapeEvent && instance._isShown()) { |
| event.preventDefault(); |
| event.stopPropagation(); |
| const currentMenu = event.target.closest(SELECTOR_MENU$2); |
| const parentSubmenuWrapper = currentMenu?.closest(SELECTOR_SUBMENU); |
| if (parentSubmenuWrapper && instance._openSubmenus.size > 0) { |
| const parentTrigger = SelectorEngine.findOne(SELECTOR_SUBMENU_TOGGLE, parentSubmenuWrapper); |
| instance._closeSubmenu(currentMenu, parentSubmenuWrapper); |
| if (parentTrigger) parentTrigger.focus(); |
| return; |
| } |
| instance.hide(); |
| getToggleButton.focus(); |
| } |
| } |
| }; |
| /** |
| * Data API implementation |
| */ |
| EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_DATA_TOGGLE$8, Menu.dataApiKeydownHandler); |
| EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_MENU$2, Menu.dataApiKeydownHandler); |
| EventHandler.on(document, EVENT_CLICK_DATA_API$5, Menu.clearMenus); |
| EventHandler.on(document, EVENT_KEYUP_DATA_API, Menu.clearMenus); |
| EventHandler.on(document, EVENT_CLICK_DATA_API$5, SELECTOR_DATA_TOGGLE$8, function(event) { |
| event.preventDefault(); |
| Menu.getOrCreateInstance(this).toggle(); |
| }); |
| //#endregion |
| //#region js/src/combobox.ts |
| /** |
| * -------------------------------------------------------------------------- |
| * Bootstrap combobox.ts |
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
| * -------------------------------------------------------------------------- |
| */ |
| /** |
| * Constants |
| */ |
| const NAME$16 = "combobox"; |
| const EVENT_KEY$13 = `.bs.combobox`; |
| const DATA_API_KEY$8 = ".data-api"; |
| const ESCAPE_KEY$1 = "Escape"; |
| const TAB_KEY = "Tab"; |
| const ARROW_UP_KEY$1 = "ArrowUp"; |
| const ARROW_DOWN_KEY$1 = "ArrowDown"; |
| const HOME_KEY$1 = "Home"; |
| const END_KEY$1 = "End"; |
| const ENTER_KEY = "Enter"; |
| const SPACE_KEY = " "; |
| const EVENT_CHANGE$3 = `change${EVENT_KEY$13}`; |
| const EVENT_SHOW$5 = `show${EVENT_KEY$13}`; |
| const EVENT_SHOWN$4 = `shown${EVENT_KEY$13}`; |
| const EVENT_HIDE$4 = `hide${EVENT_KEY$13}`; |
| const EVENT_HIDDEN$6 = `hidden${EVENT_KEY$13}`; |
| const EVENT_CLICK_DATA_API$4 = `click${EVENT_KEY$13}${DATA_API_KEY$8}`; |
| const CLASS_NAME_SHOW$3 = "show"; |
| const CLASS_NAME_SELECTED = "selected"; |
| const CLASS_NAME_PLACEHOLDER = "combobox-placeholder"; |
| const SELECTOR_DATA_TOGGLE$7 = "[data-bs-toggle=\"combobox\"]"; |
| const SELECTOR_MENU$1 = ".menu"; |
| const SELECTOR_MENU_ITEM = ".menu-item[data-bs-value]"; |
| const SELECTOR_VISIBLE_ITEMS = ".menu-item[data-bs-value]:not(.disabled):not(:disabled)"; |
| const SELECTOR_VALUE = ".combobox-value"; |
| const SELECTOR_SEARCH_INPUT = ".combobox-search-input"; |
| const SELECTOR_NO_RESULTS = ".combobox-no-results"; |
| const Default$15 = { |
| boundary: "clippingParents", |
| multiple: false, |
| name: null, |
| offset: [0, 2], |
| placeholder: "", |
| placement: "bottom-start", |
| search: false, |
| searchNormalize: false |
| }; |
| const DefaultType$15 = { |
| boundary: "(string|element)", |
| multiple: "boolean", |
| name: "(string|null)", |
| offset: "(array|string|function)", |
| placeholder: "string", |
| placement: "string", |
| search: "boolean", |
| searchNormalize: "boolean" |
| }; |
| /** |
| * Class definition |
| */ |
| var Combobox = class extends BaseComponent { |
| constructor(element, config) { |
| super(element, config); |
| this._toggle = this._element; |
| this._menu = SelectorEngine.next(this._toggle, SELECTOR_MENU$1)[0]; |
| this._valueDisplay = SelectorEngine.findOne(SELECTOR_VALUE, this._toggle); |
| this._searchInput = SelectorEngine.findOne(SELECTOR_SEARCH_INPUT, this._menu); |
| this._noResults = SelectorEngine.findOne(SELECTOR_NO_RESULTS, this._menu); |
| this._hiddenInput = null; |
| this._menuInstance = null; |
| this._createHiddenInput(); |
| this._createMenuInstance(); |
| this._syncInitialSelection(); |
| this._addEventListeners(); |
| } |
| static get Default() { |
| return Default$15; |
| } |
| static get DefaultType() { |
| return DefaultType$15; |
| } |
| static get NAME() { |
| return NAME$16; |
| } |
| toggle() { |
| return this._isShown() ? this.hide() : this.show(); |
| } |
| async show() { |
| if (isDisabled(this._toggle) || this._isShown()) return; |
| if (EventHandler.trigger(this._toggle, EVENT_SHOW$5).defaultPrevented) return; |
| this._menuInstance.show(); |
| if (this._searchInput) { |
| this._searchInput.value = ""; |
| this._filterItems(""); |
| requestAnimationFrame(() => this._searchInput.focus()); |
| } |
| EventHandler.trigger(this._toggle, EVENT_SHOWN$4); |
| } |
| async hide() { |
| if (!this._isShown()) return; |
| if (EventHandler.trigger(this._toggle, EVENT_HIDE$4).defaultPrevented) return; |
| this._menuInstance.hide(); |
| EventHandler.trigger(this._toggle, EVENT_HIDDEN$6); |
| } |
| dispose() { |
| if (this._menuInstance) { |
| this._menuInstance.dispose(); |
| this._menuInstance = null; |
| } |
| if (this._hiddenInput) { |
| this._hiddenInput.remove(); |
| this._hiddenInput = null; |
| } |
| EventHandler.off(this._menu, EVENT_KEY$13); |
| EventHandler.off(this._toggle, EVENT_KEY$13); |
| super.dispose(); |
| } |
| _isShown() { |
| return this._menu.classList.contains(CLASS_NAME_SHOW$3); |
| } |
| _createHiddenInput() { |
| const { name } = this._config; |
| if (!name) return; |
| this._hiddenInput = document.createElement("input"); |
| this._hiddenInput.type = "hidden"; |
| this._hiddenInput.name = name; |
| this._hiddenInput.value = ""; |
| this._toggle.parentNode.insertBefore(this._hiddenInput, this._toggle); |
| } |
| _createMenuInstance() { |
| this._menuInstance = new Menu(this._toggle, { |
| menu: this._menu, |
| autoClose: this._config.multiple ? "outside" : true, |
| boundary: this._config.boundary, |
| offset: this._config.offset, |
| placement: this._config.placement |
| }); |
| } |
| _syncInitialSelection() { |
| if (this._getSelectedItems().length > 0) { |
| this._updateToggleText(); |
| this._updateHiddenInput(); |
| } else this._showPlaceholder(); |
| } |
| _addEventListeners() { |
| EventHandler.on(this._menu, "click", SELECTOR_MENU_ITEM, (event) => { |
| const item = event.target.closest(SELECTOR_MENU_ITEM); |
| if (!item || isDisabled(item)) return; |
| event.preventDefault(); |
| event.stopPropagation(); |
| this._selectItem(item); |
| }); |
| EventHandler.on(this._toggle, "keydown", (event) => { |
| this._handleToggleKeydown(event); |
| }); |
| EventHandler.on(this._menu, "keydown", (event) => { |
| this._handleMenuKeydown(event); |
| }); |
| if (this._searchInput) { |
| EventHandler.on(this._searchInput, "input", () => { |
| this._filterItems(this._searchInput.value); |
| }); |
| EventHandler.on(this._searchInput, "keydown", (event) => { |
| if (event.key === ARROW_DOWN_KEY$1) { |
| event.preventDefault(); |
| const items = this._getVisibleItems(); |
| if (items.length > 0) items[0].focus(); |
| } |
| if (event.key === ESCAPE_KEY$1) { |
| this.hide(); |
| this._toggle.focus(); |
| } |
| }); |
| } |
| } |
| _selectItem(item) { |
| if (this._config.multiple) { |
| item.classList.toggle(CLASS_NAME_SELECTED); |
| setAriaAttribute(item, "aria-selected", item.classList.contains(CLASS_NAME_SELECTED)); |
| } else { |
| const previouslySelected = SelectorEngine.find(`.${CLASS_NAME_SELECTED}`, this._menu); |
| for (const prev of previouslySelected) { |
| prev.classList.remove(CLASS_NAME_SELECTED); |
| prev.setAttribute("aria-selected", "false"); |
| } |
| item.classList.add(CLASS_NAME_SELECTED); |
| item.setAttribute("aria-selected", "true"); |
| } |
| this._updateToggleText(); |
| this._updateHiddenInput(); |
| const value = this._config.multiple ? this._getSelectedItems().map((el) => el.dataset.bsValue) : item.dataset.bsValue; |
| EventHandler.trigger(this._toggle, EVENT_CHANGE$3, { |
| value, |
| item |
| }); |
| if (!this._config.multiple) { |
| this.hide(); |
| this._toggle.focus(); |
| } |
| } |
| _updateToggleText() { |
| const selectedItems = this._getSelectedItems(); |
| if (selectedItems.length === 0) { |
| this._showPlaceholder(); |
| return; |
| } |
| this._valueDisplay.classList.remove(CLASS_NAME_PLACEHOLDER); |
| if (this._config.multiple && selectedItems.length > 1) this._valueDisplay.textContent = `${selectedItems.length} selected`; |
| else { |
| const item = selectedItems[0]; |
| const label = SelectorEngine.findOne(".menu-item-content > span:first-child", item); |
| this._valueDisplay.textContent = label ? label.textContent : item.textContent.trim(); |
| } |
| } |
| _showPlaceholder() { |
| const { placeholder } = this._config; |
| if (placeholder) { |
| this._valueDisplay.textContent = placeholder; |
| this._valueDisplay.classList.add(CLASS_NAME_PLACEHOLDER); |
| } |
| } |
| _updateHiddenInput() { |
| if (!this._hiddenInput) return; |
| const values = this._getSelectedItems().map((el) => el.dataset.bsValue); |
| this._hiddenInput.value = this._config.multiple ? values.join(",") : values[0] || ""; |
| } |
| _getSelectedItems() { |
| return SelectorEngine.find(`.${CLASS_NAME_SELECTED}`, this._menu); |
| } |
| _getVisibleItems() { |
| return SelectorEngine.find(SELECTOR_VISIBLE_ITEMS, this._menu).filter((item) => isVisible(item)); |
| } |
| _filterItems(query) { |
| const normalizedQuery = this._normalizeText(query.toLowerCase().trim()); |
| const items = SelectorEngine.find(SELECTOR_MENU_ITEM, this._menu); |
| let visibleCount = 0; |
| for (const item of items) { |
| const text = this._normalizeText(item.textContent.toLowerCase().trim()); |
| const matches = !normalizedQuery || text.includes(normalizedQuery); |
| item.style.display = matches ? "" : "none"; |
| if (matches) visibleCount++; |
| } |
| if (this._noResults) this._noResults.classList.toggle("d-none", visibleCount > 0); |
| } |
| _normalizeText(text) { |
| if (this._config.searchNormalize) return text.normalize("NFD").replace(/[\u0300-\u036F]/g, ""); |
| return text; |
| } |
| _handleToggleKeydown(event) { |
| const { key } = event; |
| if (key === ARROW_DOWN_KEY$1 || key === ARROW_UP_KEY$1) { |
| event.preventDefault(); |
| if (!this._isShown()) this.show(); |
| const items = this._getVisibleItems(); |
| if (items.length > 0) (key === ARROW_DOWN_KEY$1 ? items[0] : items.at(-1)).focus(); |
| return; |
| } |
| if ((key === ENTER_KEY || key === SPACE_KEY) && !this._isShown()) { |
| event.preventDefault(); |
| this.show(); |
| } |
| } |
| _handleMenuKeydown(event) { |
| const { key, target } = event; |
| if (key === ESCAPE_KEY$1) { |
| event.preventDefault(); |
| event.stopPropagation(); |
| this.hide(); |
| this._toggle.focus(); |
| return; |
| } |
| if (key === TAB_KEY) { |
| this.hide(); |
| return; |
| } |
| const isInput = target.matches("input"); |
| if (key === ARROW_DOWN_KEY$1 || key === ARROW_UP_KEY$1) { |
| event.preventDefault(); |
| const items = this._getVisibleItems(); |
| if (items.length > 0) getNextActiveElement(items, target, key === ARROW_DOWN_KEY$1, !items.includes(target)).focus(); |
| return; |
| } |
| if (key === HOME_KEY$1 || key === END_KEY$1) { |
| event.preventDefault(); |
| const items = this._getVisibleItems(); |
| if (items.length > 0) (key === HOME_KEY$1 ? items[0] : items.at(-1)).focus(); |
| return; |
| } |
| if ((key === ENTER_KEY || key === SPACE_KEY) && !isInput) { |
| event.preventDefault(); |
| const item = target.closest(SELECTOR_MENU_ITEM); |
| if (item && !isDisabled(item)) this._selectItem(item); |
| } |
| } |
| }; |
| /** |
| * Data API implementation |
| */ |
| EventHandler.on(document, EVENT_CLICK_DATA_API$4, SELECTOR_DATA_TOGGLE$7, function(event) { |
| event.preventDefault(); |
| Combobox.getOrCreateInstance(this).toggle(); |
| }); |
| EventHandler.on(document, "DOMContentLoaded", () => { |
| for (const toggle of SelectorEngine.find(SELECTOR_DATA_TOGGLE$7)) Combobox.getOrCreateInstance(toggle); |
| }); |
| //#endregion |
| //#region node_modules/vanilla-calendar-pro/index.mjs |
| /*! name: vanilla-calendar-pro v3.2.0 | url: https://github.com/uvarov-frontend/vanilla-calendar-pro */ |
| var __defProp = Object.defineProperty; |
| var __defProps = Object.defineProperties; |
| var __getOwnPropDescs = Object.getOwnPropertyDescriptors; |
| var __getOwnPropSymbols = Object.getOwnPropertySymbols; |
| var __hasOwnProp = Object.prototype.hasOwnProperty; |
| var __propIsEnum = Object.prototype.propertyIsEnumerable; |
| var __defNormalProp = (e, t, n) => t in e ? __defProp(e, t, { |
| enumerable: !0, |
| configurable: !0, |
| writable: !0, |
| value: n |
| }) : e[t] = n; |
| var __spreadValues = (e, t) => { |
| for (var n in t || (t = {})) __hasOwnProp.call(t, n) && __defNormalProp(e, n, t[n]); |
| if (__getOwnPropSymbols) for (var n of __getOwnPropSymbols(t)) __propIsEnum.call(t, n) && __defNormalProp(e, n, t[n]); |
| return e; |
| }; |
| var __spreadProps = (e, t) => __defProps(e, __getOwnPropDescs(t)); |
| var __publicField = (e, t, n) => (__defNormalProp(e, "symbol" != typeof t ? t + "" : t, n), n); |
| const errorMessages = { |
| notFoundSelector: (e) => `${e} is not found, check the first argument passed to new Calendar. If the element lives inside a Shadow DOM, a string selector can't reach it - resolve the element yourself (e.g. shadowRoot.querySelector(...)) and pass it directly instead.`, |
| notInit: "The calendar has not been initialized, please initialize it using the \"init()\" method first.", |
| alreadyInit: "The calendar has already been initialized, calling init() again is not allowed. Create a new Calendar instance instead.", |
| alreadyDestroyed: "The calendar has already been destroyed, calling destroy() again is not allowed.", |
| notLocale: "You specified an incorrect language label or did not specify the required number of values ​​for «locale.weekdays» or «locale.months».", |
| incorrectTime: "The value of the time property can be: false, 12 or 24.", |
| incorrectMonthsCount: "For the «multiple» calendar type, the «displayMonthsCount» parameter can have a value from 2 to 12, and for all others it cannot be greater than 1." |
| }; |
| const setContext = (e, t, n) => { |
| e.context[t] = n; |
| }; |
| const destroy = (e) => { |
| var t, n, a, o, l, s, i; |
| if (!e.context.isInit) throw new Error(errorMessages.notInit); |
| if (e.context.isDestroyed) throw new Error(errorMessages.alreadyDestroyed); |
| null == (n = (t = e.context).cleanupSystemTheme) || n.call(t), e.inputMode ? (e.context.mainElement !== e.context.inputElement && (null == (a = e.context.mainElement.parentElement) || a.removeChild(e.context.mainElement)), null == (l = null == (o = e.context.inputElement) ? void 0 : o.replaceWith) || l.call(o, e.context.originalElement), setContext(e, "inputElement", void 0)) : null == (i = (s = e.context.mainElement).replaceWith) || i.call(s, e.context.originalElement), setContext(e, "mainElement", e.context.originalElement), setContext(e, "isDestroyed", !0), e.onDestroy && e.onDestroy(e); |
| }; |
| const getRootNode = (e) => e.getRootNode ? e.getRootNode() : document; |
| const skipOpenOnFocus = /* @__PURE__ */ new WeakSet(); |
| const shouldSkipOpenOnFocus = (e) => skipOpenOnFocus.has(e); |
| const setSkipOpenOnFocus = (e) => { |
| skipOpenOnFocus.add(e); |
| }; |
| const clearSkipOpenOnFocus = (e) => { |
| skipOpenOnFocus.delete(e); |
| }; |
| const PREV_TABINDEX_ATTR = "data-vc-prev-tabindex"; |
| const isFocusable = (e) => e.tabIndex >= 0 && !e.hasAttribute("disabled") && "true" !== e.getAttribute("aria-disabled"); |
| const storePrevTabIndex = (e) => { |
| if (e.hasAttribute(PREV_TABINDEX_ATTR)) return; |
| const t = e.getAttribute("tabindex"); |
| e.setAttribute(PREV_TABINDEX_ATTR, null != t ? t : ""); |
| }; |
| const restorePrevTabIndex = (e) => { |
| if (!e.hasAttribute(PREV_TABINDEX_ATTR)) return; |
| const t = e.getAttribute(PREV_TABINDEX_ATTR); |
| "" === t || null === t ? e.removeAttribute("tabindex") : e.setAttribute("tabindex", t), e.removeAttribute(PREV_TABINDEX_ATTR); |
| }; |
| const disableTabbing = (e) => { |
| isFocusable(e) && (storePrevTabIndex(e), e.tabIndex = -1); |
| const t = document.createTreeWalker(e, NodeFilter.SHOW_ELEMENT, { acceptNode: (e) => isFocusable(e) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP }); |
| for (; t.nextNode();) { |
| const e = t.currentNode; |
| storePrevTabIndex(e), e.tabIndex = -1; |
| } |
| }; |
| const restoreTabbing = (e) => { |
| restorePrevTabIndex(e), e.querySelectorAll(`[${PREV_TABINDEX_ATTR}]`).forEach(restorePrevTabIndex); |
| }; |
| const hide = (e) => { |
| if (e.context.isShowInInputMode && e.context.currentType) { |
| if (e.context.mainElement.dataset.vcCalendarHidden = "", setContext(e, "isShowInInputMode", !1), e.inputMode && disableTabbing(e.context.mainElement), e.context.cleanupHandlers[0] && (e.context.cleanupHandlers.forEach(((e) => e())), setContext(e, "cleanupHandlers", [])), e.inputMode && e.context.inputElement && e.context.mainElement.contains(getRootNode(e.context.mainElement).activeElement)) ("function" == typeof e.openOnFocus || !0 === e.openOnFocus) && setSkipOpenOnFocus(e), e.context.inputElement.focus(); |
| e.onHide && e.onHide(e); |
| } |
| }; |
| const getDate = (e) => /* @__PURE__ */ new Date(`${e}T00:00:00`); |
| const getDateString = (e) => `${e.getFullYear()}-${String(e.getMonth() + 1).padStart(2, "0")}-${String(e.getDate()).padStart(2, "0")}`; |
| const parseDates = (e) => e.reduce(((e, t) => { |
| if (t instanceof Date || "number" == typeof t) { |
| const n = t instanceof Date ? t : new Date(t); |
| e.push(getDateString(n)); |
| } else t.match(/^(\d{4}-\d{2}-\d{2})$/g) ? e.push(t) : t.replace(/(\d{4}-\d{2}-\d{2}).*?(\d{4}-\d{2}-\d{2})/g, ((t, n, a) => { |
| const o = getDate(n), l = getDate(a), s = new Date(o.getTime()); |
| for (; s <= l; s.setDate(s.getDate() + 1)) e.push(getDateString(s)); |
| return t; |
| })); |
| return e; |
| }), []); |
| function getOffset(e) { |
| if (!e || !e.getBoundingClientRect) return { |
| top: 0, |
| bottom: 0, |
| left: 0, |
| right: 0 |
| }; |
| const t = e.getBoundingClientRect(), n = document.documentElement; |
| return { |
| bottom: t.bottom, |
| right: t.right, |
| top: t.top + window.scrollY - n.clientTop, |
| left: t.left + window.scrollX - n.clientLeft |
| }; |
| } |
| function getViewportDimensions() { |
| return { |
| vw: Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0), |
| vh: Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0) |
| }; |
| } |
| function getWindowScrollPosition() { |
| return { |
| left: window.scrollX || document.documentElement.scrollLeft || 0, |
| top: window.scrollY || document.documentElement.scrollTop || 0 |
| }; |
| } |
| function calculateAvailableSpace(e) { |
| const { top: t, left: n } = getWindowScrollPosition(), { top: a, left: o } = getOffset(e), { vh: l, vw: s } = getViewportDimensions(), i = a - t, r = o - n; |
| return { |
| top: i, |
| bottom: l - (i + e.clientHeight), |
| left: r, |
| right: s - (r + e.clientWidth) |
| }; |
| } |
| function getAvailablePosition(e, t, n = 5) { |
| const a = { |
| top: !0, |
| bottom: !0, |
| left: !0, |
| right: !0 |
| }, o = []; |
| if (!t || !e) return { |
| canShow: a, |
| parentPositions: o |
| }; |
| const { bottom: l, top: s } = calculateAvailableSpace(e), { top: i, left: r } = getOffset(e), { height: c, width: d } = t.getBoundingClientRect(), { vh: u, vw: m } = getViewportDimensions(), p = m / 2, h = u / 2; |
| return [ |
| { |
| condition: i < h, |
| position: "top" |
| }, |
| { |
| condition: i > h, |
| position: "bottom" |
| }, |
| { |
| condition: r < p, |
| position: "left" |
| }, |
| { |
| condition: r > p, |
| position: "right" |
| } |
| ].forEach((({ condition: e, position: t }) => { |
| e && o.push(t); |
| })), Object.assign(a, { |
| top: c <= s - n, |
| bottom: c <= l - n, |
| left: d <= r, |
| right: d <= m - r |
| }), { |
| canShow: a, |
| parentPositions: o |
| }; |
| } |
| const handleDay = (e, t, n, a) => { |
| var o; |
| const l = a.querySelector(`[data-vc-date="${t}"]`), s = null == l ? void 0 : l.querySelector("[data-vc-date-btn]"); |
| if (!l || !s) return; |
| if (null != n && n.modifier && s.classList.add(...n.modifier.trim().split(" ")), !(null == n ? void 0 : n.html)) return; |
| const i = document.createElement("div"); |
| i.className = e.styles.datePopup, i.dataset.vcDatePopup = "", i.innerHTML = e.sanitizerHTML(n.html), s.ariaExpanded = "true", s.ariaLabel = `${s.ariaLabel}, ${null == (o = null == i ? void 0 : i.textContent) ? void 0 : o.replace(/^\s+|\s+(?=\s)|\s+$/g, "").replace(/ /g, " ")}`, l.appendChild(i), requestAnimationFrame((() => { |
| if (!i) return; |
| const { canShow: e } = getAvailablePosition(l, i), t = e.bottom ? l.offsetHeight : -i.offsetHeight, n = e.left && !e.right ? l.offsetWidth - i.offsetWidth / 2 : !e.left && e.right ? i.offsetWidth / 2 : 0; |
| Object.assign(i.style, { |
| left: `${n}px`, |
| top: `${t}px` |
| }); |
| })); |
| }; |
| const createDatePopup = (e, t) => { |
| var n; |
| e.popups && (null == (n = Object.entries(e.popups)) || n.forEach((([n, a]) => { |
| parseDates([n]).forEach(((n) => handleDay(e, n, a, t))); |
| }))); |
| }; |
| const updateAttribute = (e, t, n, a = "") => { |
| t ? e.setAttribute(n, a) : e.getAttribute(n) === a && e.removeAttribute(n); |
| }; |
| const setDateModifier = (e, t, n, a, o, l, s) => { |
| var i, r, c, d; |
| const u = getDate(e.context.displayDateMin) > getDate(l) || getDate(e.context.displayDateMax) < getDate(l) || (null == (i = e.context.disableDates) ? void 0 : i.includes(l)) || !e.selectionMonthsMode && "current" !== s || !e.selectionYearsMode && getDate(l).getFullYear() !== t; |
| updateAttribute(n, u, "data-vc-date-disabled"), a && updateAttribute(a, u, "aria-disabled", "true"), a && updateAttribute(a, u, "tabindex", "-1"), updateAttribute(n, !e.disableToday && e.context.dateToday === l, "data-vc-date-today"), updateAttribute(n, !e.disableToday && e.context.dateToday === l, "aria-current", "date"), updateAttribute(n, null == (r = e.selectedWeekends) ? void 0 : r.includes(o), "data-vc-date-weekend"); |
| const m = (null == (c = e.selectedHolidays) ? void 0 : c[0]) ? parseDates(e.selectedHolidays) : []; |
| if (updateAttribute(n, m.includes(l), "data-vc-date-holiday"), (null == (d = e.context.selectedDates) ? void 0 : d.includes(l)) ? (n.setAttribute("data-vc-date-selected", ""), a && a.setAttribute("aria-selected", "true"), e.context.selectedDates.length > 1 && "multiple-ranged" === e.selectionDatesMode && (e.context.selectedDates[0] === l && e.context.selectedDates[e.context.selectedDates.length - 1] === l ? n.setAttribute("data-vc-date-selected", "first-and-last") : e.context.selectedDates[0] === l ? n.setAttribute("data-vc-date-selected", "first") : e.context.selectedDates[e.context.selectedDates.length - 1] === l && n.setAttribute("data-vc-date-selected", "last"), e.context.selectedDates[0] !== l && e.context.selectedDates[e.context.selectedDates.length - 1] !== l && n.setAttribute("data-vc-date-selected", "middle"))) : n.hasAttribute("data-vc-date-selected") && (n.removeAttribute("data-vc-date-selected"), a && a.removeAttribute("aria-selected")), !e.context.disableDates.includes(l) && e.enableEdgeDatesOnly && e.context.selectedDates.length > 1 && "multiple-ranged" === e.selectionDatesMode) { |
| const t = getDate(e.context.selectedDates[0]), a = getDate(e.context.selectedDates[e.context.selectedDates.length - 1]), o = getDate(l); |
| updateAttribute(n, o > t && o < a, "data-vc-date-selected", "middle"); |
| } |
| }; |
| const getLocaleString = (e, t, n) => (/* @__PURE__ */ new Date(`${e}T00:00:00.000Z`)).toLocaleString(t, n); |
| const getWeekNumber = (e, t) => { |
| const n = getDate(e), a = (n.getDay() - t + 7) % 7; |
| n.setDate(n.getDate() + 3 - a); |
| const o = new Date(n.getFullYear(), 0, 1), l = Math.ceil(((+n - +o) / 864e5 + 1) / 7); |
| return { |
| year: n.getFullYear(), |
| week: l |
| }; |
| }; |
| const addWeekNumberForDate = (e, t, n) => { |
| const a = getWeekNumber(n, e.firstWeekday); |
| a && (t.dataset.vcDateWeekNumber = String(a.week)); |
| }; |
| const setDaysAsDisabled = (e, t, n) => { |
| var a, o, l, s, i; |
| const r = null == (a = e.disableWeekdays) ? void 0 : a.includes(n), c = e.disableAllDates && !!(null == (o = e.context.enableDates) ? void 0 : o[0]); |
| !r && !c || null != (l = e.context.enableDates) && l.includes(t) || null != (s = e.context.disableDates) && s.includes(t) || (e.context.disableDates.push(t), null == (i = e.context.disableDates) || i.sort(((e, t) => +new Date(e) - +new Date(t)))); |
| }; |
| const createDate = (e, t, n, a, o, l) => { |
| const s = getDate(o).getDay(), i = "string" == typeof e.locale && e.locale.length ? e.locale : "en", r = document.createElement("div"); |
| let c; |
| r.className = e.styles.date, r.dataset.vcDate = o, r.dataset.vcDateMonth = l, r.dataset.vcDateWeekDay = String(s), r.role = "gridcell", ("current" === l || e.displayDatesOutside) && (c = document.createElement("button"), c.className = e.styles.dateBtn, c.type = "button", c.ariaLabel = getLocaleString(o, i, { |
| dateStyle: "long", |
| timeZone: "UTC" |
| }), c.dataset.vcDateBtn = "", c.innerText = String(a), r.appendChild(c)), e.enableWeekNumbers && addWeekNumberForDate(e, r, o), setDaysAsDisabled(e, o, s), setDateModifier(e, t, r, c, s, o, l), n.addDate(r), e.onCreateDateEls && e.onCreateDateEls(e, r); |
| }; |
| const createDatesFromCurrentMonth = (e, t, n, a, o) => { |
| for (let l = 1; l <= n; l++) { |
| const n = new Date(a, o, l); |
| createDate(e, a, t, l, getDateString(n), "current"); |
| } |
| }; |
| const createDatesFromNextMonth = (e, t, n, a, o) => { |
| const l = o + 1 === 12 ? a + 1 : a, s = o + 1 === 12 ? "01" : o + 2 < 10 ? `0${o + 2}` : o + 2; |
| for (let o = 1; o <= n; o++) { |
| const n = o < 10 ? `0${o}` : String(o); |
| createDate(e, a, t, o, `${l}-${s}-${n}`, "next"); |
| } |
| }; |
| const createDatesFromPrevMonth = (e, t, n, a, o) => { |
| let l = new Date(n, a, 0).getDate() - (o - 1); |
| const s = 0 === a ? n - 1 : n, i = 0 === a ? 12 : a < 10 ? `0${a}` : a; |
| for (let a = o; a > 0; a--, l++) createDate(e, n, t, l, `${s}-${i}-${l}`, "prev"); |
| }; |
| const createWeekNumbers = (e, t, n, a, o) => { |
| if (!e.enableWeekNumbers) return; |
| a.textContent = ""; |
| const l = document.createElement("b"); |
| l.className = e.styles.weekNumbersTitle, l.innerText = "#", l.dataset.vcWeekNumbers = "title", a.appendChild(l); |
| const s = document.createElement("div"); |
| s.className = e.styles.weekNumbersContent, s.dataset.vcWeekNumbers = "content", a.appendChild(s); |
| const i = document.createElement("button"); |
| i.type = "button", i.className = e.styles.weekNumber; |
| const r = o.querySelectorAll("[data-vc-date]"), c = Math.ceil((t + n) / 7); |
| for (let t = 0; t < c; t++) { |
| const n = r[0 === t ? 6 : 7 * t].dataset.vcDate, a = getWeekNumber(n, e.firstWeekday); |
| if (!a) return; |
| const o = i.cloneNode(!0); |
| o.innerText = String(a.week), o.dataset.vcWeekNumber = String(a.week), o.dataset.vcWeekYear = String(a.year), o.role = "rowheader", o.ariaLabel = `${a.week}`, s.appendChild(o); |
| } |
| }; |
| const createDates = (e) => { |
| const t = new Date(e.context.selectedYear, e.context.selectedMonth, 1), n = e.context.mainElement.querySelectorAll("[data-vc=\"dates\"]"), a = e.context.mainElement.querySelectorAll("[data-vc-week=\"numbers\"]"); |
| n.forEach(((n, o) => { |
| e.selectionDatesMode || (n.dataset.vcDatesDisabled = ""), n.textContent = ""; |
| const l = new Date(t); |
| l.setMonth(l.getMonth() + o); |
| const s = l.getMonth(), i = l.getFullYear(), r = (new Date(i, s, 1).getDay() - e.firstWeekday + 7) % 7, c = new Date(i, s + 1, 0).getDate(), d = r + c, u = Math.ceil(d / 7), m = 7 * u - d, p = []; |
| for (let t = 0; t < u; t++) { |
| const t = document.createElement("div"); |
| t.className = e.styles.datesRow, t.setAttribute("data-vc-dates", "row"), t.setAttribute("role", "row"), p.push(t); |
| } |
| let h = 0, v = 0; |
| const g = { addDate: (e) => { |
| p[h].appendChild(e), v++, v >= 7 && (h++, v = 0); |
| } }; |
| createDatesFromPrevMonth(e, g, i, s, r), createDatesFromCurrentMonth(e, g, c, i, s), createDatesFromNextMonth(e, g, m, i, s); |
| for (const e of p) n.appendChild(e); |
| createDatePopup(e, n), createWeekNumbers(e, r, c, a[o], n); |
| })); |
| }; |
| const layoutDefault = (e) => `\n <div class="${e.styles.header}" data-vc="header" role="toolbar" aria-label="${e.labels.navigation}">\n <#ArrowPrev [month] />\n <div class="${e.styles.headerContent}" data-vc-header="content">\n <#Month />\n <#Year />\n </div>\n <#ArrowNext [month] />\n </div>\n <div class="${e.styles.wrapper}" data-vc="wrapper">\n <#WeekNumbers />\n <div class="${e.styles.content}" data-vc="content" role="grid">\n <#Week />\n <#Dates />\n <#DateRangeTooltip />\n </div>\n </div>\n <#ControlTime />\n`; |
| const layoutMonths = (e) => `\n <div class="${e.styles.header}" data-vc="header" role="toolbar" aria-label="${e.labels.navigation}">\n <div class="${e.styles.headerContent}" data-vc-header="content">\n <#Month />\n <#Year />\n </div>\n </div>\n <div class="${e.styles.wrapper}" data-vc="wrapper">\n <div class="${e.styles.content}" data-vc="content">\n <#Months />\n </div>\n </div>\n`; |
| const layoutMultiple = (e) => `\n <div class="${e.styles.controls}" data-vc="controls" role="toolbar" aria-label="${e.labels.navigation}">\n <#ArrowPrev [month] />\n <#ArrowNext [month] />\n </div>\n <div class="${e.styles.grid}" data-vc="grid">\n <#Multiple>\n <div class="${e.styles.column}" data-vc="column" role="region">\n <div class="${e.styles.header}" data-vc="header">\n <div class="${e.styles.headerContent}" data-vc-header="content">\n <#Month />\n <#Year />\n </div>\n </div>\n <div class="${e.styles.wrapper}" data-vc="wrapper">\n <#WeekNumbers />\n <div class="${e.styles.content}" data-vc="content" role="grid" aria-multiselectable="true">\n <#Week />\n <#Dates />\n </div>\n </div>\n </div>\n <#/Multiple>\n <#DateRangeTooltip />\n </div>\n <#ControlTime />\n`; |
| const layoutYears = (e) => `\n <div class="${e.styles.header}" data-vc="header" role="toolbar" aria-label="${e.labels.navigation}">\n <#ArrowPrev [year] />\n <div class="${e.styles.headerContent}" data-vc-header="content">\n <#Month />\n <#Year />\n </div>\n <#ArrowNext [year] />\n </div>\n <div class="${e.styles.wrapper}" data-vc="wrapper">\n <div class="${e.styles.content}" data-vc="content">\n <#Years />\n </div>\n </div>\n`; |
| const ArrowNext = (e, t) => `<button type="button" class="${e.styles.arrowNext}" data-vc-arrow="next" aria-label="${e.labels.arrowNext[t]}"></button>`; |
| const ArrowPrev = (e, t) => `<button type="button" class="${e.styles.arrowPrev}" data-vc-arrow="prev" aria-label="${e.labels.arrowPrev[t]}"></button>`; |
| const ControlTime = (e) => e.selectionTimeMode ? `<div class="${e.styles.time}" data-vc="time" role="group" aria-label="${e.labels.selectingTime}"></div>` : ""; |
| const DateRangeTooltip = (e) => e.onCreateDateRangeTooltip ? `<div class="${e.styles.dateRangeTooltip}" data-vc-date-range-tooltip="hidden"></div>` : ""; |
| const Dates = (e) => `<div class="${e.styles.dates}" data-vc="dates" role="rowgroup" aria-label="${e.labels.dates}"></div>`; |
| const Month = (e) => `<button type="button" class="${e.styles.month}" data-vc="month"></button>`; |
| const Months = (e) => `<div class="${e.styles.months}" data-vc="months" role="grid" aria-label="${e.labels.months}"></div>`; |
| const Week = (e) => `<div class="${e.styles.week}" data-vc="week" role="row" aria-label="${e.labels.week}"></div>`; |
| const WeekNumbers = (e) => e.enableWeekNumbers ? `<div class="${e.styles.weekNumbers}" data-vc-week="numbers" role="row" aria-label="${e.labels.weekNumber}"></div>` : ""; |
| const Year = (e) => `<button type="button" class="${e.styles.year}" data-vc="year"></button>`; |
| const Years = (e) => `<div class="${e.styles.years}" data-vc="years" role="grid" aria-label="${e.labels.years}"></div>`; |
| const components = { |
| ArrowNext, |
| ArrowPrev, |
| ControlTime, |
| Dates, |
| DateRangeTooltip, |
| Month, |
| Months, |
| Week, |
| WeekNumbers, |
| Year, |
| Years |
| }; |
| const getComponent = (e) => components[e]; |
| const parseLayout = (e, t) => t.replace(/[\n\t]/g, "").replace(/<#(?!\/?Multiple)(.*?)>/g, ((t, n) => { |
| const a = (n.match(/\[(.*?)\]/) || [])[1], o = n.replace(/[/\s\n\t]|\[(.*?)\]/g, ""), l = getComponent(o), s = l ? l(e, null != a ? a : null) : ""; |
| return e.sanitizerHTML(s); |
| })).replace(/[\n\t]/g, ""); |
| const parseMultipleLayout = (e, t) => t.replace(/* @__PURE__ */ new RegExp("<#Multiple>(.*?)<#\\/Multiple>", "gs"), ((t, n) => { |
| const a = Array(e.context.displayMonthsCount).fill(n).join(""); |
| return e.sanitizerHTML(a); |
| })).replace(/[\n\t]/g, ""); |
| const createLayouts = (e, t) => { |
| const n = { |
| default: layoutDefault, |
| month: layoutMonths, |
| year: layoutYears, |
| multiple: layoutMultiple |
| }; |
| if (Object.keys(n).forEach(((t) => { |
| const a = t; |
| e.layouts[a].length || (e.layouts[a] = n[a](e)); |
| })), e.context.mainElement.className = e.styles.calendar, e.context.mainElement.dataset.vc = "calendar", e.context.mainElement.dataset.vcType = e.context.currentType, e.context.mainElement.role = "application", e.context.mainElement.tabIndex = 0, e.context.mainElement.ariaLabel = e.labels.application, "multiple" !== e.context.currentType) { |
| if ("multiple" === e.type && t) { |
| const n = e.context.mainElement.querySelector("[data-vc=\"controls\"]"), a = e.context.mainElement.querySelector("[data-vc=\"grid\"]"), o = t.closest("[data-vc=\"column\"]"); |
| n && n.remove(), a && (a.dataset.vcGrid = "hidden"), o && (o.dataset.vcColumn = e.context.currentType), o && (o.innerHTML = e.sanitizerHTML(parseLayout(e, e.layouts[e.context.currentType]))); |
| return; |
| } |
| e.context.mainElement.innerHTML = e.sanitizerHTML(parseLayout(e, e.layouts[e.context.currentType])); |
| } else e.context.mainElement.innerHTML = e.sanitizerHTML(parseMultipleLayout(e, parseLayout(e, e.layouts[e.context.currentType]))); |
| }; |
| const setVisibilityArrows = (e, t, n, a) => { |
| e.style.visibility = n ? "hidden" : "", t.style.visibility = a ? "hidden" : ""; |
| }; |
| const handleDefaultType = (e, t, n) => { |
| const a = getDate(getDateString(new Date(e.context.selectedYear, e.context.selectedMonth, 1))), o = new Date(a.getTime()), l = new Date(a.getTime()); |
| o.setMonth(o.getMonth() - e.monthsToSwitch), l.setMonth(l.getMonth() + e.monthsToSwitch); |
| const s = getDate(e.context.dateMin), i = getDate(e.context.dateMax); |
| e.selectionYearsMode || (s.setFullYear(a.getFullYear()), i.setFullYear(a.getFullYear())); |
| const r = !e.selectionMonthsMode || o.getFullYear() < s.getFullYear() || o.getFullYear() === s.getFullYear() && o.getMonth() < s.getMonth(), c = !e.selectionMonthsMode || l.getFullYear() > i.getFullYear() || l.getFullYear() === i.getFullYear() && l.getMonth() > i.getMonth() - (e.context.displayMonthsCount - 1); |
| setVisibilityArrows(t, n, r, c); |
| }; |
| const handleYearType = (e, t, n) => { |
| const a = getDate(e.context.dateMin), o = getDate(e.context.dateMax), l = !!(a.getFullYear() && e.context.displayYear - 7 <= a.getFullYear()), s = !!(o.getFullYear() && e.context.displayYear + 7 >= o.getFullYear()); |
| setVisibilityArrows(t, n, l, s); |
| }; |
| const visibilityArrows = (e) => { |
| if ("month" === e.context.currentType) return; |
| const t = e.context.mainElement.querySelector("[data-vc-arrow=\"prev\"]"), n = e.context.mainElement.querySelector("[data-vc-arrow=\"next\"]"); |
| if (!t || !n) return; |
| ({ |
| default: () => handleDefaultType(e, t, n), |
| year: () => handleYearType(e, t, n) |
| })["multiple" === e.context.currentType ? "default" : e.context.currentType](); |
| }; |
| const visibilityHandler = (e, t, n, a, o) => { |
| const l = new Date(a.setFullYear(e.context.selectedYear, e.context.selectedMonth + n)).getFullYear(), s = new Date(a.setMonth(e.context.selectedMonth + n)).getMonth(), i = e.context.locale.months.long[s], r = t.closest("[data-vc=\"column\"]"); |
| r && (r.ariaLabel = `${i} ${l}`); |
| const c = { |
| month: { |
| id: s, |
| label: i |
| }, |
| year: { |
| id: l, |
| label: l |
| } |
| }; |
| t.innerText = String(c[o].label), t.dataset[`vc${o.charAt(0).toUpperCase() + o.slice(1)}`] = String(c[o].id), t.ariaLabel = `${e.labels[o]} ${c[o].label}`; |
| const d = { |
| month: e.selectionMonthsMode, |
| year: e.selectionYearsMode |
| }, u = !1 === d[o] || "only-arrows" === d[o]; |
| u && (t.tabIndex = -1), t.disabled = u; |
| }; |
| const visibilityTitle = (e) => { |
| const t = e.context.mainElement.querySelectorAll("[data-vc=\"month\"]"), n = e.context.mainElement.querySelectorAll("[data-vc=\"year\"]"), a = new Date(e.context.selectedYear, e.context.selectedMonth, 1); |
| [t, n].forEach(((t) => null == t ? void 0 : t.forEach(((t, n) => visibilityHandler(e, t, n, a, t.dataset.vc))))); |
| }; |
| const setYearModifier = (e, t, n, a, o) => { |
| var l, s; |
| const i = { |
| month: "[data-vc-months-month]", |
| year: "[data-vc-years-year]" |
| }, r = { |
| month: { |
| selected: "data-vc-months-month-selected", |
| aria: "aria-selected", |
| value: "vcMonthsMonth", |
| selectedProperty: "selectedMonth" |
| }, |
| year: { |
| selected: "data-vc-years-year-selected", |
| aria: "aria-selected", |
| value: "vcYearsYear", |
| selectedProperty: "selectedYear" |
| } |
| }; |
| o && (null == (l = e.context.mainElement.querySelectorAll(i[n])) || l.forEach(((e) => { |
| var t; |
| e.removeAttribute(r[n].selected), null == (t = e.parentElement) || t.removeAttribute(r[n].aria); |
| })), setContext(e, r[n].selectedProperty, Number(t.dataset[r[n].value])), visibilityTitle(e), "year" === n && visibilityArrows(e)), a && (t.setAttribute(r[n].selected, ""), null == (s = t.parentElement) || s.setAttribute(r[n].aria, "true")); |
| }; |
| const getColumnID = (e, t) => { |
| var n; |
| if ("multiple" !== e.type) return { |
| currentValue: null, |
| columnID: 0 |
| }; |
| const a = e.context.mainElement.querySelectorAll("[data-vc=\"column\"]"), o = Array.from(a).findIndex(((e) => e.closest(`[data-vc-column="${t}"]`))); |
| return { |
| currentValue: o >= 0 ? Number(null == (n = a[o].querySelector(`[data-vc="${t}"]`)) ? void 0 : n.getAttribute(`data-vc-${t}`)) : null, |
| columnID: Math.max(o, 0) |
| }; |
| }; |
| const createMonthEl = (e, t, n, a, o, l, s) => { |
| const i = document.createElement("div"); |
| i.className = e.styles.monthsCell, i.dataset.vcMonths = "cell", i.role = "gridcell"; |
| const r = t.cloneNode(!1); |
| return r.className = e.styles.monthsMonth, r.innerText = a, r.ariaLabel = o, r.dataset.vcMonthsMonth = `${s}`, l && (r.ariaDisabled = "true"), l && (r.tabIndex = -1), r.disabled = l, i.appendChild(r), setYearModifier(e, r, "month", n === s, !1), i; |
| }; |
| const createMonths = (e, t) => { |
| var n, a; |
| const o = null == (n = null == t ? void 0 : t.closest("[data-vc=\"header\"]")) ? void 0 : n.querySelector("[data-vc=\"year\"]"), l = o ? Number(o.dataset.vcYear) : e.context.selectedYear, s = (null == t ? void 0 : t.dataset.vcMonth) ? Number(t.dataset.vcMonth) : e.context.selectedMonth; |
| setContext(e, "currentType", "month"), createLayouts(e, t), visibilityTitle(e); |
| const i = e.context.mainElement.querySelector("[data-vc=\"months\"]"); |
| if (!e.selectionMonthsMode || !i) return; |
| const r = e.monthsToSwitch > 1 ? e.context.locale.months.long.map(((t, n) => s - e.monthsToSwitch * n)).concat(e.context.locale.months.long.map(((t, n) => s + e.monthsToSwitch * n))).filter(((e) => e >= 0 && e <= 12)) : Array.from(Array(12).keys()), c = document.createElement("button"); |
| let d; |
| c.type = "button"; |
| for (let t = 0; t < 12; t++) { |
| t % 4 == 0 && (d = document.createElement("div"), d.className = e.styles.monthsRow, d.dataset.vcMonths = "row", d.role = "row", i.appendChild(d)); |
| const n = getDate(e.context.dateMin), a = getDate(e.context.dateMax), o = e.context.displayMonthsCount - 1, { columnID: u } = getColumnID(e, "month"), m = l <= n.getFullYear() && t < n.getMonth() + u || l >= a.getFullYear() && t > a.getMonth() - o + u || l > a.getFullYear() || t !== s && !r.includes(t), p = createMonthEl(e, c, s, e.context.locale.months.short[t], e.context.locale.months.long[t], m, t); |
| d?.appendChild(p), e.onCreateMonthEls && e.onCreateMonthEls(e, p); |
| } |
| null == (a = e.context.mainElement.querySelector("[data-vc-months-month]:not([disabled])")) || a.focus(); |
| }; |
| const TimeInput = (e, t, n, a, o) => `\n <label class="${t}" data-vc-time-input="${e}">\n <input type="text" name="${e}" maxlength="2" aria-label="${n[`input${e.charAt(0).toUpperCase() + e.slice(1)}`]}" value="${a}" ${o ? "disabled" : ""}>\n </label>\n`; |
| const TimeRange = (e, t, n, a, o, l, s) => `\n <label class="${t}" data-vc-time-range="${e}">\n <input type="range" name="${e}" min="${a}" max="${o}" step="${l}" aria-label="${n[`range${e.charAt(0).toUpperCase() + e.slice(1)}`]}" value="${s}">\n </label>\n`; |
| const handleActions = (e, t, n, a) => { |
| ({ |
| hour: () => setContext(e, "selectedHours", n), |
| minute: () => setContext(e, "selectedMinutes", n) |
| })[a](), setContext(e, "selectedTime", `${e.context.selectedHours}:${e.context.selectedMinutes}${e.context.selectedKeeping ? ` ${e.context.selectedKeeping}` : ""}`), e.onChangeTime && e.onChangeTime(e, t, !1), e.inputMode && e.context.inputElement && e.context.mainElement && e.onChangeToInput && e.onChangeToInput(e, t); |
| }; |
| const transformTime24 = (e, t) => { |
| var n; |
| return (null == (n = { |
| 0: { |
| AM: "00", |
| PM: "12" |
| }, |
| 1: { |
| AM: "01", |
| PM: "13" |
| }, |
| 2: { |
| AM: "02", |
| PM: "14" |
| }, |
| 3: { |
| AM: "03", |
| PM: "15" |
| }, |
| 4: { |
| AM: "04", |
| PM: "16" |
| }, |
| 5: { |
| AM: "05", |
| PM: "17" |
| }, |
| 6: { |
| AM: "06", |
| PM: "18" |
| }, |
| 7: { |
| AM: "07", |
| PM: "19" |
| }, |
| 8: { |
| AM: "08", |
| PM: "20" |
| }, |
| 9: { |
| AM: "09", |
| PM: "21" |
| }, |
| 10: { |
| AM: "10", |
| PM: "22" |
| }, |
| 11: { |
| AM: "11", |
| PM: "23" |
| }, |
| 12: { |
| AM: "00", |
| PM: "12" |
| } |
| }[Number(e)]) ? void 0 : n[t]) || String(e); |
| }; |
| const handleClickKeepingTime = (e, t, n, a, o) => { |
| const l = (l) => { |
| const s = "AM" === e.context.selectedKeeping ? "PM" : "AM", i = transformTime24(e.context.selectedHours, s); |
| Number(i) <= a && Number(i) >= o ? (setContext(e, "selectedKeeping", s), n.value = i, handleActions(e, l, e.context.selectedHours, "hour"), t.ariaLabel = `${e.labels.btnKeeping} ${e.context.selectedKeeping}`, t.innerText = e.context.selectedKeeping) : e.onChangeTime && e.onChangeTime(e, l, !0); |
| }; |
| return t.addEventListener("click", l), () => { |
| t.removeEventListener("click", l); |
| }; |
| }; |
| const transformTime12 = (e) => ({ |
| 0: "12", |
| 13: "01", |
| 14: "02", |
| 15: "03", |
| 16: "04", |
| 17: "05", |
| 18: "06", |
| 19: "07", |
| 20: "08", |
| 21: "09", |
| 22: "10", |
| 23: "11" |
| })[Number(e)] || String(e); |
| const updateInputAndRange = (e, t, n, a) => { |
| e.value = n, t.value = a; |
| }; |
| const updateKeepingTime$1 = (e, t, n) => { |
| t && n && (setContext(e, "selectedKeeping", n), t.innerText = n); |
| }; |
| const handleInput$1 = (e, t, n, a, o, l, s) => { |
| const i = { |
| hour: (i, r, c) => { |
| if (!e.selectionTimeMode) return; |
| ({ |
| 12: () => { |
| if (!e.context.selectedKeeping) return; |
| const d = Number(transformTime24(r, e.context.selectedKeeping)); |
| if (!(d <= l && d >= s)) return updateInputAndRange(n, t, e.context.selectedHours, e.context.selectedHours), void (e.onChangeTime && e.onChangeTime(e, c, !0)); |
| updateInputAndRange(n, t, transformTime12(r), transformTime24(r, e.context.selectedKeeping)), i > 12 && updateKeepingTime$1(e, a, "PM"), handleActions(e, c, transformTime12(r), o); |
| }, |
| 24: () => { |
| if (!(i <= l && i >= s)) return updateInputAndRange(n, t, e.context.selectedHours, e.context.selectedHours), void (e.onChangeTime && e.onChangeTime(e, c, !0)); |
| updateInputAndRange(n, t, r, r), handleActions(e, c, r, o); |
| } |
| })[e.selectionTimeMode](); |
| }, |
| minute: (a, i, r) => { |
| if (!(a <= l && a >= s)) return n.value = e.context.selectedMinutes, void (e.onChangeTime && e.onChangeTime(e, r, !0)); |
| n.value = i, t.value = i, handleActions(e, r, i, o); |
| } |
| }, r = (e) => { |
| const t = Number(n.value), a = n.value.padStart(2, "0"); |
| i[o] && i[o](t, a, e); |
| }; |
| return n.addEventListener("change", r), () => { |
| n.removeEventListener("change", r); |
| }; |
| }; |
| const updateInputAndTime = (e, t, n, a, o) => { |
| t.value = o, handleActions(e, n, o, a); |
| }; |
| const updateKeepingTime = (e, t, n) => { |
| t && (setContext(e, "selectedKeeping", n), t.innerText = n); |
| }; |
| const handleRange = (e, t, n, a, o) => { |
| const l = (l) => { |
| const s = Number(t.value), i = t.value.padStart(2, "0"), r = "hour" === o, c = 24 === e.selectionTimeMode, d = s > 0 && s < 12; |
| r && !c && updateKeepingTime(e, a, 0 === s || d ? "AM" : "PM"), updateInputAndTime(e, n, l, o, !r || c || d ? i : transformTime12(t.value)); |
| }; |
| return t.addEventListener("input", l), () => { |
| t.removeEventListener("input", l); |
| }; |
| }; |
| const handleMouseOver = (e) => e.setAttribute("data-vc-input-focus", ""); |
| const handleMouseOut = (e) => e.removeAttribute("data-vc-input-focus"); |
| const handleTime = (e, t) => { |
| const n = t.querySelector("[data-vc-time-range=\"hour\"] input[name=\"hour\"]"), a = t.querySelector("[data-vc-time-range=\"minute\"] input[name=\"minute\"]"), o = t.querySelector("[data-vc-time-input=\"hour\"] input[name=\"hour\"]"), l = t.querySelector("[data-vc-time-input=\"minute\"] input[name=\"minute\"]"), s = t.querySelector("[data-vc-time=\"keeping\"]"); |
| if (!(n && a && o && l)) return; |
| const i = (e) => { |
| e.target === n && handleMouseOver(o), e.target === a && handleMouseOver(l); |
| }, r = (e) => { |
| e.target === n && handleMouseOut(o), e.target === a && handleMouseOut(l); |
| }; |
| return t.addEventListener("mouseover", i), t.addEventListener("mouseout", r), handleInput$1(e, n, o, s, "hour", e.timeMaxHour, e.timeMinHour), handleInput$1(e, a, l, s, "minute", e.timeMaxMinute, e.timeMinMinute), handleRange(e, n, o, s, "hour"), handleRange(e, a, l, s, "minute"), s && handleClickKeepingTime(e, s, n, e.timeMaxHour, e.timeMinHour), () => { |
| t.removeEventListener("mouseover", i), t.removeEventListener("mouseout", r); |
| }; |
| }; |
| const createTime = (e) => { |
| const t = e.context.mainElement.querySelector("[data-vc=\"time\"]"); |
| if (!e.selectionTimeMode || !t) return; |
| const [n, a] = [e.timeMinHour, e.timeMaxHour], [o, l] = [e.timeMinMinute, e.timeMaxMinute], s = e.context.selectedKeeping ? transformTime24(e.context.selectedHours, e.context.selectedKeeping) : e.context.selectedHours, i = "range" === e.timeControls; |
| var r; |
| t.innerHTML = e.sanitizerHTML(`\n <div class="${e.styles.timeContent}" data-vc-time="content">\n ${TimeInput("hour", e.styles.timeHour, e.labels, e.context.selectedHours, i)}\n ${TimeInput("minute", e.styles.timeMinute, e.labels, e.context.selectedMinutes, i)}\n ${12 === e.selectionTimeMode ? (r = e.context.selectedKeeping, `<button type="button" class="${e.styles.timeKeeping}" aria-label="${e.labels.btnKeeping} ${r}" data-vc-time="keeping" ${i ? "disabled" : ""}>${r}</button>`) : ""}\n </div>\n <div class="${e.styles.timeRanges}" data-vc-time="ranges">\n ${TimeRange("hour", e.styles.timeRange, e.labels, n, a, e.timeStepHour, s)}\n ${TimeRange("minute", e.styles.timeRange, e.labels, o, l, e.timeStepMinute, e.context.selectedMinutes)}\n </div>\n `), handleTime(e, t); |
| }; |
| const createWeek = (e) => { |
| const t = e.selectedWeekends ? [...e.selectedWeekends] : [], n = [...e.context.locale.weekdays.long].reduce(((n, a, o) => [...n, { |
| id: o, |
| titleShort: e.context.locale.weekdays.short[o], |
| titleLong: a, |
| isWeekend: t.includes(o) |
| }]), []), a = [...n.slice(e.firstWeekday), ...n.slice(0, e.firstWeekday)]; |
| e.context.mainElement.querySelectorAll("[data-vc=\"week\"]").forEach(((t) => { |
| const n = e.onClickWeekDay ? document.createElement("button") : document.createElement("b"); |
| e.onClickWeekDay && (n.type = "button"), a.forEach(((a) => { |
| const o = n.cloneNode(!0); |
| o.innerText = a.titleShort, o.className = e.styles.weekDay, o.role = "columnheader", o.ariaLabel = a.titleLong, o.dataset.vcWeekDay = String(a.id), a.isWeekend && (o.dataset.vcWeekDayOff = ""), t.appendChild(o); |
| })); |
| })); |
| }; |
| const createYearEl = (e, t, n, a, o) => { |
| const l = document.createElement("div"); |
| l.className = e.styles.yearsCell, l.dataset.vcYears = "cell", l.role = "gridcell"; |
| const s = t.cloneNode(!1); |
| return s.className = e.styles.yearsYear, s.innerText = String(o), s.ariaLabel = String(o), s.dataset.vcYearsYear = `${o}`, a && (s.ariaDisabled = "true"), a && (s.tabIndex = -1), s.disabled = a, l.appendChild(s), setYearModifier(e, s, "year", n === o, !1), l; |
| }; |
| const createYears = (e, t) => { |
| var n; |
| const a = (null == t ? void 0 : t.dataset.vcYear) ? Number(t.dataset.vcYear) : e.context.selectedYear; |
| setContext(e, "currentType", "year"), createLayouts(e, t), visibilityTitle(e), visibilityArrows(e); |
| const o = e.context.mainElement.querySelector("[data-vc=\"years\"]"); |
| if (!e.selectionYearsMode || !o) return; |
| const l = "multiple" !== e.type || e.context.selectedYear === a ? 0 : 1, s = document.createElement("button"); |
| let i; |
| s.type = "button"; |
| for (let t = e.context.displayYear - 7; t < e.context.displayYear + 8; t++) { |
| (t - (e.context.displayYear - 7)) % 5 == 0 && (i = document.createElement("div"), i.className = e.styles.yearsRow, i.dataset.vcYears = "row", i.role = "row", o.appendChild(i)); |
| const n = t < getDate(e.context.dateMin).getFullYear() + l || t > getDate(e.context.dateMax).getFullYear(), r = createYearEl(e, s, a, n, t); |
| i?.appendChild(r), e.onCreateYearEls && e.onCreateYearEls(e, r); |
| } |
| null == (n = e.context.mainElement.querySelector("[data-vc-years-year]:not([disabled])")) || n.focus(); |
| }; |
| const trackChangesHTMLElement = (e, t, n) => { |
| new MutationObserver(((e) => { |
| for (let a = 0; a < e.length; a++) if (e[a].attributeName === t) { |
| n(); |
| break; |
| } |
| })).observe(e, { attributes: !0 }); |
| }; |
| const haveListener = { |
| value: !1, |
| set: () => haveListener.value = !0, |
| check: () => haveListener.value |
| }; |
| const setTheme = (e, t) => e.dataset.vcTheme = t; |
| const addMediaQueryListener = (e, t) => e.addEventListener ? (e.addEventListener("change", t), () => e.removeEventListener("change", t)) : (e.addListener(t), () => e.removeListener(t)); |
| const trackChangesThemeInSystemSettings = (e, t) => { |
| if (setTheme(e.context.mainElement, t.matches ? "dark" : "light"), "system" !== e.selectedTheme || e.context.cleanupSystemTheme) return; |
| if (getRootNode(e.context.mainElement) !== document) { |
| setContext(e, "cleanupSystemTheme", addMediaQueryListener(t, ((t) => setTheme(e.context.mainElement, t.matches ? "dark" : "light")))); |
| return; |
| } |
| if (haveListener.check()) return; |
| addMediaQueryListener(t, ((e) => { |
| document.querySelectorAll("[data-vc=\"calendar\"]")?.forEach(((t) => setTheme(t, e.matches ? "dark" : "light"))); |
| })), haveListener.set(); |
| }; |
| const detectTheme = (e, t) => { |
| const n = e.themeAttrDetect.length ? document.querySelector(e.themeAttrDetect) : null, a = e.themeAttrDetect.replace(/^.*\[(.+)\]/g, ((e, t) => t)); |
| if (!n || "system" === n.getAttribute(a)) return void trackChangesThemeInSystemSettings(e, t); |
| const o = n.getAttribute(a); |
| o ? (setTheme(e.context.mainElement, o), trackChangesHTMLElement(n, a, (() => { |
| const t = n.getAttribute(a); |
| t && setTheme(e.context.mainElement, t); |
| }))) : trackChangesThemeInSystemSettings(e, t); |
| }; |
| const handleTheme = (e) => { |
| "not all" !== window.matchMedia("(prefers-color-scheme)").media ? "system" === e.selectedTheme ? detectTheme(e, window.matchMedia("(prefers-color-scheme: dark)")) : setTheme(e.context.mainElement, e.selectedTheme) : setTheme(e.context.mainElement, "light"); |
| }; |
| const capitalizeFirstLetter = (e) => e.charAt(0).toUpperCase() + e.slice(1).replace(/\./, ""); |
| const getLocaleWeekday = (e, t, n) => { |
| const a = /* @__PURE__ */ new Date(`1978-01-0${t + 1}T00:00:00.000Z`), o = a.toLocaleString(n, { |
| weekday: "short", |
| timeZone: "UTC" |
| }), l = a.toLocaleString(n, { |
| weekday: "long", |
| timeZone: "UTC" |
| }); |
| e.context.locale.weekdays.short.push(capitalizeFirstLetter(o)), e.context.locale.weekdays.long.push(capitalizeFirstLetter(l)); |
| }; |
| const getLocaleMonth = (e, t, n) => { |
| const a = /* @__PURE__ */ new Date(`1978-${String(t + 1).padStart(2, "0")}-01T00:00:00.000Z`), o = a.toLocaleString(n, { |
| month: "short", |
| timeZone: "UTC" |
| }), l = a.toLocaleString(n, { |
| month: "long", |
| timeZone: "UTC" |
| }); |
| e.context.locale.months.short.push(capitalizeFirstLetter(o)), e.context.locale.months.long.push(capitalizeFirstLetter(l)); |
| }; |
| const getLocale = (e) => { |
| var t, n, a, o, l, s, i, r; |
| if (!(e.context.locale.weekdays.short[6] && e.context.locale.weekdays.long[6] && e.context.locale.months.short[11] && e.context.locale.months.long[11])) if ("string" == typeof e.locale) { |
| if ("string" == typeof e.locale && !e.locale.length) throw new Error(errorMessages.notLocale); |
| Array.from({ length: 7 }, ((t, n) => getLocaleWeekday(e, n, e.locale))), Array.from({ length: 12 }, ((t, n) => getLocaleMonth(e, n, e.locale))); |
| } else { |
| if (!((null == (n = null == (t = e.locale) ? void 0 : t.weekdays) ? void 0 : n.short[6]) && (null == (o = null == (a = e.locale) ? void 0 : a.weekdays) ? void 0 : o.long[6]) && (null == (s = null == (l = e.locale) ? void 0 : l.months) ? void 0 : s.short[11]) && (null == (r = null == (i = e.locale) ? void 0 : i.months) ? void 0 : r.long[11]))) throw new Error(errorMessages.notLocale); |
| setContext(e, "locale", __spreadValues({}, e.locale)); |
| } |
| }; |
| const create = (e) => { |
| handleTheme(e), getLocale(e), createLayouts(e), visibilityTitle(e), visibilityArrows(e), createTime(e), { |
| default: () => { |
| createWeek(e), createDates(e); |
| }, |
| multiple: () => { |
| createWeek(e), createDates(e); |
| }, |
| month: () => createMonths(e), |
| year: () => createYears(e) |
| }[e.context.currentType](); |
| }; |
| const updateDateModifiers = (e) => { |
| e.context.mainElement.querySelectorAll("[data-vc-date]").forEach(((t) => { |
| const n = t.querySelector("[data-vc-date-btn]"), a = t.dataset.vcDate, o = getDate(a).getDay(); |
| setDateModifier(e, e.context.selectedYear, t, n, o, a, "current"); |
| })); |
| }; |
| const handleArrowKeys = (e) => { |
| const t = (t) => { |
| var n; |
| const a = t.target; |
| if (![ |
| "ArrowUp", |
| "ArrowDown", |
| "ArrowLeft", |
| "ArrowRight" |
| ].includes(t.key) || "button" !== a.localName) return; |
| const o = Array.from(e.context.mainElement.querySelectorAll("[data-vc=\"calendar\"] button")), l = o.indexOf(a); |
| if (-1 === l) return; |
| const s = (i = o[l]).hasAttribute("data-vc-date-btn") ? 7 : i.hasAttribute("data-vc-months-month") ? 4 : i.hasAttribute("data-vc-years-year") ? 5 : 1; |
| var i; |
| null == (n = o[(0, { |
| ArrowUp: () => Math.max(0, l - s), |
| ArrowDown: () => Math.min(o.length - 1, l + s), |
| ArrowLeft: () => Math.max(0, l - 1), |
| ArrowRight: () => Math.min(o.length - 1, l + 1) |
| }[t.key])()]) || n.focus(); |
| }; |
| return e.context.mainElement.addEventListener("keydown", t), () => e.context.mainElement.removeEventListener("keydown", t); |
| }; |
| const handleMonth = (e, t) => { |
| const n = getDate(getDateString(new Date(e.context.selectedYear, e.context.selectedMonth, 1))); |
| ({ |
| prev: () => n.setMonth(n.getMonth() - e.monthsToSwitch), |
| next: () => n.setMonth(n.getMonth() + e.monthsToSwitch) |
| })[t](), setContext(e, "selectedMonth", n.getMonth()), setContext(e, "selectedYear", n.getFullYear()), visibilityTitle(e), visibilityArrows(e), createDates(e); |
| }; |
| const handleClickArrow = (e, t) => { |
| const n = t.target.closest("[data-vc-arrow]"); |
| if (n) { |
| if (["default", "multiple"].includes(e.context.currentType)) handleMonth(e, n.dataset.vcArrow); |
| else if ("year" === e.context.currentType && void 0 !== e.context.displayYear) { |
| const a = { |
| prev: -15, |
| next: 15 |
| }[n.dataset.vcArrow]; |
| setContext(e, "displayYear", e.context.displayYear + a), createYears(e, t.target); |
| } |
| e.onClickArrow && e.onClickArrow(e, t); |
| } |
| }; |
| const resolveToggle = (e, t) => void 0 === t || ("function" == typeof t ? t(e) : t); |
| const canToggleSelection = (e) => resolveToggle(e, e.enableDateToggle); |
| const handleSelectDate = (e, t, n) => { |
| const a = t.dataset.vcDate, o = t.closest("[data-vc-date][data-vc-date-selected]"), l = canToggleSelection(e); |
| if (o && !l) return; |
| const s = o ? e.context.selectedDates.filter(((e) => e !== a)) : n ? [...e.context.selectedDates, a] : [a]; |
| setContext(e, "selectedDates", s); |
| }; |
| const createDateRangeTooltip = (e, t, n) => { |
| if (!t) return; |
| if (!n) return t.dataset.vcDateRangeTooltip = "hidden", void (t.textContent = ""); |
| const a = e.context.mainElement.getBoundingClientRect(), o = n.getBoundingClientRect(); |
| t.style.left = o.left - a.left + o.width / 2 + "px", t.style.top = o.bottom - a.top - o.height + "px", t.dataset.vcDateRangeTooltip = "visible", t.innerHTML = e.sanitizerHTML(e.onCreateDateRangeTooltip(e, n, t, o, a)); |
| }; |
| const state = { |
| self: null, |
| lastDateEl: null, |
| isHovering: !1, |
| rangeMin: void 0, |
| rangeMax: void 0, |
| tooltipEl: null, |
| timeoutId: null |
| }; |
| const addHoverEffect = (e, t, n) => { |
| var a, o, l; |
| if (!(null == (o = null == (a = state.self) ? void 0 : a.context) ? void 0 : o.selectedDates[0])) return; |
| const s = getDateString(e); |
| null != (l = state.self.context.disableDates) && l.includes(s) || (state.self.context.mainElement.querySelectorAll(`[data-vc-date="${s}"]`).forEach(((e) => e.dataset.vcDateHover = "")), t.forEach(((e) => e.dataset.vcDateHover = "first")), n.forEach(((e) => { |
| "first" === e.dataset.vcDateHover ? e.dataset.vcDateHover = "first-and-last" : e.dataset.vcDateHover = "last"; |
| }))); |
| }; |
| const removeHoverEffect = () => { |
| var e, t; |
| if (!(null == (t = null == (e = state.self) ? void 0 : e.context) ? void 0 : t.mainElement)) return; |
| state.self.context.mainElement.querySelectorAll("[data-vc-date-hover]").forEach(((e) => e.removeAttribute("data-vc-date-hover"))); |
| }; |
| const handleHoverDatesEvent = (e) => { |
| var t, n; |
| if (!e || !(null == (n = null == (t = state.self) ? void 0 : t.context) ? void 0 : n.selectedDates[0])) return; |
| if (!e.closest("[data-vc=\"dates\"]")) return state.lastDateEl = null, createDateRangeTooltip(state.self, state.tooltipEl, null), void removeHoverEffect(); |
| const a = e.closest("[data-vc-date]"); |
| if (!a || state.lastDateEl === a) return; |
| state.lastDateEl = a, createDateRangeTooltip(state.self, state.tooltipEl, a), removeHoverEffect(); |
| const o = a.dataset.vcDate, l = getDate(state.self.context.selectedDates[0]), s = getDate(o), i = state.self.context.mainElement.querySelectorAll(`[data-vc-date="${state.self.context.selectedDates[0]}"]`), r = state.self.context.mainElement.querySelectorAll(`[data-vc-date="${o}"]`), [c, d] = l < s ? [i, r] : [r, i], [u, m] = l < s ? [l, s] : [s, l]; |
| for (let e = new Date(u); e <= m; e.setDate(e.getDate() + 1)) addHoverEffect(e, c, d); |
| }; |
| const handleHoverSelectedDatesRangeEvent = (e) => { |
| const t = null == e ? void 0 : e.closest("[data-vc-date-selected]"); |
| if (!t && state.lastDateEl) return state.lastDateEl = null, void createDateRangeTooltip(state.self, state.tooltipEl, null); |
| t && state.lastDateEl !== t && (state.lastDateEl = t, createDateRangeTooltip(state.self, state.tooltipEl, t)); |
| }; |
| const optimizedHoverHandler = (e) => (t) => { |
| const n = t.target; |
| state.isHovering || (state.isHovering = !0, requestAnimationFrame((() => { |
| e(n), state.isHovering = !1; |
| }))); |
| }; |
| const optimizedHandleHoverDatesEvent = optimizedHoverHandler(handleHoverDatesEvent); |
| const optimizedHandleHoverSelectedDatesRangeEvent = optimizedHoverHandler(handleHoverSelectedDatesRangeEvent); |
| const handleCancelSelectionDates = (e) => { |
| state.self && "Escape" === e.key && (state.lastDateEl = null, setContext(state.self, "selectedDates", []), state.self.context.mainElement.removeEventListener("mousemove", optimizedHandleHoverDatesEvent), state.self.context.mainElement.removeEventListener("keydown", handleCancelSelectionDates), createDateRangeTooltip(state.self, state.tooltipEl, null), removeHoverEffect()); |
| }; |
| const handleMouseLeave = () => { |
| null !== state.timeoutId && clearTimeout(state.timeoutId), state.timeoutId = setTimeout((() => { |
| state.lastDateEl = null, createDateRangeTooltip(state.self, state.tooltipEl, null), removeHoverEffect(); |
| }), 50); |
| }; |
| const updateDisabledDates = () => { |
| var e, t, n, a; |
| if (!(null == (n = null == (t = null == (e = state.self) ? void 0 : e.context) ? void 0 : t.selectedDates) ? void 0 : n[0]) || !(null == (a = state.self.context.disableDates) ? void 0 : a[0])) return; |
| const o = getDate(state.self.context.selectedDates[0]), [l, s] = state.self.context.disableDates.map(((e) => getDate(e))).reduce((([e, t], n) => [o >= n ? n : e, o < n && null === t ? n : t]), [null, null]); |
| l && setContext(state.self, "displayDateMin", getDateString(new Date(l.setDate(l.getDate() + 1)))), s && setContext(state.self, "displayDateMax", getDateString(new Date(s.setDate(s.getDate() - 1)))); |
| state.self.disableDatesPast && !state.self.disableAllDates && getDate(state.self.context.displayDateMin) < getDate(state.self.context.dateToday) && setContext(state.self, "displayDateMin", state.self.context.dateToday); |
| }; |
| const handleSelectDateRange = (e, t) => { |
| state.self = e, state.lastDateEl = t, removeHoverEffect(), e.disableDatesGaps && (state.rangeMin = state.rangeMin ? state.rangeMin : e.context.displayDateMin, state.rangeMax = state.rangeMax ? state.rangeMax : e.context.displayDateMax), e.onCreateDateRangeTooltip && (state.tooltipEl = e.context.mainElement.querySelector("[data-vc-date-range-tooltip]")); |
| const n = null == t ? void 0 : t.dataset.vcDate; |
| if (n) { |
| const t = 1 === e.context.selectedDates.length && e.context.selectedDates[0].includes(n), a = t && !canToggleSelection(e) ? [n, n] : t && canToggleSelection(e) ? [] : e.context.selectedDates.length > 1 ? [n] : [...e.context.selectedDates, n]; |
| setContext(e, "selectedDates", a), e.context.selectedDates.length > 1 && e.context.selectedDates.sort(((e, t) => +new Date(e) - +new Date(t))); |
| } |
| ({ |
| set: () => (e.disableDatesGaps && updateDisabledDates(), createDateRangeTooltip(state.self, state.tooltipEl, t), state.self.context.mainElement.removeEventListener("mousemove", optimizedHandleHoverSelectedDatesRangeEvent), state.self.context.mainElement.removeEventListener("mouseleave", handleMouseLeave), state.self.context.mainElement.removeEventListener("keydown", handleCancelSelectionDates), state.self.context.mainElement.addEventListener("mousemove", optimizedHandleHoverDatesEvent), state.self.context.mainElement.addEventListener("mouseleave", handleMouseLeave), state.self.context.mainElement.addEventListener("keydown", handleCancelSelectionDates), () => { |
| state.self.context.mainElement.removeEventListener("mousemove", optimizedHandleHoverDatesEvent), state.self.context.mainElement.removeEventListener("mouseleave", handleMouseLeave), state.self.context.mainElement.removeEventListener("keydown", handleCancelSelectionDates); |
| }), |
| reset: () => { |
| const [n, a] = [e.context.selectedDates[0], e.context.selectedDates[e.context.selectedDates.length - 1]], o = e.context.selectedDates[0] !== e.context.selectedDates[e.context.selectedDates.length - 1], l = parseDates([`${n}:${a}`]).filter(((t) => !e.context.disableDates.includes(t))), s = o ? e.enableEdgeDatesOnly ? [n, a] : l : [e.context.selectedDates[0], e.context.selectedDates[0]]; |
| if (setContext(e, "selectedDates", s), e.disableDatesGaps && (setContext(e, "displayDateMin", state.rangeMin), setContext(e, "displayDateMax", state.rangeMax)), state.self.context.mainElement.removeEventListener("mousemove", optimizedHandleHoverDatesEvent), state.self.context.mainElement.removeEventListener("mouseleave", handleMouseLeave), state.self.context.mainElement.removeEventListener("keydown", handleCancelSelectionDates), e.onCreateDateRangeTooltip) return e.context.selectedDates[0] || (state.self.context.mainElement.removeEventListener("mousemove", optimizedHandleHoverSelectedDatesRangeEvent), state.self.context.mainElement.removeEventListener("mouseleave", handleMouseLeave), createDateRangeTooltip(state.self, state.tooltipEl, null)), e.context.selectedDates[0] && (state.self.context.mainElement.addEventListener("mousemove", optimizedHandleHoverSelectedDatesRangeEvent), state.self.context.mainElement.addEventListener("mouseleave", handleMouseLeave), createDateRangeTooltip(state.self, state.tooltipEl, t)), () => { |
| state.self.context.mainElement.removeEventListener("mousemove", optimizedHandleHoverSelectedDatesRangeEvent), state.self.context.mainElement.removeEventListener("mouseleave", handleMouseLeave); |
| }; |
| } |
| })[1 === e.context.selectedDates.length ? "set" : "reset"](); |
| }; |
| const handleClickDate = (e, t) => { |
| var n; |
| const a = t.target, o = a.closest("[data-vc-date-btn]"); |
| if (!e.selectionDatesMode || ![ |
| "single", |
| "multiple", |
| "multiple-ranged" |
| ].includes(e.selectionDatesMode) || !o) return; |
| const l = o.closest("[data-vc-date]"); |
| ({ |
| single: () => handleSelectDate(e, l, !1), |
| multiple: () => handleSelectDate(e, l, !0), |
| "multiple-ranged": () => handleSelectDateRange(e, l) |
| })[e.selectionDatesMode](), null == (n = e.context.selectedDates) || n.sort(((e, t) => +new Date(e) - +new Date(t))), e.onClickDate && e.onClickDate(e, t), e.inputMode && e.context.inputElement && e.context.mainElement && e.onChangeToInput && e.onChangeToInput(e, t); |
| const s = a.closest("[data-vc-date-month=\"prev\"]"), i = a.closest("[data-vc-date-month=\"next\"]"); |
| ({ |
| prev: () => e.enableMonthChangeOnDayClick ? handleMonth(e, "prev") : updateDateModifiers(e), |
| next: () => e.enableMonthChangeOnDayClick ? handleMonth(e, "next") : updateDateModifiers(e), |
| current: () => updateDateModifiers(e) |
| })[s ? "prev" : i ? "next" : "current"](); |
| }; |
| const typeClick = ["month", "year"]; |
| const getValue = (e, t, n) => { |
| const { currentValue: a, columnID: o } = getColumnID(e, t); |
| return "month" === e.context.currentType && o >= 0 ? n - o : "year" === e.context.currentType && e.context.selectedYear !== a ? n - 1 : n; |
| }; |
| const handleMultipleYearSelection = (e, t) => { |
| const n = getValue(e, "year", Number(t.dataset.vcYearsYear)), a = getDate(e.context.dateMin), o = getDate(e.context.dateMax), l = e.context.displayMonthsCount - 1, { columnID: s } = getColumnID(e, "year"), i = e.context.selectedMonth < a.getMonth() && n <= a.getFullYear(), r = e.context.selectedMonth > o.getMonth() - l + s && n >= o.getFullYear(), c = n < a.getFullYear(), d = n > o.getFullYear(), u = i || c ? a.getFullYear() : r || d ? o.getFullYear() : n, m = i || c ? a.getMonth() : r || d ? o.getMonth() - l + s : e.context.selectedMonth; |
| setContext(e, "selectedYear", u), setContext(e, "selectedMonth", m); |
| }; |
| const handleMultipleMonthSelection = (e, t) => { |
| const n = t.closest("[data-vc-column=\"month\"]").querySelector("[data-vc=\"year\"]"), a = getValue(e, "month", Number(t.dataset.vcMonthsMonth)), o = Number(n.dataset.vcYear), l = getDate(e.context.dateMin), s = getDate(e.context.dateMax), i = a < l.getMonth() && o <= l.getFullYear(), r = a > s.getMonth() && o >= s.getFullYear(); |
| setContext(e, "selectedYear", o), setContext(e, "selectedMonth", i ? l.getMonth() : r ? s.getMonth() : a); |
| }; |
| const handleItemClick = (e, t, n, a) => { |
| var o; |
| ({ |
| year: () => { |
| if ("multiple" === e.type) return handleMultipleYearSelection(e, a); |
| setContext(e, "selectedYear", Number(a.dataset.vcYearsYear)); |
| }, |
| month: () => { |
| if ("multiple" === e.type) return handleMultipleMonthSelection(e, a); |
| setContext(e, "selectedMonth", Number(a.dataset.vcMonthsMonth)); |
| } |
| })[n](); |
| ({ |
| year: () => { |
| var n; |
| return null == (n = e.onClickYear) ? void 0 : n.call(e, e, t); |
| }, |
| month: () => { |
| var n; |
| return null == (n = e.onClickMonth) ? void 0 : n.call(e, e, t); |
| } |
| })[n](), e.context.currentType !== e.type ? (setContext(e, "currentType", e.type), create(e), null == (o = e.context.mainElement.querySelector(`[data-vc="${n}"]`)) || o.focus()) : setYearModifier(e, a, n, !0, !0); |
| }; |
| const handleClickType = (e, t, n) => { |
| var a; |
| const o = t.target, l = o.closest(`[data-vc="${n}"]`), s = { |
| year: () => createYears(e, o), |
| month: () => createMonths(e, o) |
| }; |
| if (l && e.onClickTitle && e.onClickTitle(e, t), l && e.context.currentType !== n) return s[n](); |
| const i = o.closest(`[data-vc-${n}s-${n}]`); |
| if (i) return handleItemClick(e, t, n, i); |
| const r = o.closest("[data-vc=\"grid\"]"), c = o.closest("[data-vc=\"column\"]"); |
| (e.context.currentType === n && l || "multiple" === e.type && e.context.currentType === n && r && !c) && (setContext(e, "currentType", e.type), create(e), null == (a = e.context.mainElement.querySelector(`[data-vc="${n}"]`)) || a.focus()); |
| }; |
| const handleClickMonthOrYear = (e, t) => { |
| const n = { |
| month: e.selectionMonthsMode, |
| year: e.selectionYearsMode |
| }; |
| typeClick.forEach(((a) => { |
| n[a] && t.target && handleClickType(e, t, a); |
| })); |
| }; |
| const handleClickWeekNumber = (e, t) => { |
| if (!e.enableWeekNumbers || !e.onClickWeekNumber) return; |
| const n = t.target.closest("[data-vc-week-number]"), a = e.context.mainElement.querySelectorAll("[data-vc-date-week-number]"); |
| if (!n || !a[0]) return; |
| const o = Number(n.innerText), l = Number(n.dataset.vcWeekYear), s = Array.from(a).filter(((e) => Number(e.dataset.vcDateWeekNumber) === o)); |
| e.onClickWeekNumber(e, o, l, s, t); |
| }; |
| const handleClickWeekDay = (e, t) => { |
| if (!e.onClickWeekDay) return; |
| const n = t.target.closest("[data-vc-week-day]"), a = t.target.closest("[data-vc=\"column\"]"), o = a ? a.querySelectorAll("[data-vc-date-week-day]") : e.context.mainElement.querySelectorAll("[data-vc-date-week-day]"); |
| if (!n || !o[0]) return; |
| const l = Number(n.dataset.vcWeekDay), s = Array.from(o).filter(((e) => Number(e.dataset.vcDateWeekDay) === l)); |
| e.onClickWeekDay(e, l, s, t); |
| }; |
| const handleClick = (e) => { |
| const t = (t) => { |
| handleClickArrow(e, t), handleClickWeekDay(e, t), handleClickWeekNumber(e, t), handleClickDate(e, t), handleClickMonthOrYear(e, t); |
| }; |
| return e.context.mainElement.addEventListener("click", t), () => e.context.mainElement.removeEventListener("click", t); |
| }; |
| const initMonthsCount = (e) => { |
| if ("multiple" === e.type && (e.displayMonthsCount <= 1 || e.displayMonthsCount > 12)) throw new Error(errorMessages.incorrectMonthsCount); |
| if ("multiple" !== e.type && e.displayMonthsCount > 1) throw new Error(errorMessages.incorrectMonthsCount); |
| setContext(e, "displayMonthsCount", e.displayMonthsCount ? e.displayMonthsCount : "multiple" === e.type ? 2 : 1); |
| }; |
| const getLocalDate = () => { |
| const e = /* @__PURE__ */ new Date(); |
| return (/* @__PURE__ */ new Date(e.getTime() - 6e4 * e.getTimezoneOffset())).toISOString().substring(0, 10); |
| }; |
| const resolveDate = (e, t) => "today" === e ? getLocalDate() : e instanceof Date || "number" == typeof e || "string" == typeof e ? parseDates([e])[0] : t; |
| const initRange = (e) => { |
| var t, n, a; |
| const o = resolveDate(e.dateMin, e.dateMin), l = resolveDate(e.dateMax, e.dateMax), s = resolveDate(e.displayDateMin, o), i = resolveDate(e.displayDateMax, l); |
| setContext(e, "dateToday", resolveDate(e.dateToday, e.dateToday)), setContext(e, "displayDateMin", s ? getDate(o) >= getDate(s) ? o : s : o), setContext(e, "displayDateMax", i ? getDate(l) <= getDate(i) ? l : i : l); |
| const r = e.disableDatesPast && !e.disableAllDates && getDate(s) < getDate(e.context.dateToday); |
| setContext(e, "displayDateMin", r || e.disableAllDates ? e.context.dateToday : s), setContext(e, "displayDateMax", e.disableAllDates ? e.context.dateToday : i), setContext(e, "disableDates", e.disableDates[0] && !e.disableAllDates ? parseDates(e.disableDates) : e.disableAllDates ? [e.context.displayDateMin] : []), e.context.disableDates.length > 1 && e.context.disableDates.sort(((e, t) => +new Date(e) - +new Date(t))), setContext(e, "enableDates", e.enableDates[0] ? parseDates(e.enableDates) : []), null != (t = e.context.enableDates) && t[0] && null != (n = e.context.disableDates) && n[0] && setContext(e, "disableDates", e.context.disableDates.filter(((t) => !e.context.enableDates.includes(t)))), e.context.enableDates.length > 1 && e.context.enableDates.sort(((e, t) => +new Date(e) - +new Date(t))), null != (a = e.context.enableDates) && a[0] && e.disableAllDates && (setContext(e, "displayDateMin", e.context.enableDates[0]), setContext(e, "displayDateMax", e.context.enableDates[e.context.enableDates.length - 1])), setContext(e, "dateMin", e.displayDisabledDates ? o : e.context.displayDateMin), setContext(e, "dateMax", e.displayDisabledDates ? l : e.context.displayDateMax); |
| }; |
| const initSelectedDates = (e) => { |
| var t; |
| setContext(e, "selectedDates", (null == (t = e.selectedDates) ? void 0 : t[0]) ? parseDates(e.selectedDates) : []); |
| }; |
| const displayClosestValidDate = (e) => { |
| const t = (t) => { |
| const n = new Date(t); |
| setInitialContext(e, n.getMonth(), n.getFullYear()); |
| }; |
| if (e.displayDateMin && "today" !== e.displayDateMin && (n = e.displayDateMin, a = /* @__PURE__ */ new Date(), new Date(n).getTime() > a.getTime())) { |
| const n = e.selectedDates.length && e.selectedDates[0] ? parseDates(e.selectedDates)[0] : e.displayDateMin; |
| return t(getDate(resolveDate(n, e.displayDateMin))), !0; |
| } |
| var n, a; |
| if (e.displayDateMax && "today" !== e.displayDateMax && ((e, t) => new Date(e).getTime() < t.getTime())(e.displayDateMax, /* @__PURE__ */ new Date())) { |
| const n = e.selectedDates.length && e.selectedDates[0] ? parseDates(e.selectedDates)[0] : e.displayDateMax; |
| return t(getDate(resolveDate(n, e.displayDateMax))), !0; |
| } |
| return !1; |
| }; |
| const setInitialContext = (e, t, n) => { |
| setContext(e, "selectedMonth", t), setContext(e, "selectedYear", n), setContext(e, "displayYear", n); |
| }; |
| const initSelectedMonthYear = (e) => { |
| var t; |
| if (e.enableJumpToSelectedDate && (null == (t = e.selectedDates) ? void 0 : t[0]) && void 0 === e.selectedMonth && void 0 === e.selectedYear) { |
| const t = getDate(parseDates(e.selectedDates)[0]); |
| setInitialContext(e, t.getMonth(), t.getFullYear()); |
| return; |
| } |
| if (displayClosestValidDate(e)) return; |
| const n = void 0 !== e.selectedMonth && Number(e.selectedMonth) >= 0 && Number(e.selectedMonth) < 12, a = void 0 !== e.selectedYear && Number(e.selectedYear) >= 0 && Number(e.selectedYear) <= 9999; |
| setInitialContext(e, n ? Number(e.selectedMonth) : getDate(e.context.dateToday).getMonth(), a ? Number(e.selectedYear) : getDate(e.context.dateToday).getFullYear()); |
| }; |
| const initTime = (e) => { |
| var t, n, a; |
| if (!e.selectionTimeMode) return; |
| if (![12, 24].includes(e.selectionTimeMode)) throw new Error(errorMessages.incorrectTime); |
| const o = 12 === e.selectionTimeMode, l = o ? /^(0[1-9]|1[0-2]):([0-5][0-9]) ?(AM|PM)?$/i : /^([0-1]?[0-9]|2[0-3]):([0-5][0-9])$/; |
| let [s, i, r] = null != (a = null == (n = null == (t = e.selectedTime) ? void 0 : t.match(l)) ? void 0 : n.slice(1)) ? a : []; |
| s ? o && !r && (r = "AM") : (s = o ? transformTime12(String(e.timeMinHour)) : String(e.timeMinHour), i = String(e.timeMinMinute), r = o ? Number(transformTime12(String(e.timeMinHour))) >= 12 ? "PM" : "AM" : null), setContext(e, "selectedHours", s.padStart(2, "0")), setContext(e, "selectedMinutes", i.padStart(2, "0")), setContext(e, "selectedKeeping", r), setContext(e, "selectedTime", `${e.context.selectedHours}:${e.context.selectedMinutes}${r ? ` ${r}` : ""}`); |
| }; |
| const initAllVariables = (e) => { |
| setContext(e, "currentType", e.type), initMonthsCount(e), initRange(e), initSelectedMonthYear(e), initSelectedDates(e), initTime(e); |
| }; |
| const reset = (e, { year: t, month: n, dates: a, time: o, locale: l }, s = !0) => { |
| var i; |
| const r = { |
| year: e.selectedYear, |
| month: e.selectedMonth, |
| dates: e.selectedDates, |
| time: e.selectedTime |
| }; |
| if (e.selectedYear = t ? r.year : e.context.selectedYear, e.selectedMonth = n ? r.month : e.context.selectedMonth, e.selectedTime = o ? r.time : e.context.selectedTime, e.selectedDates = "only-first" === a && (null == (i = e.context.selectedDates) ? void 0 : i[0]) ? [e.context.selectedDates[0]] : !0 === a ? r.dates : e.context.selectedDates, l) setContext(e, "locale", { |
| months: { |
| short: [], |
| long: [] |
| }, |
| weekdays: { |
| short: [], |
| long: [] |
| } |
| }); |
| initAllVariables(e), s && create(e), e.selectedYear = r.year, e.selectedMonth = r.month, e.selectedDates = r.dates, e.selectedTime = r.time, "multiple-ranged" === e.selectionDatesMode && a && handleSelectDateRange(e, null); |
| }; |
| const createToInput = (e) => { |
| const t = document.createElement("div"); |
| t.className = e.styles.calendar, t.dataset.vc = "calendar", t.dataset.vcInput = "", t.dataset.vcCalendarHidden = ""; |
| const n = getRootNode(e.context.mainElement), a = n === document ? document.body : n; |
| return setContext(e, "inputModeInit", !0), setContext(e, "isShowInInputMode", !1), setContext(e, "mainElement", t), a.appendChild(e.context.mainElement), reset(e, { |
| year: !0, |
| month: !0, |
| dates: !0, |
| time: !0, |
| locale: !0 |
| }), setTimeout((() => show(e))), e.onInit && e.onInit(e), handleArrowKeys(e), handleClick(e); |
| }; |
| const canOpenOnFocus = (e) => resolveToggle(e, e.openOnFocus); |
| const handleInput = (e) => { |
| setContext(e, "inputElement", e.context.mainElement); |
| const t = () => { |
| e.context.inputModeInit ? setTimeout((() => show(e))) : createToInput(e); |
| }; |
| e.context.inputElement.addEventListener("click", t); |
| const n = "function" == typeof e.openOnFocus || !0 === e.openOnFocus, a = () => { |
| shouldSkipOpenOnFocus(e) ? clearSkipOpenOnFocus(e) : canOpenOnFocus(e) && t(); |
| }; |
| n && e.context.inputElement.addEventListener("focus", a); |
| const o = (t) => { |
| const n = "Tab" === t.key && !t.shiftKey, a = [ |
| "ArrowUp", |
| "ArrowDown", |
| "ArrowLeft", |
| "ArrowRight" |
| ].includes(t.key); |
| (n || a) && ((t) => { |
| var n; |
| if (!e.context.isShowInInputMode) return !1; |
| if (getRootNode(e.context.mainElement).activeElement !== e.context.inputElement) return !1; |
| const a = (e) => e.tabIndex >= 0 && !e.hasAttribute("disabled") && "true" !== e.getAttribute("aria-disabled"), o = null != (n = document.createTreeWalker(e.context.mainElement, NodeFilter.SHOW_ELEMENT, { acceptNode: (e) => a(e) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP }).nextNode()) ? n : a(e.context.mainElement) ? e.context.mainElement : null; |
| !o || o.tabIndex < 0 || (t.preventDefault(), o.focus()); |
| })(t); |
| }; |
| return e.context.inputElement.addEventListener("keydown", o), () => { |
| e.context.inputElement.removeEventListener("click", t), n && e.context.inputElement.removeEventListener("focus", a), e.context.inputElement.removeEventListener("keydown", o); |
| }; |
| }; |
| const init = (e) => { |
| if (e.context.isInit) throw new Error(errorMessages.alreadyInit); |
| return setContext(e, "originalElement", e.context.mainElement.cloneNode(!0)), setContext(e, "isInit", !0), e.inputMode ? handleInput(e) : (initAllVariables(e), create(e), "multiple-ranged" === e.selectionDatesMode && 1 === e.context.selectedDates.length && (handleSelectDateRange(e, null), updateDateModifiers(e)), e.onInit && e.onInit(e), handleArrowKeys(e), handleClick(e)); |
| }; |
| const update = (e, t) => { |
| if (!e.context.isInit) throw new Error(errorMessages.notInit); |
| reset(e, __spreadValues(__spreadValues({}, { |
| year: !0, |
| month: !0, |
| dates: !0, |
| time: !0, |
| locale: !0 |
| }), t), !(e.inputMode && !e.context.inputModeInit)), e.onUpdate && e.onUpdate(e); |
| }; |
| const replaceProperties = (e, t) => { |
| const n = Object.keys(t); |
| for (let a = 0; a < n.length; a++) { |
| const o = n[a]; |
| "object" != typeof e[o] || null === e[o] || "object" != typeof t[o] || null === t[o] || t[o] instanceof Date || Array.isArray(t[o]) ? void 0 !== t[o] && (e[o] = t[o]) : replaceProperties(e[o], t[o]); |
| } |
| }; |
| const set = (e, t, n) => { |
| replaceProperties(e, t), e.context.isInit && update(e, n); |
| }; |
| function findBestPickerPosition(e, t) { |
| const n = "left"; |
| if (!t || !e) return n; |
| const { canShow: a, parentPositions: o } = getAvailablePosition(e, t), l = a.left && a.right; |
| return (l && a.bottom ? "center" : l && a.top ? ["top", "center"] : Array.isArray(o) ? ["bottom" === o[0] ? "top" : "bottom", ...o.slice(1)] : o) || n; |
| } |
| const setPosition = (e, t, n) => { |
| if (!e) return; |
| const a = "auto" === n ? findBestPickerPosition(e, t) : n, o = { |
| top: -t.offsetHeight, |
| bottom: e.offsetHeight, |
| left: 0, |
| center: e.offsetWidth / 2 - t.offsetWidth / 2, |
| right: e.offsetWidth - t.offsetWidth |
| }, l = Array.isArray(a) ? a[0] : "bottom", s = Array.isArray(a) ? a[1] : a; |
| t.dataset.vcPosition = l; |
| const { top: i, left: r } = getOffset(e), c = i + o[l]; |
| let d = r + o[s]; |
| const { vw: u } = getViewportDimensions(); |
| if (d + t.clientWidth > u) { |
| const e = window.innerWidth - document.body.clientWidth; |
| d = u - t.clientWidth - e; |
| } else d < 0 && (d = 0); |
| Object.assign(t.style, { |
| left: `${d}px`, |
| top: `${c}px` |
| }); |
| }; |
| const show = (e) => { |
| if (e.context.isShowInInputMode) return; |
| if (!e.context.currentType) return void e.context.mainElement.click(); |
| setContext(e, "cleanupHandlers", []), setContext(e, "isShowInInputMode", !0), e.inputMode && restoreTabbing(e.context.mainElement), setPosition(e.context.inputElement, e.context.mainElement, e.positionToInput), e.context.mainElement.removeAttribute("data-vc-calendar-hidden"); |
| const t = () => { |
| setPosition(e.context.inputElement, e.context.mainElement, e.positionToInput); |
| }; |
| window.addEventListener("resize", t), e.context.cleanupHandlers.push((() => window.removeEventListener("resize", t))); |
| const n = (t) => { |
| "Escape" === t.key && hide(e); |
| }; |
| document.addEventListener("keydown", n), e.context.cleanupHandlers.push((() => document.removeEventListener("keydown", n))); |
| const a = (t) => { |
| var n; |
| const a = null != (n = t.composedPath()[0]) ? n : t.target; |
| a === e.context.inputElement || e.context.mainElement.contains(a) || hide(e); |
| }; |
| document.addEventListener("click", a, { capture: !0 }), e.context.cleanupHandlers.push((() => document.removeEventListener("click", a, { capture: !0 }))), e.onShow && e.onShow(e); |
| }; |
| const labels = { |
| application: "Calendar", |
| navigation: "Calendar Navigation", |
| arrowNext: { |
| month: "Next month", |
| year: "Next list of years" |
| }, |
| arrowPrev: { |
| month: "Previous month", |
| year: "Previous list of years" |
| }, |
| month: "Select month, current selected month:", |
| months: "List of months", |
| year: "Select year, current selected year:", |
| years: "List of years", |
| week: "Days of the week", |
| weekNumber: "Numbers of weeks in a year", |
| dates: "Dates in the current month", |
| selectingTime: "Selecting a time ", |
| inputHour: "Hours", |
| inputMinute: "Minutes", |
| rangeHour: "Slider for selecting hours", |
| rangeMinute: "Slider for selecting minutes", |
| btnKeeping: "Switch AM/PM, current position:" |
| }; |
| const styles = { |
| calendar: "vc", |
| controls: "vc-controls", |
| grid: "vc-grid", |
| column: "vc-column", |
| header: "vc-header", |
| headerContent: "vc-header__content", |
| month: "vc-month", |
| year: "vc-year", |
| arrowPrev: "vc-arrow vc-arrow_prev", |
| arrowNext: "vc-arrow vc-arrow_next", |
| wrapper: "vc-wrapper", |
| content: "vc-content", |
| months: "vc-months", |
| monthsRow: "vc-months__row", |
| monthsCell: "vc-months__cell", |
| monthsMonth: "vc-months__month", |
| years: "vc-years", |
| yearsRow: "vc-years__row", |
| yearsCell: "vc-years__cell", |
| yearsYear: "vc-years__year", |
| week: "vc-week", |
| weekDay: "vc-week__day", |
| weekNumbers: "vc-week-numbers", |
| weekNumbersTitle: "vc-week-numbers__title", |
| weekNumbersContent: "vc-week-numbers__content", |
| weekNumber: "vc-week-number", |
| dates: "vc-dates", |
| datesRow: "vc-dates__row", |
| date: "vc-date", |
| dateBtn: "vc-date__btn", |
| datePopup: "vc-date__popup", |
| dateRangeTooltip: "vc-date-range-tooltip", |
| time: "vc-time", |
| timeContent: "vc-time__content", |
| timeHour: "vc-time__hour", |
| timeMinute: "vc-time__minute", |
| timeKeeping: "vc-time__keeping", |
| timeRanges: "vc-time__ranges", |
| timeRange: "vc-time__range" |
| }; |
| var OptionsCalendar = class { |
| constructor() { |
| __publicField(this, "type", "default"), __publicField(this, "inputMode", !1), __publicField(this, "openOnFocus", !0), __publicField(this, "positionToInput", "left"), __publicField(this, "firstWeekday", 1), __publicField(this, "monthsToSwitch", 1), __publicField(this, "themeAttrDetect", "html[data-theme]"), __publicField(this, "locale", "en"), __publicField(this, "dateToday", "today"), __publicField(this, "dateMin", "1970-01-01"), __publicField(this, "dateMax", "2470-12-31"), __publicField(this, "displayDateMin"), __publicField(this, "displayDateMax"), __publicField(this, "displayDatesOutside", !0), __publicField(this, "displayDisabledDates", !1), __publicField(this, "displayMonthsCount"), __publicField(this, "disableDates", []), __publicField(this, "disableAllDates", !1), __publicField(this, "disableDatesPast", !1), __publicField(this, "disableDatesGaps", !1), __publicField(this, "disableWeekdays", []), __publicField(this, "disableToday", !1), __publicField(this, "enableDates", []), __publicField(this, "enableEdgeDatesOnly", !0), __publicField(this, "enableDateToggle", !0), __publicField(this, "enableWeekNumbers", !1), __publicField(this, "enableMonthChangeOnDayClick", !0), __publicField(this, "enableJumpToSelectedDate", !1), __publicField(this, "selectionDatesMode", "single"), __publicField(this, "selectionMonthsMode", !0), __publicField(this, "selectionYearsMode", !0), __publicField(this, "selectionTimeMode", !1), __publicField(this, "selectedDates", []), __publicField(this, "selectedMonth"), __publicField(this, "selectedYear"), __publicField(this, "selectedHolidays", []), __publicField(this, "selectedWeekends", [0, 6]), __publicField(this, "selectedTime"), __publicField(this, "selectedTheme", "system"), __publicField(this, "timeMinHour", 0), __publicField(this, "timeMaxHour", 23), __publicField(this, "timeMinMinute", 0), __publicField(this, "timeMaxMinute", 59), __publicField(this, "timeControls", "all"), __publicField(this, "timeStepHour", 1), __publicField(this, "timeStepMinute", 1), __publicField(this, "sanitizerHTML", ((e) => e)), __publicField(this, "onClickDate"), __publicField(this, "onClickWeekDay"), __publicField(this, "onClickWeekNumber"), __publicField(this, "onClickTitle"), __publicField(this, "onClickMonth"), __publicField(this, "onClickYear"), __publicField(this, "onClickArrow"), __publicField(this, "onChangeTime"), __publicField(this, "onChangeToInput"), __publicField(this, "onCreateDateRangeTooltip"), __publicField(this, "onCreateDateEls"), __publicField(this, "onCreateMonthEls"), __publicField(this, "onCreateYearEls"), __publicField(this, "onInit"), __publicField(this, "onUpdate"), __publicField(this, "onDestroy"), __publicField(this, "onShow"), __publicField(this, "onHide"), __publicField(this, "popups", {}), __publicField(this, "labels", __spreadValues({}, labels)), __publicField(this, "layouts", { |
| default: "", |
| multiple: "", |
| month: "", |
| year: "" |
| }), __publicField(this, "styles", __spreadValues({}, styles)); |
| } |
| }; |
| const _Calendar = class e extends OptionsCalendar { |
| constructor(t, n) { |
| var a; |
| super(), __publicField(this, "init", (() => init(this))), __publicField(this, "update", ((e) => update(this, e))), __publicField(this, "destroy", (() => { |
| const t = this.inputMode ? this.context.inputElement : this.context.mainElement; |
| if (destroy(this), t) for (const [n, a] of e.memoizedElements) a === t && e.memoizedElements.delete(n); |
| })), __publicField(this, "show", (() => show(this))), __publicField(this, "hide", (() => hide(this))), __publicField(this, "set", ((e, t) => set(this, e, t))), __publicField(this, "context"), this.context = __spreadProps(__spreadValues({}, this.context), { locale: { |
| months: { |
| short: [], |
| long: [] |
| }, |
| weekdays: { |
| short: [], |
| long: [] |
| } |
| } }), setContext(this, "mainElement", "string" == typeof t ? null != (a = e.memoizedElements.get(t)) ? a : this.queryAndMemoize(t) : t), n && replaceProperties(this, n); |
| } |
| queryAndMemoize(t) { |
| const n = document.querySelector(t); |
| if (!n) throw new Error(errorMessages.notFoundSelector(t)); |
| return e.memoizedElements.set(t, n), n; |
| } |
| }; |
| __publicField(_Calendar, "memoizedElements", /* @__PURE__ */ new Map()); |
| let Calendar = _Calendar; |
| //#endregion |
| //#region js/src/datepicker.ts |
| /** |
| * -------------------------------------------------------------------------- |
| * Bootstrap datepicker.ts |
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
| * -------------------------------------------------------------------------- |
| */ |
| /** |
| * Constants |
| */ |
| const NAME$15 = "datepicker"; |
| const EVENT_KEY$12 = `.bs.datepicker`; |
| const DATA_API_KEY$7 = ".data-api"; |
| const EVENT_CHANGE$2 = `change${EVENT_KEY$12}`; |
| const EVENT_SHOW$4 = `show${EVENT_KEY$12}`; |
| const EVENT_SHOWN$3 = `shown${EVENT_KEY$12}`; |
| const EVENT_HIDE$3 = `hide${EVENT_KEY$12}`; |
| const EVENT_HIDDEN$5 = `hidden${EVENT_KEY$12}`; |
| const EVENT_FOCUSIN$3 = `focusin${EVENT_KEY$12}`; |
| const EVENT_CLICK_DATA_API$3 = `click${EVENT_KEY$12}${DATA_API_KEY$7}`; |
| const EVENT_FOCUSIN_DATA_API = `focusin${EVENT_KEY$12}${DATA_API_KEY$7}`; |
| const SELECTOR_DATA_TOGGLE$6 = "[data-bs-toggle=\"datepicker\"]"; |
| const HIDE_DELAY = 100; |
| const Default$14 = { |
| datepickerTheme: null, |
| dateMin: null, |
| dateMax: null, |
| dateFormat: null, |
| displayElement: null, |
| displayMonthsCount: 1, |
| firstWeekday: 1, |
| inline: false, |
| locale: "default", |
| positionElement: null, |
| selectedDates: [], |
| selectionMode: "single", |
| placement: "left", |
| vcpOptions: {} |
| }; |
| const DefaultType$14 = { |
| datepickerTheme: "(null|string)", |
| dateMin: "(null|string|number|object)", |
| dateMax: "(null|string|number|object)", |
| dateFormat: "(null|object|function)", |
| displayElement: "(null|string|element|boolean)", |
| displayMonthsCount: "number", |
| firstWeekday: "number", |
| inline: "boolean", |
| locale: "string", |
| positionElement: "(null|string|element)", |
| selectedDates: "array", |
| selectionMode: "string", |
| placement: "string", |
| vcpOptions: "object" |
| }; |
| /** |
| * Class definition |
| */ |
| var Datepicker = class extends BaseComponent { |
| constructor(element, config) { |
| super(element, config); |
| this._calendar = null; |
| this._isShown = false; |
| this._initCalendar(); |
| } |
| static get Default() { |
| return Default$14; |
| } |
| static get DefaultType() { |
| return DefaultType$14; |
| } |
| static get NAME() { |
| return NAME$15; |
| } |
| toggle() { |
| if (this._config.inline) return Promise.resolve(); |
| return this._isShown ? this.hide() : this.show(); |
| } |
| async show() { |
| if (this._config.inline) return; |
| if (!this._calendar || isDisabled(this._element) || this._isShown) return; |
| if (EventHandler.trigger(this._element, EVENT_SHOW$4).defaultPrevented) return; |
| this._calendar.show(); |
| this._isShown = true; |
| EventHandler.trigger(this._element, EVENT_SHOWN$3); |
| } |
| async hide() { |
| if (this._config.inline) return; |
| if (!this._calendar || !this._isShown) return; |
| if (EventHandler.trigger(this._element, EVENT_HIDE$3).defaultPrevented) return; |
| this._calendar.hide(); |
| this._isShown = false; |
| EventHandler.trigger(this._element, EVENT_HIDDEN$5); |
| } |
| dispose() { |
| if (this._themeObserver) { |
| this._themeObserver.disconnect(); |
| this._themeObserver = null; |
| } |
| if (this._onFocusIn) EventHandler.off(document, EVENT_FOCUSIN$3, this._onFocusIn); |
| if (this._calendar) this._calendar.destroy(); |
| this._calendar = null; |
| super.dispose(); |
| } |
| getSelectedDates() { |
| const dates = this._calendar?.context?.selectedDates; |
| return dates ? [...dates] : []; |
| } |
| setSelectedDates(dates) { |
| if (this._calendar) this._calendar.set({ selectedDates: dates }); |
| } |
| _initCalendar() { |
| this._isInput = this._element.tagName === "INPUT"; |
| this._isInline = this._config.inline; |
| if (this._isInline && !this._isInput) this._boundInput = this._element.querySelector("input[type=\"hidden\"], input[name]"); |
| this._positionElement = this._resolvePositionElement(); |
| this._displayElement = this._resolveDisplayElement(); |
| const calendarOptions = this._buildCalendarOptions(); |
| this._calendar = new Calendar(this._positionElement, calendarOptions); |
| this._calendar.init(); |
| this._setupThemeObserver(); |
| this._setupDismissOnFocus(); |
| if (this._isInput && this._element.value) this._parseInputValue(); |
| this._updateDisplayWithSelectedDates(); |
| } |
| _updateDisplayWithSelectedDates() { |
| const { selectedDates } = this._config; |
| if (!selectedDates || selectedDates.length === 0) return; |
| const formattedDate = this._formatDateForInput(selectedDates); |
| if (this._isInput) this._element.value = formattedDate; |
| if (this._boundInput) this._boundInput.value = selectedDates.join(","); |
| if (this._displayElement) this._displayElement.textContent = formattedDate; |
| } |
| _resolvePositionElement() { |
| let { positionElement } = this._config; |
| if (typeof positionElement === "string") positionElement = document.querySelector(positionElement); |
| if (!positionElement && this._isInput && !this._isInline) { |
| const parent = this._element.closest(".form-adorn"); |
| if (parent) positionElement = parent; |
| } |
| return positionElement || this._element; |
| } |
| _resolveDisplayElement() { |
| const { displayElement } = this._config; |
| if (typeof displayElement === "string") return document.querySelector(displayElement); |
| if (displayElement === true || displayElement === null && !this._isInput && !this._isInline) return this._element.querySelector("[data-bs-datepicker-display]") || this._element; |
| return displayElement; |
| } |
| _getThemeAncestor() { |
| return this._element.closest("[data-bs-theme]"); |
| } |
| _getEffectiveTheme() { |
| const { datepickerTheme } = this._config; |
| if (datepickerTheme) return datepickerTheme; |
| return this._getThemeAncestor()?.getAttribute("data-bs-theme") || null; |
| } |
| _syncThemeAttribute(element) { |
| if (!element) return; |
| const theme = this._getEffectiveTheme(); |
| if (theme) element.setAttribute("data-bs-theme", theme); |
| else element.removeAttribute("data-bs-theme"); |
| } |
| _setupThemeObserver() { |
| const ancestor = this._getThemeAncestor(); |
| if (!ancestor || this._config.datepickerTheme) return; |
| this._themeObserver = new MutationObserver(() => { |
| this._syncThemeAttribute(this._calendar?.context?.mainElement); |
| }); |
| this._themeObserver.observe(ancestor, { |
| attributes: true, |
| attributeFilter: ["data-bs-theme"] |
| }); |
| } |
| _setupDismissOnFocus() { |
| if (this._isInline) return; |
| this._onFocusIn = (event) => { |
| if (!this._isShown) return; |
| const { target } = event; |
| const mainElement = this._calendar?.context?.mainElement; |
| if (target instanceof Node && (this._element.contains(target) || mainElement?.contains(target))) return; |
| this.hide(); |
| }; |
| EventHandler.on(document, EVENT_FOCUSIN$3, this._onFocusIn); |
| } |
| _buildCalendarOptions() { |
| const theme = this._getEffectiveTheme(); |
| const vcpTheme = !theme || theme === "auto" ? "system" : theme; |
| const calendarOptions = { |
| ...this._config.vcpOptions, |
| inputMode: !this._isInline, |
| positionToInput: this._config.placement, |
| firstWeekday: this._config.firstWeekday, |
| locale: this._config.locale, |
| selectionDatesMode: this._config.selectionMode, |
| selectedDates: this._config.selectedDates, |
| displayMonthsCount: this._config.displayMonthsCount, |
| type: this._config.displayMonthsCount > 1 ? "multiple" : "default", |
| selectedTheme: vcpTheme, |
| themeAttrDetect: "[data-bs-theme]", |
| onClickDate: (self, event) => this._handleDateClick(self, event), |
| onInit: (self) => { |
| this._syncThemeAttribute(self.context.mainElement); |
| }, |
| onShow: () => { |
| if (!this._calendar) return; |
| this._isShown = true; |
| this._syncThemeAttribute(this._calendar.context.mainElement); |
| }, |
| onHide: () => { |
| this._isShown = false; |
| } |
| }; |
| if (this._config.selectedDates.length > 0) { |
| const firstDate = this._parseDate(this._config.selectedDates[0]); |
| calendarOptions.selectedMonth = firstDate.getMonth(); |
| calendarOptions.selectedYear = firstDate.getFullYear(); |
| } |
| if (this._config.dateMin) calendarOptions.dateMin = this._config.dateMin; |
| if (this._config.dateMax) calendarOptions.dateMax = this._config.dateMax; |
| return calendarOptions; |
| } |
| _handleDateClick(self, event) { |
| const selectedDates = [...self.context.selectedDates]; |
| if (selectedDates.length > 0) { |
| const formattedDate = this._formatDateForInput(selectedDates); |
| if (this._isInput) this._element.value = formattedDate; |
| if (this._boundInput) this._boundInput.value = selectedDates.join(","); |
| if (this._displayElement) this._displayElement.textContent = formattedDate; |
| } |
| EventHandler.trigger(this._element, EVENT_CHANGE$2, { |
| dates: selectedDates, |
| event |
| }); |
| this._maybeHideAfterSelection(selectedDates); |
| } |
| _maybeHideAfterSelection(selectedDates) { |
| if (this._isInline) return; |
| if (this._config.selectionMode === "single" && selectedDates.length > 0 || this._config.selectionMode === "multiple-ranged" && selectedDates.length >= 2) setTimeout(() => this.hide(), HIDE_DELAY); |
| } |
| _parseDate(dateStr) { |
| const [year, month, day] = dateStr.split("-"); |
| return new Date(year, month - 1, day); |
| } |
| _formatDate(dateStr) { |
| const date = this._parseDate(dateStr); |
| const locale = this._config.locale === "default" ? void 0 : this._config.locale; |
| const { dateFormat } = this._config; |
| if (typeof dateFormat === "function") return dateFormat(date, locale); |
| if (dateFormat && typeof dateFormat === "object") return new Intl.DateTimeFormat(locale, dateFormat).format(date); |
| return date.toLocaleDateString(locale); |
| } |
| _formatDateForInput(dates) { |
| if (dates.length === 0) return ""; |
| if (dates.length === 1) return this._formatDate(dates[0]); |
| const separator = this._config.selectionMode === "multiple-ranged" ? " – " : ", "; |
| return dates.map((d) => this._formatDate(d)).join(separator); |
| } |
| _parseInputValue() { |
| const value = this._element.value.trim(); |
| if (!value) return; |
| const date = new Date(value); |
| if (!Number.isNaN(date.getTime())) { |
| const formatted = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")}`; |
| this._calendar.set({ selectedDates: [formatted] }); |
| } |
| } |
| }; |
| /** |
| * Data API implementation |
| */ |
| EventHandler.on(document, EVENT_CLICK_DATA_API$3, SELECTOR_DATA_TOGGLE$6, function(event) { |
| if (this.tagName === "INPUT" || this.dataset.bsInline === "true") return; |
| event.preventDefault(); |
| Datepicker.getOrCreateInstance(this).toggle(); |
| }); |
| EventHandler.on(document, EVENT_FOCUSIN_DATA_API, SELECTOR_DATA_TOGGLE$6, function() { |
| if (this.tagName !== "INPUT") return; |
| Datepicker.getOrCreateInstance(this).show(); |
| }); |
| EventHandler.on(document, `DOMContentLoaded${EVENT_KEY$12}${DATA_API_KEY$7}`, () => { |
| const selector = `${SELECTOR_DATA_TOGGLE$6}[data-bs-inline="true"], ${SELECTOR_DATA_TOGGLE$6}[data-bs-selected-dates]`; |
| for (const element of document.querySelectorAll(selector)) Datepicker.getOrCreateInstance(element); |
| }); |
| //#endregion |
| //#region js/src/dialog-base.ts |
| /** |
| * -------------------------------------------------------------------------- |
| * Bootstrap dialog-base.ts |
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
| * -------------------------------------------------------------------------- |
| */ |
| /** |
| * Constants |
| */ |
| const CLASS_NAME_OPEN = "dialog-open"; |
| /** |
| * Class definition |
| * |
| * Shared base class for Dialog and Drawer components that use |
| * the native <dialog> element. Provides common behavior for: |
| * - Show/hide/toggle lifecycle with events |
| * - Opening/closing via showModal()/show()/close() |
| * - Escape key handling (modal and non-modal) |
| * - Backdrop click handling |
| * - Static backdrop transition ("bounce") |
| * - Body scroll prevention |
| * - Transition coordination |
| * - Child component cleanup (tooltips, popovers, toasts) |
| */ |
| var DialogBase = class extends BaseComponent { |
| constructor(element, config) { |
| super(element, config); |
| this._isTransitioning = false; |
| this._openedAsModal = false; |
| this._addDialogListeners(); |
| } |
| static get NAME() { |
| return "dialogbase"; |
| } |
| toggle(relatedTarget) { |
| return this._element.open ? this.hide() : this.show(relatedTarget); |
| } |
| async show(relatedTarget) { |
| if (this._element.open || this._isTransitioning) return; |
| if (EventHandler.trigger(this._element, this.constructor.eventName("show"), { relatedTarget }).defaultPrevented) return; |
| this._isTransitioning = true; |
| this._onBeforeShow(); |
| const { modal, preventBodyScroll } = this._getShowOptions(); |
| this._showElement({ |
| modal, |
| preventBodyScroll |
| }); |
| await this._queueCallback(() => { |
| this._isTransitioning = false; |
| EventHandler.trigger(this._element, this.constructor.eventName("shown"), { relatedTarget }); |
| }, this._element, this._isAnimated()); |
| } |
| async hide() { |
| if (!this._element.open || this._isTransitioning) return; |
| if (EventHandler.trigger(this._element, this.constructor.eventName("hide")).defaultPrevented) return; |
| this._isTransitioning = true; |
| this._hideElement(); |
| await this._queueCallback(() => { |
| if (this._element.open) this._closeAndCleanup(); |
| this._element.classList.remove("hiding"); |
| this._onAfterHide(); |
| this._isTransitioning = false; |
| EventHandler.trigger(this._element, this.constructor.eventName("hidden")); |
| }, this._element, this._isAnimated()); |
| } |
| dispose() { |
| if (this._element.open) this._closeAndCleanup(); |
| EventHandler.off(this._element, "cancel", this._cancelHandler); |
| super.dispose(); |
| } |
| _getShowOptions() { |
| return { |
| modal: true, |
| preventBodyScroll: true |
| }; |
| } |
| _onBeforeShow() {} |
| _onAfterHide() {} |
| _isAnimated() { |
| return !this._element.classList.contains(this._getInstantClassName()); |
| } |
| _getInstantClassName() { |
| return "dialog-instant"; |
| } |
| _getStaticClassName() { |
| return "dialog-static"; |
| } |
| _onCancel() {} |
| _showElement({ modal = true, preventBodyScroll = true } = {}) { |
| this._openedAsModal = modal; |
| if (modal) this._element.showModal(); |
| else this._element.show(); |
| if (preventBodyScroll) document.documentElement.classList.add(CLASS_NAME_OPEN); |
| } |
| _hideElement() { |
| this._hideChildComponents(); |
| this._element.classList.add("hiding"); |
| if (!this._shouldDeferClose()) this._closeAndCleanup(); |
| } |
| _closeAndCleanup() { |
| this._element.close(); |
| this._openedAsModal = false; |
| if (!document.querySelector("dialog[open]:modal")) document.documentElement.classList.remove(CLASS_NAME_OPEN); |
| } |
| _shouldDeferClose() { |
| return false; |
| } |
| _triggerBackdropTransition() { |
| if (EventHandler.trigger(this._element, this.constructor.eventName("hidePrevented")).defaultPrevented) return; |
| const staticClass = this._getStaticClassName(); |
| this._element.classList.add(staticClass); |
| this._queueCallback(() => { |
| this._element.classList.remove(staticClass); |
| }, this._element); |
| } |
| _hideChildComponents() { |
| for (const el of SelectorEngine.find("[data-bs-toggle=\"tooltip\"], [data-bs-toggle=\"popover\"]", this._element)) { |
| const instance = data_default.getAny(el); |
| if (instance && typeof instance.hide === "function") instance.hide(); |
| } |
| for (const el of SelectorEngine.find(".toast.show", this._element)) { |
| const instance = data_default.getAny(el); |
| if (instance && typeof instance.hide === "function") instance.hide(); |
| } |
| } |
| _addDialogListeners() { |
| const eventKey = this.constructor.EVENT_KEY; |
| this._cancelHandler = (event) => { |
| event.preventDefault(); |
| if (!this._config.keyboard) { |
| this._triggerBackdropTransition(); |
| return; |
| } |
| this._onCancel(); |
| this.hide(); |
| }; |
| EventHandler.on(this._element, "cancel", this._cancelHandler); |
| EventHandler.on(this._element, `keydown${eventKey}`, (event) => { |
| if (event.key !== "Escape" || this._openedAsModal) return; |
| event.preventDefault(); |
| if (!this._config.keyboard) return; |
| this._onCancel(); |
| this.hide(); |
| }); |
| EventHandler.on(this._element, `click${eventKey}`, (event) => { |
| if (event.target !== this._element || !this._openedAsModal) return; |
| if (this._config.backdrop === "static") { |
| this._triggerBackdropTransition(); |
| return; |
| } |
| this.hide(); |
| }); |
| } |
| }; |
| //#endregion |
| //#region js/src/dialog.ts |
| /** |
| * -------------------------------------------------------------------------- |
| * Bootstrap dialog.ts |
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
| * -------------------------------------------------------------------------- |
| */ |
| /** |
| * Constants |
| */ |
| const NAME$14 = "dialog"; |
| const EVENT_KEY$11 = `.bs.dialog`; |
| const DATA_API_KEY$6 = ".data-api"; |
| const EVENT_SHOW$3 = `show${EVENT_KEY$11}`; |
| const EVENT_HIDDEN$4 = `hidden${EVENT_KEY$11}`; |
| const EVENT_CANCEL = `cancel${EVENT_KEY$11}`; |
| const EVENT_CLICK_DATA_API$2 = `click${EVENT_KEY$11}${DATA_API_KEY$6}`; |
| const CLASS_NAME_NONMODAL = "dialog-nonmodal"; |
| const CLASS_NAME_INSTANT$1 = "dialog-instant"; |
| const CLASS_NAME_SWAP_IN = "dialog-swap-in"; |
| const SELECTOR_DATA_TOGGLE$5 = "[data-bs-toggle=\"dialog\"]"; |
| const Default$13 = { |
| backdrop: true, |
| keyboard: true, |
| modal: true |
| }; |
| const DefaultType$13 = { |
| backdrop: "(boolean|string)", |
| keyboard: "boolean", |
| modal: "boolean" |
| }; |
| /** |
| * Class definition |
| */ |
| var Dialog = class extends DialogBase { |
| constructor(element, config) { |
| super(element, config); |
| } |
| static get Default() { |
| return Default$13; |
| } |
| static get DefaultType() { |
| return DefaultType$13; |
| } |
| static get NAME() { |
| return NAME$14; |
| } |
| handleUpdate() {} |
| _getShowOptions() { |
| return { |
| modal: this._config.modal, |
| preventBodyScroll: this._config.modal |
| }; |
| } |
| _onBeforeShow() { |
| if (!this._config.modal) this._element.classList.add(CLASS_NAME_NONMODAL); |
| } |
| _onAfterHide() { |
| this._element.classList.remove(CLASS_NAME_NONMODAL); |
| } |
| _shouldDeferClose() { |
| return this._isAnimated(); |
| } |
| _onCancel() { |
| EventHandler.trigger(this._element, EVENT_CANCEL); |
| } |
| }; |
| /** |
| * Data API implementation |
| */ |
| EventHandler.on(document, EVENT_CLICK_DATA_API$2, SELECTOR_DATA_TOGGLE$5, function(event) { |
| const target = SelectorEngine.getElementFromSelector(this); |
| if (["A", "AREA"].includes(this.tagName)) event.preventDefault(); |
| EventHandler.one(target, EVENT_SHOW$3, (showEvent) => { |
| if (showEvent.defaultPrevented) return; |
| EventHandler.one(target, EVENT_HIDDEN$4, () => { |
| if (isVisible(this)) this.focus({ preventScroll: true }); |
| }); |
| }); |
| const config = Manipulator.getDataAttributes(this); |
| const currentDialog = this.closest("dialog[open]"); |
| if (currentDialog && currentDialog !== target) { |
| const newDialog = Dialog.getOrCreateInstance(target, config); |
| target.classList.add(CLASS_NAME_SWAP_IN); |
| newDialog.show(this); |
| EventHandler.one(target, `shown${EVENT_KEY$11}`, () => { |
| target.classList.remove(CLASS_NAME_SWAP_IN); |
| }); |
| const currentInstance = Dialog.getInstance(currentDialog); |
| if (currentInstance) { |
| currentDialog.classList.add(CLASS_NAME_INSTANT$1); |
| EventHandler.one(currentDialog, EVENT_HIDDEN$4, () => { |
| currentDialog.classList.remove(CLASS_NAME_INSTANT$1); |
| }); |
| currentInstance.hide(); |
| } |
| return; |
| } |
| Dialog.getOrCreateInstance(target, config).toggle(this); |
| }); |
| enableDismissTrigger(Dialog); |
| //#endregion |
| //#region js/src/util/sanitizer.ts |
| const ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i; |
| const DefaultAllowlist = { |
| "*": [ |
| "class", |
| "dir", |
| "id", |
| "lang", |
| "role", |
| ARIA_ATTRIBUTE_PATTERN |
| ], |
| a: [ |
| "target", |
| "href", |
| "title", |
| "rel" |
| ], |
| area: [], |
| b: [], |
| br: [], |
| col: [], |
| code: [], |
| dd: [], |
| div: [], |
| dl: [], |
| dt: [], |
| em: [], |
| hr: [], |
| h1: [], |
| h2: [], |
| h3: [], |
| h4: [], |
| h5: [], |
| h6: [], |
| i: [], |
| img: [ |
| "src", |
| "srcset", |
| "alt", |
| "title", |
| "width", |
| "height" |
| ], |
| li: [], |
| ol: [], |
| p: [], |
| pre: [], |
| s: [], |
| small: [], |
| span: [], |
| sub: [], |
| sup: [], |
| strong: [], |
| u: [], |
| ul: [] |
| }; |
| /** |
| * Allowlist for icon HTML options (Chips `dismissIcon`, NavOverflow `moreIcon`, |
| * and markup supplied via `[data-bs-overflow-icon]`). Covers the default SVG |
| * icons plus common inline-icon markup. Event-handler attributes and tags not |
| * listed here are stripped by `sanitizeHtml`. |
| */ |
| const DefaultIconAllowlist = { |
| "*": [ |
| "class", |
| "role", |
| ARIA_ATTRIBUTE_PATTERN |
| ], |
| svg: [ |
| "xmlns", |
| "width", |
| "height", |
| "viewbox", |
| "fill", |
| "stroke", |
| "stroke-width", |
| "stroke-linecap", |
| "stroke-linejoin", |
| "focusable" |
| ], |
| path: [ |
| "d", |
| "fill", |
| "stroke", |
| "stroke-width", |
| "fill-rule", |
| "clip-rule" |
| ], |
| line: [ |
| "x1", |
| "y1", |
| "x2", |
| "y2", |
| "stroke", |
| "stroke-width", |
| "stroke-linecap" |
| ], |
| circle: [ |
| "cx", |
| "cy", |
| "r", |
| "fill", |
| "stroke", |
| "stroke-width" |
| ], |
| rect: [ |
| "x", |
| "y", |
| "width", |
| "height", |
| "rx", |
| "ry", |
| "fill", |
| "stroke", |
| "stroke-width" |
| ], |
| polyline: [ |
| "points", |
| "fill", |
| "stroke", |
| "stroke-width" |
| ], |
| polygon: [ |
| "points", |
| "fill", |
| "stroke", |
| "stroke-width" |
| ], |
| g: [ |
| "fill", |
| "stroke", |
| "stroke-width", |
| "transform" |
| ], |
| span: [], |
| i: [] |
| }; |
| const uriAttributes = /* @__PURE__ */ new Set([ |
| "background", |
| "cite", |
| "href", |
| "itemtype", |
| "longdesc", |
| "poster", |
| "src", |
| "xlink:href" |
| ]); |
| /** |
| * A pattern that recognizes URLs that are safe wrt. XSS in URL navigation |
| * contexts. |
| * |
| * Shout-out to Angular https://github.com/angular/angular/blob/15.2.8/packages/core/src/sanitization/url_sanitizer.ts#L38 |
| */ |
| const SAFE_URL_PATTERN = /^(?!(?:javascript|data|vbscript):)(?:[a-z0-9+.-]+:|[^&:/?#]*(?:[/?#]|$))/i; |
| /** |
| * A pattern that matches safe data URLs. Only matches image, video and audio |
| * types — notably NOT `data:text/html`, which is an XSS vector. |
| * |
| * Shout-out to Angular https://github.com/angular/angular/blob/15.2.8/packages/core/src/sanitization/url_sanitizer.ts#L49 |
| */ |
| const DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z=]+$/i; |
| const allowedAttribute = (attribute, allowedAttributeList) => { |
| const attributeName = attribute.nodeName.toLowerCase(); |
| if (allowedAttributeList.includes(attributeName)) { |
| if (uriAttributes.has(attributeName)) return Boolean(SAFE_URL_PATTERN.test(attribute.nodeValue) || DATA_URL_PATTERN.test(attribute.nodeValue)); |
| return true; |
| } |
| return allowedAttributeList.filter((attributeRegex) => attributeRegex instanceof RegExp).some((regex) => regex.test(attributeName)); |
| }; |
| function sanitizeHtml(unsafeHtml, allowList, sanitizeFunction) { |
| if (!unsafeHtml.length) return unsafeHtml; |
| if (sanitizeFunction && typeof sanitizeFunction === "function") return sanitizeFunction(unsafeHtml); |
| const createdDocument = new window.DOMParser().parseFromString(unsafeHtml, "text/html"); |
| const elements = [...createdDocument.body.querySelectorAll("*")]; |
| for (const element of elements) { |
| const elementName = element.nodeName.toLowerCase(); |
| if (!Object.keys(allowList).includes(elementName)) { |
| element.remove(); |
| continue; |
| } |
| const attributeList = [...element.attributes]; |
| const allowedAttributes = [...allowList["*"] || [], ...allowList[elementName] || []]; |
| for (const attribute of attributeList) if (!allowedAttribute(attribute, allowedAttributes)) element.removeAttribute(attribute.nodeName); |
| } |
| return createdDocument.body.innerHTML; |
| } |
| //#endregion |
| //#region js/src/nav-overflow.ts |
| /** |
| * -------------------------------------------------------------------------- |
| * Bootstrap nav-overflow.ts |
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
| * -------------------------------------------------------------------------- |
| */ |
| /** |
| * Constants |
| */ |
| const NAME$13 = "navoverflow"; |
| const EVENT_KEY$10 = `.bs.navoverflow`; |
| const EVENT_UPDATE = `update${EVENT_KEY$10}`; |
| const EVENT_OVERFLOW = `overflow${EVENT_KEY$10}`; |
| const EVENT_RESIZE$2 = `resize${EVENT_KEY$10}`; |
| const CLASS_NAME_OVERFLOW = "nav-overflow"; |
| const CLASS_NAME_OVERFLOW_MENU = "nav-overflow-menu"; |
| const CLASS_NAME_HIDDEN = "d-none"; |
| const CLASS_NAME_KEEP = "nav-overflow-keep"; |
| const SELECTOR_NAV = ".nav"; |
| const SELECTOR_NAV_ITEM = ".nav-item"; |
| const SELECTOR_NAV_LINK = ".nav-link"; |
| const SELECTOR_OVERFLOW_TOGGLE = ".nav-overflow-toggle"; |
| const SELECTOR_OVERFLOW_MENU = ".nav-overflow-menu"; |
| const SELECTOR_CUSTOM_ICON = "[data-bs-overflow-icon]"; |
| const DEFAULT_TEXT = "More"; |
| const Default$12 = { |
| collapseBelow: 0, |
| iconPlacement: "start", |
| menuPlacement: "bottom-end", |
| moreText: DEFAULT_TEXT, |
| moreIcon: "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" fill=\"currentColor\" viewBox=\"0 0 16 16\"><path d=\"M3 9.5a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3m5 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3m5 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3\"/></svg>", |
| threshold: 0 |
| }; |
| const DefaultType$12 = { |
| collapseBelow: "(number|string)", |
| iconPlacement: "string", |
| menuPlacement: "string", |
| moreText: "(string|boolean)", |
| moreIcon: "string", |
| threshold: "number" |
| }; |
| /** |
| * Class definition |
| */ |
| var NavOverflow = class extends BaseComponent { |
| constructor(element, config) { |
| super(element, config); |
| const nav = SelectorEngine.findOne(SELECTOR_NAV, this._element); |
| if (!nav) throw new TypeError(`${this._element.outerHTML} has no child ${SELECTOR_NAV} to collapse`); |
| this._nav = nav; |
| this._items = []; |
| this._overflowItems = []; |
| this._overflowMenu = null; |
| this._overflowToggle = null; |
| this._resizeObserver = null; |
| this._resizeHandler = null; |
| this._collapseBelow = 0; |
| this._init(); |
| } |
| static get Default() { |
| return Default$12; |
| } |
| static get DefaultType() { |
| return DefaultType$12; |
| } |
| static get NAME() { |
| return NAME$13; |
| } |
| update() { |
| this._calculateOverflow(); |
| EventHandler.trigger(this._element, EVENT_UPDATE); |
| } |
| dispose() { |
| if (this._resizeObserver) this._resizeObserver.disconnect(); |
| if (this._resizeHandler) EventHandler.off(window, EVENT_RESIZE$2, this._resizeHandler); |
| this._restoreItems(); |
| if (this._overflowToggle && this._overflowToggle.parentElement) this._overflowToggle.parentElement.remove(); |
| super.dispose(); |
| } |
| _init() { |
| this._element.classList.add(CLASS_NAME_OVERFLOW); |
| this._items = SelectorEngine.find(SELECTOR_NAV_ITEM, this._nav).filter((item) => !item.querySelector(SELECTOR_OVERFLOW_TOGGLE)); |
| for (const [index, item] of this._items.entries()) item.dataset.bsNavOrder = index; |
| this._collapseBelow = this._resolveCollapseBelow(); |
| this._createOverflowMenu(); |
| this._setupResizeObserver(); |
| this._calculateOverflow(); |
| } |
| _createOverflowMenu() { |
| this._overflowToggle = SelectorEngine.findOne(SELECTOR_OVERFLOW_TOGGLE, this._element); |
| if (this._overflowToggle) { |
| this._overflowMenu = SelectorEngine.findOne(SELECTOR_OVERFLOW_MENU, this._element); |
| return; |
| } |
| const { moreText } = this._config; |
| const label = typeof moreText === "string" ? moreText : ""; |
| const overflowItem = document.createElement("li"); |
| overflowItem.className = "nav-item nav-overflow-item"; |
| const button = document.createElement("button"); |
| button.type = "button"; |
| button.className = "nav-link nav-overflow-toggle"; |
| button.setAttribute("data-bs-toggle", "menu"); |
| button.setAttribute("data-bs-placement", this._config.menuPlacement); |
| button.setAttribute("aria-expanded", "false"); |
| if (label === "") button.setAttribute("aria-label", DEFAULT_TEXT); |
| const iconSpan = document.createElement("span"); |
| iconSpan.className = "nav-overflow-icon"; |
| iconSpan.innerHTML = sanitizeHtml(this._resolveIcon(), DefaultIconAllowlist); |
| if (label === "") button.append(iconSpan); |
| else { |
| const textSpan = document.createElement("span"); |
| textSpan.className = "nav-overflow-text"; |
| textSpan.textContent = label; |
| if (this._config.iconPlacement === "end") button.append(textSpan, iconSpan); |
| else button.append(iconSpan, textSpan); |
| } |
| const menu = document.createElement("div"); |
| menu.className = `${CLASS_NAME_OVERFLOW_MENU} menu`; |
| overflowItem.append(button, menu); |
| this._nav.append(overflowItem); |
| this._overflowToggle = button; |
| this._overflowMenu = menu; |
| } |
| _resolveIcon() { |
| const customIconElement = SelectorEngine.findOne(SELECTOR_CUSTOM_ICON, this._element); |
| if (!customIconElement) return this._config.moreIcon; |
| const iconClone = customIconElement.cloneNode(true); |
| iconClone.removeAttribute("data-bs-overflow-icon"); |
| const iconHtml = iconClone.outerHTML; |
| customIconElement.remove(); |
| return iconHtml; |
| } |
| _resolveCollapseBelow() { |
| const value = this._config.collapseBelow; |
| if (typeof value === "number") return value; |
| if (typeof value === "string" && value !== "") { |
| const cssValue = getComputedStyle(document.documentElement).getPropertyValue(`--bs-breakpoint-${value}`); |
| return Number.parseFloat(cssValue) || 0; |
| } |
| return 0; |
| } |
| _setupResizeObserver() { |
| if (typeof ResizeObserver === "undefined") { |
| this._resizeHandler = () => this._calculateOverflow(); |
| EventHandler.on(window, EVENT_RESIZE$2, this._resizeHandler); |
| return; |
| } |
| this._resizeObserver = new ResizeObserver(() => { |
| this._calculateOverflow(); |
| }); |
| this._resizeObserver.observe(this._element); |
| } |
| _availableWidth() { |
| const { paddingInlineStart, paddingInlineEnd } = getComputedStyle(this._element); |
| const padding = (Number.parseFloat(paddingInlineStart) || 0) + (Number.parseFloat(paddingInlineEnd) || 0); |
| return this._element.clientWidth - padding; |
| } |
| _navGap() { |
| return Number.parseFloat(getComputedStyle(this._nav).columnGap) || 0; |
| } |
| _calculateOverflow() { |
| this._restoreItems(); |
| const availableWidth = this._availableWidth(); |
| const overflowItem = this._overflowToggle?.closest(SELECTOR_NAV_ITEM) ?? null; |
| const candidates = this._items.filter((item) => !item.classList.contains(CLASS_NAME_KEEP)); |
| if (this._collapseBelow > 0 && availableWidth < this._collapseBelow) { |
| this._applyOverflow(candidates, overflowItem); |
| return; |
| } |
| const gap = this._navGap(); |
| const keepWidth = this._items.filter((item) => item.classList.contains(CLASS_NAME_KEEP)).reduce((sum, item) => sum + item.offsetWidth + gap, 0); |
| const overflowWidth = overflowItem ? overflowItem.offsetWidth + gap : 0; |
| const limit = availableWidth - keepWidth - overflowWidth; |
| let usedWidth = 0; |
| let itemsToOverflow = []; |
| for (const item of candidates) { |
| usedWidth += item.offsetWidth + gap; |
| if (usedWidth > limit + 1) itemsToOverflow.push(item); |
| } |
| if (this._items.length - itemsToOverflow.length < this._config.threshold && this._items.length > this._config.threshold) itemsToOverflow = this._items.slice(this._config.threshold).filter((item) => !item.classList.contains(CLASS_NAME_KEEP)); |
| this._applyOverflow(itemsToOverflow, overflowItem); |
| } |
| _applyOverflow(items, overflowItem) { |
| this._moveToOverflow(items); |
| overflowItem?.classList.toggle(CLASS_NAME_HIDDEN, items.length === 0); |
| if (items.length > 0) EventHandler.trigger(this._element, EVENT_OVERFLOW, { |
| overflowCount: items.length, |
| visibleCount: this._items.length - items.length |
| }); |
| } |
| _moveToOverflow(items) { |
| if (!this._overflowMenu) return; |
| this._overflowMenu.innerHTML = ""; |
| this._overflowItems = []; |
| for (const item of items) { |
| const link = SelectorEngine.findOne(SELECTOR_NAV_LINK, item); |
| if (!link) continue; |
| const clonedLink = link.cloneNode(true); |
| clonedLink.className = "menu-item"; |
| if (link.classList.contains("active")) clonedLink.classList.add("active"); |
| if (link.classList.contains("disabled") || link.hasAttribute("disabled")) clonedLink.classList.add("disabled"); |
| this._overflowMenu.append(clonedLink); |
| item.classList.add(CLASS_NAME_HIDDEN); |
| item.dataset.bsNavOverflow = "true"; |
| this._overflowItems.push(item); |
| } |
| } |
| _restoreItems() { |
| for (const item of this._items) { |
| item.classList.remove(CLASS_NAME_HIDDEN); |
| delete item.dataset.bsNavOverflow; |
| } |
| this._overflowToggle?.closest(SELECTOR_NAV_ITEM)?.classList.remove(CLASS_NAME_HIDDEN); |
| if (this._overflowMenu) this._overflowMenu.innerHTML = ""; |
| this._overflowItems = []; |
| } |
| }; |
| /** |
| * Data API implementation |
| */ |
| EventHandler.on(document, "DOMContentLoaded", () => { |
| for (const element of SelectorEngine.find("[data-bs-toggle=\"nav-overflow\"]")) NavOverflow.getOrCreateInstance(element); |
| }); |
| //#endregion |
| //#region js/src/util/swipe.ts |
| /** |
| * -------------------------------------------------------------------------- |
| * Bootstrap util/swipe.ts |
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
| * -------------------------------------------------------------------------- |
| */ |
| /** |
| * Constants |
| */ |
| const NAME$12 = "swipe"; |
| const EVENT_KEY$9 = ".bs.swipe"; |
| const EVENT_TOUCHSTART = `touchstart${EVENT_KEY$9}`; |
| const EVENT_TOUCHMOVE = `touchmove${EVENT_KEY$9}`; |
| const EVENT_TOUCHEND = `touchend${EVENT_KEY$9}`; |
| const EVENT_POINTERDOWN = `pointerdown${EVENT_KEY$9}`; |
| const EVENT_POINTERUP = `pointerup${EVENT_KEY$9}`; |
| const POINTER_TYPE_TOUCH = "touch"; |
| const POINTER_TYPE_PEN = "pen"; |
| const CLASS_NAME_POINTER_EVENT = "pointer-event"; |
| const SWIPE_THRESHOLD = 40; |
| const Default$11 = { |
| endCallback: null, |
| leftCallback: null, |
| rightCallback: null, |
| upCallback: null, |
| downCallback: null |
| }; |
| const DefaultType$11 = { |
| endCallback: "(function|null)", |
| leftCallback: "(function|null)", |
| rightCallback: "(function|null)", |
| upCallback: "(function|null)", |
| downCallback: "(function|null)" |
| }; |
| /** |
| * Class definition |
| */ |
| var Swipe = class Swipe extends Config { |
| constructor(element, config) { |
| super(); |
| this._element = element; |
| if (!element || !Swipe.isSupported()) return; |
| this._config = this._getConfig(config); |
| this._deltaX = 0; |
| this._deltaY = 0; |
| this._supportPointerEvents = Boolean(window.PointerEvent); |
| this._initEvents(); |
| } |
| static get Default() { |
| return Default$11; |
| } |
| static get DefaultType() { |
| return DefaultType$11; |
| } |
| static get NAME() { |
| return NAME$12; |
| } |
| dispose() { |
| EventHandler.off(this._element, EVENT_KEY$9); |
| } |
| _start(event) { |
| if (!this._supportPointerEvents) { |
| this._deltaX = event.touches[0].clientX; |
| this._deltaY = event.touches[0].clientY; |
| return; |
| } |
| if (this._eventIsPointerPenTouch(event)) { |
| this._deltaX = event.clientX; |
| this._deltaY = event.clientY; |
| } |
| } |
| _end(event) { |
| if (this._eventIsPointerPenTouch(event)) { |
| this._deltaX = event.clientX - this._deltaX; |
| this._deltaY = event.clientY - this._deltaY; |
| } |
| this._handleSwipe(); |
| execute(this._config.endCallback); |
| } |
| _move(event) { |
| if (event.touches && event.touches.length > 1) { |
| this._deltaX = 0; |
| this._deltaY = 0; |
| return; |
| } |
| this._deltaX = event.touches[0].clientX - this._deltaX; |
| this._deltaY = event.touches[0].clientY - this._deltaY; |
| } |
| _handleSwipe() { |
| const absDeltaX = Math.abs(this._deltaX); |
| const absDeltaY = Math.abs(this._deltaY); |
| if (absDeltaY > absDeltaX && absDeltaY > SWIPE_THRESHOLD) { |
| const direction = this._deltaY > 0 ? "down" : "up"; |
| this._deltaX = 0; |
| this._deltaY = 0; |
| execute(direction === "down" ? this._config.downCallback : this._config.upCallback); |
| return; |
| } |
| if (absDeltaX > SWIPE_THRESHOLD) { |
| const direction = absDeltaX / this._deltaX; |
| this._deltaX = 0; |
| this._deltaY = 0; |
| if (!direction) return; |
| execute(direction > 0 ? this._config.rightCallback : this._config.leftCallback); |
| return; |
| } |
| this._deltaX = 0; |
| this._deltaY = 0; |
| } |
| _initEvents() { |
| if (this._supportPointerEvents) { |
| EventHandler.on(this._element, EVENT_POINTERDOWN, (event) => this._start(event)); |
| EventHandler.on(this._element, EVENT_POINTERUP, (event) => this._end(event)); |
| this._element.classList.add(CLASS_NAME_POINTER_EVENT); |
| } else { |
| EventHandler.on(this._element, EVENT_TOUCHSTART, (event) => this._start(event)); |
| EventHandler.on(this._element, EVENT_TOUCHMOVE, (event) => this._move(event)); |
| EventHandler.on(this._element, EVENT_TOUCHEND, (event) => this._end(event)); |
| } |
| } |
| _eventIsPointerPenTouch(event) { |
| return this._supportPointerEvents && (event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH); |
| } |
| static isSupported() { |
| return "ontouchstart" in document.documentElement || navigator.maxTouchPoints > 0; |
| } |
| }; |
| //#endregion |
| //#region js/src/drawer.ts |
| /** |
| * -------------------------------------------------------------------------- |
| * Bootstrap drawer.ts |
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
| * -------------------------------------------------------------------------- |
| */ |
| /** |
| * Constants |
| */ |
| const NAME$11 = "drawer"; |
| const EVENT_KEY$8 = `.bs.drawer`; |
| const DATA_API_KEY$5 = ".data-api"; |
| const EVENT_LOAD_DATA_API$2 = `load${EVENT_KEY$8}${DATA_API_KEY$5}`; |
| const EVENT_HIDDEN$3 = `hidden${EVENT_KEY$8}`; |
| const EVENT_RESIZE$1 = `resize${EVENT_KEY$8}`; |
| const EVENT_CLICK_DATA_API$1 = `click${EVENT_KEY$8}${DATA_API_KEY$5}`; |
| const SELECTOR_DATA_TOGGLE$4 = "[data-bs-toggle=\"drawer\"]"; |
| const Default$10 = { |
| backdrop: true, |
| keyboard: true, |
| scroll: false |
| }; |
| const DefaultType$10 = { |
| backdrop: "(boolean|string)", |
| keyboard: "boolean", |
| scroll: "boolean" |
| }; |
| /** |
| * Class definition |
| */ |
| var Drawer = class extends DialogBase { |
| constructor(element, config) { |
| super(element, config); |
| this._swipeHelper = null; |
| } |
| static get Default() { |
| return Default$10; |
| } |
| static get DefaultType() { |
| return DefaultType$10; |
| } |
| static get NAME() { |
| return NAME$11; |
| } |
| dispose() { |
| if (this._swipeHelper) this._swipeHelper.dispose(); |
| super.dispose(); |
| } |
| _getShowOptions() { |
| return { |
| modal: Boolean(this._config.backdrop) || !this._config.scroll, |
| preventBodyScroll: !this._config.scroll |
| }; |
| } |
| _onBeforeShow() { |
| this._initSwipe(); |
| } |
| _getInstantClassName() { |
| return "drawer-instant"; |
| } |
| _getStaticClassName() { |
| return "drawer-static"; |
| } |
| _initSwipe() { |
| if (this._swipeHelper || !Swipe.isSupported()) return; |
| const swipeConfig = {}; |
| const element = this._element; |
| if (element.classList.contains("drawer-bottom")) swipeConfig.downCallback = () => this.hide(); |
| else if (element.classList.contains("drawer-top")) swipeConfig.upCallback = () => this.hide(); |
| else if (element.classList.contains("drawer-end")) if (isRTL$1()) swipeConfig.leftCallback = () => this.hide(); |
| else swipeConfig.rightCallback = () => this.hide(); |
| else if (isRTL$1()) swipeConfig.rightCallback = () => this.hide(); |
| else swipeConfig.leftCallback = () => this.hide(); |
| this._swipeHelper = new Swipe(element, swipeConfig); |
| } |
| }; |
| /** |
| * Data API implementation |
| */ |
| EventHandler.on(document, EVENT_CLICK_DATA_API$1, SELECTOR_DATA_TOGGLE$4, function(event) { |
| const target = SelectorEngine.getElementFromSelector(this); |
| if (["A", "AREA"].includes(this.tagName)) event.preventDefault(); |
| if (isDisabled(this)) return; |
| EventHandler.one(target, EVENT_HIDDEN$3, () => { |
| if (isVisible(this)) this.focus({ preventScroll: true }); |
| }); |
| const alreadyOpen = SelectorEngine.findOne("dialog.drawer[open]"); |
| if (alreadyOpen && alreadyOpen !== target) Drawer.getInstance(alreadyOpen).hide(); |
| Drawer.getOrCreateInstance(target).toggle(this); |
| }); |
| EventHandler.on(window, EVENT_LOAD_DATA_API$2, () => { |
| for (const selector of SelectorEngine.find("dialog.drawer[open]")) Drawer.getOrCreateInstance(selector).show(); |
| }); |
| EventHandler.on(window, EVENT_RESIZE$1, () => { |
| for (const element of SelectorEngine.find("dialog[open][class*=\"\\:drawer\"]")) if (getComputedStyle(element).position !== "fixed") Drawer.getOrCreateInstance(element).hide(); |
| }); |
| enableDismissTrigger(Drawer); |
| //#endregion |
| //#region js/src/strength.ts |
| /** |
| * -------------------------------------------------------------------------- |
| * Bootstrap strength.ts |
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
| * -------------------------------------------------------------------------- |
| */ |
| /** |
| * Constants |
| */ |
| const NAME$10 = "strength"; |
| const EVENT_KEY$7 = `.bs.strength`; |
| const DATA_API_KEY$4 = ".data-api"; |
| const EVENT_STRENGTH_CHANGE = `strengthChange${EVENT_KEY$7}`; |
| const SELECTOR_DATA_STRENGTH = "[data-bs-strength]"; |
| const STRENGTH_LEVELS = [ |
| "weak", |
| "fair", |
| "good", |
| "strong" |
| ]; |
| const Default$9 = { |
| input: null, |
| minLength: 8, |
| messages: { |
| weak: "Weak", |
| fair: "Fair", |
| good: "Good", |
| strong: "Strong" |
| }, |
| weights: { |
| minLength: 1, |
| extraLength: 1, |
| lowercase: 1, |
| uppercase: 1, |
| numbers: 1, |
| special: 1, |
| multipleSpecial: 1, |
| longPassword: 1 |
| }, |
| thresholds: [ |
| 2, |
| 4, |
| 6 |
| ], |
| scorer: null |
| }; |
| const DefaultType$9 = { |
| input: "(string|element|null)", |
| minLength: "number", |
| messages: "object", |
| weights: "object", |
| thresholds: "array", |
| scorer: "(function|null)" |
| }; |
| /** |
| * Class definition |
| */ |
| var Strength = class extends BaseComponent { |
| constructor(element, config) { |
| super(element, config); |
| this._input = this._getInput(); |
| this._segments = SelectorEngine.find(".strength-segment", this._element); |
| this._textElement = SelectorEngine.findOne(".strength-text", this._element.parentElement); |
| this._currentStrength = null; |
| if (this._input) { |
| this._addEventListeners(); |
| this._evaluate(); |
| } |
| } |
| static get Default() { |
| return Default$9; |
| } |
| static get DefaultType() { |
| return DefaultType$9; |
| } |
| static get NAME() { |
| return NAME$10; |
| } |
| getStrength() { |
| return this._currentStrength; |
| } |
| evaluate() { |
| this._evaluate(); |
| } |
| _getInput() { |
| if (this._config.input) return typeof this._config.input === "string" ? SelectorEngine.findOne(this._config.input) : this._config.input; |
| const parent = this._element.parentElement; |
| return SelectorEngine.findOne("input[type=\"password\"]", parent); |
| } |
| _addEventListeners() { |
| EventHandler.on(this._input, "input", () => this._evaluate()); |
| EventHandler.on(this._input, "change", () => this._evaluate()); |
| } |
| _evaluate() { |
| const password = this._input.value; |
| const score = this._calculateScore(password); |
| const strength = this._scoreToStrength(score); |
| if (strength !== this._currentStrength) { |
| this._currentStrength = strength; |
| this._updateUI(strength); |
| EventHandler.trigger(this._element, EVENT_STRENGTH_CHANGE, { |
| strength, |
| score, |
| password: password.length > 0 ? "***" : "" |
| }); |
| } |
| } |
| _calculateScore(password) { |
| if (!password) return 0; |
| if (typeof this._config.scorer === "function") return this._config.scorer(password); |
| const { weights } = this._config; |
| let score = 0; |
| if (password.length >= this._config.minLength) score += weights.minLength; |
| if (password.length >= this._config.minLength + 4) score += weights.extraLength; |
| if (/[a-z]/.test(password)) score += weights.lowercase; |
| if (/[A-Z]/.test(password)) score += weights.uppercase; |
| if (/\d/.test(password)) score += weights.numbers; |
| if (/[!@#$%^&*(),.?":{}|<>]/.test(password)) score += weights.special; |
| if (/[!@#$%^&*(),.?":{}|<>].*[!@#$%^&*(),.?":{}|<>]/.test(password)) score += weights.multipleSpecial; |
| if (password.length >= 16) score += weights.longPassword; |
| return score; |
| } |
| _scoreToStrength(score) { |
| if (score === 0) return null; |
| const [weak, fair, good] = this._config.thresholds; |
| if (score <= weak) return "weak"; |
| if (score <= fair) return "fair"; |
| if (score <= good) return "good"; |
| return "strong"; |
| } |
| _updateUI(strength) { |
| if (strength) this._element.dataset.bsStrength = strength; |
| else delete this._element.dataset.bsStrength; |
| const strengthIndex = strength ? STRENGTH_LEVELS.indexOf(strength) : -1; |
| for (const [index, segment] of this._segments.entries()) if (index <= strengthIndex) segment.classList.add("active"); |
| else segment.classList.remove("active"); |
| if (this._textElement) if (strength && this._config.messages[strength]) { |
| this._textElement.textContent = this._config.messages[strength]; |
| this._textElement.dataset.bsStrength = strength; |
| this._textElement.style.setProperty("--strength-color", `var(--${{ |
| weak: "danger", |
| fair: "warning", |
| good: "info", |
| strong: "success" |
| }[strength]}-text)`); |
| } else { |
| this._textElement.textContent = ""; |
| delete this._textElement.dataset.bsStrength; |
| } |
| } |
| }; |
| /** |
| * Data API implementation |
| */ |
| EventHandler.on(document, `DOMContentLoaded${EVENT_KEY$7}${DATA_API_KEY$4}`, () => { |
| for (const element of SelectorEngine.find(SELECTOR_DATA_STRENGTH)) Strength.getOrCreateInstance(element); |
| }); |
| //#endregion |
| //#region js/src/otp-input.ts |
| /** |
| * -------------------------------------------------------------------------- |
| * Bootstrap otp-input.ts |
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
| * -------------------------------------------------------------------------- |
| */ |
| /** |
| * Constants |
| */ |
| const NAME$9 = "otpInput"; |
| const EVENT_KEY$6 = `.bs.otpInput`; |
| const DATA_API_KEY$3 = ".data-api"; |
| const EVENT_COMPLETE = `complete${EVENT_KEY$6}`; |
| const EVENT_INPUT$1 = `input${EVENT_KEY$6}`; |
| const EVENT_DOMCONTENT_LOADED = `DOMContentLoaded${EVENT_KEY$6}${DATA_API_KEY$3}`; |
| const SELECTOR_DATA_OTP = "[data-bs-otp]"; |
| const SELECTOR_INPUT$1 = "input"; |
| const SYNC_EVENTS = [ |
| "blur", |
| "keyup", |
| "select" |
| ]; |
| const CLASS_NAME_INPUT = "otp-input"; |
| const CLASS_NAME_RENDERED = "otp-rendered"; |
| const CLASS_NAME_SLOTS = "otp-slots"; |
| const CLASS_NAME_SLOT = "otp-slot"; |
| const CLASS_NAME_SLOT_FILLED = "otp-slot-filled"; |
| const CLASS_NAME_SLOT_ACTIVE = "otp-slot-active"; |
| const CLASS_NAME_SEPARATOR = "otp-separator"; |
| const MASK_CHARACTER = "•"; |
| const TYPES = { |
| numeric: { |
| inputmode: "numeric", |
| pattern: "[0-9]*", |
| filter: /[^0-9]/g |
| }, |
| alphanumeric: { |
| inputmode: "text", |
| pattern: "[A-Za-z0-9]*", |
| filter: /[^A-Za-z0-9]/g |
| }, |
| alpha: { |
| inputmode: "text", |
| pattern: "[A-Za-z]*", |
| filter: /[^A-Za-z]/g |
| } |
| }; |
| const Default$8 = { |
| groups: null, |
| length: null, |
| mask: false, |
| separator: "·", |
| type: "numeric" |
| }; |
| const DefaultType$8 = { |
| groups: "(array|null)", |
| length: "(number|null)", |
| mask: "boolean", |
| separator: "string", |
| type: "string" |
| }; |
| /** |
| * Class definition |
| */ |
| var OtpInput = class extends BaseComponent { |
| constructor(element, config) { |
| super(element, config); |
| const input = SelectorEngine.findOne(SELECTOR_INPUT$1, this._element); |
| if (!input) return; |
| this._input = input; |
| this._type = TYPES[this._config.type] || TYPES.numeric; |
| this._length = this._resolveLength(); |
| this._slots = []; |
| this._pointerActive = false; |
| this._pointerIndex = 0; |
| this._setupInput(); |
| this._renderSlots(); |
| this._addEventListeners(); |
| this._render(); |
| } |
| static get Default() { |
| return Default$8; |
| } |
| static get DefaultType() { |
| return DefaultType$8; |
| } |
| static get NAME() { |
| return NAME$9; |
| } |
| getValue() { |
| return this._input.value; |
| } |
| setValue(value) { |
| this._input.value = this._sanitize(String(value)); |
| this._render(); |
| this._checkComplete(); |
| } |
| clear() { |
| this._input.value = ""; |
| this._render(); |
| this._input.focus(); |
| } |
| focus() { |
| this._input.focus(); |
| this._selectSlot(this._firstEmptyIndex()); |
| this._render(); |
| } |
| dispose() { |
| EventHandler.off(this._input, "input", this._onInput); |
| EventHandler.off(this._input, "beforeinput", this._onBeforeInput); |
| EventHandler.off(this._input, "focus", this._onFocus); |
| EventHandler.off(this._input, "pointerdown", this._onPointerDown); |
| EventHandler.off(document, "selectionchange", this._onSelectionChange); |
| for (const type of SYNC_EVENTS) EventHandler.off(this._input, type, this._onSync); |
| this._slotsContainer?.remove(); |
| this._element.classList.remove(CLASS_NAME_RENDERED); |
| super.dispose(); |
| } |
| _resolveLength() { |
| if (this._config.length) return this._config.length; |
| const maxLength = Number.parseInt(this._input.getAttribute("maxlength"), 10); |
| return Number.isNaN(maxLength) || maxLength < 1 ? 6 : maxLength; |
| } |
| _setupInput() { |
| const input = this._input; |
| if (input.type === "number" || input.type === "password") input.type = "text"; |
| input.classList.add(CLASS_NAME_INPUT); |
| input.setAttribute("maxlength", String(this._length)); |
| input.setAttribute("inputmode", this._type.inputmode); |
| input.setAttribute("pattern", this._type.pattern); |
| if (!input.getAttribute("autocomplete")) input.setAttribute("autocomplete", "one-time-code"); |
| if (input.value) input.value = this._sanitize(input.value); |
| } |
| _renderSlots() { |
| const container = document.createElement("div"); |
| container.className = CLASS_NAME_SLOTS; |
| container.setAttribute("aria-hidden", "true"); |
| const { groups } = this._config; |
| let groupIndex = 0; |
| let inGroup = 0; |
| for (let i = 0; i < this._length; i++) { |
| const slot = document.createElement("div"); |
| slot.className = CLASS_NAME_SLOT; |
| container.append(slot); |
| this._slots.push(slot); |
| if (Array.isArray(groups) && groups.length > 0) { |
| inGroup++; |
| if (inGroup === groups[groupIndex] && i < this._length - 1) { |
| const separator = document.createElement("div"); |
| separator.className = CLASS_NAME_SEPARATOR; |
| separator.textContent = this._config.separator; |
| container.append(separator); |
| groupIndex = Math.min(groupIndex + 1, groups.length - 1); |
| inGroup = 0; |
| } |
| } |
| } |
| this._slotsContainer = container; |
| this._element.append(container); |
| this._element.classList.add(CLASS_NAME_RENDERED); |
| } |
| _addEventListeners() { |
| this._onInput = () => this._handleInput(); |
| this._onBeforeInput = (event) => this._handleBeforeInput(event); |
| this._onPointerDown = (event) => this._handlePointerDown(event); |
| this._onFocus = () => { |
| if (this._pointerActive) { |
| this._pointerActive = false; |
| this._selectSlot(this._pointerIndex); |
| this._render(); |
| return; |
| } |
| this._selectSlot(this._firstEmptyIndex()); |
| this._render(); |
| }; |
| this._onSync = () => this._render(); |
| this._onSelectionChange = () => { |
| if (document.activeElement === this._input) this._render(); |
| }; |
| EventHandler.on(this._input, "input", this._onInput); |
| EventHandler.on(this._input, "beforeinput", this._onBeforeInput); |
| EventHandler.on(this._input, "focus", this._onFocus); |
| EventHandler.on(this._input, "pointerdown", this._onPointerDown); |
| EventHandler.on(document, "selectionchange", this._onSelectionChange); |
| for (const type of SYNC_EVENTS) EventHandler.on(this._input, type, this._onSync); |
| } |
| _handleInput() { |
| const sanitized = this._sanitize(this._input.value); |
| if (sanitized !== this._input.value) this._input.value = sanitized; |
| if (document.activeElement === this._input) this._selectSlot(this._firstEmptyIndex()); |
| this._afterValueChange(); |
| } |
| _handleBeforeInput(event) { |
| const { inputType, data } = event; |
| if (inputType === "insertText" && data && data.length === 1) { |
| event.preventDefault(); |
| const char = this._sanitize(data); |
| if (!char) return; |
| const index = Math.min(this._input.selectionStart ?? 0, this._length - 1); |
| const chars = [...this._input.value]; |
| chars[index] = char; |
| this._input.value = chars.join("").slice(0, this._length); |
| this._selectSlot(index + 1); |
| this._afterValueChange(); |
| return; |
| } |
| if (inputType === "deleteContentBackward") { |
| event.preventDefault(); |
| const start = this._input.selectionStart ?? 0; |
| const end = this._input.selectionEnd ?? start; |
| const chars = [...this._input.value]; |
| if (end > start) { |
| chars.splice(start, end - start); |
| this._input.value = chars.join(""); |
| this._selectSlot(start); |
| } else if (start > 0) { |
| chars.splice(start - 1, 1); |
| this._input.value = chars.join(""); |
| this._selectSlot(start - 1); |
| } |
| this._afterValueChange(); |
| } |
| } |
| _handlePointerDown(event) { |
| const index = this._slotIndexFromPoint(event.clientX); |
| if (index === null) return; |
| const target = Math.min(index, this._firstEmptyIndex()); |
| if (document.activeElement === this._input) { |
| event.preventDefault(); |
| this._selectSlot(target); |
| this._render(); |
| return; |
| } |
| this._pointerActive = true; |
| this._pointerIndex = target; |
| } |
| _slotIndexFromPoint(x) { |
| for (const [index, slot] of this._slots.entries()) if (x <= slot.getBoundingClientRect().right || index === this._slots.length - 1) return index; |
| return null; |
| } |
| _afterValueChange() { |
| this._render(); |
| EventHandler.trigger(this._element, EVENT_INPUT$1, { value: this._input.value }); |
| this._checkComplete(); |
| } |
| _firstEmptyIndex() { |
| return Math.min(this._input.value.length, this._length - 1); |
| } |
| _selectSlot(index) { |
| const clamped = Math.max(0, Math.min(index, this._length - 1)); |
| const end = clamped < this._input.value.length ? clamped + 1 : clamped; |
| this._input.setSelectionRange(clamped, end); |
| } |
| _sanitize(value) { |
| return value.replace(this._type.filter, "").slice(0, this._length); |
| } |
| _render() { |
| const { value } = this._input; |
| const isFocused = document.activeElement === this._input; |
| const caret = Math.min(this._input.selectionStart ?? value.length, this._length - 1); |
| for (const [index, slot] of this._slots.entries()) { |
| const char = value[index] ?? ""; |
| slot.textContent = char && this._config.mask ? MASK_CHARACTER : char; |
| slot.classList.toggle(CLASS_NAME_SLOT_FILLED, Boolean(char)); |
| slot.classList.toggle(CLASS_NAME_SLOT_ACTIVE, isFocused && index === caret); |
| } |
| } |
| _checkComplete() { |
| const { value } = this._input; |
| if (value.length === this._length) EventHandler.trigger(this._element, EVENT_COMPLETE, { value }); |
| } |
| }; |
| /** |
| * Data API implementation |
| */ |
| EventHandler.on(document, EVENT_DOMCONTENT_LOADED, () => { |
| for (const element of SelectorEngine.find(SELECTOR_DATA_OTP)) OtpInput.getOrCreateInstance(element); |
| }); |
| //#endregion |
| //#region js/src/chips.ts |
| /** |
| * -------------------------------------------------------------------------- |
| * Bootstrap chips.ts |
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
| * -------------------------------------------------------------------------- |
| */ |
| /** |
| * Constants |
| */ |
| const NAME$8 = "chips"; |
| const EVENT_KEY$5 = `.bs.chips`; |
| const DATA_API_KEY$2 = ".data-api"; |
| const EVENT_ADD = `add${EVENT_KEY$5}`; |
| const EVENT_REMOVE = `remove${EVENT_KEY$5}`; |
| const EVENT_CHANGE$1 = `change${EVENT_KEY$5}`; |
| const EVENT_SELECT = `select${EVENT_KEY$5}`; |
| const SELECTOR_DATA_CHIPS = "[data-bs-chips]"; |
| const SELECTOR_GHOST_INPUT = ".form-ghost"; |
| const SELECTOR_CHIP = ".chip"; |
| const SELECTOR_CHIP_DISMISS = ".chip-dismiss"; |
| const CLASS_NAME_CHIP = "chip"; |
| const CLASS_NAME_CHIP_DISMISS = "chip-dismiss"; |
| const CLASS_NAME_ACTIVE$2 = "active"; |
| const Default$7 = { |
| separator: ",", |
| allowDuplicates: false, |
| maxChips: null, |
| placeholder: "", |
| dismissible: true, |
| dismissIcon: "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"><line x1=\"4\" y1=\"4\" x2=\"12\" y2=\"12\"/><line x1=\"12\" y1=\"4\" x2=\"4\" y2=\"12\"/></svg>", |
| createOnBlur: true |
| }; |
| const DefaultType$7 = { |
| separator: "(string|null)", |
| allowDuplicates: "boolean", |
| maxChips: "(number|null)", |
| placeholder: "string", |
| dismissible: "boolean", |
| dismissIcon: "string", |
| createOnBlur: "boolean" |
| }; |
| /** |
| * Class definition |
| */ |
| var Chips = class extends BaseComponent { |
| constructor(element, config) { |
| super(element, config); |
| const ghostInput = SelectorEngine.findOne(SELECTOR_GHOST_INPUT, this._element); |
| this._chips = []; |
| this._selectedChips = /* @__PURE__ */ new Set(); |
| this._anchorChip = null; |
| if (ghostInput) this._input = ghostInput; |
| else this._createInput(); |
| this._initializeExistingChips(); |
| this._addEventListeners(); |
| } |
| static get Default() { |
| return Default$7; |
| } |
| static get DefaultType() { |
| return DefaultType$7; |
| } |
| static get NAME() { |
| return NAME$8; |
| } |
| add(value) { |
| const trimmedValue = String(value).trim(); |
| if (!trimmedValue) return null; |
| if (!this._config.allowDuplicates && this._chips.includes(trimmedValue)) return null; |
| if (this._config.maxChips !== null && this._chips.length >= this._config.maxChips) return null; |
| if (EventHandler.trigger(this._element, EVENT_ADD, { |
| value: trimmedValue, |
| relatedTarget: this._input |
| }).defaultPrevented) return null; |
| const chip = this._createChip(trimmedValue); |
| this._element.insertBefore(chip, this._input); |
| this._chips.push(trimmedValue); |
| EventHandler.trigger(this._element, EVENT_CHANGE$1, { values: this.getValues() }); |
| return chip; |
| } |
| remove(chipOrValue) { |
| let chip; |
| let value; |
| if (typeof chipOrValue === "string") { |
| value = chipOrValue; |
| chip = this._findChipByValue(value); |
| } else { |
| chip = chipOrValue; |
| value = this._getChipValue(chip); |
| } |
| if (!chip || !value) return false; |
| if (EventHandler.trigger(this._element, EVENT_REMOVE, { |
| value, |
| chip, |
| relatedTarget: this._input |
| }).defaultPrevented) return false; |
| this._selectedChips.delete(chip); |
| if (this._anchorChip === chip) this._anchorChip = null; |
| chip.remove(); |
| this._chips = this._getChipElements().map((chipElement) => this._getChipValue(chipElement)).filter(Boolean); |
| EventHandler.trigger(this._element, EVENT_CHANGE$1, { values: this.getValues() }); |
| return true; |
| } |
| removeSelected() { |
| const chipsToRemove = [...this._selectedChips]; |
| for (const chip of chipsToRemove) this.remove(chip); |
| this._input?.focus(); |
| } |
| getValues() { |
| return [...this._chips]; |
| } |
| getSelectedValues() { |
| return [...this._selectedChips].map((chip) => this._getChipValue(chip)); |
| } |
| clear() { |
| const chips = SelectorEngine.find(SELECTOR_CHIP, this._element); |
| for (const chip of chips) chip.remove(); |
| this._chips = []; |
| this._selectedChips.clear(); |
| this._anchorChip = null; |
| EventHandler.trigger(this._element, EVENT_CHANGE$1, { values: [] }); |
| } |
| clearSelection() { |
| for (const chip of this._selectedChips) chip.classList.remove(CLASS_NAME_ACTIVE$2); |
| this._selectedChips.clear(); |
| this._anchorChip = null; |
| EventHandler.trigger(this._element, EVENT_SELECT, { selected: [] }); |
| } |
| selectChip(chip, options = {}) { |
| const { addToSelection = false, rangeSelect = false } = options; |
| const chipElements = this._getChipElements(); |
| if (!chipElements.includes(chip)) return; |
| if (rangeSelect && this._anchorChip) { |
| const anchorIndex = chipElements.indexOf(this._anchorChip); |
| const chipIndex = chipElements.indexOf(chip); |
| const start = Math.min(anchorIndex, chipIndex); |
| const end = Math.max(anchorIndex, chipIndex); |
| if (!addToSelection) this.clearSelection(); |
| for (let i = start; i <= end; i++) { |
| this._selectedChips.add(chipElements[i]); |
| chipElements[i].classList.add(CLASS_NAME_ACTIVE$2); |
| } |
| } else if (addToSelection) if (this._selectedChips.has(chip)) { |
| this._selectedChips.delete(chip); |
| chip.classList.remove(CLASS_NAME_ACTIVE$2); |
| } else { |
| this._selectedChips.add(chip); |
| chip.classList.add(CLASS_NAME_ACTIVE$2); |
| this._anchorChip = chip; |
| } |
| else { |
| this.clearSelection(); |
| this._selectedChips.add(chip); |
| chip.classList.add(CLASS_NAME_ACTIVE$2); |
| this._anchorChip = chip; |
| } |
| EventHandler.trigger(this._element, EVENT_SELECT, { selected: this.getSelectedValues() }); |
| } |
| focus() { |
| this._input?.focus(); |
| } |
| _getChipElements() { |
| return SelectorEngine.find(SELECTOR_CHIP, this._element); |
| } |
| _createInput() { |
| const input = document.createElement("input"); |
| input.type = "text"; |
| input.className = "form-ghost"; |
| if (this._config.placeholder) input.placeholder = this._config.placeholder; |
| this._element.append(input); |
| this._input = input; |
| } |
| _initializeExistingChips() { |
| const existingChips = SelectorEngine.find(SELECTOR_CHIP, this._element); |
| for (const chip of existingChips) { |
| const value = this._getChipValue(chip); |
| if (value) { |
| this._chips.push(value); |
| this._setupChip(chip); |
| } |
| } |
| } |
| _setupChip(chip) { |
| chip.setAttribute("tabindex", "0"); |
| if (this._config.dismissible && !SelectorEngine.findOne(SELECTOR_CHIP_DISMISS, chip)) chip.append(this._createDismissButton()); |
| } |
| _createChip(value) { |
| const chip = document.createElement("span"); |
| chip.className = CLASS_NAME_CHIP; |
| chip.dataset.bsChipValue = value; |
| chip.append(document.createTextNode(value)); |
| this._setupChip(chip); |
| return chip; |
| } |
| _createDismissButton() { |
| const button = document.createElement("button"); |
| button.type = "button"; |
| button.className = CLASS_NAME_CHIP_DISMISS; |
| button.setAttribute("aria-label", "Remove"); |
| button.setAttribute("tabindex", "-1"); |
| button.innerHTML = sanitizeHtml(this._config.dismissIcon, DefaultIconAllowlist); |
| return button; |
| } |
| _findChipByValue(value) { |
| return this._getChipElements().find((chip) => this._getChipValue(chip) === value); |
| } |
| _getChipValue(chip) { |
| if (chip.dataset.bsChipValue) return chip.dataset.bsChipValue; |
| const clone = chip.cloneNode(true); |
| const dismiss = SelectorEngine.findOne(SELECTOR_CHIP_DISMISS, clone); |
| if (dismiss) dismiss.remove(); |
| return clone.textContent?.trim() || ""; |
| } |
| _addEventListeners() { |
| EventHandler.on(this._input, "keydown", (event) => this._handleInputKeydown(event)); |
| EventHandler.on(this._input, "input", (event) => this._handleInput(event)); |
| EventHandler.on(this._input, "paste", (event) => this._handlePaste(event)); |
| EventHandler.on(this._input, "focus", () => this.clearSelection()); |
| if (this._config.createOnBlur) EventHandler.on(this._input, "blur", (event) => { |
| if (!event.relatedTarget?.closest(SELECTOR_CHIP)) this._createChipFromInput(); |
| }); |
| EventHandler.on(this._element, "click", SELECTOR_CHIP, (event) => { |
| if (event.target.closest(SELECTOR_CHIP_DISMISS)) return; |
| const chip = event.target.closest(SELECTOR_CHIP); |
| if (chip) { |
| event.preventDefault(); |
| this.selectChip(chip, { |
| addToSelection: event.metaKey || event.ctrlKey, |
| rangeSelect: event.shiftKey |
| }); |
| chip.focus(); |
| } |
| }); |
| EventHandler.on(this._element, "click", SELECTOR_CHIP_DISMISS, (event) => { |
| event.stopPropagation(); |
| const chip = event.target.closest(SELECTOR_CHIP); |
| if (chip) { |
| this.remove(chip); |
| this._input?.focus(); |
| } |
| }); |
| EventHandler.on(this._element, "keydown", SELECTOR_CHIP, (event) => { |
| this._handleChipKeydown(event); |
| }); |
| EventHandler.on(this._element, "click", (event) => { |
| if (event.target === this._element) { |
| this.clearSelection(); |
| this._input?.focus(); |
| } |
| }); |
| } |
| _handleInputKeydown(event) { |
| const { key } = event; |
| switch (key) { |
| case "Enter": |
| event.preventDefault(); |
| this._createChipFromInput(); |
| break; |
| case "Backspace": |
| case "Delete": |
| if (this._input.value === "") { |
| event.preventDefault(); |
| const chips = this._getChipElements(); |
| if (chips.length > 0) { |
| const lastChip = chips.at(-1); |
| this.selectChip(lastChip); |
| lastChip.focus(); |
| } |
| } |
| break; |
| case "ArrowLeft": |
| if (this._input.selectionStart === 0 && this._input.selectionEnd === 0) { |
| event.preventDefault(); |
| const chips = this._getChipElements(); |
| if (chips.length > 0) { |
| const lastChip = chips.at(-1); |
| if (event.shiftKey) this.selectChip(lastChip, { addToSelection: true }); |
| else this.selectChip(lastChip); |
| lastChip.focus(); |
| } |
| } |
| break; |
| case "Escape": |
| this._input.value = ""; |
| this.clearSelection(); |
| this._input.blur(); |
| break; |
| } |
| } |
| _handleChipKeydown(event) { |
| const { key } = event; |
| const chip = event.target.closest(SELECTOR_CHIP); |
| if (!chip) return; |
| const chips = this._getChipElements(); |
| const currentIndex = chips.indexOf(chip); |
| switch (key) { |
| case "Backspace": |
| case "Delete": |
| event.preventDefault(); |
| this._handleChipDelete(currentIndex, chips); |
| break; |
| case "ArrowLeft": |
| event.preventDefault(); |
| this._navigateChip(chips, currentIndex, -1, event.shiftKey); |
| break; |
| case "ArrowRight": |
| event.preventDefault(); |
| this._navigateChip(chips, currentIndex, 1, event.shiftKey); |
| break; |
| case "Home": |
| event.preventDefault(); |
| this._navigateToEdge(chips, 0, event.shiftKey); |
| break; |
| case "End": |
| event.preventDefault(); |
| this.clearSelection(); |
| this._input?.focus(); |
| break; |
| case "a": |
| this._handleSelectAll(event, chips); |
| break; |
| case "Escape": |
| event.preventDefault(); |
| this.clearSelection(); |
| this._input?.focus(); |
| break; |
| } |
| } |
| _handleChipDelete(currentIndex, chips) { |
| if (this._selectedChips.size === 0) return; |
| const nextIndex = Math.min(currentIndex, chips.length - this._selectedChips.size - 1); |
| this.removeSelected(); |
| const remainingChips = this._getChipElements(); |
| if (remainingChips.length > 0) { |
| const focusIndex = Math.max(0, Math.min(nextIndex, remainingChips.length - 1)); |
| remainingChips[focusIndex].focus(); |
| this.selectChip(remainingChips[focusIndex]); |
| } else this._input?.focus(); |
| } |
| _navigateChip(chips, currentIndex, direction, shiftKey) { |
| const targetIndex = currentIndex + direction; |
| if (direction < 0 && targetIndex >= 0) { |
| const targetChip = chips[targetIndex]; |
| this.selectChip(targetChip, shiftKey ? { |
| addToSelection: true, |
| rangeSelect: true |
| } : {}); |
| targetChip.focus(); |
| } else if (direction > 0 && targetIndex < chips.length) { |
| const targetChip = chips[targetIndex]; |
| this.selectChip(targetChip, shiftKey ? { |
| addToSelection: true, |
| rangeSelect: true |
| } : {}); |
| targetChip.focus(); |
| } else if (direction > 0) { |
| this.clearSelection(); |
| this._input?.focus(); |
| } |
| } |
| _navigateToEdge(chips, targetIndex, shiftKey) { |
| if (chips.length === 0) return; |
| const targetChip = chips[targetIndex]; |
| this.selectChip(targetChip, shiftKey ? { rangeSelect: true } : {}); |
| targetChip.focus(); |
| } |
| _handleSelectAll(event, chips) { |
| if (!(event.metaKey || event.ctrlKey)) return; |
| event.preventDefault(); |
| for (const c of chips) { |
| this._selectedChips.add(c); |
| c.classList.add(CLASS_NAME_ACTIVE$2); |
| } |
| EventHandler.trigger(this._element, EVENT_SELECT, { selected: this.getSelectedValues() }); |
| } |
| _handleInput(event) { |
| const { value } = event.target; |
| const { separator } = this._config; |
| if (separator && value.includes(separator)) { |
| const parts = value.split(separator); |
| for (const part of parts.slice(0, -1)) this.add(part.trim()); |
| this._input.value = parts.at(-1); |
| } |
| } |
| _handlePaste(event) { |
| const { separator } = this._config; |
| if (!separator) return; |
| const pastedData = (event.clipboardData || window.clipboardData).getData("text"); |
| if (pastedData.includes(separator)) { |
| event.preventDefault(); |
| const parts = pastedData.split(separator); |
| for (const part of parts) this.add(part.trim()); |
| } |
| } |
| _createChipFromInput() { |
| const value = this._input.value.trim(); |
| if (value) { |
| this.add(value); |
| this._input.value = ""; |
| } |
| } |
| }; |
| /** |
| * Data API implementation |
| */ |
| EventHandler.on(document, `DOMContentLoaded${EVENT_KEY$5}${DATA_API_KEY$2}`, () => { |
| for (const element of SelectorEngine.find(SELECTOR_DATA_CHIPS)) Chips.getOrCreateInstance(element); |
| }); |
| //#endregion |
| //#region js/src/util/template-factory.ts |
| /** |
| * -------------------------------------------------------------------------- |
| * Bootstrap util/template-factory.ts |
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
| * -------------------------------------------------------------------------- |
| */ |
| /** |
| * Constants |
| */ |
| const NAME$7 = "TemplateFactory"; |
| const Default$6 = { |
| allowList: DefaultAllowlist, |
| content: {}, |
| extraClass: "", |
| html: false, |
| sanitize: true, |
| sanitizeFn: null, |
| template: "<div></div>" |
| }; |
| const DefaultType$6 = { |
| allowList: "object", |
| content: "object", |
| extraClass: "(string|function)", |
| html: "boolean", |
| sanitize: "boolean", |
| sanitizeFn: "(null|function)", |
| template: "string" |
| }; |
| const DefaultContentType = { |
| entry: "(string|element|function|null)", |
| selector: "(string|element)" |
| }; |
| /** |
| * Class definition |
| */ |
| var TemplateFactory = class extends Config { |
| constructor(config) { |
| super(); |
| this._config = this._getConfig(config); |
| } |
| static get Default() { |
| return Default$6; |
| } |
| static get DefaultType() { |
| return DefaultType$6; |
| } |
| static get NAME() { |
| return NAME$7; |
| } |
| getContent() { |
| return Object.values(this._config.content).map((config) => this._resolvePossibleFunction(config)).filter(Boolean); |
| } |
| hasContent() { |
| return this.getContent().length > 0; |
| } |
| changeContent(content) { |
| this._checkContent(content); |
| this._config.content = { |
| ...this._config.content, |
| ...content |
| }; |
| return this; |
| } |
| toHtml() { |
| const templateWrapper = document.createElement("div"); |
| templateWrapper.innerHTML = this._maybeSanitize(this._config.template); |
| for (const [selector, text] of Object.entries(this._config.content)) this._setContent(templateWrapper, text, selector); |
| const template = templateWrapper.children[0]; |
| const extraClass = this._resolvePossibleFunction(this._config.extraClass); |
| if (extraClass) template.classList.add(...extraClass.split(" ")); |
| return template; |
| } |
| _typeCheckConfig(config) { |
| super._typeCheckConfig(config); |
| this._checkContent(config.content); |
| } |
| _checkContent(arg) { |
| for (const [selector, content] of Object.entries(arg)) super._typeCheckConfig({ |
| selector, |
| entry: content |
| }, DefaultContentType); |
| } |
| _setContent(template, content, selector) { |
| const templateElement = SelectorEngine.findOne(selector, template); |
| if (!templateElement) return; |
| content = this._resolvePossibleFunction(content); |
| if (!content) { |
| templateElement.remove(); |
| return; |
| } |
| if (isElement$1(content)) { |
| this._putElementInTemplate(getElement(content), templateElement); |
| return; |
| } |
| if (this._config.html) { |
| templateElement.innerHTML = this._maybeSanitize(content); |
| return; |
| } |
| templateElement.textContent = content; |
| } |
| _maybeSanitize(arg) { |
| return this._config.sanitize ? sanitizeHtml(arg, this._config.allowList, this._config.sanitizeFn) : arg; |
| } |
| _resolvePossibleFunction(arg) { |
| return execute(arg, [void 0, this]); |
| } |
| _putElementInTemplate(element, templateElement) { |
| if (this._config.html) { |
| templateElement.innerHTML = ""; |
| templateElement.append(element); |
| return; |
| } |
| templateElement.textContent = element.textContent; |
| } |
| }; |
| //#endregion |
| //#region js/src/tooltip.ts |
| /** |
| * -------------------------------------------------------------------------- |
| * Bootstrap tooltip.ts |
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
| * -------------------------------------------------------------------------- |
| */ |
| /** |
| * Constants |
| */ |
| const NAME$6 = "tooltip"; |
| const DISALLOWED_ATTRIBUTES = /* @__PURE__ */ new Set([ |
| "sanitize", |
| "allowList", |
| "sanitizeFn" |
| ]); |
| const ESCAPE_KEY = "Escape"; |
| const CLASS_NAME_MODAL = "modal"; |
| const CLASS_NAME_SHOW$2 = "show"; |
| const SELECTOR_TOOLTIP_INNER = ".tooltip-inner"; |
| const SELECTOR_MODAL = `.${CLASS_NAME_MODAL}`; |
| const SELECTOR_DATA_TOGGLE$3 = "[data-bs-toggle=\"tooltip\"]"; |
| const EVENT_MODAL_HIDE = "hide.bs.modal"; |
| const TRIGGER_HOVER = "hover"; |
| const TRIGGER_FOCUS = "focus"; |
| const TRIGGER_CLICK = "click"; |
| const TRIGGER_MANUAL = "manual"; |
| const EVENT_HIDE$2 = "hide"; |
| const EVENT_HIDDEN$2 = "hidden"; |
| const EVENT_SHOW$2 = "show"; |
| const EVENT_SHOWN$2 = "shown"; |
| const EVENT_INSERTED = "inserted"; |
| const EVENT_CLICK$3 = "click"; |
| const EVENT_FOCUSIN$2 = "focusin"; |
| const EVENT_FOCUSOUT$1 = "focusout"; |
| const EVENT_MOUSEENTER$1 = "mouseenter"; |
| const EVENT_MOUSELEAVE = "mouseleave"; |
| const EVENT_KEYDOWN$1 = "keydown"; |
| const AttachmentMap = { |
| AUTO: "auto", |
| TOP: "top", |
| RIGHT: isRTL$1() ? "left" : "right", |
| BOTTOM: "bottom", |
| LEFT: isRTL$1() ? "right" : "left" |
| }; |
| const Default$5 = { |
| allowList: DefaultAllowlist, |
| animation: true, |
| boundary: "clippingParents", |
| container: false, |
| customClass: "", |
| delay: 0, |
| fallbackPlacements: [ |
| "top", |
| "right", |
| "bottom", |
| "left" |
| ], |
| html: false, |
| offset: [0, 6], |
| placement: "top", |
| floatingConfig: null, |
| sanitize: true, |
| sanitizeFn: null, |
| selector: false, |
| template: "<div class=\"tooltip\" role=\"tooltip\"><div class=\"tooltip-arrow\"></div><div class=\"tooltip-inner\"></div></div>", |
| title: "", |
| trigger: "hover focus" |
| }; |
| const DefaultType$5 = { |
| allowList: "object", |
| animation: "boolean", |
| boundary: "(string|element)", |
| container: "(string|element|boolean)", |
| customClass: "(string|function)", |
| delay: "(number|object)", |
| fallbackPlacements: "array", |
| html: "boolean", |
| offset: "(array|string|function)", |
| placement: "(string|function)", |
| floatingConfig: "(null|object|function)", |
| sanitize: "boolean", |
| sanitizeFn: "(null|function)", |
| selector: "(string|boolean)", |
| template: "string", |
| title: "(string|element|function)", |
| trigger: "string" |
| }; |
| /** |
| * Class definition |
| */ |
| var Tooltip = class extends BaseComponent { |
| constructor(element, config) { |
| if (typeof computePosition === "undefined") throw new TypeError("Bootstrap's tooltips require Floating UI (https://floating-ui.com)"); |
| super(element, config); |
| this._isEnabled = true; |
| this._timeout = 0; |
| this._resolveTimeout = null; |
| this._isHovered = null; |
| this._activeTrigger = {}; |
| this._floatingCleanup = null; |
| this._keydownHandler = null; |
| this._tipEventOut = null; |
| this._templateFactory = null; |
| this._newContent = null; |
| this._mediaQueryListeners = []; |
| this._responsivePlacements = null; |
| this.tip = null; |
| this._parseResponsivePlacements(); |
| this._setListeners(); |
| if (!this._config.selector) this._fixTitle(); |
| } |
| static get Default() { |
| return Default$5; |
| } |
| static get DefaultType() { |
| return DefaultType$5; |
| } |
| static get NAME() { |
| return NAME$6; |
| } |
| enable() { |
| this._isEnabled = true; |
| } |
| disable() { |
| this._isEnabled = false; |
| } |
| toggleEnabled() { |
| this._isEnabled = !this._isEnabled; |
| } |
| toggle() { |
| if (!this._isEnabled) return Promise.resolve(); |
| return this._isShown() ? this._leave() : this._enter(); |
| } |
| dispose() { |
| this._clearTimeout(); |
| this._removeEscapeListener(); |
| EventHandler.off(this._element.closest(SELECTOR_MODAL), EVENT_MODAL_HIDE, this._hideModalHandler); |
| if (this._element.getAttribute("data-bs-original-title")) this._element.setAttribute("title", this._element.getAttribute("data-bs-original-title")); |
| this._disposeFloating(); |
| this._disposeMediaQueryListeners(); |
| super.dispose(); |
| } |
| async show() { |
| if (this._element.style.display === "none") throw new Error("Please use show on visible elements"); |
| if (!(this._isWithContent() && this._isEnabled)) return; |
| const showEvent = EventHandler.trigger(this._element, this.constructor.eventName(EVENT_SHOW$2)); |
| const isInTheDom = (findShadowRoot(this._element) || this._element.ownerDocument.documentElement).contains(this._element); |
| if (showEvent.defaultPrevented || !isInTheDom) { |
| this._isHovered = false; |
| return; |
| } |
| this._disposeFloating(); |
| const tip = this._getTipElement(); |
| this._element.setAttribute("aria-describedby", tip.getAttribute("id")); |
| let { container } = this._config; |
| const closestDialog = this._element.closest("dialog[open]"); |
| if (closestDialog && container === document.body) container = closestDialog; |
| if (!this._element.ownerDocument.documentElement.contains(this.tip)) { |
| container.append(tip); |
| EventHandler.trigger(this._element, this.constructor.eventName(EVENT_INSERTED)); |
| this._setTipListeners(tip); |
| } |
| await this._createFloating(tip); |
| tip.classList.add(CLASS_NAME_SHOW$2); |
| this._setEscapeListener(); |
| if ("ontouchstart" in document.documentElement) for (const element of document.body.children) EventHandler.on(element, "mouseover", noop); |
| const complete = () => { |
| EventHandler.trigger(this._element, this.constructor.eventName(EVENT_SHOWN$2)); |
| if (this._isHovered === false) this._leave(); |
| this._isHovered = false; |
| }; |
| await this._queueCallback(complete, this.tip, this._isAnimated()); |
| } |
| async hide() { |
| if (!this._isShown()) return; |
| if (EventHandler.trigger(this._element, this.constructor.eventName(EVENT_HIDE$2)).defaultPrevented) return; |
| this._removeEscapeListener(); |
| this._getTipElement().classList.remove(CLASS_NAME_SHOW$2); |
| if ("ontouchstart" in document.documentElement) for (const element of document.body.children) EventHandler.off(element, "mouseover", noop); |
| this._activeTrigger[TRIGGER_CLICK] = false; |
| this._activeTrigger[TRIGGER_FOCUS] = false; |
| this._activeTrigger[TRIGGER_HOVER] = false; |
| this._isHovered = null; |
| const complete = () => { |
| if (this._isWithActiveTrigger()) return; |
| if (!this._isHovered) this._disposeFloating(); |
| this._element.removeAttribute("aria-describedby"); |
| EventHandler.trigger(this._element, this.constructor.eventName(EVENT_HIDDEN$2)); |
| }; |
| await this._queueCallback(complete, this.tip, this._isAnimated()); |
| } |
| update() { |
| if (this._floatingCleanup && this.tip) this._updateFloatingPosition(); |
| } |
| _isWithContent() { |
| return Boolean(this._getTitle()) || this._hasNewContent(); |
| } |
| _hasNewContent() { |
| return Boolean(this._newContent) && Object.values(this._newContent).some(Boolean); |
| } |
| _getTipElement() { |
| if (!this.tip) this.tip = this._createTipElement(this._newContent || this._getContentForTemplate()); |
| return this.tip; |
| } |
| _createTipElement(content) { |
| const tip = this._getTemplateFactory(content).toHtml(); |
| tip.classList.remove(CLASS_NAME_SHOW$2); |
| tip.classList.add(`bs-${this.constructor.NAME}-auto`); |
| const tipId = getUID(this.constructor.NAME).toString(); |
| tip.setAttribute("id", tipId); |
| if (!this._config.animation) tip.classList.add(this._getInstantClassName()); |
| return tip; |
| } |
| setContent(content) { |
| this._newContent = content; |
| if (this._isShown()) { |
| this._disposeFloating(); |
| this.show(); |
| } |
| } |
| _getTemplateFactory(content) { |
| if (this._templateFactory) this._templateFactory.changeContent(content); |
| else this._templateFactory = new TemplateFactory({ |
| ...this._config, |
| content, |
| extraClass: this._resolvePossibleFunction(this._config.customClass) |
| }); |
| return this._templateFactory; |
| } |
| _getContentForTemplate() { |
| return { [SELECTOR_TOOLTIP_INNER]: this._getTitle() }; |
| } |
| _getTitle() { |
| return this._resolvePossibleFunction(this._config.title) || this._element.getAttribute("data-bs-original-title"); |
| } |
| _initializeOnDelegatedTarget(event) { |
| return this.constructor.getOrCreateInstance(event.delegateTarget, this._getDelegateConfig()); |
| } |
| _getInstantClassName() { |
| return `${this.constructor.NAME}-instant`; |
| } |
| _isAnimated() { |
| return getTransitionDurationFromElement(this.tip) > 0; |
| } |
| _isShown() { |
| return this.tip && this.tip.classList.contains(CLASS_NAME_SHOW$2); |
| } |
| _getPlacement(tip) { |
| if (this._responsivePlacements) { |
| const placement = getResponsivePlacement(this._responsivePlacements, "top"); |
| return AttachmentMap[placement.toUpperCase()] || placement; |
| } |
| const placement = execute(this._config.placement, [ |
| this, |
| tip, |
| this._element |
| ]); |
| return AttachmentMap[placement.toUpperCase()] || placement; |
| } |
| _parseResponsivePlacements() { |
| if (typeof this._config.placement !== "string") { |
| this._responsivePlacements = null; |
| return; |
| } |
| this._responsivePlacements = parseResponsivePlacement(this._config.placement, "top"); |
| if (this._responsivePlacements) this._setupMediaQueryListeners(); |
| } |
| _setupMediaQueryListeners() { |
| this._disposeMediaQueryListeners(); |
| this._mediaQueryListeners = createBreakpointListeners(() => { |
| if (this._isShown()) this._updateFloatingPosition(); |
| }); |
| } |
| _disposeMediaQueryListeners() { |
| disposeBreakpointListeners(this._mediaQueryListeners); |
| this._mediaQueryListeners = []; |
| } |
| async _createFloating(tip) { |
| const placement = this._getPlacement(tip); |
| const arrowElement = tip.querySelector(`.${this.constructor.NAME}-arrow`); |
| await this._updateFloatingPosition(tip, placement, arrowElement); |
| this._floatingCleanup = autoUpdate(this._element, tip, () => this._updateFloatingPosition(tip, null, arrowElement)); |
| } |
| async _updateFloatingPosition(tip = this.tip, placement = null, arrowElement = null) { |
| if (!tip) return; |
| if (!placement) placement = this._getPlacement(tip); |
| if (!arrowElement) arrowElement = tip.querySelector(`.${this.constructor.NAME}-arrow`); |
| const middleware = this._getFloatingMiddleware(arrowElement); |
| const floatingConfig = this._getFloatingConfig(placement, middleware); |
| const { x, y, placement: finalPlacement, middlewareData } = await computePosition(this._element, tip, floatingConfig); |
| Object.assign(tip.style, { |
| position: "absolute", |
| left: `${x}px`, |
| top: `${y}px` |
| }); |
| if (arrowElement) arrowElement.style.position = "absolute"; |
| Manipulator.setDataAttribute(tip, "placement", finalPlacement); |
| if (arrowElement && middlewareData.arrow) { |
| const { x: arrowX, y: arrowY } = middlewareData.arrow; |
| const isVertical = finalPlacement.startsWith("top") || finalPlacement.startsWith("bottom"); |
| Object.assign(arrowElement.style, { |
| left: isVertical && arrowX !== void 0 ? `${arrowX}px` : "", |
| top: !isVertical && arrowY !== void 0 ? `${arrowY}px` : "", |
| right: "", |
| bottom: "" |
| }); |
| } |
| } |
| _getOffset() { |
| const { offset } = this._config; |
| if (typeof offset === "string") return offset.split(",").map((value) => Number.parseInt(value, 10)); |
| if (typeof offset === "function") return ({ placement, rects }) => { |
| return toFloatingOffset(offset({ |
| placement, |
| reference: rects.reference, |
| floating: rects.floating |
| }, this._element)); |
| }; |
| return offset; |
| } |
| _resolvePossibleFunction(arg) { |
| return execute(arg, [this._element, this._element]); |
| } |
| _getFloatingMiddleware(arrowElement) { |
| const offsetValue = this._getOffset(); |
| const middleware = [ |
| offset(typeof offsetValue === "function" ? offsetValue : toFloatingOffset(offsetValue)), |
| flip({ fallbackPlacements: this._config.fallbackPlacements }), |
| shift({ boundary: this._config.boundary === "clippingParents" ? "clippingAncestors" : this._config.boundary }) |
| ]; |
| if (arrowElement) middleware.push(arrow({ element: arrowElement })); |
| return middleware; |
| } |
| _getFloatingConfig(placement, middleware) { |
| const defaultConfig = { |
| placement, |
| middleware |
| }; |
| return { |
| ...defaultConfig, |
| ...execute(this._config.floatingConfig, [void 0, defaultConfig]) |
| }; |
| } |
| _setListeners() { |
| const triggers = this._config.trigger.split(" "); |
| for (const trigger of triggers) if (trigger === "click") EventHandler.on(this._element, this.constructor.eventName(EVENT_CLICK$3), this._config.selector, (event) => { |
| const context = this._initializeOnDelegatedTarget(event); |
| context._activeTrigger[TRIGGER_CLICK] = !(context._isShown() && context._activeTrigger[TRIGGER_CLICK]); |
| context.toggle(); |
| }); |
| else if (trigger !== TRIGGER_MANUAL) { |
| const [eventIn, eventOut] = this._getTriggerEvents(trigger); |
| EventHandler.on(this._element, eventIn, this._config.selector, (event) => { |
| const context = this._initializeOnDelegatedTarget(event); |
| context._activeTrigger[event.type === "focusin" ? TRIGGER_FOCUS : TRIGGER_HOVER] = true; |
| context._enter(); |
| }); |
| EventHandler.on(this._element, eventOut, this._config.selector, (event) => { |
| const context = this._initializeOnDelegatedTarget(event); |
| context._activeTrigger[event.type === "focusout" ? TRIGGER_FOCUS : TRIGGER_HOVER] = context._isInside(event.relatedTarget); |
| context._leave(); |
| }); |
| } |
| this._hideModalHandler = () => { |
| if (this._element) this.hide(); |
| }; |
| EventHandler.on(this._element.closest(SELECTOR_MODAL), EVENT_MODAL_HIDE, this._hideModalHandler); |
| } |
| _setTipListeners(tip) { |
| const trigger = this._getTrigger(); |
| if (trigger === TRIGGER_MANUAL || trigger.includes(TRIGGER_CLICK)) return; |
| this._tipEventOut = (event) => { |
| this._activeTrigger[event.type === "focusout" ? TRIGGER_FOCUS : TRIGGER_HOVER] = this._isInside(event.relatedTarget); |
| this._leave(); |
| }; |
| for (const name of trigger.split(" ")) if (name === TRIGGER_HOVER || name === TRIGGER_FOCUS) { |
| const [, eventOut] = this._getTriggerEvents(name); |
| EventHandler.on(tip, eventOut, this._tipEventOut); |
| } |
| } |
| _removeTipListeners(tip) { |
| if (!this._tipEventOut) return; |
| const trigger = this._getTrigger(); |
| for (const name of trigger.split(" ")) if (name === TRIGGER_HOVER || name === TRIGGER_FOCUS) { |
| const [, eventOut] = this._getTriggerEvents(name); |
| EventHandler.off(tip, eventOut, this._tipEventOut); |
| } |
| this._tipEventOut = null; |
| } |
| _isInside(element) { |
| return this._element.contains(element) || Boolean(this.tip?.contains(element)); |
| } |
| _getTrigger() { |
| return this._config._trigger; |
| } |
| _getTriggerEvents(trigger) { |
| return { |
| [TRIGGER_HOVER]: [this.constructor.eventName(EVENT_MOUSEENTER$1), this.constructor.eventName(EVENT_MOUSELEAVE)], |
| [TRIGGER_FOCUS]: [this.constructor.eventName(EVENT_FOCUSIN$2), this.constructor.eventName(EVENT_FOCUSOUT$1)] |
| }[trigger]; |
| } |
| _setEscapeListener() { |
| if (this._keydownHandler) return; |
| this._keydownHandler = (event) => { |
| if (event.key !== ESCAPE_KEY || !this._isShown() || !this.tip.isConnected) return; |
| event.preventDefault(); |
| event.stopPropagation(); |
| this.hide(); |
| }; |
| this._element.ownerDocument.addEventListener(EVENT_KEYDOWN$1, this._keydownHandler, true); |
| } |
| _removeEscapeListener() { |
| if (!this._keydownHandler) return; |
| this._element.ownerDocument.removeEventListener(EVENT_KEYDOWN$1, this._keydownHandler, true); |
| this._keydownHandler = null; |
| } |
| _fixTitle() { |
| const title = this._element.getAttribute("title"); |
| if (!title) return; |
| if (!this._element.getAttribute("aria-label") && !this._element.textContent.trim()) this._element.setAttribute("aria-label", title); |
| this._element.setAttribute("data-bs-original-title", title); |
| this._element.removeAttribute("title"); |
| } |
| _enter() { |
| if (this._isShown() || this._isHovered) { |
| this._isHovered = true; |
| return Promise.resolve(); |
| } |
| this._isHovered = true; |
| return this._setTimeout(() => this._isHovered ? this.show() : void 0, this._config.delay.show); |
| } |
| _leave() { |
| if (this._isWithActiveTrigger()) return Promise.resolve(); |
| this._isHovered = false; |
| return this._setTimeout(() => this._isHovered ? void 0 : this.hide(), this._config.delay.hide); |
| } |
| _setTimeout(handler, timeout) { |
| this._clearTimeout(); |
| return new Promise((resolve) => { |
| this._resolveTimeout = resolve; |
| this._timeout = setTimeout(() => { |
| this._resolveTimeout = null; |
| resolve(handler()); |
| }, timeout); |
| }); |
| } |
| _clearTimeout() { |
| clearTimeout(this._timeout); |
| if (this._resolveTimeout) { |
| this._resolveTimeout(); |
| this._resolveTimeout = null; |
| } |
| } |
| _isWithActiveTrigger() { |
| return Object.values(this._activeTrigger).includes(true); |
| } |
| _getConfig(config) { |
| const dataAttributes = Manipulator.getDataAttributes(this._element); |
| for (const dataAttribute of Object.keys(dataAttributes)) if (DISALLOWED_ATTRIBUTES.has(dataAttribute)) delete dataAttributes[dataAttribute]; |
| config = { |
| ...dataAttributes, |
| ...typeof config === "object" && config ? config : {} |
| }; |
| config = this._mergeConfigObj(config); |
| config = this._configAfterMerge(config); |
| this._typeCheckConfig(config); |
| return config; |
| } |
| _configAfterMerge(config) { |
| config.container = config.container === false ? document.body : getElement(config.container); |
| config._trigger = config._trigger || config.trigger; |
| if (typeof config.delay === "number") config.delay = { |
| show: config.delay, |
| hide: config.delay |
| }; |
| if (typeof config.title === "number" || typeof config.title === "boolean") config.title = config.title.toString(); |
| if (typeof config.content === "number" || typeof config.content === "boolean") config.content = config.content.toString(); |
| return config; |
| } |
| _getDelegateConfig() { |
| const config = {}; |
| for (const [key, value] of Object.entries(this._config)) if (this.constructor.Default[key] !== value) config[key] = value; |
| config.selector = false; |
| config.trigger = "manual"; |
| return config; |
| } |
| _disposeFloating() { |
| if (this._floatingCleanup) { |
| this._floatingCleanup(); |
| this._floatingCleanup = null; |
| } |
| if (this.tip) { |
| this._removeTipListeners(this.tip); |
| this.tip.remove(); |
| this.tip = null; |
| } |
| } |
| }; |
| /** |
| * Data API implementation - auto-initialize tooltips |
| */ |
| const initTooltip = (event) => { |
| const target = event.target.closest(SELECTOR_DATA_TOGGLE$3); |
| if (!target) return; |
| Tooltip.getOrCreateInstance(target); |
| }; |
| EventHandler.on(document, EVENT_FOCUSIN$2, SELECTOR_DATA_TOGGLE$3, initTooltip); |
| EventHandler.on(document, EVENT_MOUSEENTER$1, SELECTOR_DATA_TOGGLE$3, initTooltip); |
| //#endregion |
| //#region js/src/popover.ts |
| /** |
| * -------------------------------------------------------------------------- |
| * Bootstrap popover.ts |
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
| * -------------------------------------------------------------------------- |
| */ |
| /** |
| * Constants |
| */ |
| const NAME$5 = "popover"; |
| const SELECTOR_TITLE = ".popover-header"; |
| const SELECTOR_CONTENT = ".popover-body"; |
| const SELECTOR_DATA_TOGGLE$2 = "[data-bs-toggle=\"popover\"]"; |
| const EVENT_CLICK$2 = "click"; |
| const EVENT_FOCUSIN$1 = "focusin"; |
| const EVENT_MOUSEENTER = "mouseenter"; |
| const Default$4 = { |
| ...Tooltip.Default, |
| content: "", |
| offset: [0, 8], |
| placement: "right", |
| template: "<div class=\"popover\" role=\"tooltip\"><div class=\"popover-arrow\"></div><h3 class=\"popover-header\"></h3><div class=\"popover-body\"></div></div>", |
| trigger: "click" |
| }; |
| const DefaultType$4 = { |
| ...Tooltip.DefaultType, |
| content: "(null|string|element|function)" |
| }; |
| /** |
| * Class definition |
| */ |
| var Popover = class extends Tooltip { |
| constructor(element, config) { |
| super(element, config); |
| } |
| static get Default() { |
| return Default$4; |
| } |
| static get DefaultType() { |
| return DefaultType$4; |
| } |
| static get NAME() { |
| return NAME$5; |
| } |
| _isWithContent() { |
| return Boolean(this._getTitle() || this._getContent()) || this._hasNewContent(); |
| } |
| _getContentForTemplate() { |
| return { |
| [SELECTOR_TITLE]: this._getTitle(), |
| [SELECTOR_CONTENT]: this._getContent() |
| }; |
| } |
| _getContent() { |
| return this._resolvePossibleFunction(this._config.content); |
| } |
| }; |
| /** |
| * Data API implementation - auto-initialize popovers |
| */ |
| const initPopover = (event) => { |
| const target = event.target.closest(SELECTOR_DATA_TOGGLE$2); |
| if (!target) return; |
| if (event.type === "click") event.preventDefault(); |
| Popover.getOrCreateInstance(target); |
| }; |
| EventHandler.on(document, EVENT_CLICK$2, SELECTOR_DATA_TOGGLE$2, initPopover); |
| EventHandler.on(document, EVENT_FOCUSIN$1, SELECTOR_DATA_TOGGLE$2, initPopover); |
| EventHandler.on(document, EVENT_MOUSEENTER, SELECTOR_DATA_TOGGLE$2, initPopover); |
| //#endregion |
| //#region js/src/range.ts |
| /** |
| * -------------------------------------------------------------------------- |
| * Bootstrap range.ts |
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
| * -------------------------------------------------------------------------- |
| */ |
| /** |
| * Constants |
| */ |
| const NAME$4 = "range"; |
| const EVENT_KEY$4 = `.bs.range`; |
| const DATA_API_KEY$1 = ".data-api"; |
| const EVENT_CHANGED = `changed${EVENT_KEY$4}`; |
| const EVENT_DOM_CONTENT_LOADED = `DOMContentLoaded${EVENT_KEY$4}${DATA_API_KEY$1}`; |
| const EVENT_INPUT = "input"; |
| const EVENT_CHANGE = "change"; |
| const SELECTOR_RANGE = ".form-range"; |
| const SELECTOR_INPUT = ".form-range-input"; |
| const CLASS_NAME_BUBBLE = "form-range-bubble"; |
| const CLASS_NAME_TICKS = "form-range-ticks"; |
| const CLASS_NAME_TICK = "form-range-tick"; |
| const CLASS_NAME_TICK_LABEL = "form-range-tick-label"; |
| const PROPERTY_FILL = "--bs-range-fill"; |
| const Default$3 = { |
| bubble: false, |
| formatter: null |
| }; |
| const DefaultType$3 = { |
| bubble: "(boolean|null)", |
| formatter: "(function|null)" |
| }; |
| /** |
| * Class definition |
| */ |
| var Range = class extends BaseComponent { |
| constructor(element, config) { |
| super(element, config); |
| if (!this._element) return; |
| this._input = SelectorEngine.findOne(SELECTOR_INPUT, this._element); |
| if (!this._input) return; |
| this._bubble = null; |
| this._bubbleText = null; |
| this._ticks = null; |
| this._updateHandler = () => this._update(); |
| if (this._config.bubble) this._createBubble(); |
| this._createTicks(); |
| this._addEventListeners(); |
| this._update(); |
| } |
| static get Default() { |
| return Default$3; |
| } |
| static get DefaultType() { |
| return DefaultType$3; |
| } |
| static get NAME() { |
| return NAME$4; |
| } |
| update() { |
| this._update(); |
| } |
| dispose() { |
| EventHandler.off(this._input, EVENT_INPUT, this._updateHandler); |
| EventHandler.off(this._input, EVENT_CHANGE, this._updateHandler); |
| this._bubble?.remove(); |
| this._ticks?.remove(); |
| super.dispose(); |
| } |
| _configAfterMerge(config) { |
| if (config.bubble === null) config.bubble = true; |
| return config; |
| } |
| _addEventListeners() { |
| EventHandler.on(this._input, EVENT_INPUT, this._updateHandler); |
| EventHandler.on(this._input, EVENT_CHANGE, this._updateHandler); |
| } |
| _min() { |
| return this._input.min === "" ? 0 : Number.parseFloat(this._input.min); |
| } |
| _max() { |
| return this._input.max === "" ? 100 : Number.parseFloat(this._input.max); |
| } |
| _value() { |
| return Number.parseFloat(this._input.value); |
| } |
| _ratio() { |
| const span = this._max() - this._min(); |
| return span > 0 ? (this._value() - this._min()) / span : 0; |
| } |
| _update() { |
| this._element.style.setProperty(PROPERTY_FILL, `${this._ratio()}`); |
| if (this._bubbleText) this._bubbleText.textContent = this._format(this._value()); |
| EventHandler.trigger(this._input, EVENT_CHANGED, { value: this._value() }); |
| } |
| _format(value) { |
| return typeof this._config.formatter === "function" ? this._config.formatter(value) : String(value); |
| } |
| _createBubble() { |
| this._bubble = document.createElement("output"); |
| this._bubble.className = `${CLASS_NAME_BUBBLE} tooltip bs-tooltip-top show`; |
| this._bubble.setAttribute("aria-hidden", "true"); |
| const arrow = document.createElement("div"); |
| arrow.className = "tooltip-arrow"; |
| this._bubbleText = document.createElement("div"); |
| this._bubbleText.className = "tooltip-inner"; |
| this._bubble.append(arrow, this._bubbleText); |
| this._input.insertAdjacentElement("afterend", this._bubble); |
| } |
| _createTicks() { |
| const listId = this._input.getAttribute("list"); |
| const datalist = listId ? document.getElementById(listId) : null; |
| if (!datalist) return; |
| const min = this._min(); |
| const span = this._max() - min || 1; |
| const points = []; |
| for (const option of SelectorEngine.find("option", datalist)) { |
| const value = Number.parseFloat(option.value); |
| if (!Number.isNaN(value)) { |
| const ratio = Math.min(Math.max((value - min) / span, 0), 1); |
| points.push({ |
| ratio, |
| label: option.label |
| }); |
| } |
| } |
| if (points.length === 0) return; |
| points.sort((a, b) => a.ratio - b.ratio); |
| this._ticks = document.createElement("div"); |
| this._ticks.className = CLASS_NAME_TICKS; |
| this._ticks.setAttribute("aria-hidden", "true"); |
| const stops = [ |
| 0, |
| ...points.map((point) => point.ratio), |
| 1 |
| ]; |
| this._ticks.style.gridTemplateColumns = stops.slice(1).map((stop, index) => `${stop - stops[index]}fr`).join(" "); |
| for (const [index, point] of points.entries()) { |
| const tick = document.createElement("span"); |
| tick.className = CLASS_NAME_TICK; |
| tick.style.gridColumnStart = `${index + 2}`; |
| if (point.label) { |
| const label = document.createElement("span"); |
| label.className = CLASS_NAME_TICK_LABEL; |
| label.textContent = point.label; |
| tick.append(label); |
| } |
| this._ticks.append(tick); |
| } |
| this._element.append(this._ticks); |
| } |
| }; |
| /** |
| * Data API implementation |
| */ |
| EventHandler.on(document, EVENT_DOM_CONTENT_LOADED, () => { |
| for (const element of SelectorEngine.find(SELECTOR_RANGE)) Range.getOrCreateInstance(element); |
| }); |
| //#endregion |
| //#region js/src/scrollspy.ts |
| /** |
| * -------------------------------------------------------------------------- |
| * Bootstrap scrollspy.ts |
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
| * -------------------------------------------------------------------------- |
| */ |
| /** |
| * Constants |
| */ |
| const NAME$3 = "scrollspy"; |
| const EVENT_KEY$3 = `.bs.scrollspy`; |
| const DATA_API_KEY = ".data-api"; |
| const EVENT_ACTIVATE = `activate${EVENT_KEY$3}`; |
| const EVENT_CLICK$1 = `click${EVENT_KEY$3}`; |
| const EVENT_SCROLL = `scroll${EVENT_KEY$3}`; |
| const EVENT_SCROLLEND = `scrollend${EVENT_KEY$3}`; |
| const EVENT_RESIZE = `resize${EVENT_KEY$3}`; |
| const EVENT_LOAD_DATA_API$1 = `load${EVENT_KEY$3}${DATA_API_KEY}`; |
| const CLASS_NAME_MENU_ITEM = "menu-item"; |
| const CLASS_NAME_ACTIVE$1 = "active"; |
| const SELECTOR_DATA_SPY = "[data-bs-spy=\"scroll\"]"; |
| const SELECTOR_TARGET_LINKS = "[href]"; |
| const SELECTOR_NAV_LIST_GROUP = ".nav, .list-group"; |
| const SELECTOR_NAV_LINKS = ".nav-link"; |
| const SELECTOR_LINK_ITEMS = `${SELECTOR_NAV_LINKS}, .nav-item > ${SELECTOR_NAV_LINKS}, .list-group-item`; |
| const SELECTOR_MENU_TOGGLE$1 = "[data-bs-toggle=\"menu\"]"; |
| const SCROLL_IDLE_TIMEOUT = 100; |
| const RESIZE_DEBOUNCE = 100; |
| const Default$2 = { |
| rootMargin: null, |
| smoothScroll: false, |
| target: null, |
| threshold: [0], |
| topMargin: "12%" |
| }; |
| const DefaultType$2 = { |
| rootMargin: "(string|null)", |
| smoothScroll: "boolean", |
| target: "element", |
| threshold: "array", |
| topMargin: "string" |
| }; |
| /** |
| * Class definition |
| */ |
| var ScrollSpy = class extends BaseComponent { |
| constructor(element, config) { |
| super(element, config); |
| this._sections = []; |
| this._linkBySection = /* @__PURE__ */ new Map(); |
| this._sectionByLink = /* @__PURE__ */ new Map(); |
| this._intersecting = /* @__PURE__ */ new Set(); |
| this._activeTarget = null; |
| this._lastActive = null; |
| this._atBottom = false; |
| this._rootElement = getComputedStyle(this._element).overflowY === "visible" ? null : this._element; |
| this._observer = null; |
| this._sentinel = null; |
| this._sentinelObserver = null; |
| this._pendingNavigation = null; |
| this._settleTimeout = null; |
| this._settleHandler = null; |
| this._scrollIdleHandler = null; |
| this._resizeHandler = null; |
| this._resizeTimeout = null; |
| this.refresh(); |
| } |
| static get Default() { |
| return Default$2; |
| } |
| static get DefaultType() { |
| return DefaultType$2; |
| } |
| static get NAME() { |
| return NAME$3; |
| } |
| refresh() { |
| this._initializeTargetsAndObservables(); |
| this._maybeEnableSmoothScroll(); |
| this._observer?.disconnect(); |
| this._intersecting.clear(); |
| this._observer = this._getNewObserver(); |
| for (const section of this._sections) this._observer.observe(section); |
| this._setUpSentinel(); |
| this._maybeAddResizeListener(); |
| } |
| dispose() { |
| this._observer?.disconnect(); |
| this._teardownSentinel(); |
| this._disarmSettle(); |
| this._removeResizeListener(); |
| EventHandler.off(this._config.target, EVENT_CLICK$1); |
| super.dispose(); |
| } |
| _configAfterMerge(config) { |
| config.target = getElement(config.target) || document.body; |
| if (typeof config.threshold === "string") config.threshold = config.threshold.split(",").map((value) => Number.parseFloat(value)); |
| return config; |
| } |
| _getNewObserver() { |
| const options = { |
| root: this._rootElement, |
| threshold: this._config.threshold, |
| rootMargin: this._config.rootMargin ?? this._getDerivedRootMargin() |
| }; |
| return new IntersectionObserver((entries) => this._onIntersect(entries), options); |
| } |
| _onIntersect(entries) { |
| for (const entry of entries) if (entry.isIntersecting) this._intersecting.add(entry.target); |
| else this._intersecting.delete(entry.target); |
| this._computeActive(); |
| } |
| _computeActive() { |
| if (!this._element?.isConnected || this._sections.length === 0) return; |
| let active = null; |
| if (this._atBottom) active = this._sections.at(-1); |
| else { |
| for (const section of this._sections) if (this._intersecting.has(section)) active = section; |
| active ||= this._lastActive ?? this._sections.at(0); |
| } |
| if (!active) return; |
| this._lastActive = active; |
| const link = this._linkBySection.get(active); |
| if (link) this._process(link); |
| } |
| _parseTopMargin() { |
| const value = String(this._config.topMargin); |
| return { |
| value: Number.parseFloat(value) || 0, |
| unit: value.endsWith("%") ? "%" : "px" |
| }; |
| } |
| _getDerivedRootMargin() { |
| const { value, unit } = this._parseTopMargin(); |
| let percent = value; |
| if (unit === "px") { |
| const rootHeight = this._rootElement ? this._rootElement.clientHeight : document.documentElement.clientHeight || window.innerHeight; |
| percent = rootHeight ? value / rootHeight * 100 : 12; |
| } |
| return `0px 0px -${Math.min(Math.max(100 - percent, 0), 100)}% 0px`; |
| } |
| _usesPixelMargin() { |
| return !this._config.rootMargin && this._parseTopMargin().unit === "px"; |
| } |
| _setUpSentinel() { |
| this._teardownSentinel(); |
| if (this._sections.length === 0) return; |
| const sentinel = document.createElement("div"); |
| sentinel.setAttribute("aria-hidden", "true"); |
| sentinel.style.cssText = "position:relative;width:0;height:0;margin:0;padding:0;border:0;visibility:hidden;"; |
| this._element.append(sentinel); |
| this._sentinel = sentinel; |
| this._sentinelObserver = new IntersectionObserver((entries) => this._onSentinel(entries), { |
| root: this._rootElement, |
| threshold: [0] |
| }); |
| this._sentinelObserver.observe(sentinel); |
| } |
| _onSentinel(entries) { |
| const entry = entries.at(-1); |
| this._atBottom = Boolean(entry?.isIntersecting) && this._isOverflowing(); |
| this._computeActive(); |
| } |
| _isOverflowing() { |
| const scroller = this._rootElement || document.scrollingElement || document.documentElement; |
| return scroller.scrollHeight > scroller.clientHeight; |
| } |
| _teardownSentinel() { |
| this._sentinelObserver?.disconnect(); |
| this._sentinelObserver = null; |
| this._sentinel?.remove(); |
| this._sentinel = null; |
| this._atBottom = false; |
| } |
| _maybeAddResizeListener() { |
| this._removeResizeListener(); |
| if (!this._usesPixelMargin()) return; |
| this._resizeHandler = () => { |
| clearTimeout(this._resizeTimeout); |
| this._resizeTimeout = setTimeout(() => this._rebuildObserver(), RESIZE_DEBOUNCE); |
| }; |
| EventHandler.on(window, EVENT_RESIZE, this._resizeHandler); |
| } |
| _removeResizeListener() { |
| clearTimeout(this._resizeTimeout); |
| this._resizeTimeout = null; |
| if (this._resizeHandler) { |
| EventHandler.off(window, EVENT_RESIZE, this._resizeHandler); |
| this._resizeHandler = null; |
| } |
| } |
| _rebuildObserver() { |
| if (!this._observer) return; |
| this._observer.disconnect(); |
| this._intersecting.clear(); |
| this._observer = this._getNewObserver(); |
| for (const section of this._sections) this._observer.observe(section); |
| } |
| _maybeEnableSmoothScroll() { |
| if (!this._config.smoothScroll) return; |
| EventHandler.off(this._config.target, EVENT_CLICK$1); |
| EventHandler.on(this._config.target, EVENT_CLICK$1, SELECTOR_TARGET_LINKS, (event) => { |
| const link = event.target.closest(SELECTOR_TARGET_LINKS); |
| const section = link && this._sectionByLink.get(link); |
| if (!section || !this._element) return; |
| event.preventDefault(); |
| const root = this._rootElement || window; |
| const height = section.offsetTop - this._element.offsetTop; |
| const currentTop = this._rootElement ? this._rootElement.scrollTop : window.scrollY ?? window.pageYOffset; |
| if (matchMedia("(prefers-reduced-motion: reduce)").matches || Math.abs(currentTop - height) <= 2) { |
| if (root.scrollTo) root.scrollTo({ |
| top: height, |
| behavior: "auto" |
| }); |
| else root.scrollTop = height; |
| this._settleNavigation(link.hash, section); |
| return; |
| } |
| this._pendingNavigation = { |
| hash: link.hash, |
| section |
| }; |
| this._armSettle(); |
| if (root.scrollTo) root.scrollTo({ |
| top: height, |
| behavior: "smooth" |
| }); |
| else root.scrollTop = height; |
| }); |
| } |
| _armSettle() { |
| this._disarmSettle(); |
| const target = this._getSettleTarget(); |
| this._settleHandler = () => this._onSettle(); |
| this._scrollIdleHandler = () => { |
| clearTimeout(this._settleTimeout); |
| this._settleTimeout = setTimeout(() => this._onSettle(), SCROLL_IDLE_TIMEOUT); |
| }; |
| EventHandler.on(target, EVENT_SCROLLEND, this._settleHandler); |
| EventHandler.on(target, EVENT_SCROLL, this._scrollIdleHandler); |
| } |
| _disarmSettle() { |
| clearTimeout(this._settleTimeout); |
| this._settleTimeout = null; |
| const target = this._getSettleTarget(); |
| if (this._settleHandler) { |
| EventHandler.off(target, EVENT_SCROLLEND, this._settleHandler); |
| this._settleHandler = null; |
| } |
| if (this._scrollIdleHandler) { |
| EventHandler.off(target, EVENT_SCROLL, this._scrollIdleHandler); |
| this._scrollIdleHandler = null; |
| } |
| } |
| _getSettleTarget() { |
| return this._rootElement || document; |
| } |
| _onSettle() { |
| this._disarmSettle(); |
| if (!this._pendingNavigation) return; |
| const { hash, section } = this._pendingNavigation; |
| this._settleNavigation(hash, section); |
| } |
| _settleNavigation(hash, section) { |
| this._pendingNavigation = null; |
| if (window.history?.replaceState) window.history.replaceState(null, "", hash); |
| if (!section.hasAttribute("tabindex")) section.setAttribute("tabindex", "-1"); |
| section.focus({ preventScroll: true }); |
| } |
| _initializeTargetsAndObservables() { |
| this._sections = []; |
| this._linkBySection = /* @__PURE__ */ new Map(); |
| this._sectionByLink = /* @__PURE__ */ new Map(); |
| const targetLinks = SelectorEngine.find(SELECTOR_TARGET_LINKS, this._config.target); |
| const seen = /* @__PURE__ */ new Set(); |
| for (const anchor of targetLinks) { |
| if (!anchor.hash || isDisabled(anchor)) continue; |
| const id = decodeFragment(anchor.hash.slice(1)); |
| if (!id) continue; |
| const section = document.getElementById(id); |
| if (!section || !this._element.contains(section) || !isVisible(section)) continue; |
| this._sectionByLink.set(anchor, section); |
| this._linkBySection.set(section, anchor); |
| if (!seen.has(section)) { |
| seen.add(section); |
| this._sections.push(section); |
| } |
| } |
| this._sections.sort((a, b) => a.getBoundingClientRect().top - b.getBoundingClientRect().top); |
| } |
| _process(target) { |
| if (this._activeTarget === target) return; |
| this._clearActiveClass(this._config.target); |
| this._activeTarget = target; |
| target.classList.add(CLASS_NAME_ACTIVE$1); |
| this._activateParents(target); |
| EventHandler.trigger(this._element, EVENT_ACTIVATE, { relatedTarget: target }); |
| } |
| _activateParents(target) { |
| if (target.classList.contains(CLASS_NAME_MENU_ITEM)) { |
| const menuToggle = target.closest(".menu")?.previousElementSibling; |
| if (menuToggle?.matches(SELECTOR_MENU_TOGGLE$1)) menuToggle.classList.add(CLASS_NAME_ACTIVE$1); |
| return; |
| } |
| for (const listGroup of SelectorEngine.parents(target, SELECTOR_NAV_LIST_GROUP)) for (const item of SelectorEngine.prev(listGroup, SELECTOR_LINK_ITEMS)) item.classList.add(CLASS_NAME_ACTIVE$1); |
| } |
| _clearActiveClass(parent) { |
| parent.classList.remove(CLASS_NAME_ACTIVE$1); |
| const activeNodes = SelectorEngine.find(`${SELECTOR_TARGET_LINKS}.${CLASS_NAME_ACTIVE$1}`, parent); |
| for (const node of activeNodes) node.classList.remove(CLASS_NAME_ACTIVE$1); |
| } |
| }; |
| function decodeFragment(hash) { |
| try { |
| return decodeURIComponent(hash); |
| } catch { |
| return hash; |
| } |
| } |
| /** |
| * Data API implementation |
| */ |
| EventHandler.on(window, EVENT_LOAD_DATA_API$1, () => { |
| for (const spy of SelectorEngine.find(SELECTOR_DATA_SPY)) ScrollSpy.getOrCreateInstance(spy); |
| }); |
| //#endregion |
| //#region js/src/tab.ts |
| /** |
| * -------------------------------------------------------------------------- |
| * Bootstrap tab.ts |
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
| * -------------------------------------------------------------------------- |
| */ |
| /** |
| * Constants |
| */ |
| const NAME$2 = "tab"; |
| const EVENT_KEY$2 = `.bs.tab`; |
| const EVENT_HIDE$1 = `hide${EVENT_KEY$2}`; |
| const EVENT_HIDDEN$1 = `hidden${EVENT_KEY$2}`; |
| const EVENT_SHOW$1 = `show${EVENT_KEY$2}`; |
| const EVENT_SHOWN$1 = `shown${EVENT_KEY$2}`; |
| const EVENT_CLICK_DATA_API = `click${EVENT_KEY$2}`; |
| const EVENT_KEYDOWN = `keydown${EVENT_KEY$2}`; |
| const EVENT_LOAD_DATA_API = `load${EVENT_KEY$2}`; |
| const ARROW_LEFT_KEY = "ArrowLeft"; |
| const ARROW_RIGHT_KEY = "ArrowRight"; |
| const ARROW_UP_KEY = "ArrowUp"; |
| const ARROW_DOWN_KEY = "ArrowDown"; |
| const HOME_KEY = "Home"; |
| const END_KEY = "End"; |
| const CLASS_NAME_ACTIVE = "active"; |
| const CLASS_NAME_SHOW$1 = "show"; |
| const SELECTOR_MENU_TOGGLE = "[data-bs-toggle=\"menu\"]"; |
| const SELECTOR_MENU = ".menu"; |
| const NOT_SELECTOR_MENU_TOGGLE = `:not(${SELECTOR_MENU_TOGGLE})`; |
| const SELECTOR_TAB_PANEL = ".list-group, .nav, [role=\"tablist\"]"; |
| const SELECTOR_OUTER = ".nav-item, .list-group-item"; |
| const SELECTOR_INNER = `.nav-link${NOT_SELECTOR_MENU_TOGGLE}, .list-group-item${NOT_SELECTOR_MENU_TOGGLE}, [role="tab"]${NOT_SELECTOR_MENU_TOGGLE}`; |
| const SELECTOR_DATA_TOGGLE$1 = "[data-bs-toggle=\"tab\"]"; |
| const SELECTOR_INNER_ELEM = `${SELECTOR_INNER}, ${SELECTOR_DATA_TOGGLE$1}`; |
| const SELECTOR_DATA_TOGGLE_ACTIVE = `.${CLASS_NAME_ACTIVE}[data-bs-toggle="tab"]`; |
| /** |
| * Class definition |
| */ |
| var Tab = class Tab extends BaseComponent { |
| constructor(element) { |
| super(element); |
| this._parent = this._element.closest(SELECTOR_TAB_PANEL); |
| if (!this._parent) throw new TypeError(`${this._element.outerHTML} has no valid parent ${SELECTOR_TAB_PANEL}`); |
| this._setInitialAttributes(this._parent, this._getChildren()); |
| EventHandler.on(this._element, EVENT_KEYDOWN, (event) => this._keydown(event)); |
| } |
| static get NAME() { |
| return NAME$2; |
| } |
| async show() { |
| const innerElem = this._element; |
| if (this._elemIsActive(innerElem)) return; |
| const active = this._getActiveElem(); |
| const hideEvent = active ? EventHandler.trigger(active, EVENT_HIDE$1, { relatedTarget: innerElem }) : null; |
| if (EventHandler.trigger(innerElem, EVENT_SHOW$1, { relatedTarget: active }).defaultPrevented || hideEvent && hideEvent.defaultPrevented) return; |
| this._deactivate(active, innerElem); |
| await this._activate(innerElem, active); |
| } |
| async _activate(element, relatedElem) { |
| if (!element) return; |
| element.classList.add(CLASS_NAME_ACTIVE); |
| if (element.getAttribute("role") !== "tab") { |
| element.classList.add(CLASS_NAME_SHOW$1); |
| return; |
| } |
| const pane = SelectorEngine.getElementFromSelector(element); |
| this._activate(pane); |
| const complete = () => { |
| element.removeAttribute("tabindex"); |
| setAriaAttribute(element, "aria-selected", true); |
| this._toggleMenu(element, true); |
| EventHandler.trigger(element, EVENT_SHOWN$1, { relatedTarget: relatedElem }); |
| }; |
| await this._queueCallback(complete, pane ?? element, getTransitionDurationFromElement(pane) > 0); |
| } |
| async _deactivate(element, relatedElem) { |
| if (!element) return; |
| element.classList.remove(CLASS_NAME_ACTIVE); |
| element.blur(); |
| if (element.getAttribute("role") !== "tab") { |
| element.classList.remove(CLASS_NAME_SHOW$1); |
| return; |
| } |
| this._deactivate(SelectorEngine.getElementFromSelector(element)); |
| const complete = () => { |
| setAriaAttribute(element, "aria-selected", false); |
| element.setAttribute("tabindex", "-1"); |
| this._toggleMenu(element, false); |
| EventHandler.trigger(element, EVENT_HIDDEN$1, { relatedTarget: relatedElem }); |
| }; |
| await this._queueCallback(complete, element, false); |
| } |
| _keydown(event) { |
| if (![ |
| ARROW_LEFT_KEY, |
| ARROW_RIGHT_KEY, |
| ARROW_UP_KEY, |
| ARROW_DOWN_KEY, |
| HOME_KEY, |
| END_KEY |
| ].includes(event.key)) return; |
| if (event.altKey || event.ctrlKey || event.metaKey) return; |
| event.stopPropagation(); |
| event.preventDefault(); |
| const children = this._getChildren().filter((element) => !isDisabled(element)); |
| let nextActiveElement; |
| if ([HOME_KEY, END_KEY].includes(event.key)) nextActiveElement = event.key === HOME_KEY ? children[0] : children.at(-1); |
| else { |
| const isNext = [ARROW_RIGHT_KEY, ARROW_DOWN_KEY].includes(event.key); |
| nextActiveElement = getNextActiveElement(children, event.target, isNext, true); |
| } |
| if (nextActiveElement) { |
| nextActiveElement.focus({ preventScroll: true }); |
| Tab.getOrCreateInstance(nextActiveElement).show(); |
| } |
| } |
| _getChildren() { |
| return SelectorEngine.find(SELECTOR_INNER_ELEM, this._parent); |
| } |
| _getActiveElem() { |
| return this._getChildren().find((child) => this._elemIsActive(child)) || null; |
| } |
| _setInitialAttributes(parent, children) { |
| this._setAttributeIfNotExists(parent, "role", "tablist"); |
| for (const child of children) this._setInitialAttributesOnChild(child); |
| } |
| _setInitialAttributesOnChild(child) { |
| child = this._getInnerElement(child); |
| const isActive = this._elemIsActive(child); |
| const outerElem = this._getOuterElement(child); |
| setAriaAttribute(child, "aria-selected", isActive); |
| if (outerElem !== child) this._setAttributeIfNotExists(outerElem, "role", "presentation"); |
| if (!isActive) child.setAttribute("tabindex", "-1"); |
| this._setAttributeIfNotExists(child, "role", "tab"); |
| this._setInitialAttributesOnTargetPanel(child); |
| } |
| _setInitialAttributesOnTargetPanel(child) { |
| const target = SelectorEngine.getElementFromSelector(child); |
| if (!target) return; |
| this._setAttributeIfNotExists(target, "role", "tabpanel"); |
| if (child.id) this._setAttributeIfNotExists(target, "aria-labelledby", `${child.id}`); |
| } |
| _toggleMenu(element, open) { |
| const outerElem = this._getOuterElement(element); |
| const menuToggle = SelectorEngine.findOne(SELECTOR_MENU_TOGGLE, outerElem); |
| if (!menuToggle) return; |
| const menu = SelectorEngine.findOne(SELECTOR_MENU, outerElem); |
| menuToggle.classList.toggle(CLASS_NAME_ACTIVE, open); |
| if (menu) menu.classList.toggle(CLASS_NAME_SHOW$1, open); |
| setAriaAttribute(menuToggle, "aria-expanded", open); |
| } |
| _setAttributeIfNotExists(element, attribute, value) { |
| if (!element.hasAttribute(attribute)) element.setAttribute(attribute, value); |
| } |
| _elemIsActive(elem) { |
| return elem.classList.contains(CLASS_NAME_ACTIVE); |
| } |
| _getInnerElement(elem) { |
| return elem.matches(SELECTOR_INNER_ELEM) ? elem : SelectorEngine.findOne(SELECTOR_INNER_ELEM, elem); |
| } |
| _getOuterElement(elem) { |
| return elem.closest(SELECTOR_OUTER) || elem; |
| } |
| }; |
| /** |
| * Data API implementation |
| */ |
| EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE$1, function(event) { |
| if (["A", "AREA"].includes(this.tagName)) event.preventDefault(); |
| if (isDisabled(this)) return; |
| Tab.getOrCreateInstance(this).show(); |
| }); |
| /** |
| * Initialize on focus |
| */ |
| EventHandler.on(window, EVENT_LOAD_DATA_API, () => { |
| for (const element of SelectorEngine.find(SELECTOR_DATA_TOGGLE_ACTIVE)) Tab.getOrCreateInstance(element); |
| }); |
| //#endregion |
| //#region js/src/toast.ts |
| /** |
| * -------------------------------------------------------------------------- |
| * Bootstrap toast.ts |
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
| * -------------------------------------------------------------------------- |
| */ |
| /** |
| * Constants |
| */ |
| const NAME$1 = "toast"; |
| const EVENT_KEY$1 = `.bs.toast`; |
| const EVENT_MOUSEOVER = `mouseover${EVENT_KEY$1}`; |
| const EVENT_MOUSEOUT = `mouseout${EVENT_KEY$1}`; |
| const EVENT_FOCUSIN = `focusin${EVENT_KEY$1}`; |
| const EVENT_FOCUSOUT = `focusout${EVENT_KEY$1}`; |
| const EVENT_HIDE = `hide${EVENT_KEY$1}`; |
| const EVENT_HIDDEN = `hidden${EVENT_KEY$1}`; |
| const EVENT_SHOW = `show${EVENT_KEY$1}`; |
| const EVENT_SHOWN = `shown${EVENT_KEY$1}`; |
| const CLASS_NAME_INSTANT = "toast-instant"; |
| const CLASS_NAME_SHOW = "show"; |
| const DefaultType$1 = { |
| autohide: "boolean", |
| delay: "number" |
| }; |
| const Default$1 = { |
| autohide: true, |
| delay: 5e3 |
| }; |
| /** |
| * Class definition |
| */ |
| var Toast = class extends BaseComponent { |
| constructor(element, config) { |
| super(element, config); |
| this._timeout = null; |
| this._hasMouseInteraction = false; |
| this._hasKeyboardInteraction = false; |
| this._setListeners(); |
| } |
| static get Default() { |
| return Default$1; |
| } |
| static get DefaultType() { |
| return DefaultType$1; |
| } |
| static get NAME() { |
| return NAME$1; |
| } |
| async show() { |
| if (EventHandler.trigger(this._element, EVENT_SHOW).defaultPrevented) return; |
| this._clearTimeout(); |
| const complete = () => { |
| EventHandler.trigger(this._element, EVENT_SHOWN); |
| this._maybeScheduleHide(); |
| }; |
| this._element.classList.add(CLASS_NAME_SHOW); |
| await this._queueCallback(complete, this._element, this._isAnimated()); |
| } |
| async hide() { |
| if (!this.isShown()) return; |
| if (EventHandler.trigger(this._element, EVENT_HIDE).defaultPrevented) return; |
| const complete = () => { |
| EventHandler.trigger(this._element, EVENT_HIDDEN); |
| }; |
| this._element.classList.remove(CLASS_NAME_SHOW); |
| await this._queueCallback(complete, this._element, this._isAnimated()); |
| } |
| dispose() { |
| this._clearTimeout(); |
| if (this.isShown()) this._element.classList.remove(CLASS_NAME_SHOW); |
| super.dispose(); |
| } |
| isShown() { |
| return this._element.classList.contains(CLASS_NAME_SHOW); |
| } |
| _isAnimated() { |
| return !this._element.classList.contains(CLASS_NAME_INSTANT); |
| } |
| _maybeScheduleHide() { |
| if (!this._config.autohide) return; |
| if (this._hasMouseInteraction || this._hasKeyboardInteraction) return; |
| this._timeout = setTimeout(() => { |
| this.hide(); |
| }, this._config.delay); |
| } |
| _onInteraction(event, isInteracting) { |
| switch (event.type) { |
| case "mouseover": |
| case "mouseout": |
| this._hasMouseInteraction = isInteracting; |
| break; |
| case "focusin": |
| case "focusout": |
| this._hasKeyboardInteraction = isInteracting; |
| break; |
| default: break; |
| } |
| if (isInteracting) { |
| this._clearTimeout(); |
| return; |
| } |
| const nextElement = event.relatedTarget; |
| if (this._element === nextElement || this._element.contains(nextElement)) return; |
| this._maybeScheduleHide(); |
| } |
| _setListeners() { |
| EventHandler.on(this._element, EVENT_MOUSEOVER, (event) => this._onInteraction(event, true)); |
| EventHandler.on(this._element, EVENT_MOUSEOUT, (event) => this._onInteraction(event, false)); |
| EventHandler.on(this._element, EVENT_FOCUSIN, (event) => this._onInteraction(event, true)); |
| EventHandler.on(this._element, EVENT_FOCUSOUT, (event) => this._onInteraction(event, false)); |
| } |
| _clearTimeout() { |
| clearTimeout(this._timeout); |
| this._timeout = null; |
| } |
| }; |
| /** |
| * Data API implementation |
| */ |
| enableDismissTrigger(Toast); |
| //#endregion |
| //#region js/src/toggler.ts |
| /** |
| * -------------------------------------------------------------------------- |
| * Bootstrap toggler.ts |
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
| * -------------------------------------------------------------------------- |
| */ |
| /** |
| * Constants |
| */ |
| const NAME = "toggler"; |
| const EVENT_KEY = `.bs.toggler`; |
| const EVENT_TOGGLE = `toggle${EVENT_KEY}`; |
| const EVENT_TOGGLED = `toggled${EVENT_KEY}`; |
| const EVENT_CLICK = "click"; |
| const SELECTOR_DATA_TOGGLE = "[data-bs-toggle=\"toggler\"]"; |
| const DefaultType = { |
| attribute: "string", |
| value: "(string|number|boolean|null)" |
| }; |
| const Default = { |
| attribute: "class", |
| value: null |
| }; |
| /** |
| * Class definition |
| */ |
| var Toggler = class extends BaseComponent { |
| static get Default() { |
| return Default; |
| } |
| static get DefaultType() { |
| return DefaultType; |
| } |
| static get NAME() { |
| return NAME; |
| } |
| toggle() { |
| if (EventHandler.trigger(this._element, EVENT_TOGGLE).defaultPrevented) return; |
| this._execute(); |
| EventHandler.trigger(this._element, EVENT_TOGGLED); |
| } |
| _execute() { |
| const { attribute, value } = this._config; |
| if (attribute === "id") return; |
| if (value === null || value === void 0) return; |
| if (attribute === "class") { |
| this._element.classList.toggle(value); |
| return; |
| } |
| if (this._element.getAttribute(attribute) === String(value)) { |
| this._element.removeAttribute(attribute); |
| return; |
| } |
| this._element.setAttribute(attribute, value); |
| } |
| }; |
| /** |
| * Data API implementation |
| */ |
| eventActionOnPlugin(Toggler, EVENT_CLICK, SELECTOR_DATA_TOGGLE, "toggle"); |
| //#endregion |
| export { Alert, Button, Carousel, Chips, Collapse, Combobox, Datepicker, Dialog, Drawer, Menu, NavOverflow, OtpInput, Popover, Range, ScrollSpy, Strength, Tab, Toast, Toggler, Tooltip }; |
| |
| //# sourceMappingURL=bootstrap.bundle.js.map |