UNPKG

v-calendar

Version:

A clean and extendable plugin for building simple attributed calendars in Vue.js.

206 lines (193 loc) 5.52 kB
import { isObject, isString, has, hasAny, set, toPairs, defaults } from './_'; const targetProps = ['base', 'start', 'end', 'startEnd']; const displayProps = [ 'class', 'contentClass', 'style', 'contentStyle', 'color', 'fillMode', ]; const defConfig = { color: 'blue', isDark: false, highlight: { base: { fillMode: 'light' }, start: { fillMode: 'solid' }, end: { fillMode: 'solid' }, }, dot: { base: { fillMode: 'solid' }, start: { fillMode: 'solid' }, end: { fillMode: 'solid' }, }, bar: { base: { fillMode: 'solid' }, start: { fillMode: 'solid' }, end: { fillMode: 'solid' }, }, content: { base: {}, start: {}, end: {}, }, }; export default class Theme { constructor(config) { Object.assign(this, defConfig, config); } // Normalizes attribute config to the structure defined by the properties normalizeAttr({ config, type }) { let rootColor = this.color; let root = {}; // Get the normalized root config const normAttr = this[type]; if (config === true || isString(config)) { // Assign default color for booleans or strings rootColor = isString(config) ? config : rootColor; // Set the default root root = { ...normAttr }; } else if (isObject(config)) { if (hasAny(config, targetProps)) { // Mixin target configs root = { ...config }; } else { // Mixin display configs root = { base: { ...config }, start: { ...config }, end: { ...config }, }; } } else { return null; } // Fill in missing targets defaults(root, { start: root.startEnd, end: root.startEnd }, normAttr); // Normalize each target toPairs(root).forEach(([targetType, targetConfig]) => { let targetColor = rootColor; if (targetConfig === true || isString(targetConfig)) { targetColor = isString(targetConfig) ? targetConfig : targetColor; root[targetType] = { color: targetColor }; } else if (isObject(targetConfig)) { if (hasAny(targetConfig, displayProps)) { root[targetType] = { ...targetConfig }; } else { root[targetType] = {}; } } // Set the theme color if it is missing if (!has(root, `${targetType}.color`)) { set(root, `${targetType}.color`, targetColor); } }); return root; } normalizeHighlight(config) { const highlight = this.normalizeAttr({ config, type: 'highlight', }); toPairs(highlight).forEach(([_, targetConfig]) => { const c = defaults(targetConfig, { isDark: this.isDark, color: this.color, }); targetConfig.style = { ...this.getHighlightBgStyle(c), ...targetConfig.style, }; targetConfig.contentStyle = { ...this.getHighlightContentStyle(c), ...targetConfig.contentStyle, }; }); return highlight; } getHighlightBgStyle({ fillMode, color, isDark }) { switch (fillMode) { case 'outline': case 'none': return { backgroundColor: isDark ? 'var(--gray-900)' : 'var(--white)', border: '2px solid', borderColor: isDark ? `var(--${color}-200)` : `var(--${color}-700)`, borderRadius: 'var(--rounded-full)', }; case 'light': return { backgroundColor: isDark ? `var(--${color}-800)` : `var(--${color}-200)`, opacity: isDark ? 0.75 : 1, borderRadius: 'var(--rounded-full)', }; case 'solid': return { backgroundColor: isDark ? `var(--${color}-500)` : `var(--${color}-600)`, borderRadius: 'var(--rounded-full)', }; default: return { borderRadius: 'var(--rounded-full)', }; } } getHighlightContentStyle({ fillMode, color, isDark }) { switch (fillMode) { case 'outline': case 'none': return { fontWeight: 'var(--font-bold)', color: isDark ? `var(--${color}-100)` : `var(--${color}-900)`, }; case 'light': return { fontWeight: 'var(--font-bold)', color: isDark ? `var(--${color}-100)` : `var(--${color}-900)`, }; case 'solid': return { fontWeight: 'var(--font-bold)', color: 'var(--white)', }; default: return ''; } } bgAccentHigh({ color, isDark }) { return { backgroundColor: isDark ? `var(--${color}-500)` : `var(--${color}-600)`, }; } contentAccent({ color, isDark }) { if (!color) return null; return { fontWeight: 'var(--font-bold)', color: isDark ? `var(--${color}-100)` : `var(--${color}-900)`, }; } normalizeDot(config) { return this.normalizeNonHighlight('dot', config, this.bgAccentHigh); } normalizeBar(config) { return this.normalizeNonHighlight('bar', config, this.bgAccentHigh); } normalizeContent(config) { return this.normalizeNonHighlight('content', config, this.contentAccent); } normalizeNonHighlight(type, config, styleFn) { const attr = this.normalizeAttr({ type, config }); toPairs(attr).forEach(([_, targetConfig]) => { defaults(targetConfig, { isDark: this.isDark, color: this.color }); targetConfig.style = { ...styleFn(targetConfig), ...targetConfig.style, }; }); return attr; } }