summaryrefslogtreecommitdiff
path: root/node_modules/swup/src/utils
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/swup/src/utils')
-rw-r--r--node_modules/swup/src/utils/index.ts68
1 files changed, 68 insertions, 0 deletions
diff --git a/node_modules/swup/src/utils/index.ts b/node_modules/swup/src/utils/index.ts
new file mode 100644
index 00000000..2d0e77a2
--- /dev/null
+++ b/node_modules/swup/src/utils/index.ts
@@ -0,0 +1,68 @@
+/** Find an element by selector. */
+export const query = (selector: string, context: Document | Element = document) => {
+ return context.querySelector<HTMLElement>(selector);
+};
+
+/** Find a set of elements by selector. */
+export const queryAll = (
+ selector: string,
+ context: Document | Element = document
+): HTMLElement[] => {
+ return Array.from(context.querySelectorAll(selector));
+};
+
+/** Return a Promise that resolves after the next event loop. */
+export const nextTick = (): Promise<void> => {
+ return new Promise((resolve) => {
+ requestAnimationFrame(() => {
+ requestAnimationFrame(() => {
+ resolve();
+ });
+ });
+ });
+};
+
+/** Check if an object is a Promise or a Thenable */
+export function isPromise<T>(obj: unknown): obj is PromiseLike<T> {
+ return (
+ !!obj &&
+ (typeof obj === 'object' || typeof obj === 'function') &&
+ typeof (obj as Record<string, unknown>).then === 'function'
+ );
+}
+
+/** Call a function as a Promise. Resolves with the returned Promsise or immediately. */
+// eslint-disable-next-line @typescript-eslint/ban-types, @typescript-eslint/no-explicit-any
+export function runAsPromise(func: Function, args: unknown[] = []): Promise<unknown> {
+ return new Promise((resolve, reject) => {
+ const result: unknown = func(...args);
+ if (isPromise(result)) {
+ result.then(resolve, reject);
+ } else {
+ resolve(result);
+ }
+ });
+}
+
+/**
+ * Force a layout reflow, e.g. after adding classnames
+ * @see https://stackoverflow.com/a/21665117/3759615
+ */
+export function forceReflow(element?: HTMLElement): void {
+ element = element || document.body;
+ element?.getBoundingClientRect();
+}
+
+/**
+ * Read data attribute from closest element with that attribute.
+ *
+ * Returns `undefined` if no element is found or attribute is missing.
+ * Returns `true` if attribute is present without a value.
+ */
+export function getContextualAttr(
+ el: Element | undefined,
+ attr: string
+): string | boolean | undefined {
+ const target = el?.closest(`[${attr}]`);
+ return target?.hasAttribute(attr) ? target?.getAttribute(attr) || true : undefined;
+}