import Translations from "../i18n/Translations" import Combine from "./Combine" import BaseUIElement from "../BaseUIElement" import Link from "./Link" import Img from "./Img" import { Store, UIEventSource } from "../../Logic/UIEventSource" import { UIElement } from "../UIElement" import { VariableUiElement } from "./VariableUIElement" import Lazy from "./Lazy" import Loading from "./Loading" export class SubtleButton extends UIElement { private readonly imageUrl: string | BaseUIElement private readonly message: string | BaseUIElement private readonly options: { url?: string | Store; newTab?: boolean; imgSize?: string } constructor( imageUrl: string | BaseUIElement, message: string | BaseUIElement, options: { url?: string | Store newTab?: boolean imgSize?: "h-11 w-11" | string } = undefined ) { super() this.imageUrl = imageUrl this.message = message this.options = options } protected InnerRender(): string | BaseUIElement { const classes = "block flex p-3 my-2 bg-subtle rounded-lg hover:shadow-xl hover:bg-unsubtle transition-colors transition-shadow link-no-underline" const message = Translations.W(this.message)?.SetClass( "block text-ellipsis no-images flex-shrink" ) let img const imgClasses = "block justify-center flex-none mr-4 " + (this.options?.imgSize ?? "h-11 w-11") if ((this.imageUrl ?? "") === "") { img = undefined } else if (typeof this.imageUrl === "string") { img = new Img(this.imageUrl)?.SetClass(imgClasses) } else { img = this.imageUrl?.SetClass(imgClasses) } const button = new Combine([img, message]).SetClass("flex items-center group w-full") if (this.options?.url == undefined) { this.SetClass(classes) return button } return new Link(button, this.options.url, this.options.newTab ?? false).SetClass(classes) } public OnClickWithLoading( loadingText: BaseUIElement | string, action: () => Promise ): BaseUIElement { const state = new UIEventSource<"idle" | "running">("idle") const button = this button.onClick(async () => { state.setData("running") try { await action() } catch (e) { console.error(e) } finally { state.setData("idle") } }) const loading = new Lazy(() => new Loading(loadingText)) return new VariableUiElement( state.map((st) => { if (st === "idle") { return button } return loading }) ) } }