vueless
Version:
Vue Styleless UI Component Library, powered by Tailwind CSS.
110 lines (84 loc) • 2.84 kB
text/typescript
import { onMounted, ref, watch, computed, onBeforeUnmount } from "vue";
import { isSSR } from "../utils/helper.ts";
import type { Ref } from "vue";
enum BreakpointName {
Xs = "xs",
Sm = "sm",
Md = "md",
Lg = "lg",
Xl = "xl",
"2xl" = "2xl",
}
enum BreakpointWidth {
Xs = 0,
Sm = 640,
Md = 768,
Lg = 1024,
Xl = 1280,
"2xl" = 1536,
}
type Breakpoint = `${BreakpointName}`;
const mobileDevices = ["xs", "sm"];
const portableDevices = ["xs", "sm", "md"];
export default function useBreakpoint() {
let timeout: number | undefined;
const windowWidth = ref(0);
const currentBreakpoint: Ref<Breakpoint> = ref(BreakpointName.Xs);
const isMobileBreakpoint = computed(() => {
return mobileDevices.includes(currentBreakpoint.value);
});
const isTabletBreakpoint = computed(() => {
return mobileDevices.includes(currentBreakpoint.value);
});
const isLaptopBreakpoint = computed(() => {
return currentBreakpoint.value === BreakpointName.Lg;
});
const isPortableBreakpoint = computed(() => {
return portableDevices.includes(currentBreakpoint.value);
});
// TODO: Why do we need this? Maybe we should rename it.
const elementSize = computed(() => {
return isMobileBreakpoint.value ? BreakpointName.Md : BreakpointName.Lg;
});
onMounted(() => {
if (isSSR) return;
windowWidth.value = window.innerWidth;
window.addEventListener("resize", resizeListener, { passive: true });
});
onBeforeUnmount(() => {
if (isSSR) return;
window.removeEventListener("resize", resizeListener);
});
watch(windowWidth, setBreakpoint, { immediate: true });
function resizeListener() {
if (isSSR) return;
if (timeout) {
window.cancelAnimationFrame(timeout);
}
timeout = window.requestAnimationFrame(() => {
windowWidth.value = window.innerWidth;
});
}
function setBreakpoint(newWindowWidth: number) {
if (newWindowWidth === undefined) return;
currentBreakpoint.value = "xs";
if (newWindowWidth >= BreakpointWidth.Sm && newWindowWidth < BreakpointWidth.Sm) {
currentBreakpoint.value = BreakpointName.Sm;
} else if (newWindowWidth >= BreakpointWidth.Md && newWindowWidth < BreakpointWidth.Lg) {
currentBreakpoint.value = BreakpointName.Md;
} else if (newWindowWidth >= BreakpointWidth.Lg && newWindowWidth < BreakpointWidth.Xl) {
currentBreakpoint.value = BreakpointName.Lg;
} else if (newWindowWidth >= BreakpointWidth.Xl && newWindowWidth < BreakpointWidth["2xl"]) {
currentBreakpoint.value = BreakpointName.Xl;
} else if (newWindowWidth >= BreakpointWidth["2xl"]) {
currentBreakpoint.value = BreakpointName["2xl"];
}
}
return {
isLaptopBreakpoint,
isTabletBreakpoint,
isMobileBreakpoint,
isPortableBreakpoint,
elementSize,
};
}