165 lines
5 KiB
JavaScript
165 lines
5 KiB
JavaScript
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
|
|
}
|
|
};
|
|
});
|