| // Copyright 2022 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // Like Object.values but with a stronger return type. |
| export function values<T extends {[key: string]: any}, K extends keyof T>( |
| o: T |
| ): Required<T>[K][] { |
| return Object.values(o); |
| } |
| |
| // Like Object.entries but with a stronger return type. |
| export function entries<T extends {[key: string]: any}, K extends keyof T>( |
| o: T |
| ): [keyof T, Required<T>[K]][] { |
| return Object.entries(o); |
| } |
| |
| // Wraps text to the given maximum width, preserving existing newlines. |
| export function wordWrap(text: string, width: number): string { |
| function wrap(line: string): string { |
| const words = line.split(' '); |
| let lineLength = 0; |
| const withNewlines = words.map(w => { |
| lineLength += w.length + 1; |
| if (lineLength > width) { |
| lineLength = w.length; |
| return '\n' + w; |
| } |
| return w; |
| }); |
| return withNewlines.join(' '); |
| } |
| const lines = text.split('\n'); |
| return lines.map(wrap).join('\n'); |
| } |
| |
| // A type for timeout IDs. |
| export type Timeout = ReturnType<typeof setTimeout>; |
| |
| // Wraps a promise with a timeout, in milliseconds. |
| export function withTimeout<T>( |
| ms: number, |
| errMsg: string, |
| promise: Promise<T> |
| ): Promise<T> { |
| return new Promise((resolve, reject) => { |
| const timeout = setTimeout(() => { |
| reject(new Error(errMsg)); |
| }, ms); |
| promise.then( |
| (res: T) => { |
| clearTimeout(timeout); |
| resolve(res); |
| }, |
| err => { |
| clearTimeout(timeout); |
| reject(err); |
| } |
| ); |
| }); |
| } |
| |
| // Like getElementById, but waits for up to a second for the element to appear. |
| export async function waitForElement(id: string): Promise<HTMLElement> { |
| const element = document.getElementById(id); |
| if (element != undefined) { |
| return element; |
| } |
| let observer: MutationObserver; |
| const promise = new Promise<HTMLElement>(resolve => { |
| observer = new MutationObserver(() => { |
| const element = document.getElementById(id); |
| if (element != undefined) { |
| resolve(element); |
| } |
| }); |
| observer.observe(document.body, { |
| childList: true, |
| subtree: true, |
| }); |
| }); |
| return withTimeout( |
| 1000, |
| `Timed out waiting for #${id} to appear`, |
| promise |
| ).finally(() => { |
| observer.disconnect(); |
| }); |
| } |