import { ref, toRef, onMounted, onUnmounted } from 'vue' import type { MaybeRefOrGetter } from 'vue' const THEME_ATTRIBUTE = 'data-bs-theme' /** * Tracks the Bootstrap color mode (`data-bs-theme`) of the closest themed ancestor. * * @param element - Element to resolve the color mode from; defaults to the document body. * @param defaultColorMode - Color mode to fall back on when no themed ancestor exists. * @returns An object with a reactive `colorMode` ref that stays in sync with the ancestor's theme. * @example * */ export function useColorMode( element: MaybeRefOrGetter = window?.document?.body, defaultColorMode = 'light' ) { const elementRef = toRef(element) const colorMode = ref(defaultColorMode) const findClosestThemeElement = () => elementRef.value?.closest(`[${THEME_ATTRIBUTE}]`) const updateColorMode = () => { colorMode.value = findClosestThemeElement()?.getAttribute(THEME_ATTRIBUTE) ?? defaultColorMode } let observer: MutationObserver | null = null onMounted(() => { updateColorMode() observer = new MutationObserver(updateColorMode) const themeElement = findClosestThemeElement() if (themeElement) { observer.observe(themeElement, { attributes: true, attributeFilter: [THEME_ATTRIBUTE] }) } }) onUnmounted(() => observer && observer.disconnect()) return { colorMode } }