import { Quasar, useQuasar } from "quasar"; import { defuFn } from "defu"; import { defineNuxtPlugin } from "#app"; import { computed, reactive, useAppConfig, useHead, watch } from "#imports"; import { appConfigKey, componentsWithDefaults, quasarNuxtConfig } from "#build/quasar.config.mjs"; function getUpdatedDefaults(cfg, prevCfg) { const prevKeys = Object.keys(prevCfg); return { ...Object.fromEntries(prevKeys.map((k) => [k, void 0])), ...cfg }; } function getPrimaryColor() { return getComputedStyle(document.body).getPropertyValue("--q-primary").trim(); } function omit(object, keys) { return Object.keys(object).reduce((output, key) => { if (!keys.includes(key)) { output[key] = object[key]; } return output; }, {}); } export default defineNuxtPlugin((nuxt) => { const quasarAppConfig = useAppConfig()[appConfigKey]; const { lang, iconSet, plugins, components } = quasarNuxtConfig; let ssrContext; let quasarProxy; let config = defuFn(quasarAppConfig, omit(quasarNuxtConfig.config || {}, ["brand"])); if (import.meta.server) { const BRAND_RE = /--q-[\w-]+:.+?;/g; const meta = reactive({ bodyClasses: "", htmlAttrs: "", endingHeadTags: "" }); const htmlAttrsRecord = computed( () => Object.fromEntries( meta.htmlAttrs.split(" ").map((attr) => attr.split("=")) ) ); const bodyStyles = computed(() => { return [...meta.endingHeadTags.matchAll(BRAND_RE)].map((match) => match[0]).join(""); }); useHead( computed(() => ({ bodyAttrs: { class: meta.bodyClasses, style: bodyStyles.value }, htmlAttrs: htmlAttrsRecord.value })) ); ssrContext = { req: nuxt.ssrContext.event.node.req, res: nuxt.ssrContext.event.node.res }; quasarProxy = { install({ ssrContext: ssrContext2 }) { meta.bodyClasses = ssrContext2._meta.bodyClasses; meta.htmlAttrs = ssrContext2._meta.htmlAttrs; meta.endingHeadTags = ssrContext2._meta.endingHeadTags; ssrContext2._meta = new Proxy({}, { get(target, key) { return meta[key] ?? target[key]; }, set(target, key, value) { if (typeof meta[key] === "string") { meta[key] = value; } else { target[key] = value; } return true; } }); } }; } else { quasarProxy = { install({ onSSRHydrated }) { nuxt.hook("app:suspense:resolve", () => { onSSRHydrated.forEach((fn) => fn()); }); } }; } nuxt.vueApp.use(Quasar, { lang, iconSet, plugins: { quasarProxy, ...plugins }, config }, ssrContext); const quasar = useQuasar(); const asDefault = (value) => value && typeof value === "object" ? () => value : value; for (const [name, propDefaults] of Object.entries(components.defaults || {})) { const component = componentsWithDefaults[name]; if (!component) { continue; } for (const [propName, defaultValue] of Object.entries(propDefaults)) { const propConfig = component.props[propName]; if (Array.isArray(propConfig) || typeof propConfig === "function") { component.props[propName] = { type: propConfig, default: asDefault(defaultValue) }; } else if (typeof propConfig === "object") { if (propConfig) { propConfig.default = asDefault(defaultValue); } else { component.props[propName] = { default: asDefault(defaultValue) }; } } else { throw new TypeError(`Unexpected prop definition type used at ${name}.props.${propName}, please open an issue.`); } } } if (import.meta.dev && import.meta.client) { watch( () => quasarAppConfig, (newAppConfig) => { const prevConfig = config; config = defuFn(newAppConfig, quasarNuxtConfig.config); quasar.addressbarColor?.set(config.addressbarColor || getPrimaryColor()); const modifiedBrand = getUpdatedDefaults( config.brand || {}, prevConfig.brand || {} ); for (const [name, color] of Object.entries(modifiedBrand)) { if (!color) { document.body.style.removeProperty(`--q-${name}`); } else { document.body.style.setProperty(`--q-${name}`, color); } } if (prevConfig.dark !== config.dark) { quasar.dark.set(config.dark || false); } quasar.loading?.setDefaults(getUpdatedDefaults( config.loading || {}, prevConfig.loading || {} )); quasar.loadingBar?.setDefaults(getUpdatedDefaults( config.loadingBar || {}, prevConfig.loadingBar || {} )); plugins.Notify?.setDefaults(getUpdatedDefaults( config.loadingBar || {}, prevConfig.loadingBar || {} )); }, { deep: true } ); } return { provide: { q: quasar } }; });