/* eslint-disable no-multi-spaces */ // Extensions import { Service } from '../service'; // Utilities import * as ThemeUtils from './utils'; // Types import Vue from 'vue'; export class Theme extends Service { constructor(options = {}) { super(); this.disabled = false; this.themes = { light: { primary: '#1976D2', secondary: '#424242', accent: '#82B1FF', error: '#FF5252', info: '#2196F3', success: '#4CAF50', warning: '#FB8C00' }, dark: { primary: '#2196F3', secondary: '#424242', accent: '#FF4081', error: '#FF5252', info: '#2196F3', success: '#4CAF50', warning: '#FB8C00' } }; this.defaults = this.themes; this.isDark = null; this.vueInstance = null; if (options.disable) { this.disabled = true; return; } this.options = { ...this.options, ...options.options }; this.dark = Boolean(options.dark); const themes = options.themes || {}; this.themes = { dark: this.fillVariant(themes.dark, true), light: this.fillVariant(themes.light, false) }; } // When setting css, check for element // and apply new values set css(val) { this.checkOrCreateStyleElement() && (this.styleEl.innerHTML = val); } set dark(val) { const oldDark = this.isDark; this.isDark = val; // Only apply theme after dark // has already been set before oldDark != null && this.applyTheme(); } get dark() { return Boolean(this.isDark); } // Apply current theme default // only called on client side applyTheme() { if (this.disabled) return this.clearCss(); this.css = this.generatedStyles; } clearCss() { this.css = ''; } // Initialize theme for SSR and SPA // Attach to ssrContext head or // apply new theme to document init(root, ssrContext) { if (this.disabled) return; const meta = Boolean(root.$meta); // TODO: don't import public types from /src const ssr = Boolean(ssrContext); /* istanbul ignore else */ if (meta) { this.initNuxt(root); } else if (ssr) { this.initSSR(ssrContext); } this.initTheme(); } // Allows for you to set target theme setTheme(theme, value) { this.themes[theme] = Object.assign(this.themes[theme], value); this.applyTheme(); } // Reset theme defaults resetThemes() { this.themes.light = Object.assign({}, this.defaults.light); this.themes.dark = Object.assign({}, this.defaults.dark); this.applyTheme(); } // Check for existence of style element checkOrCreateStyleElement() { this.styleEl = document.getElementById('vuetify-theme-stylesheet'); /* istanbul ignore next */ if (this.styleEl) return true; this.genStyleElement(); // If doesn't have it, create it return Boolean(this.styleEl); } fillVariant(theme = {}, dark) { const defaultTheme = this.themes[dark ? 'dark' : 'light']; return Object.assign({}, defaultTheme, theme); } // Generate the style element // if applicable genStyleElement() { if (typeof document === 'undefined') return; /* istanbul ignore next */ const options = this.options || {}; this.styleEl = document.createElement('style'); this.styleEl.type = 'text/css'; this.styleEl.id = 'vuetify-theme-stylesheet'; if (options.cspNonce) { this.styleEl.setAttribute('nonce', options.cspNonce); } document.head.appendChild(this.styleEl); } initNuxt(root) { const options = this.options || {}; root.$children.push(new Vue({ head: { style: [{ cssText: this.generatedStyles, type: 'text/css', id: 'vuetify-theme-stylesheet', nonce: options.cspNonce }] } })); } initSSR(ssrContext) { const options = this.options || {}; // SSR const nonce = options.cspNonce ? ` nonce="${options.cspNonce}"` : ''; ssrContext.head = ssrContext.head || ''; ssrContext.head += ``; } initTheme() { // Only watch for reactivity on client side if (typeof document === 'undefined') return; // If we get here somehow, ensure // existing instance is removed if (this.vueInstance) this.vueInstance.$destroy(); // Use Vue instance to track reactivity // TODO: Update to use RFC if merged // https://github.com/vuejs/rfcs/blob/advanced-reactivity-api/active-rfcs/0000-advanced-reactivity-api.md this.vueInstance = new Vue({ data: { themes: this.themes }, watch: { themes: { immediate: true, deep: true, handler: () => this.applyTheme() } } }); } get currentTheme() { const target = this.dark ? 'dark' : 'light'; return this.themes[target]; } get generatedStyles() { const theme = this.parsedTheme; /* istanbul ignore next */ const options = this.options || {}; let css; if (options.themeCache != null) { css = options.themeCache.get(theme); /* istanbul ignore if */ if (css != null) return css; } css = ThemeUtils.genStyles(theme, options.customProperties); if (options.minifyTheme != null) { css = options.minifyTheme(css); } if (options.themeCache != null) { options.themeCache.set(theme, css); } return css; } get parsedTheme() { /* istanbul ignore next */ const theme = this.currentTheme || {}; return ThemeUtils.parse(theme); } } Theme.property = 'theme'; //# sourceMappingURL=index.js.map