UNPKG

@nuxtjs/color-mode

Version:

Dark and Light mode for Nuxt with auto detection

61 lines (60 loc) 2.1 kB
import { reactive, ref } from "vue"; import { defineNuxtPlugin, isVue2, isVue3, useHead, useState, useRouter, useRequestHeaders } from "#imports"; import { preference, hid, script, dataValue, storage, storageKey } from "#color-mode-options"; const addScript = (head) => { head.script = head.script || []; head.script.push({ hid, innerHTML: script }); const serializeProp = "__dangerouslyDisableSanitizersByTagID"; head[serializeProp] = head[serializeProp] || {}; head[serializeProp][hid] = ["innerHTML"]; }; export default defineNuxtPlugin((nuxtApp) => { const colorMode = nuxtApp.ssrContext?.islandContext ? ref({}) : useState("color-mode", () => reactive({ preference, value: preference, unknown: true, forced: false })).value; const htmlAttrs = {}; if (isVue2) { const app = nuxtApp.nuxt2Context.app; if (typeof app.head === "function") { const originalHead = app.head; app.head = function() { const head = originalHead.call(this) || {}; addScript(head); head.htmlAttrs = htmlAttrs; return head; }; } else { addScript(app.head); app.head.htmlAttrs = htmlAttrs; } } if (isVue3) { if (storage === "cookie") { const { cookie } = useRequestHeaders(["cookie"]); const [, value] = cookie?.split("; ").map((s) => s.split("=")).find(([k]) => k === storageKey) ?? []; if (value) { colorMode.preference = value; } } useHead({ htmlAttrs }); } useRouter().afterEach((to) => { const forcedColorMode = isVue2 ? to.matched[0]?.components.default?.options?.colorMode : to.meta.colorMode; if (forcedColorMode && forcedColorMode !== "system") { colorMode.value = htmlAttrs["data-color-mode-forced"] = forcedColorMode; if (dataValue) { htmlAttrs[`data-${dataValue}`] = colorMode.value; } colorMode.forced = true; } else if (forcedColorMode === "system") { console.warn("You cannot force the colorMode to system at the page level."); } }); nuxtApp.provide("colorMode", colorMode); });