// utility methods for DOM interaction
interface HTMLElement {
on(
event: string,
handler: EventListenerOrEventListenerObject,
options?: boolean | AddEventListenerOptions
): void;
off(
event: string,
handler: EventListenerOrEventListenerObject,
options?: boolean | EventListenerOptions
): void;
$(selector: string): Element | null;
$$(selector: string): NodeListOf<Element>;
}
export const $ = (selector: string): Element | null =>
document.querySelector(selector);
export const $$ = (selector: string): NodeListOf<Element> =>
document.querySelectorAll(selector);
export const selectWithThrow = (selector: string): Element => {
const el = $(selector);
if (!el) {
throw new Error(`Element not found: ${selector}`);
}
return el;
};
HTMLElement.prototype.$ = function (
this: HTMLElement,
selector: string
): Element | null {
return this.querySelector(selector);
};
HTMLElement.prototype.$$ = function (
this: HTMLElement,
selector: string
): NodeListOf<Element> {
return this.querySelectorAll(selector);
};
export function debounce(callback: Function, delay: number) {
let timeoutId: ReturnType<Window["setTimeout"]>;
return (...args: any[]) => {
if (timeoutId) {
clearTimeout(timeoutId);
}
timeoutId = window.setTimeout(() => {
callback(...args);
}, delay);
};
}
export function createReactiveProxy<T extends Record<keyof T, V>, V>(
state: T,
onSet: (state: T) => void
) {
const singleProperty = Object.keys(state)[0] as keyof T;
const proxy = new Proxy(state, {
set(target, p, newValue, receiver) {
if (p === singleProperty) {
// @ts-ignore
target[p] = newValue as V;
onSet(target);
}
return Reflect.set(target, p, newValue, receiver);
},
});
return proxy;
}
export function createReactiveFunction<T extends CallableFunction>(
func: T,
onCall: (argsList: any[]) => void
) {
const proxy = new Proxy(func, {
apply(targetFunc, thisArg, argArray) {
onCall(argArray);
return Reflect.apply(targetFunc, thisArg, argArray);
},
});
return proxy;
}
export class ObservableStore<T extends CallableFunction> {
private observers: Set<T> = new Set();
notify(...args: any[]) {
this.observers.forEach((observer) => observer(...args));
}
notifyAndReturn(...args: any[]) {
const returnValues = Array.from(this.observers).map((observer) =>
observer(...args)
);
return returnValues;
}
addObserver(observer: T) {
this.observers.add(observer);
}
removeObserver(observer: T) {
this.observers.delete(observer);
}
}
Last active
July 8, 2024 14:34
-
-
Save aadilmallick/f63e4e081ed9fa87a3d7093dfdbca06f to your computer and use it in GitHub Desktop.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment