import type { LGraphNode, LGraphNodeConstructor } from "typings/litegraph.js"; import { createElement as $el, getClosestOrSelf, setAttributes } from "./utils_dom.js"; type RgthreeDialogButton = { label: string; className?: string; closes?: boolean; disabled?: boolean; callback?: (e: PointerEvent | MouseEvent) => void; }; export type RgthreeDialogOptions = { content: string | HTMLElement | HTMLElement[]; class?: string | string[]; title?: string | HTMLElement | HTMLElement[]; closeX?: boolean; closeOnEsc?: boolean; closeOnModalClick?: boolean; closeButtonLabel?: string | boolean; buttons?: RgthreeDialogButton[]; onBeforeClose?: () => Promise | boolean; }; /** * A Dialog that shows content, and closes. */ export class RgthreeDialog extends EventTarget { element: HTMLDialogElement; contentElement: HTMLDivElement; titleElement: HTMLDivElement; options: RgthreeDialogOptions; constructor(options: RgthreeDialogOptions) { super(); this.options = options; let container = $el("div.rgthree-dialog-container"); this.element = $el("dialog", { classes: ["rgthree-dialog", options.class || ""], child: container, parent: document.body, events: { click: (event: MouseEvent) => { // Close the dialog if we've clicked outside of our container. The dialog modal will // report itself as the dialog itself, so we use the inner container div (and CSS to // remove default padding from the dialog element). if ( !this.element.open || event.target === container || getClosestOrSelf(event.target, `.rgthree-dialog-container`) === container ) { return; } return this.close(); }, }, }); this.element.addEventListener("close", (event) => { this.onDialogElementClose(); }); this.titleElement = $el("div.rgthree-dialog-container-title", { parent: container, children: !options.title ? null : options.title instanceof Element || Array.isArray(options.title) ? options.title : typeof options.title === "string" ? !options.title.includes(" { button.callback?.(e); }, }, }); } if (options.closeButtonLabel !== false) { $el("button", { text: options.closeButtonLabel || "Close", className: "rgthree-button", parent: footerEl, events: { click: (e: MouseEvent) => { this.close(e); }, }, }); } } setTitle(content: string | HTMLElement | HTMLElement[]) { const title = typeof content !== "string" || content.includes(" = {}, ) { const title = (node.type || node.title || "").replace( /\s*\(rgthree\).*/, " by rgthree", ); const options = Object.assign({}, opts, { class: "-iconed -help", title, content, }); super(options); } }