Tools for awaiting ready -- still can't make focus() work

This commit is contained in:
Ian Gulliver
2024-12-23 14:09:06 -08:00
parent 5e3d144d7a
commit 2082444b3b
14 changed files with 145 additions and 45 deletions

View File

@@ -1,15 +1,14 @@
export function whenLoaded(callback: () => void) {
import { waitForEvent } from "./event";
export async function awaitLoaded() {
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", callback);
} else {
callback();
await waitForEvent(document, "DOMContentLoaded");
}
}
export function addStyle(style: string) {
whenLoaded(() => {
addStyleNow(style);
});
export async function addStyle(style: string) {
await awaitLoaded();
addStyleNow(style);
}
export function addStyleNow(style: string) {
@@ -17,3 +16,14 @@ export function addStyleNow(style: string) {
sheet.replaceSync(style);
document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet];
}
export async function awaitCustomElements() {
await Promise.allSettled([
customElements.whenDefined("sl-card"),
customElements.whenDefined("sl-icon"),
customElements.whenDefined("sl-input"),
customElements.whenDefined("sl-tab"),
customElements.whenDefined("sl-tab-group"),
customElements.whenDefined("sl-tab-panel"),
]);
}

View File

@@ -1,3 +1,5 @@
import { waitForAnimationFrame } from "./event";
export class ElemWrapper {
public elem: HTMLElement;
@@ -51,4 +53,10 @@ export class ElemWrapper {
setID(id: string) {
this.elem.id = id;
}
}
async waitForShadowQuerySelector(selector: string) {
while (this.elem.shadowRoot?.querySelector(selector) === undefined) {
await waitForAnimationFrame();
}
}
}

16
ts/event.ts Normal file
View File

@@ -0,0 +1,16 @@
export function waitForEvent(target: EventTarget, eventType: string) {
return new Promise((resolve) => {
function handler(event: Event) {
target.removeEventListener(eventType, handler);
resolve(event);
}
target.addEventListener(eventType, handler);
});
}
export function waitForAnimationFrame() {
return new Promise((resolve) => {
requestAnimationFrame(resolve);
});
}

View File

@@ -1,4 +1,4 @@
import { addStyle, addStyleNow } from "./document";
import { addStyleNow, awaitLoaded } from "./document";
import { ElemWrapper } from "./elemwrapper";
import { Highlighter } from "./highlighter";
import { SLCard } from "./slcard";
@@ -67,4 +67,5 @@ addStyleNow(`
}
`);
document.addEventListener("DOMContentLoaded", main);
await awaitLoaded();
await main();

View File

@@ -1,10 +1,18 @@
import { ElemWrapper } from "./elemwrapper";
interface SLBaseElem extends HTMLElement {
updateComplete: Promise<void>;
}
export class SLElem extends ElemWrapper {
constructor(tagName: string) {
super(document.createElement(tagName));
}
public async awaitUpdate() {
await (this.elem as SLBaseElem).updateComplete;
}
public setSlot(slot: string) {
this.setAttribute("slot", slot);
}

View File

@@ -1,3 +1,4 @@
import { waitForAnimationFrame } from "./event";
import { SLElem } from "./slelem";
import { SLIcon } from "./slicon";
@@ -6,34 +7,34 @@ export class SLInput extends SLElem {
super("sl-input");
}
public addIcon(name: string, slot: "prefix" | "suffix"): SLIcon {
addIcon(name: string, slot: "prefix" | "suffix"): SLIcon {
const icon = new SLIcon(name);
icon.setSlot(slot);
this.append(icon);
return icon;
}
public addPrefixIcon(name: string): SLIcon {
addPrefixIcon(name: string): SLIcon {
return this.addIcon(name, "prefix");
}
public addSuffixIcon(name: string): SLIcon {
addSuffixIcon(name: string): SLIcon {
return this.addIcon(name, "suffix");
}
public clear() {
clear() {
(this.elem as HTMLInputElement).value = "";
}
public getValue(): string {
getValue(): string {
return (this.elem as HTMLInputElement).value;
}
public focus() {
focus() {
(this.elem as HTMLInputElement).focus();
}
public setPill() {
setPill() {
this.setAttribute("pill", "");
}
}
}