rhino-editor
Version:
A custom element wrapped rich text editor
4,600 lines • 150 kB
JavaScript
import {
TipTapEditorBase
} from "./chunk-VCBD7GOA.js";
import {
toolbarButtonStyles
} from "./chunk-6LK3B3JM.js";
import {
findNodeViewAnchor
} from "./chunk-V5KR23GU.js";
import {
e,
i,
o,
t
} from "./chunk-EWF3FTF7.js";
import {
getNodeType,
isNodeSelection,
objectIncludes,
posToDOMRect
} from "./chunk-4CJ3F2XK.js";
import {
icons_exports
} from "./chunk-IXOHWJ3R.js";
import {
isiOS,
translations
} from "./chunk-5B6NQHMA.js";
import {
E,
T,
Z,
i as i2,
i2 as i3,
x
} from "./chunk-6JX5B4GC.js";
import {
__publicField
} from "./chunk-UM27USL5.js";
// node_modules/.pnpm/lit-html@3.3.1/node_modules/lit-html/directive-helpers.js
var { I: t2 } = Z;
var f = (o4) => void 0 === o4.strings;
// node_modules/.pnpm/lit-html@3.3.1/node_modules/lit-html/async-directive.js
var s = (i4, t3) => {
const e4 = i4._$AN;
if (void 0 === e4) return false;
for (const i5 of e4) i5._$AO?.(t3, false), s(i5, t3);
return true;
};
var o2 = (i4) => {
let t3, e4;
do {
if (void 0 === (t3 = i4._$AM)) break;
e4 = t3._$AN, e4.delete(i4), i4 = t3;
} while (0 === e4?.size);
};
var r = (i4) => {
for (let t3; t3 = i4._$AM; i4 = t3) {
let e4 = t3._$AN;
if (void 0 === e4) t3._$AN = e4 = /* @__PURE__ */ new Set();
else if (e4.has(i4)) break;
e4.add(i4), c(t3);
}
};
function h(i4) {
void 0 !== this._$AN ? (o2(this), this._$AM = i4, r(this)) : this._$AM = i4;
}
function n(i4, t3 = false, e4 = 0) {
const r2 = this._$AH, h3 = this._$AN;
if (void 0 !== h3 && 0 !== h3.size) if (t3) if (Array.isArray(r2)) for (let i5 = e4; i5 < r2.length; i5++) s(r2[i5], false), o2(r2[i5]);
else null != r2 && (s(r2, false), o2(r2));
else s(this, i4);
}
var c = (i4) => {
i4.type == t.CHILD && (i4._$AP ?? (i4._$AP = n), i4._$AQ ?? (i4._$AQ = h));
};
var f2 = class extends i {
constructor() {
super(...arguments), this._$AN = void 0;
}
_$AT(i4, t3, e4) {
super._$AT(i4, t3, e4), r(this), this.isConnected = i4._$AU;
}
_$AO(i4, t3 = true) {
i4 !== this.isConnected && (this.isConnected = i4, i4 ? this.reconnected?.() : this.disconnected?.()), t3 && (s(this, i4), o2(this));
}
setValue(t3) {
if (f(this._$Ct)) this._$Ct._$AI(t3, this);
else {
const i4 = [...this._$Ct._$AH];
i4[this._$Ci] = t3, this._$Ct._$AI(i4, this, 0);
}
}
disconnected() {
}
reconnected() {
}
};
// node_modules/.pnpm/lit-html@3.3.1/node_modules/lit-html/directives/ref.js
var e2 = () => new h2();
var h2 = class {
};
var o3 = /* @__PURE__ */ new WeakMap();
var n2 = e(class extends f2 {
render(i4) {
return E;
}
update(i4, [s2]) {
const e4 = s2 !== this.G;
return e4 && void 0 !== this.G && this.rt(void 0), (e4 || this.lt !== this.ct) && (this.G = s2, this.ht = i4.options?.host, this.rt(this.ct = i4.element)), E;
}
rt(t3) {
if (this.isConnected || (t3 = void 0), "function" == typeof this.G) {
const i4 = this.ht ?? globalThis;
let s2 = o3.get(i4);
void 0 === s2 && (s2 = /* @__PURE__ */ new WeakMap(), o3.set(i4, s2)), void 0 !== s2.get(this.G) && this.G.call(this.ht, void 0), s2.set(this.G, t3), void 0 !== t3 && this.G.call(this.ht, t3);
} else this.G.value = t3;
}
get lt() {
return "function" == typeof this.G ? o3.get(this.ht ?? globalThis)?.get(this.G) : this.G?.value;
}
disconnected() {
this.lt === this.ct && this.rt(void 0);
}
reconnected() {
this.rt(this.ct);
}
});
// node_modules/.pnpm/web-component-define@2.0.11/node_modules/web-component-define/src/internal/defineable-mixin.js
function DefineableMixin(superclass) {
var _a;
return _a = class extends superclass {
/**
* @param {null | undefined | string} [name=this.baseName]
* @param {null | undefined | CustomElementConstructor} [ctor=this]
* @param {ElementDefinitionOptions | undefined} [options]
*/
static define(name, ctor, options) {
if (!name) name = this.baseName;
if (!ctor) ctor = this;
let registry = window.customElements;
if (this.__registry instanceof CustomElementRegistry) {
registry = this.__registry;
}
const alreadyExists = Boolean(registry.get(name));
if (alreadyExists && this.warnOnExistingElement) {
console.warn(`${name} has already been registered.`);
}
if (!alreadyExists && ctor) {
registry.define(name, class extends ctor {
}, options);
}
}
}, /**
* The tag name to register your custom element under.
* @type {string}
*/
__publicField(_a, "baseName", ""), /**
* Emits a console warning if the name for an element is already taken.
* @type {boolean}
*/
__publicField(_a, "warnOnExistingElement", false), _a;
}
var DefineableElement = class extends DefineableMixin(HTMLElement) {
};
// node_modules/.pnpm/@open-wc+dedupe-mixin@1.4.0/node_modules/@open-wc/dedupe-mixin/src/dedupeMixin.js
var appliedClassMixins = /* @__PURE__ */ new WeakMap();
function wasMixinPreviouslyApplied(mixin, superClass) {
let klass = superClass;
while (klass) {
if (appliedClassMixins.get(klass) === mixin) {
return true;
}
klass = Object.getPrototypeOf(klass);
}
return false;
}
function dedupeMixin(mixin) {
return (superClass) => {
if (wasMixinPreviouslyApplied(mixin, superClass)) {
return superClass;
}
const mixedClass = mixin(superClass);
appliedClassMixins.set(mixedClass, mixin);
return mixedClass;
};
}
// node_modules/.pnpm/web-component-define@2.0.11/node_modules/web-component-define/src/internal/scoped-elements-mixin.js
var supportsScopedRegistry = !!ShadowRoot.prototype.createElement;
var ScopedElementsMixinImplementation = (superclass) => {
var _a;
return _a = class extends superclass {
/**
* Obtains the scoped elements definitions map if specified.
*
* @returns {ScopedElementsMap}
*/
static get scopedElements() {
return {};
}
/**
* Obtains the ShadowRoot options.
*
* @type {ShadowRootInit}
*/
static get shadowRootOptions() {
return this.__shadowRootOptions || { mode: "open" };
}
/**
* Set the shadowRoot options.
*
* @param {ShadowRootInit} value
*/
static set shadowRootOptions(value) {
this.__shadowRootOptions = value;
}
/**
* @param {any[]} args
*/
constructor(...args) {
super(...args);
this.renderOptions = this.renderOptions || void 0;
}
/**
* Obtains the CustomElementRegistry associated to the ShadowRoot.
*
* @returns {CustomElementRegistry}
*/
get registry() {
const constructor = this.constructor;
return constructor.__registry;
}
/**
* Set the CustomElementRegistry associated to the ShadowRoot
*
* @param {CustomElementRegistry} registry
*/
set registry(registry) {
const constructor = this.constructor;
constructor.__registry = registry;
}
createRenderRoot() {
const constructor = this.constructor;
const { scopedElements, shadowRootOptions } = constructor;
const shouldCreateRegistry = !this.registry || this.registry === constructor.__registry && !Object.prototype.hasOwnProperty.call(this.constructor, "__registry");
if (shouldCreateRegistry) {
this.registry = supportsScopedRegistry ? new CustomElementRegistry() : customElements;
for (const [tagName, klass] of Object.entries(scopedElements)) {
this.defineScopedElement(tagName, klass);
}
}
const options = {
// @ts-expect-error multiple assignment. Sue me.
mode: "open",
...shadowRootOptions,
customElements: this.registry
};
const createdRoot = this.attachShadow(options);
if (supportsScopedRegistry) {
this.renderOptions.creationScope = createdRoot;
}
if (createdRoot instanceof ShadowRoot) {
this.adoptStyles(createdRoot);
}
return createdRoot;
}
/**
* @param {string} tagName
*/
createScopedElement(tagName) {
const root = supportsScopedRegistry ? this.shadowRoot : document;
return root.createElement(tagName);
}
/**
* Hook for attaching constructable stylesheets to a render root.
* Used in the {LitScopedElementsMixin} .
* @param {ShadowRoot} _shadowRoot
* @returns {void}
*/
adoptStyles(_shadowRoot) {
}
/**
* Defines a scoped element.
*
* @param {string} tagName
* @param {typeof HTMLElement} klass
*/
defineScopedElement(tagName, klass) {
const registeredClass = this.registry.get(tagName);
if (registeredClass && supportsScopedRegistry === false && registeredClass !== klass) {
console.error(
[
`You are trying to re-register the "${tagName}" custom element with a different class via ScopedElementsMixin.`,
"This is only possible with a CustomElementRegistry.",
"Your browser does not support this feature so you will need to load a polyfill for it.",
'Load "@webcomponents/scoped-custom-element-registry" before you register ANY web component to the global customElements registry.',
'e.g. add "<script src="/node_modules/@webcomponents/scoped-custom-element-registry/scoped-custom-element-registry.min.js"><\/script>" as your first script tag.',
"For more details you can visit https://open-wc.org/docs/development/scoped-elements/"
].join("\n")
);
}
if (!registeredClass) {
return this.registry.define(tagName, klass);
}
return this.registry.get(tagName);
}
}, /**
* @protected
* @type {CustomElementRegistry}
*/
__publicField(_a, "__registry", window.customElements), _a;
};
var ScopedElementsMixin = dedupeMixin(ScopedElementsMixinImplementation);
// node_modules/.pnpm/web-component-define@2.0.11/node_modules/web-component-define/src/internal/create-render-root-mixin.js
var CreateRenderRootMixinImplementation = (superclass) => {
return class CreateRenderRootHost extends superclass {
/**
* Obtains the ShadowRoot options.
*
* @type {ShadowRootInit}
*/
static get shadowRootOptions() {
return this.__shadowRootOptions || { mode: "open" };
}
/**
* Set the shadowRoot options.
*
* @param {ShadowRootInit} value
*/
static set shadowRootOptions(value) {
this.__shadowRootOptions = value;
}
/** @type {ShadowRootInit} */
get shadowRootOptions() {
return this.constructor.shadowRootOptions;
}
createRenderRoot() {
const renderRoot = this.shadowRoot ?? this.attachShadow(this.shadowRootOptions || { mode: "open" });
return renderRoot;
}
connectedCallback() {
if (typeof super.connectedCallback === "function") {
super.connectedCallback();
}
if (this.renderRoot == null) {
this.renderRoot = this.createRenderRoot();
}
}
};
};
var CreateRenderRootMixin = dedupeMixin(CreateRenderRootMixinImplementation);
// node_modules/.pnpm/role-components@3.1.0/node_modules/role-components/internal/uuid.js
function uuidv4() {
const crypto = window.crypto || window.msCrypto;
return ("10000000-1000-4000-8000" + -1e11).replace(
/[018]/g,
(c2) => (c2 ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c2 / 4).toString(16)
);
}
// node_modules/.pnpm/role-components@3.1.0/node_modules/role-components/internal/language-observer.js
var _LanguageObserver = class _LanguageObserver {
/**
* @param {HTMLElement} element
*/
constructor(element) {
this.element = element;
this.handleLangChange = () => {
};
this.handleDirChange = () => {
};
this.__handleLangChange = () => this.handleLangChange();
this.__handleDirChange = () => this.handleDirChange();
this.constructor.eventTarget.addEventListener("lang-change", this.__handleLangChange);
this.constructor.eventTarget.addEventListener("dir-change", this.__handleDirChange);
}
start() {
const ctor = (
/** @type {typeof LanguageObserver} */
this.constructor
);
ctor.observer.observe(document.documentElement, ctor.options);
const host = this.element.getRootNode().host;
if (host) {
ctor.observer.observe(host, ctor.options);
}
return this;
}
stop() {
;
this.constructor.observer.disconnect();
return this;
}
};
/**
* @type {MutationObserverInit}
*/
__publicField(_LanguageObserver, "options", {
subtree: true,
attributes: true,
childList: true,
attributeFilter: ["lang", "dir"],
attributeOldValue: true
});
/**
* @type {null | ReturnType<typeof setTimeout>}
*/
__publicField(_LanguageObserver, "langTimeout", null);
/**
* @type {null | ReturnType<typeof setTimeout>}
*/
__publicField(_LanguageObserver, "dirTimeout", null);
__publicField(_LanguageObserver, "eventTarget", new EventTarget());
__publicField(_LanguageObserver, "observer", new MutationObserver((mutationList) => {
for (const mutation of mutationList) {
if (mutation.type === "attributes") {
if (mutation.attributeName === "lang") {
if (_LanguageObserver.langTimeout) {
clearTimeout(_LanguageObserver.langTimeout);
}
_LanguageObserver.langTimeout = setTimeout(() => {
_LanguageObserver.eventTarget.dispatchEvent(new Event("lang-change"));
}, 20);
}
if (mutation.attributeName === "dir") {
if (_LanguageObserver.dirTimeout) {
clearTimeout(_LanguageObserver.dirTimeout);
}
_LanguageObserver.dirTimeout = setTimeout(() => {
_LanguageObserver.eventTarget.dispatchEvent(new Event("dir-change"));
}, 20);
}
}
}
}));
var LanguageObserver = _LanguageObserver;
// node_modules/.pnpm/role-components@3.1.0/node_modules/role-components/internal/base-element.js
var EventHandler = class {
/**
* @param {T} element
*/
constructor(element) {
this.element = element;
this.events = /* @__PURE__ */ new WeakMap();
}
/**
* @param {EventHandlerFunction} fn
*/
get(fn) {
let handler = this.events.get(fn);
if (!handler) {
handler = (...args) => fn.apply(this.element, args);
this.events.set(fn, handler);
}
return handler;
}
};
var BaseElement = class extends DefineableMixin(i3) {
/**
* @type {Record<string, typeof HTMLElement>}
*/
static get dependencies() {
return {};
}
/**
* @param {...any[]} args
*/
constructor(...args) {
super(...args);
Object.entries(
/** @type {typeof BaseElement} */
this.constructor.dependencies
).forEach(([key, ctor]) => {
if (!customElements.get(key)) {
customElements.define(key, ctor);
}
});
this.textDirection = "ltr";
this.eventHandler = new EventHandler(this);
this.languageObserver = new LanguageObserver(this).start();
this.languageObserver.handleLangChange = () => {
const oldDirection = this.textDirection;
this.textDirection = this.getTextDirection();
this.requestUpdate("textDirection", oldDirection);
};
this.languageObserver.handleDirChange = () => {
const oldDirection = this.textDirection;
this.textDirection = this.getTextDirection();
this.requestUpdate("textDirection", oldDirection);
};
this.__debounceMap__ = null;
if (!this.internals) {
this.internals = this.attachInternals();
}
}
/**
* Assign a random UUID with a prefix if no id is found. Will return the "id" of the element if its already assigned.
* @param {string} [prefix=""] - Prefix to add to the uuid
* @param {boolean} [force=false] - If true, will not check if `this.id` already exists.
* @returns {string}
*/
getOrAssignId(prefix = "", force = false) {
let str = this.id;
if (!str || force) {
str = prefix + "-" + uuidv4();
this.id = str;
}
return str;
}
/**
* @returns {"ltr" | "rtl"}
*/
getTextDirection() {
return this.matches(":dir(rtl)") ? "rtl" : "ltr";
}
disconnectedCallback() {
super.disconnectedCallback();
this.__debounceMap__ = null;
}
/**
* @param {(...args: any[]) => any} callback
* @param {{ key: any, wait: number }} options
* @return {ReturnType<typeof setTimeout>}
*/
debounce(callback, options) {
if (this.__debounceMap__ == null) {
this.__debounceMap__ = /* @__PURE__ */ new Map();
}
let timeout = this.__debounceMap__.get(options.key);
if (timeout) {
clearTimeout(timeout);
}
timeout = setTimeout(() => {
callback();
}, options.wait);
this.__debounceMap__.set(options.key, timeout);
return timeout;
}
/**
* @template {keyof ARIAMixin} T
* @param {T} key
* @param {ARIAMixin[T]} value
*/
setAria(key, value) {
this.internals[key] = value;
this[key] = value;
}
};
// node_modules/.pnpm/role-components@3.1.0/node_modules/role-components/exports/styles/host-styles.js
var visuallyHiddenStr = i2`
clip: rect(0 0 0 0);
clip-path: inset(50%);
height: 1px;
overflow: hidden;
position: absolute;
white-space: nowrap;
width: 1px;
`;
var hostStyles = i2`
:host {
--role-background-hover-color: #005a9c;
--role-border-focus-color: #005a9c;
display: block;
box-sizing: border-box;
}
*,
*:after,
*:before {
box-sizing: border-box;
}
[hidden] {
display: none !important;
}
[invisible] {
visibility: hidden !important;
}
[popover]:not(:popover-open):not(dialog[open]) {
display: none;
}
.visually-hidden:not(:focus-within):not(:active) {
${visuallyHiddenStr}
}
.always-visually-hidden {
${visuallyHiddenStr}
}
`;
// node_modules/.pnpm/role-components@3.1.0/node_modules/role-components/exports/components/toolbar/toolbar.js
var RoleToolbar = class extends BaseElement {
constructor() {
super();
this._currentFocusIndex = 0;
this.orientation = "horizontal";
this._toolbarItems = [];
this.orientation = "horizontal";
this.ignoreQuery = "textarea, select, input, [contenteditable='true'], [data-toolbar-ignore]";
this.addEventListener("click", this.eventHandler.get(this.handleClick));
this.addEventListener("keydown", this.eventHandler.get(this.handleKeyDown));
this.addEventListener("focus", this.eventHandler.get(this.handleClick));
}
/**
* @param {import("lit").PropertyValues<this>} changedProperties
*/
willUpdate(changedProperties) {
if (changedProperties.has("_toolbarItems")) {
this.updateToolbarItems();
}
if (changedProperties.has("orientation")) {
this.ariaOrientation = this.orientation;
}
super.willUpdate(changedProperties);
}
/** @returns {string} */
static get baseName() {
return "role-toolbar";
}
static get styles() {
return [
hostStyles,
i2`
.base {
display: flex;
max-width: 100%;
padding: 0.4rem 0.6rem;
border-radius: 4px;
border: 2px solid transparent;
gap: 4px;
overflow: auto;
}
:host([orientation="vertical"]) .base {
flex-direction: column;
}
:host(:focus-within) .base {
border-color: var(--role-border-focus-color);
}
`
];
}
/**
* @return {Record<string, (event: Event) => void>}
*/
get keydownHandlers() {
if (this._keydownHandlers) return this._keydownHandlers;
this._keydownHandlers = {
arrowleft: this.focusPrevious,
arrowup: this.focusPrevious,
arrowright: this.focusNext,
arrowdown: this.focusNext,
home: this.focusFirst,
end: this.focusLast
};
return this._keydownHandlers;
}
render() {
return x`
<div role="toolbar" class="base" part="base">
<slot @slotchange=${this.updateToolbarItems}></slot>
</div>
`;
}
/** @param {Event} event */
handleClick(event) {
let cancelEvent = false;
const focusedElement = event.composedPath().find((el) => {
if (el?.matches?.(this.ignoreQuery)) {
cancelEvent = true;
return;
}
const role = el?.getAttribute?.("data-role") || "";
return role.includes("toolbar-item");
});
if (cancelEvent) {
return;
}
if (focusedElement) {
this._toolbarItems.forEach((el, index) => {
if (el === focusedElement) {
this._currentFocusIndex = index;
return;
}
el.setAttribute("tabindex", "-1");
});
this.setTabIndex({ focus: false });
} else {
this.setTabIndex({ focus: true });
}
}
/** @param {KeyboardEvent} event */
handleKeyDown(event) {
const key = event.key?.toLowerCase();
if (this.orientation === "vertical" && (key === "arrowleft" || key === "arrowright"))
return;
if (this.orientation === "horizontal" && (key === "arrowdown" || key === "arrowup"))
return;
if (event.composedPath().find((el) => {
return el.matches?.(this.ignoreQuery);
})) {
return;
}
if (Object.keys(this.keydownHandlers).includes(key)) {
event.preventDefault();
this.keydownHandlers[key].call(this, event);
}
}
/** @param {Event} _event */
focusNext(_event) {
this.currentFocusElement?.setAttribute("tabindex", "-1");
this._currentFocusIndex += 1;
if (this._currentFocusIndex >= this._toolbarItems.length) {
this.focusFirst();
return;
}
this.setTabIndex();
}
/** @param {Event} _event */
focusPrevious(_event) {
this.currentFocusElement?.setAttribute("tabindex", "-1");
this._currentFocusIndex -= 1;
if (this._currentFocusIndex < 0) {
this.focusLast();
return;
}
this.setTabIndex();
}
focusFirst() {
this._currentFocusIndex = 0;
this.setTabIndex();
}
focusLast() {
if (this._toolbarItems == null) return;
this._currentFocusIndex = this._toolbarItems.length - 1;
this.setTabIndex();
}
setTabIndex({ focus = true } = {}) {
this.currentFocusElement?.setAttribute("tabindex", "0");
if (focus) {
this.currentFocusElement?.focus?.();
}
}
get currentFocusElement() {
if (this._toolbarItems == null) return;
return this._toolbarItems[this._currentFocusIndex];
}
/**
* @param {undefined | null | Event} [evt] - triggered by a slot change event.
*/
updateToolbarItems(evt) {
const slot = evt?.target || this.shadowRoot.querySelector("slot");
if (slot == null) return;
const items = slot.assignedElements({ flatten: true }).filter((el) => {
return el instanceof HTMLElement && el.dataset.role?.match(/toolbar-item/);
});
this._toolbarItems = items;
this._currentFocusIndex = this._toolbarItems.findIndex(
(el) => el.getAttribute("tabindex") === "0"
);
this._toolbarItems.forEach((el) => {
if (this._toolbarItems[this._currentFocusIndex] === el) return;
el.setAttribute("tabindex", "-1");
});
if (this._currentFocusIndex === -1) {
this._currentFocusIndex = 0;
this.currentFocusElement?.setAttribute("tabindex", "0");
}
}
};
__publicField(RoleToolbar, "properties", {
orientation: { reflect: true },
ariaOrientation: { reflect: true },
_currentFocusIndex: { state: true },
_toolbarItems: { state: true }
});
// node_modules/.pnpm/@floating-ui+utils@0.2.10/node_modules/@floating-ui/utils/dist/floating-ui.utils.mjs
var min = Math.min;
var max = Math.max;
var round = Math.round;
var floor = Math.floor;
var createCoords = (v) => ({
x: v,
y: v
});
var oppositeSideMap = {
left: "right",
right: "left",
bottom: "top",
top: "bottom"
};
var oppositeAlignmentMap = {
start: "end",
end: "start"
};
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";
}
var yAxisSides = /* @__PURE__ */ new Set(["top", "bottom"]);
function getSideAxis(placement) {
return yAxisSides.has(getSide(placement)) ? "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.replace(/start|end/g, (alignment) => oppositeAlignmentMap[alignment]);
}
var lrPlacement = ["left", "right"];
var rlPlacement = ["right", "left"];
var tbPlacement = ["top", "bottom"];
var 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) {
return placement.replace(/left|right|bottom|top/g, (side) => oppositeSideMap[side]);
}
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: x2,
y,
width,
height
} = rect;
return {
width,
height,
top: y,
left: x2,
right: x2 + width,
bottom: y + height,
x: x2,
y
};
}
// node_modules/.pnpm/@floating-ui+core@1.7.3/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;
}
var computePosition = async (reference, floating, config) => {
const {
placement = "bottom",
strategy = "absolute",
middleware = [],
platform: platform2
} = config;
const validMiddleware = middleware.filter(Boolean);
const rtl = await (platform2.isRTL == null ? void 0 : platform2.isRTL(floating));
let rects = await platform2.getElementRects({
reference,
floating,
strategy
});
let {
x: x2,
y
} = computeCoordsFromPlacement(rects, placement, rtl);
let statefulPlacement = placement;
let middlewareData = {};
let resetCount = 0;
for (let i4 = 0; i4 < validMiddleware.length; i4++) {
const {
name,
fn
} = validMiddleware[i4];
const {
x: nextX,
y: nextY,
data,
reset
} = await fn({
x: x2,
y,
initialPlacement: placement,
placement: statefulPlacement,
strategy,
middlewareData,
rects,
platform: platform2,
elements: {
reference,
floating
}
});
x2 = nextX != null ? nextX : x2;
y = nextY != null ? nextY : y;
middlewareData = {
...middlewareData,
[name]: {
...middlewareData[name],
...data
}
};
if (reset && resetCount <= 50) {
resetCount++;
if (typeof reset === "object") {
if (reset.placement) {
statefulPlacement = reset.placement;
}
if (reset.rects) {
rects = reset.rects === true ? await platform2.getElementRects({
reference,
floating,
strategy
}) : reset.rects;
}
({
x: x2,
y
} = computeCoordsFromPlacement(rects, statefulPlacement, rtl));
}
i4 = -1;
}
}
return {
x: x2,
y,
placement: statefulPlacement,
strategy,
middlewareData
};
};
async function detectOverflow(state, options) {
var _await$platform$isEle;
if (options === void 0) {
options = {};
}
const {
x: x2,
y,
platform: platform2,
rects,
elements,
strategy
} = state;
const {
boundary = "clippingAncestors",
rootBoundary = "viewport",
elementContext = "floating",
altBoundary = false,
padding = 0
} = evaluate(options, state);
const paddingObject = getPaddingObject(padding);
const altContext = elementContext === "floating" ? "reference" : "floating";
const element = elements[altBoundary ? altContext : elementContext];
const clippingClientRect = rectToClientRect(await platform2.getClippingRect({
element: ((_await$platform$isEle = await (platform2.isElement == null ? void 0 : platform2.isElement(element))) != null ? _await$platform$isEle : true) ? element : element.contextElement || await (platform2.getDocumentElement == null ? void 0 : platform2.getDocumentElement(elements.floating)),
boundary,
rootBoundary,
strategy
}));
const rect = elementContext === "floating" ? {
x: x2,
y,
width: rects.floating.width,
height: rects.floating.height
} : rects.reference;
const offsetParent = await (platform2.getOffsetParent == null ? void 0 : platform2.getOffsetParent(elements.floating));
const offsetScale = await (platform2.isElement == null ? void 0 : platform2.isElement(offsetParent)) ? await (platform2.getScale == null ? void 0 : platform2.getScale(offsetParent)) || {
x: 1,
y: 1
} : {
x: 1,
y: 1
};
const elementClientRect = rectToClientRect(platform2.convertOffsetParentRelativeRectToViewportRelativeRect ? await platform2.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
};
}
var arrow = (options) => ({
name: "arrow",
options,
async fn(state) {
const {
x: x2,
y,
placement,
rects,
platform: platform2,
elements,
middlewareData
} = state;
const {
element,
padding = 0
} = evaluate(options, state) || {};
if (element == null) {
return {};
}
const paddingObject = getPaddingObject(padding);
const coords = {
x: x2,
y
};
const axis = getAlignmentAxis(placement);
const length = getAxisLength(axis);
const arrowDimensions = await platform2.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 (platform2.getOffsetParent == null ? void 0 : platform2.getOffsetParent(element));
let clientSize = arrowOffsetParent ? arrowOffsetParent[clientProp] : 0;
if (!clientSize || !await (platform2.isElement == null ? void 0 : platform2.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 max2 = clientSize - arrowDimensions[length] - maxPadding;
const center = clientSize / 2 - arrowDimensions[length] / 2 + centerToReference;
const offset3 = clamp(min$1, center, max2);
const shouldAddOffset = !middlewareData.arrow && getAlignment(placement) != null && center !== offset3 && rects.reference[length] / 2 - (center < min$1 ? minPadding : maxPadding) - arrowDimensions[length] / 2 < 0;
const alignmentOffset = shouldAddOffset ? center < min$1 ? center - min$1 : center - max2 : 0;
return {
[axis]: coords[axis] + alignmentOffset,
data: {
[axis]: offset3,
centerOffset: center - offset3 - alignmentOffset,
...shouldAddOffset && {
alignmentOffset
}
},
reset: shouldAddOffset
};
}
});
var flip = 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: platform2,
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 (platform2.isRTL == null ? void 0 : platform2.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 placements2 = [initialPlacement, ...fallbackPlacements];
const overflow = await 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 sides2 = getAlignmentSides(placement, rects, rtl);
overflows.push(overflow[sides2[0]], overflow[sides2[1]]);
}
overflowsData = [...overflowsData, {
placement,
overflows
}];
if (!overflows.every((side2) => side2 <= 0)) {
var _middlewareData$flip2, _overflowsData$filter;
const nextIndex = (((_middlewareData$flip2 = middlewareData.flip) == null ? void 0 : _middlewareData$flip2.index) || 0) + 1;
const nextPlacement = placements2[nextIndex];
if (nextPlacement) {
const ignoreCrossAxisOverflow = checkCrossAxis === "alignment" ? initialSideAxis !== getSideAxis(nextPlacement) : false;
if (!ignoreCrossAxisOverflow || // We leave the current main axis only if every placement on that axis
// overflows the main axis.
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 placement2 = (_overflowsData$filter2 = overflowsData.filter((d) => {
if (hasFallbackAxisSideDirection) {
const currentSideAxis = getSideAxis(d.placement);
return currentSideAxis === initialSideAxis || // Create a bias to the `y` side axis due to horizontal
// reading directions favoring greater width.
currentSideAxis === "y";
}
return true;
}).map((d) => [d.placement, d.overflows.filter((overflow2) => overflow2 > 0).reduce((acc, overflow2) => acc + overflow2, 0)]).sort((a, b) => a[1] - b[1])[0]) == null ? void 0 : _overflowsData$filter2[0];
if (placement2) {
resetPlacement = placement2;
}
break;
}
case "initialPlacement":
resetPlacement = initialPlacement;
break;
}
}
if (placement !== resetPlacement) {
return {
reset: {
placement: resetPlacement
}
};
}
}
return {};
}
};
};
var originSides = /* @__PURE__ */ new Set(["left", "top"]);
async function convertValueToCoords(state, options) {
const {
placement,
platform: platform2,
elements
} = state;
const rtl = await (platform2.isRTL == null ? void 0 : platform2.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
};
}
var offset = function(options) {
if (options === void 0) {
options = 0;
}
return {
name: "offset",
options,
async fn(state) {
var _middlewareData$offse, _middlewareData$arrow;
const {
x: x2,
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: x2 + diffCoords.x,
y: y + diffCoords.y,
data: {
...diffCoords,
placement
}
};
}
};
};
var shift = function(options) {
if (options === void 0) {
options = {};
}
return {
name: "shift",
options,
async fn(state) {
const {
x: x2,
y,
placement
} = state;
const {
mainAxis: checkMainAxis = true,
crossAxis: checkCrossAxis = false,
limiter = {
fn: (_ref) => {
let {
x: x3,
y: y2
} = _ref;
return {
x: x3,
y: y2
};
}
},
...detectOverflowOptions
} = evaluate(options, state);
const coords = {
x: x2,
y
};
const overflow = await 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 min2 = mainAxisCoord + overflow[minSide];
const max2 = mainAxisCoord - overflow[maxSide];
mainAxisCoord = clamp(min2, mainAxisCoord, max2);
}
if (checkCrossAxis) {
const minSide = crossAxis === "y" ? "top" : "left";
const maxSide = crossAxis === "y" ? "bottom" : "right";
const min2 = crossAxisCoord + overflow[minSide];
const max2 = crossAxisCoord - overflow[maxSide];
crossAxisCoord = clamp(min2, crossAxisCoord, max2);
}
const limitedCoords = limiter.fn({
...state,
[mainAxis]: mainAxisCoord,
[crossAxis]: crossAxisCoord
});
return {
...limitedCoords,
data: {
x: limitedCoords.x - x2,
y: limitedCoords.y - y,
enabled: {
[mainAxis]: checkMainAxis,
[crossAxis]: checkCrossAxis
}
}
};
}
};
};
var size = function(options) {
if (options === void 0) {
options = {};
}
return {
name: "size",
options,
async fn(state) {
var _state$middlewareData, _state$middlewareData2;
const {
placement,
rects,
platform: platform2,
elements
} = state;
const {
apply = () => {
},
...detectOverflowOptions
} = evaluate(options, state);
const overflow = await detectOverflow(state, detectOverflowOptions);
const side = getSide(placement);
const alignment = getAlignment(placement);
const isYAxis = getSideAxis(placement) === "y";
const {
width,
height
} = rects.floating;
let heightSide;
let widthSide;
if (side === "top" || side === "bottom") {
heightSide = side;
widthSide = alignment === (await (platform2.isRTL == null ? void 0 : platform2.isRTL(elements.floating)) ? "start" : "end") ? "left" : "right";
} else {
widthSide = side;
heightSide = alignment === "end" ? "top" : "bottom";
}
const maximumClippingHeight = height - overflow.top - overflow.bottom;
const maximumClippingWidth = width - overflow.left - overflow.right;
const overflowAvailableHeight = min(height - overflow[heightSide], maximumClippingHeight);
const overflowAvailableWidth = min(width - overflow[widthSide], maximumClippingWidth);
const noShift = !state.middlewareData.shift;
let availableHeight = overflowAvailableHeight;
let availableWidth = overflowAvailableWidth;
if ((_state$middlewareData = state.middlewareData.shift) != null && _state$middlewareData.enabled.x) {
availableWidth = maximumClippingWidth;
}
if ((_state$middlewareData2 = state.middlewareData.shift) != null && _state$middlewareData2.enabled.y) {
availableHeight = maximumClippingHeight;
}
if (noShift && !alignment) {
const xMin = max(overflow.left, 0);
const xMax = max(overflow.right, 0);
const yMin = max(overflow.top, 0);
const yMax = max(overflow.bottom, 0);
if (isYAxis) {
availableWidth = width - 2 * (xMin !== 0 || xMax !== 0 ? xMin + xMax : max(overflow.left, overflow.right));
} else {
availableHeight = height - 2 * (yMin !== 0 || yMax !== 0 ? yMin + yMax : max(overflow.top, overflow.bottom));
}
}
await apply({
...state,
availableWidth,
availableHeight
});
const nextDimensions = await platform2.getDimensions(elements.floating);
if (width !== nextDimensions.width || height !== nextDimensions.height) {
return {
reset: {
rects: true
}
};
}
return {};
}
};
};
// node_modules/.pnpm/@floating-ui+utils@0.2.10/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;
}
var invalidOverflowDisplayValues = /* @__PURE__ */ new Set(["inline", "contents"]);
function isOverflowElement(element) {
const {
overflow,
overflowX,
overflowY,
display
} = getComputedStyle2(element);
return /auto|scroll|overlay|hidden|clip/.test(overflow + overflowY + overflowX) && !invalidOverflowDisplayValues.has(display);
}
var tableElements = /* @__PURE__ */ new Set(["table", "td", "th"]);
function isTableElement(element) {
return tableElements.has(getNodeName(element));
}
var topLayerSelectors = [":popover-open", ":modal"];
function isTopLayer(element) {
return topLayerSelectors.some((selector) => {
try {
return element.matches(selector);
} catch (_e) {
return false;
}
});
}
var transformProperties = ["transform", "translate", "scale", "rotate", "perspective"];
var willChangeValues = ["transform", "translate", "scale", "rotate", "perspective", "filter"];
var containValues = ["paint", "layout", "strict", "content"];
function isContainingBlock(elementOrCss) {
const webkit = isWebKit();
const css = isElement(elementOrCss) ? getComputedStyle2(elementOrCss) : elementOrCss;
return transformProperties.some((value) => css[value] ? css[value] !== "none" : false) || (css.containerType ? css.containerType !== "normal" : false) || !webkit && (css.backdropFilter ? css.backdropFilter !== "none" : false) || !webkit && (css.filter ? css.filter !== "none" : false) || willChangeValues.some((value) => (css.willChange || "").includes(value)) || containValues.some((value) => (css.contain || "").includes(value));
}
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 (typeof CSS === "undefined" || !CSS.supports) return false;
return CSS.supports("-webkit-backdrop-filter", "none");
}
var lastTraversableNodeNames = /* @__PURE__ */ new Set(["html", "body", "#document"]);
function isLastTraversableNode(node) {
return lastTraversableNodeNames.has(getNodeName(node));
}
function getComputedStyle2(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 = (
// Step into the shadow DOM of the parent of a slotted node.
node.assignedSlot || // DOM Element detected.
node.parentNode || // ShadowRoot detected.
isShadowRoot(node) && node.host || // Fallback.
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) : []);
}
return list.concat(scrollableAncestor, getOverflowAncestors(scrollableAncestor, [], traverseIframes));
}
function getFrameElement(win) {
return win.parent && Object.getPrototypeOf(win.parent) ? win.frameElement : null;
}
// node_modules/.pnpm/@floating-ui+dom@1.7.4/node_modules/@floating-ui/dom/dist/floating-ui.dom.mjs
function getCssDimensions(element) {
const css = getComputedStyle2(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 x2 = ($ ? round(rect.width) : rect.width) / width;
let y = ($ ? round(rect.height) : rect.height) / height;
if (!x2 || !Number.isFinite(x2)) {
x2 = 1;
}
if (!y || !Number.isFinite(y)) {
y = 1;
}
return {
x: x2,
y
};
}
var 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 x2 = (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 = getComputedStyle2(currentIFrame);
const left = iframeRect.left + (currentIFrame.clientLeft + parseFloat(css.paddingLeft)) * iframeScale.x;
const top = iframeRect.top + (currentIFrame.clientTop + parseFloat(css.paddingTop)) * iframeScale.y;
x2 *= iframeScale.x;
y *= iframeScale.y;
width *= iframeScale.x;
height *= iframeScale.y;
x2 += left;
y += top;
currentWin = getWindow(currentIFrame);
currentIFrame = getFrameElement(currentWin);
}
}
return rectToClientRect({
width,
height,
x: x2,
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();
const x2 = htmlRect.left + scroll.scrollLeft - getWindowScrollBarX(documentElement, htmlRect);
const y = htmlRect.top + scroll.scrollTop;
return {
x: x2,
y
};
}
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 (isHTMLElement(offsetParent)) {
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 x2 = -scroll.scrollLeft + getWindowScrollBarX(element);
const y = -scroll.scrollTop;
if (getComputedStyle2(body).direction === "rtl") {
x2 += max(html.clientWidth, body.clientWidth) - width;
}
return {
width,
height,
x: x2,
y
};
}
var 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 x2 = 0;
let y = 0;
if (visualViewport) {
width = visualViewport.width;
height = visualViewport.height;
const visualViewportBased = isWebKit();
if (!visualViewportBased || visualViewportBased && strategy === "fixed") {
x2 = 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: x2,
y
};
}
var absoluteOrFixed = /* @__PURE__ */ new Set(["absolute", "fixed"]);
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);
const width = element.clientWidth * scale.x;
const height = element.clientHeight * scale.y;
const x2 = left * scale.x;
const y = top * scale.y;
return {
width,
height,
x: x2,
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 getComputedStyle2(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 = getComputedStyle2(element).position === "fixed";
let currentNode = elementIsFixed ? getParentNode(element) : element;
while (isElement(currentNode) && !isLastTraversableNode(currentNode)) {
const computedStyle = getComputedStyle2(currentNode);
const currentNodeIsContaining = isContainingBlock(currentNode);
if (!currentNodeIsContaining && computedStyle.position === "fixed") {
currentContainingBlockComputedStyle = null;
}
const shouldDropCurrentNode = elementIsFixed ? !currentNodeIsContaining && !currentContainingBlockComputedStyle : !currentNodeIsContaining && computedStyle.position === "static" && !!currentContainingBlockComputedStyle && absoluteOrFixed.has(currentContainingBlockComputedStyle.position) || isOverflowElement(currentNode) && !currentNodeIsContaining && hasFixedPositionAncestor(element, currentNode);
if (shouldDropCurrentNode) {
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 elementClippingAncestors = boundary === "clippingAncestors" ? isTopLayer(element) ? [] : getClippingElementAncestors(element, this._c) : [].concat(boundary);
const clippingAncestors = [...elementClippingAncestors, rootBoundary];
const firstClippingAncestor = clippingAncestors[0];
const clippingRect = clippingAncestors.reduce((accRect, clippingAncestor) => {
const rect = getClientRectFromClippingAncestor(element, clippingAncestor, strategy);
accRect.top = max(rect.top, accRect.top);
accRect.right = min(rect.right, accRect.right);
accRect.bottom = min(rect.bottom, accRect.bottom);
accRect.left = max(rect.left, accRect.left);
return accRect;
}, getClientRectFromClippingAncestor(element, firstClippingAncestor, strategy));
return {
width: clippingRect.right - clippingRect.left,
height: clippingRect.bottom - clippingRect.top,
x: clippingRect.left,
y: clippingRect.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);
const x2 = rect.left + scroll.scrollLeft - offsets.x - htmlOffset.x;
const y = rect.top + scroll.scrollTop - offsets.y - htmlOffset.y;
return {
x: x2,
y,
width: rect.width,
height: rect.height
};
}
function isStaticPositioned(element) {
return getComputedStyle2(element).position === "static";
}
function getTrueOffsetParent(element, polyfill) {
if (!isHTMLElement(element) || getComputedStyle2(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;
}
var 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 getComputedStyle2(element).direction === "rtl";
}
var 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 rootMargin = -insetTop + "px " + -insetRight + "px " + -insetBottom + "px " + -insetLeft + "px";
const options = {
rootMargin,
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,
// Handle <iframe>s
root: root.ownerDocument
});
} catch (_e) {
io = new IntersectionObserver(handleObserve, options);
}
io.observe(element);
}
refresh(true);
return cleanup;
}
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) : [], ...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) {
resizeObserver.unobserve(floating);
cancelAnimationFrame(reobserveFrame);
reobserveFrame = requestAnimationFrame(() => {
var _resizeObserver;
(_resizeObserver = resizeObserver) == null || _resizeObserver.observe(floating);
});
}
update();
});
if (referenceEl && !animationFrame) {
resizeObserver.observe(referenceEl);
}
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 == null || cleanupIo();
(_resizeObserver2 = resizeObserver) == null || _resizeObserver2.disconnect();
resizeObserver = null;
if (animationFrame) {
cancelAnimationFrame(frameId);
}
};
}
var offset2 = offset;
var shift2 = shift;
var flip2 = flip;
var size2 = size;
var arrow2 = arrow;
var computePosition2 = (reference, floating, options) => {
const cache = /* @__PURE__ */ new Map();
const mergedOptions = {
platform,
...options
};
const platformWithCache = {
...mergedOptions.platform,
_c: cache
};
return computePosition(reference, floating, {
...mergedOptions,
platform: platformWithCache
});
};
// node_modules/.pnpm/lit-html@3.3.1/node_modules/lit-html/directives/class-map.js
var e3 = e(class extends i {
constructor(t3) {
if (super(t3), t3.type !== t.ATTRIBUTE || "class" !== t3.name || t3.strings?.length > 2) throw Error("`classMap()` can only be used in the `class` attribute and must be the only part in the attribute.");
}
render(t3) {
return " " + Object.keys(t3).filter((s2) => t3[s2]).join(" ") + " ";
}
update(s2, [i4]) {
if (void 0 === this.st) {
this.st = /* @__PURE__ */ new Set(), void 0 !== s2.strings && (this.nt = new Set(s2.strings.join(" ").split(/\s/).filter((t3) => "" !== t3)));
for (const t3 in i4) i4[t3] && !this.nt?.has(t3) && this.st.add(t3);
return this.render(i4);
}
const r2 = s2.element.classList;
for (const t3 of this.st) t3 in i4 || (r2.remove(t3), this.st.delete(t3));
for (const t3 in i4) {
const s3 = !!i4[t3];
s3 === this.st.has(t3) || this.nt?.has(t3) || (s3 ? (r2.add(t3), this.st.add(t3)) : (r2.remove(t3), this.st.delete(t3)));
}
return T;
}
});
// node_modules/.pnpm/role-components@3.1.0/node_modules/role-components/internal/string-map.js
function stringMap(obj) {
let string = "";
for (const [key, value] of Object.entries(obj)) {
if (Boolean(value)) {
string += `${key} `;
}
}
return string;
}
// node_modules/.pnpm/role-components@3.1.0/node_modules/role-components/exports/events/base-event.js
var BaseEvent = class extends Event {
/**
* @param {string} name
* @param {EventInit} [options]
*/
constructor(name, options) {
if (options == null) options = {};
if (options.bubbles == null) options.bubbles = true;
if (options.composed == null) options.composed = true;
if (options.cancelable == null) options.cancelable = false;
super(name, options);
}
};
// node_modules/.pnpm/role-components@3.1.0/node_modules/role-components/exports/events/role-reposition-event.js
var RoleRepositionEvent = class extends BaseEvent {
/**
* @param {EventInit} [init={}]
*/
constructor(init = {}) {
super("role-reposition", init);
}
};
// node_modules/.pnpm/role-components@3.1.0/node_modules/role-components/exports/components/anchored-region/anchored-region.js
function isVirtualElement(e4) {
return e4 !== null && typeof e4 === "object" && "getBoundingClientRect" in e4 && ("contextElement" in e4 ? e4 instanceof Element : true);
}
function AnchoredRegionMixin(superclass) {
return class __AnchoredRegionMixin__ extends superclass {
/**
* @param {any[]} args
*/
constructor(...args) {
super(...args);
this.anchor = this.anchor ?? null;
this.placement = this.placement ?? "top";
this.currentPlacement = this.placement ?? null;
this.strategy = this.strategy ?? "fixed";
this.distance = this.distance ?? 0;
this.skidding = this.skidding ?? 0;
this.arrow = this.arrow ?? false;
this.arrowPlacement = this.arrowPlacement ?? "anchor";
this.arrowPadding = this.arrowPadding ?? 10;
this.flip = this.flip ?? true;
this.flipFallbackPlacements = this.flipFallbackPlacements ?? "";
this.flipFallbackStrategy = this.flipFallbackStrategy ?? "best-fit";
this.flipBoundary = this.flipBoundary ?? void 0;
this.flipPadding = this.flipPadding ?? 0;
this.shift = this.shift ?? true;
this.shiftBoundary = this.shiftBoundary ?? void 0;
this.shiftPadding = this.shiftPadding ?? 0;
this.autoSize = this.autoSize ?? null;
this.sync = this.sync ?? null;
this.autoSizeBoundary = this.autoSizeBoundary ?? void 0;
this.autoSizePadding = this.autoSizePadding ?? 0;
this.hoverBridge = this.hoverBridge ?? true;
this.active = this.active ?? false;
this.anchoredPopoverType = this.anchoredPopoverType ?? "auto";
}
};
}
var AnchoredRegionProperties = () => (
/** @const */
{
active: { type: Boolean, reflect: true },
anchor: { attribute: false, state: true },
placement: { reflect: true },
currentPlacement: { attribute: "current-placement", reflect: true },
strategy: { reflect: true },
distance: { type: Number },
skidding: { type: Number },
arrow: { type: Boolean },
arrowPlacement: { attribute: "arrow-placement" },
arrowPadding: { attribute: "arrow-padding", type: Number },
flip: { type: Boolean },
flipFallbackPlacements: {
attribute: "flip-fallback-placements",
converter: {
/**
* @param {string} value
*/
fromAttribute: (value) => {
return value.split(" ").map((p) => p.trim()).filter((p) => p !== "");
},
/**
* @param {[]} value
*/
toAttribute: (value) => {
return value.join(" ");
}
}
},
flipFallbackStrategy: { attribute: "flip-fallback-strategy" },
flipBoundary: { attribute: false, type: Object },
flipPadding: { attribute: "flip-padding", type: Number },
shift: { type: Boolean },
shiftBoundary: { attribute: false, type: Object },
shiftPadding: { attribute: "shift-padding", type: Number },
autoSize: { attribute: "auto-size" },
sync: {},
autoSizeBoundary: { type: Object },
autoSizePadding: { attribute: "auto-size-padding", type: Number },
hoverBridge: { attribute: "hover-bridge", type: Boolean },
anchoredPopoverType: { attribute: "anchored-popover-type", reflect: true }
}
);
var RoleAnchoredRegion = class extends AnchoredRegionMixin(BaseElement) {
constructor() {
super();
__publicField(this, "updateHoverBridge", () => {
if (this.hoverBridge && this.__anchorEl && this.popoverElement) {
const anchorRect = this.__anchorEl.getBoundingClientRect();
const popoverRect = this.popoverElement.getBoundingClientRect();
const isVertical = (this.currentPlacement?.includes("top") || this.currentPlacement?.includes("bottom")) ?? true;
let topLeftX = 0;
let topLeftY = 0;
let topRightX = 0;
let topRightY = 0;
let bottomLeftX = 0;
let bottomLeftY = 0;
let bottomRightX = 0;
let bottomRightY = 0;
if (isVertical) {
if (anchorRect.top < popoverRect.top) {
topLeftX = anchorRect.left;
topLeftY = anchorRect.bottom;
topRightX = anchorRect.right;
topRightY = anchorRect.bottom;
bottomLeftX = popoverRect.left;
bottomLeftY = popoverRect.top;
bottomRightX = popoverRect.right;
bottomRightY = popoverRect.top;
} else {
topLeftX = popoverRect.left;
topLeftY = popoverRect.bottom;
topRightX = popoverRect.right;
topRightY = popoverRect.bottom;
bottomLeftX = anchorRect.left;
bottomLeftY = anchorRect.top;
bottomRightX = anchorRect.right;
bottomRightY = anchorRect.top;
}
} else {
if (this.currentPlacement?.includes("left")) {
topLeftX = popoverRect.right;
topLeftY = popoverRect.top;
topRightX = anchorRect.right;
topRightY = anchorRect.top;
bottomLeftX = popoverRect.right;
bottomLeftY = popoverRect.bottom;
bottomRightX = anchorRect.right;
bottomRightY = anchorRect.bottom;
} else {
topLeftX = anchorRect.left;
topLeftY = anchorRect.top;
topRightX = popoverRect.left;
topRightY = popoverRect.top;
bottomLeftX = anchorRect.left;
bottomLeftY = anchorRect.bottom;
bottomRightX = popoverRect.left;
bottomRightY = popoverRect.bottom;
}
}
this.style.setProperty("--hover-bridge-top-left-x", `${topLeftX}px`);
this.style.setProperty("--hover-bridge-top-left-y", `${topLeftY}px`);
this.style.setProperty("--hover-bridge-top-right-x", `${topRightX}px`);
this.style.setProperty("--hover-bridge-top-right-y", `${topRightY}px`);
this.style.setProperty("--hover-bridge-bottom-left-x", `${bottomLeftX}px`);
this.style.setProperty("--hover-bridge-bottom-left-y", `${bottomLeftY}px`);
this.style.setProperty("--hover-bridge-bottom-right-x", `${bottomRightX}px`);
this.style.setProperty("--hover-bridge-bottom-right-y", `${bottomRightY}px`);
}
});
if (window.process == null) window.process = {};
if (window.process.env == null) window.process.env = "development";
this.anchor = null;
this.active = false;
this.__anchorEl = null;
this.__cleanup;
}
async connectedCallback() {
super.connectedCallback();
await this.updateComplete;
this.__start();
}
disconnectedCallback() {
super.disconnectedCallback();
this.__stop();
}
/**
* @param {import('lit').PropertyValues<this>} changedProps
*/
willUpdate(changedProps) {
super.willUpdate(changedProps);
if (changedProps.has("active")) {
if (this.active) {
this.__start();
} else {
this.__stop();
}
}
if (changedProps.has("anchor")) {
this.__handleAnchorChange();
}
}
/**
* @param {import('lit').PropertyValues<this>} changedProps
*/
async updated(changedProps) {
super.updated(changedProps);
if (this.active) {
await this.updateComplete;
this.reposition();
}
}
/**
* A reference to the internal popover container. Useful for animating and styling the popover with JavaScript.
*
*/
get popoverElement() {
return (
/** @type {null | HTMLElement} */
this.shadowRoot?.querySelector('[part~="popover"]') || null
);
}
get arrowElement() {
return (
/** @type {null | HTMLElement} */
this.shadowRoot?.querySelector('[part~="arrow"]') || null
);
}
/**
* @internal
*/
async __handleAnchorChange() {
await this.__stop();
if (this.anchor && typeof this.anchor === "string") {
const root = (
/** @type {Document | ShadowRoot} */
this.getRootNode()
);
this.__anchorEl = root.getElementById(this.anchor);
} else if (this.anchor instanceof Element || isVirtualElement(this.anchor)) {
this.__anchorEl = /** @type {Element | VirtualElement} */
this.anchor;
} else {
this.__anchorEl = /** @type {HTMLElement} */
this.querySelector('[slot="anchor"]');
}
if (this.__anchorEl instanceof HTMLSlotElement) {
this.__anchorEl = /** @type {HTMLElement} */
this.__anchorEl.assignedElements({ flatten: true })[0];
}
if (this.__anchorEl) {
this.__start();
}
}
/**
* @internal
*/
__start() {
if (!this.__anchorEl) {
return;
}
if (!this.popoverElement) {
return;
}
this.__togglePopover__();
this.cleanup = autoUpdate(this.__anchorEl, this.popoverElement, () => {
this.reposition();
});
}
/**
* @internal
* @returns {Promise<void>}
*/
async __stop() {
return new Promise((resolve) => {
if (this.cleanup) {
this.cleanup();
this.cleanup = void 0;
this.currentPlacement = null;
this.style.removeProperty("--auto-size-available-width");
this.style.removeProperty("--auto-size-available-height");
requestAnimationFrame(() => {
resolve();
this.__togglePopover__();
});
} else {
this.__togglePopover__();
resolve();
}
});
}
__togglePopover__() {
const popover = this.shadowRoot?.querySelector("[popover]") || null;
if (popover) {
if (this.active) {
try {
popover.showPopover();
} catch (_) {
}
} else {
try {
popover.hidePopover();
} catch (_) {
}
}
}
}
/** Forces the popover to recalculate and reposition itself. */
reposition() {
const popoverElement = this.popoverElement;
if (!this.active || !this.__anchorEl || !popoverElement) {
return;
}
const middleware = [
// The offset middleware goes first
offset2({ mainAxis: this.distance, crossAxis: this.skidding })
];
if (this.sync) {
middleware.push(
size2({
apply: ({ rects }) => {
const syncWidth = this.sync === "width" || this.sync === "both";
const syncHeight = this.sync === "height" || this.sync === "both";
popoverElement.style.width = syncWidth ? `${rects.reference.width}px` : "";
popoverElement.style.height = syncHeight ? `${rects.reference.height}px` : "";
}
})
);
} else {
popoverElement.style.width = "";
popoverElement.style.height = "";
}
if (this.flip) {
middleware.push(
flip2({
boundary: this.flipBoundary,
// @ts-expect-error - We're converting a string attribute to an array here
fallbackPlacements: this.flipFallbackPlacements,
fallbackStrategy: this.flipFallbackStrategy === "best-fit" ? "bestFit" : "initialPlacement",
padding: this.flipPadding
})
);
}
if (this.shift) {
middleware.push(
shift2({
boundary: this.shiftBoundary,
padding: this.shiftPadding
})
);
}
if (this.autoSize) {
middleware.push(
size2({
boundary: this.autoSizeBoundary,
padding: this.autoSizePadding,
apply: ({ availableWidth, availableHeight }) => {
if (this.autoSize === "vertical" || this.autoSize === "both") {
this.style.setProperty("--auto-size-available-height", `${availableHeight}px`);
} else {
this.style.removeProperty("--auto-size-available-height");
}
if (this.autoSize === "horizontal" || this.autoSize === "both") {
this.style.setProperty("--auto-size-available-width", `${availableWidth}px`);
} else {
this.style.removeProperty("--auto-size-available-width");
}
}
})
);
} else {
this.style.removeProperty("--auto-size-available-width");
this.style.removeProperty("--auto-size-available-height");
}
if (this.arrow && this.arrowElement) {
middleware.push(
arrow2({
element: this.arrowElement,
padding: this.arrowPadding
})
);
}
computePosition2(this.__anchorEl, popoverElement, {
placement: this.placement,
middleware,
strategy: this.strategy
}).then(({ x: x2, y, middlewareData, placement }) => {
const isRtl = getComputedStyle(this).direction === "rtl";
this.currentPlacement = placement;
const staticSide = { top: "bottom", right: "left", bottom: "top", left: "right" }[placement.split("-")[0]] || this.placement;
Object.assign(popoverElement.style, {
left: `${x2}px`,
top: `${y}px`
});
if (this.arrow && middlewareData.arrow) {
const arrowX = middlewareData.arrow.x;
const arrowY = middlewareData.arrow.y;
let top = "";
let right = "";
let bottom = "";
let left = "";
if (this.arrowPlacement === "start") {
const value = typeof arrowX === "number" ? `calc(${this.arrowPadding}px - var(--arrow-padding-offset))` : "";
top = typeof arrowY === "number" ? `calc(${this.arrowPadding}px - var(--arrow-padding-offset))` : "";
right = isRtl ? value : "";
left = isRtl ? "" : value;
} else if (this.arrowPlacement === "end") {
const value = typeof arrowX === "number" ? `calc(${this.arrowPadding}px - var(--arrow-padding-offset))` : "";
right = isRtl ? "" : value;
left = isRtl ? value : "";
bottom = typeof arrowY === "number" ? `calc(${this.arrowPadding}px - var(--arrow-padding-offset))` : "";
} else if (this.arrowPlacement === "center") {
left = typeof arrowX === "number" ? `calc(50% - var(--arrow-size-diagonal))` : "";
top = typeof arrowY === "number" ? `calc(50% - var(--arrow-size-diagonal))` : "";
} else {
left = typeof arrowX === "number" ? `${arrowX}px` : "";
top = typeof arrowY === "number" ? `${arrowY}px` : "";
}
if (this.arrowElement) {
Object.assign(this.arrowElement.style, {
top,
right,
bottom,
left,
[staticSide]: "calc(var(--arrow-size-diagonal) * -1)"
});
}
}
});
requestAnimationFrame(() => this.updateHoverBridge());
this.dispatchEvent(new RoleRepositionEvent());
}
render() {
return x`
<slot name="anchor" @slotchange=${this.__handleAnchorChange}></slot>
<div
part="popover-base"
popover=${o(this.anchoredPopoverType === "none" ? null : this.anchoredPopoverType)}
>
<span
part=${stringMap({
"hover-bridge": true,
"hover-bridge--visible": this.hoverBridge && this.active
})}
></span>
<div
part=${stringMap({
popover: true,
"popover--active": this.active,
"popover--fixed": this.strategy === "fixed",
"popover--has-arrow": this.arrow
})}
class=${e3({
"visually-hidden": !this.active
})}
>
<slot></slot>
${this.arrow ? x`<div part="arrow" role="presentation"></div>` : ""}
</div>
</div>
`;
}
};
__publicField(RoleAnchoredRegion, "baseName", "role-anchored-region");
__publicField(RoleAnchoredRegion, "styles", [
hostStyles,
i2`
:host {
--__background: var(--background, #222);
--__border-color: var(--border-color, #222);
--__border-width: var(--border-width, 1px);
--__arrow-size: var(--arrow-size, 8px);
/*
* These properties are computed to account for the arrow's dimensions after being rotated 45º. The constant
* 0.7071 is derived from sin(45), which is the diagonal size of the arrow's container after rotating.
*/
--arrow-size-diagonal: calc(var(--__arrow-size) * 0.7071);
--arrow-padding-offset: calc(var(--arrow-size-diagonal) - var(--__arrow-size));
display: contents;
}
[part~="popover"] {
position: absolute;
isolation: isolate;
max-width: var(--auto-size-available-width, none);
max-height: var(--auto-size-available-height, none);
border: var(--__border-width) solid var(--__border-color);
background: var(--__background);
}
[popover] {
position: fixed;
border: none;
background: none;
inset: unset;
color: inherit;
margin: 0;
padding: 0;
}
[part~="popover--fixed"] {
position: fixed;
}
[part~="arrow"] {
position: absolute;
width: calc(var(--arrow-size-diagonal) * 2);
height: calc(var(--arrow-size-diagonal) * 2);
background: var(--__background);
/* background: tomato; */
z-index: -1;
margin: 0;
transform-style: preserve-3d;
border: var(--__border-width) solid var(--__border-color);
border-top-color: transparent;
border-right-color: transparent;
}
/* Hover bridge */
[part~="hover-bridge"]:not([part~="hover-bridge--visible"]) {
display: none;
}
[part~="hover-bridge"] {
/* background: tomato; */
position: fixed;
z-index: calc(var(--z-index-dropdown, 900) - 1);
top: 0;
right: 0;
bottom: 0;
left: 0;
clip-path: polygon(
var(--hover-bridge-top-left-x, 0) var(--hover-bridge-top-left-y, 0),
var(--hover-bridge-top-right-x, 0) var(--hover-bridge-top-right-y, 0),
var(--hover-bridge-bottom-right-x, 0) var(--hover-bridge-bottom-right-y, 0),
var(--hover-bridge-bottom-left-x, 0) var(--hover-bridge-bottom-left-y, 0)
);
}
:host([current-placement="top"]) [part~="arrow"] {
transform: rotate(315deg);
}
:host([current-placement="bottom"]) [part~="arrow"] {
transform: rotate(135deg);
}
:host([current-placement="left"]) [part~="arrow"] {
transform: rotate(225deg);
}
:host([current-placement="right"]) [part~="arrow"] {
transform: rotate(45deg);
}
`
]);
__publicField(RoleAnchoredRegion, "properties", {
...AnchoredRegionProperties()
});
// node_modules/.pnpm/role-components@3.1.0/node_modules/role-components/exports/events/role-tooltip-toggle-event.js
var RoleTooltipToggleEvent = class extends BaseEvent {
/**
* @param {EventInit & {triggerElement: Element, triggerEvent: Event}} init
*/
constructor(init) {
super("role-tooltip-toggle", init);
this.triggerElement = init.triggerElement;
this.triggerEvent = init.triggerEvent;
}
};
// node_modules/.pnpm/role-components@3.1.0/node_modules/role-components/exports/components/tooltip/tooltip.js
function findTriggerElementFromEvent(e4) {
const triggerElement = (
/** @type {HTMLElement[]} */
e4.composedPath().find((el) => el.getAttribute?.("data-role-tooltip"))
);
if (!triggerElement) {
return null;
}
return triggerElement;
}
function findPopoverElementFromTriggerElement(triggerElement) {
const rootNode = (
/** @type {Element} */
triggerElement.getRootNode()
);
const popoverTarget = triggerElement.getAttribute("data-role-tooltip");
if (!popoverTarget) {
return null;
}
const popover = rootNode.querySelector(`#${popoverTarget}`);
if (!popover) {
return null;
}
return popover;
}
function patchPopoverTriggerClick(e4) {
const triggerElement = findTriggerElementFromEvent(e4);
if (!triggerElement) return;
const popoverElement = findPopoverElementFromTriggerElement(triggerElement);
if (!popoverElement) return;
const roleToggleEvent = new RoleTooltipToggleEvent({
triggerElement,
triggerEvent: e4
});
popoverElement.dispatchEvent(roleToggleEvent);
}
var RoleTooltip = class extends AnchoredRegionMixin(BaseElement) {
static get properties() {
return {
...AnchoredRegionProperties(),
role: { reflect: true },
__triggerSource: { attribute: false, state: true }
};
}
/** @returns {string} */
static get baseName() {
return "role-tooltip";
}
static get styles() {
return [
hostStyles,
i2`
@media screen and (prefers-color-scheme: dark) {
:host {
--border-color: CanvasText;
}
}
@media screen and not (prefers-color-scheme: dark) {
:host {
--border-color: transparent;
}
}
:host {
--background: #222;
--border-color: #222;
--border-width: 2px;
--arrow-size: 8px;
color: white;
margin: 0;
border: none;
background: transparent;
display: inline-block;
}
:host([active]) [part~="anchored-region"]::part(popover) {
opacity: 1;
transform: scale(1.0);
}
:host([active][trigger-source="hover"]) [part~="anchored-region"]::part(popover) {
transition:
opacity var(--transition-speed, 200ms) var(--transition-timing, ease-in-out) var(--transition-delay, 100ms),
transform var(--transition-speed, 200ms) var(--transition-timing, ease-in-out) var(--transition-delay, 100ms);
}
[part~="anchored-region"]::part(popover) {
opacity: 0;
transform: scale(0.8);
padding: 0.2em 0.4em;
border-radius: 4px;
}
`
];
}
constructor() {
super();
this.role = "tooltip";
this.active = false;
this.anchor = null;
this.arrow = true;
this.distance = 10;
this.__triggerSource = null;
this.__eventAbortController = new AbortController();
this.addEventListener("role-tooltip-toggle", this.eventHandler.get(this.handlePopoverTriggerEvent));
this.addEventListener("role-reposition", this.eventHandler.get(this.handleReposition));
document.addEventListener("click", patchPopoverTriggerClick);
this.__activeElements = [];
}
/**
* @param {RoleTooltipToggleEvent} e
*/
handlePopoverTriggerEvent(e4) {
this.active ? this.hide("click") : this.show(e4.triggerElement, "click");
}
handleReposition() {
const anchoredRegion = this.anchoredRegion;
if (!anchoredRegion) {
return;
}
const popoverElement = anchoredRegion.popoverElement;
if (!popoverElement) {
return;
}
this.currentPlacement = this.anchoredRegion.currentPlacement;
}
get anchoredRegion() {
return (
/** @type {RoleAnchoredRegion | null} */
this.shadowRoot?.querySelector("[part~='anchored-region']") || null
);
}
connectedCallback() {
super.connectedCallback();
const { signal } = this.__eventAbortController;
const rootNode = (
/** @type {Document | ShadowRoot} */
this.getRootNode()
);
document.addEventListener("focusout", this.eventHandler.get(this.handleHide), { signal });
rootNode.addEventListener("pointerover", this.eventHandler.get(this.handleShow), { passive: true, signal });
rootNode.addEventListener("focusin", this.eventHandler.get(this.handleFocusChange), { passive: true, signal });
rootNode.addEventListener("focusout", this.eventHandler.get(this.handleFocusChange), { passive: true, signal });
document.addEventListener("focusin", this.eventHandler.get(this.handleFocusChange), { passive: true, signal });
document.addEventListener("focusout", this.eventHandler.get(this.handleFocusChange), { passive: true, signal });
document.addEventListener("keydown", this.eventHandler.get(this.handleKeyDown), { passive: true, signal });
}
disconnectedCallback() {
super.disconnectedCallback();
this.__eventAbortController?.abort();
}
/**
* @param {KeyboardEvent} e
*/
handleKeyDown(e4) {
if (e4.key === "Escape") {
this.hide("focus");
return;
}
if (e4.key === "Tab") {
this.handleFocusChange();
}
}
/**
* This is a hack. Unfortunately, there's no reliable way to get the active elements from just "focusin" / "focusout"
*/
handleFocusChange() {
this.__activeElements = [];
const addActiveElements = (activeElement) => {
this.__activeElements.push(activeElement);
const nextActiveElement = activeElement?.shadowRoot?.activeElement;
if (nextActiveElement) {
addActiveElements(nextActiveElement);
}
};
const rootNode = document.activeElement;
if (!rootNode) {
this.hide("focus");
return;
}
addActiveElements(rootNode);
const focusedElement = this.__activeElements.find((el) => {
return el.getAttribute?.("data-role-tooltip") === this.id;
});
if (focusedElement) {
this.anchor = focusedElement;
this.active = true;
this.__triggerSource = "focus";
return;
}
this.hide("focus");
}
render() {
return x`
<role-anchored-region
part="anchored-region"
exportparts="
popover,
popover--active,
popover--fixed,
popover--has-arrow,
arrow,
hover-bridge,
hover-bridge--visible
"
.anchor=${this.anchor}
?active=${this.active}
.anchoredPopoverType=${this.anchoredPopoverType}
.placement=${this.placement}
.strategy=${this.strategy}
.distance=${this.distance}
.skidding=${this.skidding}
.arrow=${this.arrow}
.arrowPlacement=${this.arrowPlacement}
.arrowPadding=${this.arrowPadding}
.flip=${this.flip}
.flipFallbackPlacements=${this.flipFallbackPlacements}
.flipFallbackStrategy=${this.flipFallbackStrategy}
.flipBoundary=${this.flipBoundary}
.flipPadding=${this.flipPadding}
.shift=${this.shift}
.shiftBoundary=${this.shiftBoundary}
.shiftPadding=${this.shiftPadding}
.autoSize=${this.autoSize}
.sync=${this.sync}
.autoSizeBoundary=${this.autoSizeBoundary}
.autoSizePadding=${this.autoSizePadding}
.hoverBridge=${this.hoverBridge}
class="${this.active ? "" : "visually-hidden"}"
>
<slot></slot>
</role-anchored-region>
`;
}
/**
* Used to show from event listeners.
* @param {Event} event
*/
handleShow(event) {
const triggerSource = event.type.startsWith("pointer") ? "hover" : "focus";
const triggerElement = this.findTriggerForTooltip(event);
if (!triggerElement) return;
this.show(triggerElement, triggerSource);
}
/**
* @param {Element} triggerElement
* @param {RoleTooltip["__triggerSource"]} triggerSource
* @returns {void}
*/
show(triggerElement, triggerSource = null) {
if (!triggerSource) {
triggerSource = null;
}
if (this.__triggerSource !== "focus") {
this.__triggerSource = triggerSource;
}
this.anchor = triggerElement;
this.active = true;
}
/**
* @param {Event} e
*/
findTriggerForTooltip(e4) {
const target = (
/** @type {Element | null} */
e4.target
);
if (!target) {
return null;
}
const popoverTriggerElement = target.closest("[data-role-tooltip]");
if (!popoverTriggerElement) {
return null;
}
const popoverTriggerAttribute = popoverTriggerElement.getAttribute?.("data-role-tooltip");
if (!popoverTriggerAttribute) {
return null;
}
if (popoverTriggerAttribute !== this.id) {
return null;
}
return popoverTriggerElement;
}
/**
* @param {import("lit").PropertyValues<this>} changedProperties
*/
willUpdate(changedProperties) {
if (changedProperties.has("active")) {
const rootNode = (
/** @type {Document | ShadowRoot} */
this.getRootNode()
);
const { signal } = this.__eventAbortController;
if (this.active) {
rootNode.addEventListener("pointermove", this.eventHandler.get(this.handleHide), { signal });
document.addEventListener("pointermove", this.eventHandler.get(this.handleHide), { signal });
if (this.anchor instanceof Element) {
const ids = this.anchor?.getAttribute("aria-describedby") || "";
if (!ids) {
this.anchor?.setAttribute("aria-describedby", this.id);
}
if (!ids.split(/\s+/).includes(this.id)) {
this.anchor?.setAttribute("aria-describedby", ids + " " + this.id);
}
}
} else {
rootNode.removeEventListener("pointermove", this.eventHandler.get(this.handleHide));
document.removeEventListener("pointermove", this.eventHandler.get(this.handleHide));
}
}
super.willUpdate(changedProperties);
}
/**
* @param {Event} event
* @returns {void}
*/
handleHide(event) {
const composedPath = event.composedPath();
if (composedPath.includes(this) || this.anchor instanceof HTMLElement && composedPath.includes(this.anchor)) {
return;
}
let triggerSource = event.type.startsWith("pointer") ? "hover" : "focus";
this.hide(triggerSource);
}
/**
* @param {null | RoleTooltip["__triggerSource"]} [triggerSource]
* @returns {void}
*/
hide(triggerSource) {
if (!triggerSource) {
triggerSource = null;
}
if (this.active && this.__triggerSource === "focus" && triggerSource === "hover") {
return;
}
this.__triggerSource = null;
this.active = false;
}
};
__publicField(RoleTooltip, "dependencies", {
"role-anchored-region": RoleAnchoredRegion
});
// src/internal/string-map.ts
function stringMap2(obj) {
let string = "";
for (const [key, value] of Object.entries(obj)) {
if (value) {
string += `${key} `;
}
}
return string;
}
// src/internal/is-exact-node-active.ts
function isExactNodeActive(state, typeOrName, attributes = {}) {
const { from, to, empty } = state.selection;
const type = typeOrName ? getNodeType(typeOrName, state.schema) : null;
const nodeRanges = [];
state.doc.nodesBetween(from, to, (node, pos) => {
if (node.isText) {
return;
}
const relativeFrom = Math.max(from, pos);
const relativeTo = Math.min(to, pos + node.nodeSize);
nodeRanges.push({
node,
from: relativeFrom,
to: relativeTo
});
});
const selectionRange = to - from;
const matchedNodeRanges = nodeRanges.slice(-3).filter((nodeRange) => {
if (!type) {
return true;
}
return type.name === nodeRange.node.type.name;
}).filter(
(nodeRange) => objectIncludes(nodeRange.node.attrs, attributes, { strict: false })
);
if (empty) {
return !!matchedNodeRanges.length;
}
const range = matchedNodeRanges.reduce(
(sum, nodeRange) => sum + nodeRange.to - nodeRange.from,
0
);
return range >= selectionRange;
}
// src/exports/elements/tip-tap-editor.ts
function findElement(editor) {
if (!editor) {
return null;
}
const state = editor.state;
const { selection } = state;
const view = editor.view;
if (view.composing) {
return null;
}
const { ranges } = selection;
const from = Math.min(...ranges.map((range) => range.$from.pos));
const to = Math.max(...ranges.map((range) => range.$to.pos));
let clientRect = null;
if (isNodeSelection(state.selection)) {
const node = findNodeViewAnchor?.({
editor,
view,
from
}) || view.nodeDOM(from);
if (node) {
node.scrollIntoView({ block: "nearest" });
clientRect = () => {
const rect = node.getBoundingClientRect();
return rect;
};
}
} else {
const toNode = view.domAtPos(to).node;
if (toNode instanceof HTMLElement) {
toNode.scrollIntoView({ block: "nearest" });
}
clientRect = () => {
const rect = posToDOMRect(view, from, to);
rect.x = rect.x - rect.width / 2;
return rect;
};
}
return clientRect;
}
var TipTapEditor = class extends TipTapEditorBase {
constructor() {
super();
/**
* Whether or not to enable the alt text editor.
*/
this.altTextEditor = false;
/**
* The heading level to use for the heading button
*/
this.defaultHeadingLevel = 1;
/**
* Translations for various aspects of the editor.
*/
this.translations = translations;
/**
* The <input> for inserting links
*/
this.linkInputRef = e2();
/**
* The dialog that contains the link input + link / unlink buttons
*/
this.linkDialogExpanded = false;
this.__invalidLink__ = false;
/** Closes the dialog for link previews */
this.handleKeyboardDialogToggle = (e4) => {
let { key, metaKey, ctrlKey } = e4;
if (key == null) return;
key = key.toLowerCase();
if (key === "escape" && this.linkDialogExpanded) {
this.closeLinkDialog();
return;
}
const shortcutModifier = isiOS ? metaKey : ctrlKey;
if (key === "k" && shortcutModifier) {
this.showLinkDialog();
}
};
/**
* @private
*/
this.__handleLinkDialogClick = (e4) => {
if (e4.defaultPrevented) {
return;
}
const linkDialogContainer = this.shadowRoot?.querySelector(
".link-dialog__container"
);
if (!linkDialogContainer) {
this.linkDialogExpanded = false;
return;
}
const composedPath = e4.composedPath();
const linkButton = this.shadowRoot?.querySelector("[name='link-button']");
if (composedPath.includes(linkDialogContainer)) {
return;
}
if (linkButton && composedPath.includes(linkButton)) {
return;
}
this.linkDialogExpanded = false;
};
this.starterKitOptions = Object.assign(this.starterKitOptions, {
rhinoPlaceholder: {
placeholder: this.translations.placeholder
},
rhinoAttachment: {
fileUploadErrorMessage: this.translations.fileUploadErrorMessage,
captionPlaceholder: this.translations.captionPlaceholder
}
});
this.addEventListener("keydown", this.handleKeyboardDialogToggle);
}
static get styles() {
return TipTapEditorBase.styles.concat([toolbarButtonStyles]);
}
static get properties() {
return Object.assign(TipTapEditorBase.properties, {
linkDialogExpanded: {
type: Boolean,
reflect: true,
attribute: "link-dialog-expanded"
},
altTextEditor: {
type: Boolean,
reflect: true,
attribute: "alt-text-editor"
},
defaultHeadingLevel: { attribute: "default-heading-level", type: Number },
linkInputRef: { state: true },
translations: { state: true },
__invalidLink__: { state: true, type: Boolean }
});
}
/**
* @override
*/
registerDependencies() {
super.registerDependencies();
[RoleToolbar, RoleTooltip, RoleAnchoredRegion].forEach((el) => el.define());
}
updated(changedProperties) {
if (changedProperties.has("altTextEditor")) {
if (this.starterKitOptions.rhinoAttachment !== false) {
this.starterKitOptions = {
...this.starterKitOptions,
rhinoAttachment: {
...this.starterKitOptions.rhinoAttachment,
altTextEditor: this.altTextEditor
}
};
}
}
if (!this.hasInitialized) {
return super.updated(changedProperties);
}
if (changedProperties.has("translations")) {
const { rhinoAttachment, rhinoPlaceholder } = this.starterKitOptions;
if (rhinoPlaceholder) {
rhinoPlaceholder.placeholder = this.translations.placeholder;
}
if (rhinoAttachment) {
rhinoAttachment.captionPlaceholder = this.translations.captionPlaceholder;
rhinoAttachment.fileUploadErrorMessage = this.translations.fileUploadErrorMessage;
}
}
return super.updated(changedProperties);
}
/**
* @override
*/
async connectedCallback() {
super.connectedCallback();
await this.updateComplete;
this.starterKitOptions = Object.assign(this.starterKitOptions, {
rhinoBubbleMenu: {
...this.starterKitOptions.rhinoBubbleMenu,
element: this.shadowRoot?.querySelector("role-anchored-region")
}
});
document.addEventListener("click", this.__handleLinkDialogClick);
}
/**
* @override
*/
async startEditor() {
await super.startEditor();
if (this.editor) {
this.editor.on("focus", this.closeLinkDialog);
}
}
disconnectedCallback() {
super.disconnectedCallback();
document.removeEventListener("click", this.__handleLinkDialogClick);
}
get icons() {
return icons_exports;
}
toggleLinkDialog() {
if (this.linkDialogExpanded) {
this.closeLinkDialog();
return;
}
this.showLinkDialog();
}
closeLinkDialog() {
this.linkDialogExpanded = false;
this.editor?.commands.focus();
}
showLinkDialog() {
const inputElement = this.linkInputRef.value;
if (inputElement != null) {
inputElement.value = this.editor?.getAttributes("link").href || "";
inputElement.setSelectionRange(0, inputElement.value.length);
}
this.__invalidLink__ = false;
this.linkDialogExpanded = true;
setTimeout(() => {
requestAnimationFrame(() => {
if (inputElement != null) {
inputElement.focus();
}
});
});
}
get linkDialog() {
return this.shadowRoot?.querySelector("#link-dialog");
}
attachFiles() {
const input = this.fileInputEl;
if (input == null) return;
input.click();
}
addLink() {
const inputElement = this.linkInputRef.value;
if (inputElement == null) return;
const href = inputElement.value;
try {
new URL(href);
inputElement.setCustomValidity("");
this.__invalidLink__ = false;
} catch (error) {
inputElement.setCustomValidity("Not a valid URL");
this.__invalidLink__ = true;
inputElement.reportValidity();
return;
}
if (!this.editor) {
return;
}
if (href) {
this.closeLinkDialog();
inputElement.value = "";
if (this.editor.state.selection.empty && !this.editor.getAttributes("link").href) {
const from = this.editor.state.selection.anchor;
this.editor.commands.insertContent(href);
const to = this.editor.state.selection.anchor;
this.editor.commands.setTextSelection({ from, to });
}
this.editor?.chain().extendMarkRange("link").setLink({ href }).run();
}
}
get fileInputEl() {
return this.shadowRoot?.getElementById(
"file-input"
);
}
async handleFileUpload() {
const input = this.fileInputEl;
if (input == null) return;
if (input.files == null) return;
const attachments = await this.handleFiles(input.files);
if (attachments.length > 0) {
this.editor?.chain().focus().setAttachment(attachments).run();
}
input.value = "";
}
get __tooltipExportParts() {
return "base:toolbar__tooltip__base, arrow:toolbar__tooltip__arrow";
}
renderBoldButton(prefix = "") {
const boldEnabled = this.starterKitOptions.bold !== false || Boolean(this.editor?.commands.toggleBold);
if (!boldEnabled) return x``;
const isDisabled = this.editor == null || !this.editor.can().toggleBold();
const isActive = Boolean(this.editor?.isActive("bold"));
let tooltip_slot_name = "bold-tooltip";
let tooltip_id = "bold";
let tooltip_parts = "toolbar__tooltip toolbar__tooltip--bold";
let icon_slot_name = "bold-icon";
if (prefix) {
tooltip_slot_name = prefix + "__" + tooltip_slot_name;
icon_slot_name = prefix + "__" + icon_slot_name;
tooltip_id = prefix + "__" + tooltip_id;
}
return x`
<slot name=${tooltip_slot_name}>
<role-tooltip
id=${tooltip_id}
part=${tooltip_parts}
exportparts=${this.__tooltipExportParts}
>
${this.translations.bold}
</role-tooltip>
</slot>
<button
class="toolbar__button rhino-toolbar-button"
type="button"
part=${stringMap2({
toolbar__button: true,
"toolbar__button--bold": true,
"toolbar__button--active": isActive,
"toolbar__button--disabled": isDisabled
})}
aria-disabled=${isDisabled}
aria-pressed=${isActive}
data-role="toolbar-item"
data-role-tooltip=${tooltip_id}
@click=${async (e4) => {
if (elementDisabled(e4.currentTarget)) return;
this.editor?.chain().focus().toggleBold().run();
}}
>
<slot name=${icon_slot_name}>${this.icons.bold}</slot>
</button>
`;
}
renderItalicButton(prefix = "") {
const italicEnabled = this.starterKitOptions.italic !== false || Boolean(this.editor?.commands.toggleItalic);
if (!italicEnabled) return x``;
const isActive = Boolean(this.editor?.isActive("italic"));
const isDisabled = this.editor == null || !this.editor.can().toggleItalic();
let tooltip_slot_name = "italics-tooltip";
let tooltip_id = "italics";
let tooltip_parts = "toolbar__tooltip toolbar__tooltip--italics";
let icon_slot_name = "italics-icon";
if (prefix) {
tooltip_slot_name = prefix + "__" + tooltip_slot_name;
icon_slot_name = prefix + "__" + icon_slot_name;
tooltip_id = prefix + "__" + tooltip_id;
}
return x`
<slot name=${tooltip_slot_name}>
<role-tooltip
id=${tooltip_id}
part=${tooltip_parts}
exportparts=${this.__tooltipExportParts}
>
${this.translations.italics}
</role-tooltip>
</slot>
<button
class="toolbar__button rhino-toolbar-button"
tabindex="-1"
type="button"
part=${stringMap2({
toolbar__button: true,
"toolbar__button--italic": true,
"toolbar__button--active": isActive,
"toolbar__button--disabled": isDisabled
})}
aria-disabled=${isDisabled}
aria-pressed=${isActive}
data-role="toolbar-item"
data-role-tooltip=${tooltip_id}
@click=${(e4) => {
if (elementDisabled(e4.currentTarget)) {
return;
}
this.editor?.chain().focus().toggleItalic().run();
}}
>
<slot name=${icon_slot_name}> ${this.icons.italics} </slot>
</button>
`;
}
renderStrikeButton(prefix = "") {
const strikeEnabled = this.starterKitOptions.rhinoStrike !== false || Boolean(this.editor?.commands.toggleStrike);
if (!strikeEnabled) return x``;
const isActive = Boolean(this.editor?.isActive("rhino-strike"));
const isDisabled = this.editor == null || !this.editor.can().toggleStrike();
let tooltip_slot_name = "strike-tooltip";
let tooltip_id = "strike";
let tooltip_parts = "toolbar__tooltip toolbar__tooltip--strike";
let icon_slot_name = "strike-icon";
if (prefix) {
tooltip_slot_name = prefix + "__" + tooltip_slot_name;
icon_slot_name = prefix + "__" + icon_slot_name;
tooltip_id = prefix + "__" + tooltip_id;
}
return x`
<slot name=${tooltip_slot_name}>
<role-tooltip
id=${tooltip_id}
part=${tooltip_parts}
exportparts=${this.__tooltipExportParts}
>
${this.translations.strike}
</role-tooltip>
</slot>
<button
class="toolbar__button rhino-toolbar-button"
type="button"
tabindex="-1"
part=${stringMap2({
toolbar__button: true,
"toolbar__button--strike": true,
"toolbar__button--active": isActive,
"toolbar__button--disabled": isDisabled
})}
aria-disabled=${isDisabled}
aria-pressed=${isActive}
data-role-tooltip=${tooltip_id}
data-role="toolbar-item"
@click=${(e4) => {
if (elementDisabled(e4.currentTarget)) {
return;
}
this.editor?.chain().focus().toggleStrike().run();
}}
>
<slot name=${icon_slot_name}>${this.icons.strike}</slot>
</button>
`;
}
renderLinkButton(prefix = "") {
const linkEnabled = this.starterKitOptions.rhinoLink !== false || Boolean(this.editor?.commands.setLink);
if (!linkEnabled) return x``;
const isActive = Boolean(
this.editor?.isActive("link") || this.linkDialogExpanded
);
const isDisabled = this.editor == null || !this.editor.can().setLink({ href: "" });
let tooltip_slot_name = "link-tooltip";
let tooltip_id = "link";
let tooltip_parts = "toolbar__tooltip toolbar__tooltip--link";
let icon_slot_name = "link-icon";
if (prefix) {
tooltip_slot_name = prefix + "__" + tooltip_slot_name;
icon_slot_name = prefix + "__" + icon_slot_name;
tooltip_id = prefix + "__" + tooltip_id;
}
return x`
<slot name=${tooltip_slot_name}>
<role-tooltip
id=${tooltip_id}
part=${tooltip_parts}
exportparts=${this.__tooltipExportParts}
>
${this.translations.link}
</role-tooltip>
</slot>
<button
class="toolbar__button rhino-toolbar-button"
type="button"
tabindex="-1"
part=${stringMap2({
toolbar__button: true,
"toolbar__button--link": true,
"toolbar__button--active": isActive,
"toolbar__button--disabled": isDisabled
})}
aria-disabled=${isDisabled}
aria-pressed=${isActive}
aria-controls="link-dialog"
data-role="toolbar-item"
data-role-tooltip=${tooltip_id}
@click=${(e4) => {
if (this.editor == null) return;
if (elementDisabled(e4.currentTarget)) return;
e4.preventDefault();
this.toggleLinkDialog();
}}
>
<slot name=${icon_slot_name}>${this.icons.link}</slot>
</button>
`;
}
renderHeadingButton(prefix = "") {
const headingEnabled = this.starterKitOptions.heading !== false || Boolean(this.editor?.commands.toggleHeading);
if (!headingEnabled) return x``;
const defaultHeadingLevel = this.defaultHeadingLevel || 1;
const isActive = Boolean(this.editor?.isActive("heading"));
const isDisabled = this.editor == null || !this.editor.can().toggleHeading({ level: defaultHeadingLevel });
let tooltip_slot_name = "heading-tooltip";
let tooltip_id = "heading";
let tooltip_parts = "toolbar__tooltip toolbar__tooltip--heading";
let icon_slot_name = "heading-icon";
if (prefix) {
icon_slot_name = prefix + "__" + icon_slot_name;
tooltip_slot_name = prefix + "__" + tooltip_slot_name;
tooltip_id = prefix + "__" + tooltip_id;
}
return x`
<slot name=${tooltip_slot_name}>
<role-tooltip
id=${tooltip_id}
part=${tooltip_parts}
exportparts=${this.__tooltipExportParts}
>
${this.translations.heading}
</role-tooltip>
</slot>
<button
class="toolbar__button rhino-toolbar-button"
type="button"
tabindex="-1"
part=${stringMap2({
toolbar__button: true,
"toolbar__button--heading": true,
"toolbar__button--active": isActive,
"toolbar__button--disabled": isDisabled
})}
aria-disabled=${isDisabled}
aria-pressed=${isActive}
data-role="toolbar-item"
data-role-tooltip=${tooltip_id}
@click=${(e4) => {
if (elementDisabled(e4.currentTarget)) {
return;
}
this.editor?.chain().focus().toggleHeading({ level: defaultHeadingLevel }).run();
}}
>
<slot name=${icon_slot_name}>${this.icons.heading}</slot>
</button>
`;
}
renderBlockquoteButton(prefix = "") {
const blockQuoteEnabled = this.starterKitOptions.blockquote !== false || Boolean(this.editor?.commands.toggleBlockquote);
if (!blockQuoteEnabled) return x``;
const isActive = Boolean(this.editor?.isActive("blockquote"));
const isDisabled = this.editor == null || !this.editor.can().toggleBlockquote();
let tooltip_slot_name = "blockquote-tooltip";
let tooltip_id = "blockquote";
let tooltip_parts = "toolbar__tooltip toolbar__tooltip--blockquote";
let icon_slot_name = "blockquote-icon";
if (prefix) {
icon_slot_name = prefix + "__" + icon_slot_name;
tooltip_slot_name = prefix + "__" + tooltip_slot_name;
tooltip_id = prefix + "__" + tooltip_id;
}
return x`
<slot name=${tooltip_slot_name}>
<role-tooltip
id=${tooltip_id}
part=${tooltip_parts}
exportparts=${this.__tooltipExportParts}
>
${this.translations.blockQuote}
</role-tooltip>
</slot>
<button
class="toolbar__button rhino-toolbar-button"
type="button"
tabindex="-1"
part=${stringMap2({
toolbar__button: true,
"toolbar__button--blockquote": true,
"toolbar__button--active": isActive,
"toolbar__button--disabled": isDisabled
})}
aria-disabled=${isDisabled}
aria-pressed=${isActive}
data-role-tooltip=${tooltip_id}
data-role="toolbar-item"
@click=${(e4) => {
if (elementDisabled(e4.currentTarget)) {
return;
}
this.editor?.chain().focus().toggleBlockquote().run();
}}
>
<slot name=${icon_slot_name}>${this.icons.blockQuote}</slot>
</button>
`;
}
renderCodeButton(prefix = "") {
const codeEnabled = this.starterKitOptions.code !== false || Boolean(this.editor?.commands.toggleCode);
if (!codeEnabled) return x``;
const isActive = Boolean(this.editor?.isActive("code"));
const isDisabled = this.editor == null || !this.editor.can().toggleCode();
let tooltip_slot_name = "code-tooltip";
let tooltip_id = "code";
let tooltip_parts = "toolbar__tooltip toolbar__tooltip--code";
let icon_slot_name = "code-icon";
if (prefix) {
icon_slot_name = prefix + "__" + icon_slot_name;
tooltip_slot_name = prefix + "__" + tooltip_slot_name;
tooltip_id = prefix + "__" + tooltip_id;
}
return x`
<slot name=${tooltip_slot_name}>
<role-tooltip
id=${tooltip_id}
part=${tooltip_parts}
exportparts=${this.__tooltipExportParts}
>
${this.translations.code}
</role-tooltip>
</slot>
<button
class="toolbar__button rhino-toolbar-button"
type="button"
tabindex="-1"
part=${stringMap2({
toolbar__button: true,
"toolbar__button--code": true,
"toolbar__button--active": isActive,
"toolbar__button--disabled": isDisabled
})}
aria-disabled=${isDisabled}
aria-pressed=${isActive}
data-role-tooltip=${tooltip_id}
data-role="toolbar-item"
@click=${(e4) => {
if (elementDisabled(e4.currentTarget)) {
return;
}
this.editor?.chain().focus().toggleCode().run();
}}
>
<slot name=${icon_slot_name}>${this.icons.code}</slot>
</button>
`;
}
renderCodeBlockButton(prefix = "") {
const codeBlockEnabled = this.starterKitOptions.codeBlock !== false || Boolean(this.editor?.commands.toggleCodeBlock);
if (!codeBlockEnabled) return x``;
const isActive = Boolean(this.editor?.isActive("codeBlock"));
const isDisabled = this.editor == null || !this.editor.can().toggleCodeBlock();
let tooltip_slot_name = "code-block-tooltip";
let tooltip_id = "code-block";
let tooltip_parts = "toolbar__tooltip toolbar__tooltip--code-block";
let icon_slot_name = "code-block-icon";
if (prefix) {
icon_slot_name = prefix + "__" + icon_slot_name;
tooltip_slot_name = prefix + "__" + tooltip_slot_name;
tooltip_id = prefix + "__" + tooltip_id;
}
return x`
<slot name=${tooltip_slot_name}>
<role-tooltip
id=${tooltip_id}
part=${tooltip_parts}
exportparts=${this.__tooltipExportParts}
>
${this.translations.codeBlock}
</role-tooltip>
</slot>
<button
class="toolbar__button rhino-toolbar-button"
type="button"
tabindex="-1"
part=${stringMap2({
toolbar__button: true,
"toolbar__button--code-block": true,
"toolbar__button--active": isActive,
"toolbar__button--disabled": isDisabled
})}
aria-disabled=${isDisabled}
aria-pressed=${isActive}
data-role-tooltip=${tooltip_id}
data-role="toolbar-item"
@click=${(e4) => {
if (elementDisabled(e4.currentTarget)) {
return;
}
this.editor?.chain().focus().toggleCodeBlock().run();
}}
>
<slot name=${icon_slot_name}>${this.icons.codeBlock}</slot>
</button>
`;
}
renderBulletListButton(prefix = "") {
const bulletListEnabled = this.starterKitOptions.bulletList !== false || Boolean(this.editor?.commands.toggleBulletList);
if (!bulletListEnabled) return x``;
const isDisabled = this.editor == null || !(this.editor.can().toggleOrderedList?.() || this.editor.can().toggleBulletList());
const isActive = Boolean(
this.editor != null && isExactNodeActive(this.editor.state, "bulletList")
);
let tooltip_slot_name = "bullet-list-tooltip";
let tooltip_id = "bullet-list";
let tooltip_parts = "toolbar__tooltip toolbar__tooltip--bullet-list";
let icon_slot_name = "bullet-list-icon";
if (prefix) {
icon_slot_name = prefix + "__" + icon_slot_name;
tooltip_slot_name = prefix + "__" + tooltip_slot_name;
tooltip_id = prefix + "__" + tooltip_id;
}
return x`
<slot name=${tooltip_slot_name}>
<role-tooltip
id=${tooltip_id}
part=${tooltip_parts}
exportparts=${this.__tooltipExportParts}
>
${this.translations.bulletList}
</role-tooltip>
</slot>
<button
class="toolbar__button rhino-toolbar-button"
type="button"
tabindex="-1"
part=${stringMap2({
toolbar__button: true,
"toolbar__button--bullet-list": true,
"toolbar__button--active": isActive,
"toolbar__button--disabled": isDisabled
})}
aria-disabled=${isDisabled}
aria-pressed=${isActive}
data-role-tooltip=${tooltip_id}
data-role="toolbar-item"
@click=${(e4) => {
if (elementDisabled(e4.currentTarget)) {
return;
}
this.editor?.chain().focus().toggleBulletList().run();
}}
>
<slot name=${icon_slot_name}>${this.icons.bulletList}</slot>
</button>
`;
}
renderOrderedListButton(prefix = "") {
const orderedListEnabled = this.starterKitOptions.orderedList !== false || Boolean(this.editor?.commands.toggleOrderedList);
if (!orderedListEnabled) return x``;
const isDisabled = this.editor == null || !(this.editor.can().toggleOrderedList() || this.editor.can().toggleBulletList?.());
const isActive = Boolean(
this.editor != null && isExactNodeActive(this.editor.state, "orderedList")
);
let tooltip_slot_name = "ordered-list-tooltip";
let tooltip_id = "ordered-list";
let tooltip_parts = "toolbar__tooltip toolbar__tooltip--ordered-list";
let icon_slot_name = "ordered-list-icon";
if (prefix) {
icon_slot_name = prefix + "__" + icon_slot_name;
tooltip_slot_name = prefix + "__" + tooltip_slot_name;
tooltip_id = prefix + "__" + tooltip_id;
}
return x`
<slot name=${tooltip_slot_name}>
<role-tooltip
id=${tooltip_id}
part=${tooltip_parts}
exportparts=${this.__tooltipExportParts}
>
${this.translations.orderedList}
</role-tooltip>
</slot>
<button
class="toolbar__button rhino-toolbar-button"
type="button"
tabindex="-1"
part=${stringMap2({
toolbar__button: true,
"toolbar__button--ordered-list": true,
"toolbar__button--active": isActive,
"toolbar__button--disabled": isDisabled
})}
aria-disabled=${isDisabled}
aria-pressed=${isActive}
data-role-tooltip=${tooltip_id}
data-role="toolbar-item"
@click=${(e4) => {
if (elementDisabled(e4.currentTarget)) {
return;
}
this.editor?.chain().focus().toggleOrderedList().run();
}}
>
<slot name=${icon_slot_name}>${this.icons.orderedList}</slot>
</button>
`;
}
renderAttachmentButton(prefix = "") {
const attachmentEnabled = this.starterKitOptions.rhinoAttachment !== false || Boolean(this.editor?.commands.setAttachment);
if (!attachmentEnabled) return x``;
const isDisabled = this.editor == null;
let tooltip_slot_name = "attach-files-tooltip";
let tooltip_id = "attach-files";
let tooltip_parts = "toolbar__tooltip toolbar__tooltip--attach-files";
let icon_slot_name = "attach-files-icon";
let file_input_id = "file-input";
if (prefix) {
icon_slot_name = prefix + "__" + icon_slot_name;
tooltip_slot_name = prefix + "__" + tooltip_slot_name;
tooltip_id = prefix + "__" + tooltip_id;
file_input_id = prefix + "__" + file_input_id;
}
return x`
<slot name=${tooltip_slot_name}>
<role-tooltip
id=${tooltip_id}
part=${tooltip_parts}
exportparts=${this.__tooltipExportParts}
>
${this.translations.attachFiles}
</role-tooltip>
</slot>
<button
class="toolbar__button rhino-toolbar-button"
tabindex="-1"
type="button"
part=${stringMap2({
toolbar__button: true,
"toolbar__button--attach-files": true,
"toolbar__button--disabled": isDisabled
})}
aria-disabled=${isDisabled}
data-role-tooltip=${tooltip_id}
data-role="toolbar-item"
@click=${this.attachFiles}
>
<slot name=${icon_slot_name}>${this.icons.attachFiles}</slot>
<!-- @TODO: Write documentation. Hookup onchange to the slotted elements? -->
<slot name="attach-files-input">
<input
id=${file_input_id}
type="file"
hidden
multiple
accept=${this.accept || "*"}
@change=${this.handleFileUpload}
/>
</slot>
</button>
`;
}
renderUndoButton(prefix = "") {
const undoEnabled = this.starterKitOptions.undoRedo !== false || Boolean(this.editor?.commands.undo);
if (!undoEnabled) return x``;
const isDisabled = this.editor == null || !this.editor.can().undo();
let tooltip_slot_name = "undo-tooltip";
let tooltip_id = "undo";
let tooltip_parts = "toolbar__tooltip toolbar__tooltip--undo";
let icon_slot_name = "undo-icon";
if (prefix) {
icon_slot_name = prefix + "__" + icon_slot_name;
tooltip_slot_name = prefix + "__" + tooltip_slot_name;
tooltip_id = prefix + "__" + tooltip_id;
}
return x`
<slot name=${tooltip_slot_name}>
<role-tooltip
id=${tooltip_id}
part=${tooltip_parts}
exportparts=${this.__tooltipExportParts}
>
${this.translations.undo}
</role-tooltip>
</slot>
<button
class="toolbar__button rhino-toolbar-button"
type="button"
tabindex="-1"
part=${stringMap2({
toolbar__button: true,
"toolbar__button--undo": true,
"toolbar__button--disabled": isDisabled
})}
aria-disabled=${isDisabled}
data-role-tooltip=${tooltip_id}
data-role="toolbar-item"
@click=${(e4) => {
if (elementDisabled(e4.currentTarget)) {
return;
}
this.editor?.chain().focus().undo().run();
}}
>
<slot name=${icon_slot_name}>${this.icons.undo}</slot>
</button>
`;
}
renderDecreaseIndentation(prefix = "") {
const decreaseIndentationEnabled = this.starterKitOptions.decreaseIndentation !== false;
if (!decreaseIndentationEnabled) return x``;
const isDisabled = this.editor == null || !this.editor.can().liftListItem("listItem");
let tooltip_slot_name = "decrease-indentation-tooltip";
let tooltip_id = "decrease-indentation";
let tooltip_parts = "toolbar__tooltip toolbar__tooltip--decrease-indentation";
let icon_slot_name = "decrease-indentation-icon";
if (prefix) {
icon_slot_name = prefix + "__" + icon_slot_name;
tooltip_slot_name = prefix + "__" + tooltip_slot_name;
tooltip_id = prefix + "__" + tooltip_id;
}
return x`
<slot name=${tooltip_slot_name}>
<role-tooltip
id=${tooltip_id}
part=${tooltip_parts}
exportparts=${this.__tooltipExportParts}
>
${this.translations.decreaseIndentation}
</role-tooltip>
</slot>
<button
class="toolbar__button rhino-toolbar-button"
type="button"
tabindex="-1"
part=${stringMap2({
toolbar__button: true,
"toolbar__button--decrease-indentation": true,
"toolbar__button--disabled": isDisabled
})}
aria-disabled=${isDisabled}
data-role-tooltip=${tooltip_id}
data-role="toolbar-item"
@click=${(e4) => {
if (elementDisabled(e4.currentTarget)) {
return;
}
this.editor?.chain().focus().liftListItem("listItem").run();
}}
>
<slot name=${icon_slot_name}> ${this.icons.decreaseIndentation} </slot>
</button>
`;
}
renderIncreaseIndentation(prefix = "") {
const increaseIndentationEnabled = this.starterKitOptions.increaseIndentation !== false;
if (!increaseIndentationEnabled) return x``;
const isDisabled = this.editor == null || !this.editor.can().sinkListItem("listItem");
let tooltip_slot_name = "increase-indentation-tooltip";
let tooltip_id = "increase-indentation";
let tooltip_parts = "toolbar__tooltip toolbar__tooltip--increase-indentation";
let icon_slot_name = "increase-indentation-icon";
if (prefix) {
icon_slot_name = prefix + "__" + icon_slot_name;
tooltip_slot_name = prefix + "__" + tooltip_slot_name;
tooltip_id = prefix + "__" + tooltip_id;
}
return x`
<slot name=${tooltip_slot_name}>
<role-tooltip
id=${tooltip_id}
part=${tooltip_parts}
exportparts=${this.__tooltipExportParts}
>
${this.translations.increaseIndentation}
</role-tooltip>
</slot>
<button
class="toolbar__button rhino-toolbar-button"
type="button"
tabindex="-1"
part=${stringMap2({
toolbar__button: true,
"toolbar__button--increase-indentation": true,
"toolbar__button--disabled": isDisabled
})}
aria-disabled=${isDisabled}
data-role-tooltip=${tooltip_id}
data-role="toolbar-item"
@click=${(e4) => {
if (elementDisabled(e4.currentTarget)) {
return;
}
this.editor?.chain().focus().sinkListItem("listItem").run();
}}
>
<slot name=${icon_slot_name}> ${this.icons.increaseIndentation} </slot>
</button>
`;
}
renderRedoButton(prefix = "") {
const redoEnabled = this.starterKitOptions.undoRedo !== false || Boolean(this.editor?.commands.redo);
if (!redoEnabled) return x``;
const isDisabled = this.editor == null || !this.editor.can().redo?.();
let tooltip_slot_name = "redo-indentation-tooltip";
let tooltip_id = "redo-indentation";
let tooltip_parts = "toolbar__tooltip toolbar__tooltip--redo-indentation";
let icon_slot_name = "redo-indentation-icon";
if (prefix) {
icon_slot_name = prefix + "__" + icon_slot_name;
tooltip_slot_name = prefix + "__" + tooltip_slot_name;
tooltip_id = prefix + "__" + tooltip_id;
}
return x`
<slot name=${tooltip_slot_name}>
<role-tooltip
id=${tooltip_id}
part=${tooltip_parts}
exportparts=${this.__tooltipExportParts}
>
${this.translations.redo}
</role-tooltip>
</slot>
<button
class="toolbar__button rhino-toolbar-button"
tabindex="-1"
type="button"
part=${stringMap2({
toolbar__button: true,
"toolbar__button--redo": true,
"toolbar__button--disabled": isDisabled
})}
aria-disabled=${isDisabled}
data-role-tooltip=${tooltip_id}
data-role="toolbar-item"
@click=${(e4) => {
if (elementDisabled(e4.currentTarget)) {
return;
}
this.editor?.chain().focus().redo().run();
}}
>
<slot name=${icon_slot_name}>${this.icons.redo}</slot>
</button>
`;
}
renderToolbarStart() {
return x``;
}
renderToolbarEnd() {
return x``;
}
renderToolbar() {
if (this.readonly) return x``;
return x`
<slot name="toolbar">
<role-toolbar
part="toolbar main__toolbar"
role="toolbar"
exportparts="
base:toolbar__base,
base:main__toolbar__base
"
>
<slot name="toolbar-start">${this.renderToolbarStart()}</slot>
<!-- Bold -->
<slot name="before-bold-button"></slot>
<slot name="bold-button">${this.renderBoldButton()}</slot>
<slot name="after-bold-button"></slot>
<!-- Italic -->
<slot name="before-italic-button"></slot>
<slot name="italic-button">${this.renderItalicButton()}</slot>
<slot name="after-italic-button"></slot>
<!-- Strike -->
<slot name="before-strike-button"></slot>
<slot name="strike-button">${this.renderStrikeButton()}</slot>
<slot name="after-strike-button"></slot>
<!-- Code -->
<slot name="before-code-button"></slot>
<slot name="code-button">${this.renderCodeButton()}</slot>
<slot name="after-code-button"></slot>
<!-- Link -->
<slot name="before-link-button"></slot>
<slot name="link-button">${this.renderLinkButton()}</slot>
<slot name="after-link-button"></slot>
<!-- Heading -->
<slot name="before-heading-button"></slot>
<slot name="heading-button">${this.renderHeadingButton()}</slot>
<slot name="after-heading-button"></slot>
<!-- Blockquote -->
<slot name="before-blockquote-button"></slot>
<slot name="blockquote-button">${this.renderBlockquoteButton()}</slot>
<slot name="after-blockquote-button"></slot>
<!-- Code block -->
<slot name="before-code-block-button"></slot>
<slot name="code-block-button">${this.renderCodeBlockButton()}</slot>
<slot name="after-code-block-button"></slot>
<!-- Bullet List -->
<slot name="before-bullet-list-button"></slot>
<slot name="bullet-list-button"
>${this.renderBulletListButton()}</slot
>
<slot name="after-bullet-list-button"></slot>
<!-- Ordered list -->
<slot name="before-ordered-list-button"></slot>
<slot name="ordered-list-button">
${this.renderOrderedListButton()}
</slot>
<slot name="after-ordered-list-button"></slot>
<slot name="before-decrease-indentation-button"></slot>
<slot name="decrease-indentation-button"
>${this.renderDecreaseIndentation()}</slot
>
<slot name="after-decrease-indentation-button"></slot>
<slot name="before-increase-indentation-button"></slot>
<slot name="increase-indentation-button"
>${this.renderIncreaseIndentation()}</slot
>
<slot name="after-increase-indentation-button"></slot>
<!-- Attachments -->
<slot name="before-attach-files-button"></slot>
<slot name="attach-files-button"
>${this.renderAttachmentButton()}</slot
>
<slot name="after-attach-files-button"></slot>
<!-- Undo -->
<slot name="before-undo-button"></slot>
<!-- @ts-expect-error -->
<slot name="undo-button"> ${this.renderUndoButton()} </slot>
<slot name="after-undo-button"></slot>
<!-- Redo -->
<slot name="before-redo-button"></slot>
<slot name="redo-button"> ${this.renderRedoButton()} </slot>
<slot name="after-redo-button"></slot>
<slot name="toolbar-end">${this.renderToolbarEnd()}</slot>
</role-toolbar>
</slot>
${this.renderBubbleMenuToolbar()} ${this.renderLinkDialogAnchoredRegion()}
`;
}
renderLinkDialogAnchoredRegion() {
const clientRect = this.linkDialogExpanded ? findElement(this.editor) : null;
return x`
<role-anchored-region
part="link-bubble-menu__anchored-region"
exportparts="
popover-base:link-bubble-menu__popover-base,
hover-bridge:link-bubble-menu__hover-bridge,
hover-bridge--visible:link-bubble-menu__hover-bridge--visible,
popover:link-bubble-menu__popover,
popover--active:link-bubble-menu__popover--active,
popover--fixed:link-bubble-menu__popover--fixed,
popover--has-arrow:link-bubble-menu__popover--has-arrow,
arrow:link-bubble-menu__arrow
"
anchored-popover-type="manual"
distance="4"
.active=${this.linkDialogExpanded}
.shiftBoundary=${this.querySelector(".ProseMirror") || this}
.flipBoundary=${this.querySelector(".ProseMirror") || this}
.anchor=${typeof clientRect === "function" ? { getBoundingClientRect: clientRect } : null}
>
<slot name="link-bubble-menu-dialog"> ${this.renderLinkDialog()} </slot>
</role-anchored-region>
`;
}
/** @TODO: Lets think of a more friendly way to render dialogs for users to extend. */
renderLinkDialog() {
if (this.readonly) {
return x``;
}
return x` <div
id="link-dialog"
part=${stringMap2({
"link-dialog": true,
"link-dialog--expanded": this.linkDialogExpanded
})}
>
<div class="link-dialog__container" part="link-dialog__container">
<input
id="link-dialog__input"
class=${`link-dialog__input ${this.__invalidLink__ ? "link-validate" : ""}`}
part=${`link-dialog__input ${this.__invalidLink__ ? "link-dialog__input--invalid" : ""}`}
type="text"
placeholder="Enter a URL..."
aria-label="Enter a URL"
required
type="url"
${n2(this.linkInputRef)}
@input=${() => {
const inputElement = this.linkInputRef.value;
if (inputElement == null) return;
inputElement.setCustomValidity("");
this.__invalidLink__ = false;
}}
@blur=${() => {
const inputElement = this.linkInputRef.value;
if (inputElement == null) return;
this.__invalidLink__ = false;
}}
@keydown=${(e4) => {
if (e4.key?.toLowerCase() === "enter") {
e4.preventDefault();
this.addLink();
}
}}
/>
<div class="link-dialog__buttons" part="link-dialog__buttons">
<button
class="rhino-toolbar-button link-dialog__button"
part="link-dialog__button link-dialog__button--link"
@click=${this.addLink}
>
${this.translations.linkDialogLink}
</button>
<button
class="rhino-toolbar-button link-dialog__button"
part="link-dialog__button link-dialog__button--unlink"
@click=${() => {
this.linkDialogExpanded = false;
this.editor?.chain().focus().extendMarkRange("link").unsetLink().run();
}}
>
${this.translations.linkDialogUnlink}
</button>
</div>
</div>
</div>`;
}
/**
* Returns the bubble menu toolbar from the shadow root.
*/
get defaultBubbleMenuToolbar() {
return this.shadowRoot?.querySelector(
"[part~='bubble-menu__toolbar']"
);
}
renderBubbleMenuToolbar() {
return x`
<role-anchored-region
part="bubble-menu__anchored-region"
exportparts="
popover-base:bubble-menu__popover-base,
hover-bridge:bubble-menu__hover-bridge,
hover-bridge--visible:bubble-menu__hover-bridge--visible,
popover:bubble-menu__popover,
popover--active:bubble-menu__popover--active,
popover--fixed:bubble-menu__popover--fixed,
popover--has-arrow:bubble-menu__popover--has-arrow,
arrow:bubble-menu__arrow
"
@rhino-bubble-menu-show=${(e4) => {
if (e4.defaultPrevented) {
return;
}
const anchoredRegion = e4.currentTarget;
anchoredRegion.anchor = { getBoundingClientRect: e4.clientRect };
anchoredRegion.shiftBoundary = this.querySelector(".ProseMirror") || this;
anchoredRegion.flipBoundary = this.querySelector(".ProseMirror") || this;
anchoredRegion.active = true;
}}
@rhino-bubble-menu-hide=${(e4) => {
if (e4.defaultPrevented) {
return;
}
const anchoredRegion = e4.currentTarget;
anchoredRegion.anchor = null;
anchoredRegion.active = false;
}}
anchored-popover-type="manual"
distance="4"
>
<slot name="bubble-menu-toolbar">
<role-toolbar
part="toolbar bubble-menu__toolbar"
role="toolbar"
exportparts="
base:toolbar__base,
base:bubble-menu__toolbar__base
"
>
<slot name="before-bubble-menu-toolbar-items"></slot>
<slot name="bubble-menu-toolbar-items">
${this.renderBoldButton("bubble-menu")}
${this.renderItalicButton("bubble-menu")}
${this.renderStrikeButton("bubble-menu")}
${this.renderCodeButton("bubble-menu")}
${this.renderLinkButton("bubble-menu")}
</slot>
<slot name="after-bubble-menu-toolbar-items"></slot>
</role-toolbar>
</slot>
<slot name="additional-bubble-menu-toolbar"></slot>
</role-anchored-region>
`;
}
};
function elementDisabled(element) {
if (element == null) return true;
if (!("getAttribute" in element)) return true;
return element.getAttribute("aria-disabled") === "true" || element.hasAttribute("disabled");
}
export {
TipTapEditor
};
/*! Bundled license information:
lit-html/directive-helpers.js:
(**
* @license
* Copyright 2020 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*)
lit-html/async-directive.js:
(**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*)
lit-html/directives/ref.js:
(**
* @license
* Copyright 2020 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*)
lit-html/directives/class-map.js:
(**
* @license
* Copyright 2018 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*)
*/
//# sourceMappingURL=chunk-A24N63RD.js.map