diff --git a/packages/core/useColorMode/index.test.ts b/packages/core/useColorMode/index.test.ts index ca2674f77d6..7c05915c743 100644 --- a/packages/core/useColorMode/index.test.ts +++ b/packages/core/useColorMode/index.test.ts @@ -117,10 +117,10 @@ describe('useColorMode', () => { expect(htmlEl?.className).toMatch(/dark/) }) - it('should use state to access mode & preference', () => { - const state = useColorMode() - expect(state.store.value).toBe('auto') - expect(state.system.value).toBe('light') - expect(state.value).toBe('light') + it('should be able access the store & system preference', () => { + const mode = useColorMode() + expect(mode.store.value).toBe('auto') + expect(mode.system.value).toBe('light') + expect(mode.state.value).toBe('light') }) }) diff --git a/packages/core/useColorMode/index.ts b/packages/core/useColorMode/index.ts index 5062052ac42..cbee918da7a 100644 --- a/packages/core/useColorMode/index.ts +++ b/packages/core/useColorMode/index.ts @@ -1,6 +1,7 @@ -import type { Ref } from 'vue-demi' -import { computed, ref, watch } from 'vue-demi' -import { tryOnMounted } from '@vueuse/shared' +import type { ComputedRef, Ref } from 'vue-demi' +import { computed, watch } from 'vue-demi' +import type { MaybeRefOrGetter } from '@vueuse/shared' +import { toRef, tryOnMounted } from '@vueuse/shared' import type { StorageLike } from '../ssr-handlers' import { getSSRHandler } from '../ssr-handlers' import type { UseStorageOptions } from '../useStorage' @@ -10,9 +11,10 @@ import { usePreferredDark } from '../usePreferredDark' import type { MaybeElementRef } from '../unrefElement' import { unrefElement } from '../unrefElement' -export type BasicColorSchema = 'light' | 'dark' | 'auto' +export type BasicColorMode = 'light' | 'dark' +export type BasicColorSchema = BasicColorMode | 'auto' -export interface UseColorModeOptions extends UseStorageOptions { +export interface UseColorModeOptions extends UseStorageOptions { /** * CSS Selector for the target element applying to * @@ -32,7 +34,7 @@ export interface UseColorModeOptions extend * * @default 'auto' */ - initialValue?: T | BasicColorSchema + initialValue?: MaybeRefOrGetter /** * Prefix when adding value to the attribute @@ -45,7 +47,7 @@ export interface UseColorModeOptions extend * * @default undefined */ - onChanged?: (mode: T | BasicColorSchema, defaultHandler:((mode: T | BasicColorSchema) => void)) => void + onChanged?: (mode: T | BasicColorMode, defaultHandler:((mode: T | BasicColorMode) => void)) => void /** * Custom storage ref @@ -77,6 +79,8 @@ export interface UseColorModeOptions extend * This is useful when the fact that `auto` mode was selected needs to be known. * * @default undefined + * @deprecated use `store.value` when `auto` mode needs to be known + * @see https://vueuse.org/core/useColorMode/#advanced-usage */ emitAuto?: boolean @@ -89,10 +93,11 @@ export interface UseColorModeOptions extend disableTransition?: boolean } -export type UseColorModeReturn = - Ref & { - store: Ref - system: Ref<'light' | 'dark'> +export type UseColorModeReturn = + Ref & { + store: Ref + system: ComputedRef + state: ComputedRef } /** @@ -101,7 +106,7 @@ export type UseColorModeReturn = * @see https://vueuse.org/useColorMode * @param options */ -export function useColorMode( +export function useColorMode( options: UseColorModeOptions = {}, ): UseColorModeReturn { const { @@ -127,20 +132,17 @@ export function useColorMode( const preferredDark = usePreferredDark({ window }) const system = computed(() => preferredDark.value ? 'dark' : 'light') - const store = storageRef || (storageKey == null - ? ref(initialValue) as Ref - : useStorage(storageKey, initialValue as BasicColorSchema, storage, { window, listenToStorageChanges })) + const store = storageRef || ( + storageKey == null + ? toRef(initialValue) as Ref + : useStorage(storageKey, initialValue, storage, { window, listenToStorageChanges }) + ) - const state = computed({ - get() { - return (store.value === 'auto' && !emitAuto) - ? system.value - : store.value - }, - set(v) { - store.value = v - }, - }) + const state = computed(() => + store.value === 'auto' + ? system.value + : store.value, + ) const updateHTMLAttrs = getSSRHandler( 'updateHTMLAttrs', @@ -182,12 +184,11 @@ export function useColorMode( } }) - function defaultOnChanged(mode: T | BasicColorSchema) { - const resolvedMode = mode === 'auto' ? system.value : mode - updateHTMLAttrs(selector, attribute, modes[resolvedMode] ?? resolvedMode) + function defaultOnChanged(mode: T | BasicColorMode) { + updateHTMLAttrs(selector, attribute, modes[mode] ?? mode) } - function onChanged(mode: T | BasicColorSchema) { + function onChanged(mode: T | BasicColorMode) { if (options.onChanged) options.onChanged(mode, defaultOnChanged) else @@ -196,16 +197,22 @@ export function useColorMode( watch(state, onChanged, { flush: 'post', immediate: true }) - if (emitAuto) - watch(system, () => onChanged(state.value), { flush: 'post' }) - tryOnMounted(() => onChanged(state.value)) + const auto = computed({ + get() { + return emitAuto ? store.value : state.value + }, + set(v) { + store.value = v + }, + }) + try { - return Object.assign(state, { store, system }) as UseColorModeReturn + return Object.assign(auto, { store, system, state }) as UseColorModeReturn } catch (e) { // In Vue 2.6, ref might not be extensible - return state as any as UseColorModeReturn + return auto as any as UseColorModeReturn } } diff --git a/packages/core/useDark/index.ts b/packages/core/useDark/index.ts index 3ed0d947e34..1468069adef 100644 --- a/packages/core/useDark/index.ts +++ b/packages/core/useDark/index.ts @@ -1,8 +1,6 @@ import { computed } from 'vue-demi' -import { defaultWindow } from '../_configurable' -import { usePreferredDark } from '../usePreferredDark' -import type { BasicColorSchema, UseColorModeOptions } from '../useColorMode' import { useColorMode } from '../useColorMode' +import type { BasicColorSchema, UseColorModeOptions } from '../useColorMode' export interface UseDarkOptions extends Omit, 'modes' | 'onChanged'> { /** @@ -38,7 +36,6 @@ export function useDark(options: UseDarkOptions = {}) { const { valueDark = 'dark', valueLight = '', - window = defaultWindow, } = options const mode = useColorMode({ @@ -55,17 +52,16 @@ export function useDark(options: UseDarkOptions = {}) { }, }) - const preferredDark = usePreferredDark({ window }) - const isDark = computed({ get() { return mode.value === 'dark' }, set(v) { - if (v === preferredDark.value) + const modeVal = v ? 'dark' : 'light' + if (mode.system.value === modeVal) mode.value = 'auto' else - mode.value = v ? 'dark' : 'light' + mode.value = modeVal }, })