mirror of
https://github.com/rio-labs/rio.git
synced 2026-01-03 03:39:44 -06:00
126 lines
3.2 KiB
TypeScript
126 lines
3.2 KiB
TypeScript
import { componentsByElement } from './componentManagement';
|
|
|
|
export class AsyncQueue<T> {
|
|
private waitingForValue: ((value: T) => void)[] = [];
|
|
private values: T[] = [];
|
|
|
|
push(value: T): void {
|
|
// If someone is waiting for a value, give it to them
|
|
let notifyFirstWaiter = this.waitingForValue.shift();
|
|
if (notifyFirstWaiter !== undefined) {
|
|
notifyFirstWaiter(value);
|
|
return;
|
|
}
|
|
|
|
// Otherwise, push it onto the stack
|
|
this.values.push(value);
|
|
}
|
|
|
|
async get(): Promise<T> {
|
|
// If a value exists in the queue, just return that
|
|
let value = this.values.shift();
|
|
if (value !== undefined) {
|
|
return value;
|
|
}
|
|
|
|
// Otherwise, create a Promise that will be resolved when a new value is
|
|
// added to the queue
|
|
let waitForValue = new Promise((resolve: (value: T) => void) => {
|
|
this.waitingForValue.push(resolve);
|
|
});
|
|
return await waitForValue;
|
|
}
|
|
}
|
|
|
|
export function commitCss(element: HTMLElement): void {
|
|
element.offsetHeight;
|
|
}
|
|
|
|
export function disableTransitions(element: HTMLElement) {
|
|
element.style.transition = 'none';
|
|
element.offsetHeight;
|
|
}
|
|
|
|
export function enableTransitions(element: HTMLElement) {
|
|
element.style.removeProperty('transition');
|
|
element.offsetHeight;
|
|
}
|
|
|
|
export function withoutTransitions(
|
|
element: HTMLElement,
|
|
func: () => void
|
|
): void {
|
|
disableTransitions(element);
|
|
|
|
func();
|
|
|
|
enableTransitions(element);
|
|
}
|
|
|
|
/// Asynchronously sleeps for the given number of seconds.
|
|
export async function sleep(durationInSeconds: number): Promise<void> {
|
|
await new Promise((resolve, reject) =>
|
|
setTimeout(resolve, durationInSeconds * 1000)
|
|
);
|
|
}
|
|
|
|
export function reprElement(element: Element): string {
|
|
let chunks = [element.tagName.toLowerCase()];
|
|
|
|
for (let attr of element.attributes) {
|
|
chunks.push(`${attr.name}=${JSON.stringify(attr.value)}`);
|
|
}
|
|
|
|
return `<${chunks.join(' ')}>`;
|
|
}
|
|
|
|
/// Returns an array containing all numbers from `start` (inclusive) to `end`
|
|
/// (exclusive).
|
|
export function range(start: number, end: number): number[] {
|
|
let result: number[] = [];
|
|
|
|
for (let ii = start; ii < end; ii++) {
|
|
result.push(ii);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/// Returns the first argument that isn't `undefined`.
|
|
export function firstDefined(...args: any[]): any {
|
|
for (let arg of args) {
|
|
if (arg !== undefined) {
|
|
return arg;
|
|
}
|
|
}
|
|
|
|
return undefined;
|
|
}
|
|
|
|
/// Copies the given text to the clipboard
|
|
export function copyToClipboard(text: string): void {
|
|
const textArea = document.createElement('textarea');
|
|
textArea.value = text;
|
|
|
|
document.body.appendChild(textArea);
|
|
textArea.select();
|
|
document.execCommand('copy');
|
|
document.body.removeChild(textArea);
|
|
}
|
|
|
|
/// Checks if there's an #url-fragment, and if so, scrolls the corresponding
|
|
/// ScrollTarget into view
|
|
export function scrollToUrlFragment(): void {
|
|
let fragment = window.location.hash.substring(1);
|
|
if (!fragment) {
|
|
return;
|
|
}
|
|
|
|
let element = document.getElementById(fragment);
|
|
if (element === null) {
|
|
return;
|
|
}
|
|
|
|
element.scrollIntoView();
|
|
}
|