type ColorType = "hsla"; export type VarOptions = { type: ColorType; transparency?: number; apply?: (value: string) => string; }; export type Breakpoints = { sm: boolean; md: boolean; lg: boolean; xl: boolean; xxl: boolean; }; export function useBreakpoints(): Breakpoints { const breakpoints: Breakpoints = reactive({ sm: false, md: false, lg: false, xl: false, xxl: false, }); const updateBreakpoints = () => { breakpoints.sm = window.innerWidth < 640; breakpoints.md = window.innerWidth >= 640; breakpoints.lg = window.innerWidth >= 768; breakpoints.xl = window.innerWidth >= 1024; breakpoints.xxl = window.innerWidth >= 1280; }; onMounted(() => { updateBreakpoints(); window.addEventListener("resize", updateBreakpoints); }); onUnmounted(() => { window.removeEventListener("resize", updateBreakpoints); }); return breakpoints; } class ThemeObserver { // eslint-disable-next-line no-use-before-define private static instance?: ThemeObserver; private readonly observer: MutationObserver; private fns: (() => void)[] = []; private constructor() { this.observer = new MutationObserver(mutations => { mutations.forEach(mutation => { if (mutation.attributeName === "data-theme") { this.fire(); } }); }); const html = document.querySelector("html"); if (!html) { throw new Error("No html element found"); } this.observer.observe(html, { attributes: true }); } public static getInstance() { if (!ThemeObserver.instance) { ThemeObserver.instance = new ThemeObserver(); } return ThemeObserver.instance; } private fire() { this.fns.forEach(fn => fn()); } public add(fn: () => void) { this.fns.push(fn); } public remove(fn: () => void) { this.fns = this.fns.filter(f => f !== fn); } } export function useCssVar(name: string, options?: VarOptions) { if (!options) { options = { type: "hsla", transparency: 1, apply: undefined, }; } const cssVal = ref(getComputedStyle(document.documentElement).getPropertyValue(name).trim()); const update = () => { cssVal.value = getComputedStyle(document.documentElement).getPropertyValue(name).trim(); }; ThemeObserver.getInstance().add(update); onUnmounted(() => { ThemeObserver.getInstance().remove(update); }); switch (options.type) { case "hsla": { return computed(() => { if (!document) { return ""; } let val = cssVal.value.trim().split(" ").join(", "); if (options?.transparency) { val += `, ${options.transparency}`; } return `hsla(${val})`; }); } } }