<:import src="base.htm" /> <:import src="button.htm" /> <:define tag="bs-toast:div" class="toast" role="alert" aria-live="assertive" aria-atomic="true" // parameters ::extra=${null} // extra classes for this instance ::title=${null} ::time=${null} ::variant=${null} ::open=${false} ::autohide=${true} ::delay=${5000} // private :_class=${['toast', variant ? `text-bg-${variant} border-0` : '', extra] .filter(s => s).join(' ')} class=${_class} data-bs-autohide=${autohide ? null : 'false'} data-bs-delay=${delay} :handle-open=${(v) => { // only while this markup is in the page: an `:if`/`:for-data` region // can take it out with `open` still true, and Bootstrap asked // to show a detached element walks into its own internals if (!$dom.isConnected) return; const toast = globalThis.bootstrap.Toast.getOrCreateInstance($dom); v ? toast.show() : toast.hide(); }} /* Bootstrap's plugins own DOM outside this element -- a backdrop, a popper, a body class -- so an element removed without a dispose() leaves it behind. `:will-detach` rather than `:will-dispose`: an `:if`/`:for-data` region takes its markup out of the page without its scope going anywhere, and the leak is the same either way */ :will-detach=${() => globalThis.bootstrap.Toast.getInstance($dom)?.dispose()} :on-hidden.bs.toast=${() => open = false} >
${title} ${time}
<:slot />
<:define tag="bs-toast-container:div" // parameters ::extra=${null} // extra classes for this instance ::placement=${'bottom-end'} // 'top-start' | 'top-end' | 'bottom-start' | 'bottom-end' | 'top-center' // private :_class=${[ 'toast-container position-fixed p-3', placement.startsWith('top') ? 'top-0' : 'bottom-0', placement.endsWith('start') ? 'start-0' : '', placement.endsWith('end') ? 'end-0' : '', placement.endsWith('center') ? 'start-50 translate-middle-x' : '', extra, ].filter(s => s).join(' ')} class=${_class} style="z-index: 1090" > <:slot />