-
+
@@ -32,7 +32,7 @@
computed: {
classes() {
return {
- 'md-checked': typeof this.value !== 'undefined' && this.mdValue.toString() === this.value.toString(),
+ 'md-checked': typeof this.value !== 'undefined' && this.value !== null && this.mdValue.toString() === this.value.toString(),
'md-disabled': this.disabled
};
}
diff --git a/src/components/mdSelect/mdOption.vue b/src/components/mdSelect/mdOption.vue
index 08e45ce..12c6ac7 100644
--- a/src/components/mdSelect/mdOption.vue
+++ b/src/components/mdSelect/mdOption.vue
@@ -22,7 +22,7 @@
export default {
name: 'md-option',
props: {
- value: [String, Boolean, Number]
+ value: [String, Boolean, Number, Object]
},
data: () => ({
parentSelect: {},
diff --git a/src/components/mdSnackbar/mdSnackbar.scss b/src/components/mdSnackbar/mdSnackbar.scss
index e9fefbf..56165e3 100644
--- a/src/components/mdSnackbar/mdSnackbar.scss
+++ b/src/components/mdSnackbar/mdSnackbar.scss
@@ -177,21 +177,3 @@ $snackbar-space: $snackbar-height / 2;
}
}
}
-
-.md-has-toast {
- .md-fab.md-fab-top-right,
- .md-fab.md-fab-top-center,
- .md-fab.md-fab-top-left {
- @include layout-xsmall {
- transform: translate3D(0, $snackbar-height - 4px, 0);
- }
- }
-
- .md-fab.md-fab-bottom-right,
- .md-fab.md-fab-bottom-center,
- .md-fab.md-fab-bottom-left {
- @include layout-xsmall {
- transform: translate3D(0, -$snackbar-height + 4px, 0);
- }
- }
-}
diff --git a/src/components/mdSwitch/mdSwitch.vue b/src/components/mdSwitch/mdSwitch.vue
index b5b2a0b..cec9bd2 100644
--- a/src/components/mdSwitch/mdSwitch.vue
+++ b/src/components/mdSwitch/mdSwitch.vue
@@ -38,13 +38,13 @@
data() {
return {
leftPos: initialPosition,
- checked: this.value
+ checked: Boolean(this.value)
};
},
computed: {
classes() {
return {
- 'md-checked': Boolean(this.value),
+ 'md-checked': this.checked,
'md-disabled': this.disabled
};
},
diff --git a/src/components/mdTable/mdTablePagination.vue b/src/components/mdTable/mdTablePagination.vue
index 6fcd7a8..357eb08 100644
--- a/src/components/mdTable/mdTablePagination.vue
+++ b/src/components/mdTable/mdTablePagination.vue
@@ -49,11 +49,14 @@
subTotal: 0,
totalItems: 0,
currentPage: 1,
- currentSize: 0
+ currentSize: parseInt(this.mdSize, 10)
};
},
watch: {
mdTotal(val) {
+ const sub = this.currentPage * this.currentSize;
+
+ this.subTotal = sub > val ? val : sub;
this.totalItems = isNaN(val) ? Number.MAX_SAFE_INTEGER : parseInt(val, 10);
},
mdSize(val) {
@@ -108,7 +111,7 @@
this.$nextTick(() => {
this.subTotal = this.currentPage * this.currentSize;
this.mdPageOptions = this.mdPageOptions || [10, 25, 50, 100];
- this.currentSize = this.mdPageOptions[0];
+ this.currentSize = this.mdPageOptions.includes(this.currentSize) ? this.currentSize : this.mdPageOptions[0];
this.canFireEvents = true;
});
}
diff --git a/src/core/components/mdTheme/dom.js b/src/core/components/mdTheme/dom.js
new file mode 100644
index 0000000..ab02670
--- /dev/null
+++ b/src/core/components/mdTheme/dom.js
@@ -0,0 +1,38 @@
+export var changeHtmlMetaColor;
+export var createNewStyleElement;
+
+if (process.env.VUE_ENV !== 'server') {
+ changeHtmlMetaColor = (color, themeClass, previousClass) => {
+ var elem = document.querySelector('meta[name="theme-color"]');
+
+ if (elem) {
+ elem.setAttribute('content', color);
+ } else {
+ elem = document.createElement('meta');
+ elem.setAttribute('name', 'theme-color');
+ elem.setAttribute('content', color);
+
+ document.head.appendChild(elem);
+ }
+
+ document.body.classList.remove(previousClass);
+ document.body.classList.add(themeClass);
+ };
+
+ createNewStyleElement = (style, styleId) => {
+ const head = document.head;
+ const styleElement = head.querySelector('#' + styleId);
+
+ if (!styleElement) {
+ const newTag = document.createElement('style');
+
+ newTag.type = 'text/css';
+ newTag.id = styleId;
+ newTag.textContent = style;
+
+ head.appendChild(newTag);
+ } else {
+ styleElement.textContent = style;
+ }
+ };
+}
diff --git a/src/core/components/mdTheme/index.js b/src/core/components/mdTheme/index.js
index 2da6bf1..c9ee292 100644
--- a/src/core/components/mdTheme/index.js
+++ b/src/core/components/mdTheme/index.js
@@ -1,8 +1,10 @@
import palette from './palette';
import rgba from './rgba';
import mdTheme from './mdTheme';
+import { changeHtmlMetaColor, createNewStyleElement } from './dom';
const VALID_THEME_TYPE = ['primary', 'accent', 'background', 'warn', 'hue-1', 'hue-2', 'hue-3'];
+const TYPE_REGEX = new RegExp('(' + VALID_THEME_TYPE.join('|').toUpperCase() + ')-(COLOR|CONTRAST)-?(A?\\d*)-?(\\d*\\.?\\d+)?', 'g');
const DEFAULT_THEME_COLORS = {
primary: 'indigo',
accent: 'pink',
@@ -22,170 +24,158 @@ const DEFAULT_THEME_COLORS = {
}
};*/
-const createNewStyleElement = (style, name) => {
- let head = document.head;
- let styleId = 'md-theme-' + name;
- let styleElement = head.querySelector('#' + styleId);
-
- if (!styleElement) {
- let newTag = document.createElement('style');
-
- style = style.replace(/THEME_NAME/g, styleId);
-
- newTag.type = 'text/css';
- newTag.id = styleId;
- newTag.textContent = style;
-
- head.appendChild(newTag);
- } else {
- styleElement.textContent = style;
- }
-};
-
-let registeredThemes = [];
-let registeredPrimaryColor = {};
+const registeredPrimaryColor = {};
+const injectedStyles = {};
const parseStyle = (style, theme, name) => {
- VALID_THEME_TYPE.forEach((type) => {
- style = style.replace(RegExp('(' + type.toUpperCase() + ')-(COLOR|CONTRAST)-?(A?\\d*)-?(\\d*\\.?\\d+)?', 'g'), (match, paletteType, colorType, hue, opacity) => {
- let color;
- let colorVariant = +hue === 0 ? 500 : hue;
+ return style.replace(TYPE_REGEX, (match, type, colorType, hue, opacity) => {
+ let color;
+ let colorVariant = +hue === 0 ? 500 : hue;
- if (theme[type]) {
- if (typeof theme[type] === 'string') {
- color = palette[theme[type]];
- } else {
- color = palette[theme[type].color] || palette[DEFAULT_THEME_COLORS[type]];
- colorVariant = +hue === 0 ? theme[type].hue : hue;
- }
+ type = type.toLowerCase();
+
+ if (theme[type]) {
+ if (typeof theme[type] === 'string') {
+ color = palette[theme[type]];
} else {
- color = palette[DEFAULT_THEME_COLORS[type]];
+ color = palette[theme[type].color] || palette[DEFAULT_THEME_COLORS[type]];
+ colorVariant = +hue === 0 ? theme[type].hue : hue;
}
+ } else {
+ color = palette[DEFAULT_THEME_COLORS[type]];
+ }
- if (colorType === 'COLOR') {
- let isDefault = palette[theme[type]];
+ if (colorType === 'COLOR') {
+ let isDefault = palette[theme[type]];
- if (!colorVariant && !isDefault) {
- if (type === 'accent') {
- colorVariant = 'A200';
- } else if (type === 'background') {
- colorVariant = 50;
- }
+ if (!colorVariant && !isDefault) {
+ if (type === 'accent') {
+ colorVariant = 'A200';
+ } else if (type === 'background') {
+ colorVariant = 50;
}
+ }
- if (type === 'primary') {
- registeredPrimaryColor[name] = color[colorVariant];
- }
-
- if (opacity) {
- return rgba(color[colorVariant], opacity);
- }
-
- return color[colorVariant];
- }
-
- let isDarkText = color.darkText.indexOf(colorVariant) >= 0;
-
- if (theme[type] && typeof theme[type] !== 'string' && theme[type].textColor) {
- if (theme[type].textColor === 'black') {
- isDarkText = true;
- } else if (theme[type].textColor === 'white') {
- isDarkText = false;
- }
- }
-
- if (isDarkText) {
- if (opacity) {
- return rgba('#000', opacity);
- }
-
- return 'rgba(0, 0, 0, .87)';
+ if (type === 'primary') {
+ registeredPrimaryColor[name] = color[colorVariant];
}
if (opacity) {
- return rgba('#fff', opacity);
+ return rgba(color[colorVariant], opacity);
}
- return 'rgba(255, 255, 255, .87)';
- });
- });
+ return color[colorVariant];
+ }
- return style;
-};
+ let isDarkText = color.darkText.indexOf(colorVariant) >= 0;
-const registerTheme = (theme, name, themeStyles) => {
- let parsedStyle = [];
+ if (theme[type] && typeof theme[type] !== 'string' && theme[type].textColor) {
+ if (theme[type].textColor === 'black') {
+ isDarkText = true;
+ } else if (theme[type].textColor === 'white') {
+ isDarkText = false;
+ }
+ }
- themeStyles.forEach((style) => {
- parsedStyle.push(parseStyle(style, theme, name));
- });
+ if (isDarkText) {
+ if (opacity) {
+ return rgba('#000', opacity);
+ }
- createNewStyleElement(parsedStyle.join('\n'), name);
-};
+ return 'rgba(0, 0, 0, .87)';
+ }
-const registerAllThemes = (themes, themeStyles) => {
- let themeNames = themes ? Object.keys(themes) : [];
+ if (opacity) {
+ return rgba('#fff', opacity);
+ }
- themeNames.forEach((name) => {
- registerTheme(themes[name], name, themeStyles);
- registeredThemes.push(name);
+ return 'rgba(255, 255, 255, .87)';
});
};
-const changeHtmlMetaColor = (color) => {
- let themeColorElement = document.querySelector('meta[name="theme-color"]');
+function warnNotFound(themeName) {
+ console.warn(`The theme '${themeName}' doesn't exists. You need to register` +
+ ' it first in order to use.');
+}
- if (themeColorElement) {
- themeColorElement.setAttribute('content', color);
- } else {
- themeColorElement = document.createElement('meta');
- themeColorElement.setAttribute('name', 'theme-color');
- themeColorElement.setAttribute('content', color);
-
- document.head.appendChild(themeColorElement);
- }
-};
+function injectStyle(style, spec, name, styleId) {
+ if (createNewStyleElement) {
+ style = parseStyle(style, spec, name);
+ style = style.replace(/THEME_NAME/g, styleId);
+
+ createNewStyleElement(style, styleId);
+ }
+}
export default function install(Vue) {
Vue.material = new Vue({
- data: () => ({
+ data: {
+ currentTheme: 'default',
+ inkRipple: true,
+ prefix: 'md-theme-',
styles: [],
- currentTheme: null,
- inkRipple: true
- }),
+ themes: {
+ default: DEFAULT_THEME_COLORS
+ }
+ },
+ watch: {
+ styles() {
+ this.refreshInjectedStyles();
+ }
+ },
methods: {
registerPalette(name, spec) {
palette[name] = spec;
},
+ useTheme(name) {
+ if (name in injectedStyles) {
+ return;
+ }
+ const spec = this.themes[name];
+
+ if (!spec) {
+ return warnNotFound(name);
+ }
+
+ injectStyle(this.styles.join('\n'), spec, name, this.prefix + name);
+
+ return injectedStyles[name] = true;
+ },
+ refreshInjectedStyles() {
+ const styles = this.styles.join('\n');
+ const prefix = this.prefix;
+
+ Object.keys(injectedStyles).forEach((name) => {
+ const spec = this.themes[name];
+
+ injectStyle(styles, spec, name, prefix + name);
+ });
+ },
registerTheme(name, spec) {
- let theme = {};
-
if (typeof name === 'string') {
- theme[name] = spec;
+ this.themes[name] = spec;
} else {
- theme = name;
+ Object.keys(name).forEach((k) => this.themes[k] = name[k]);
+ }
+ },
+ setCurrentTheme(name) {
+ if (name === this.currentTheme) {
+ return;
}
- registerAllThemes(theme, this.styles);
- },
- applyCurrentTheme(themeName) {
- changeHtmlMetaColor(registeredPrimaryColor[themeName]);
- document.body.classList.remove('md-theme-' + this.currentTheme);
- document.body.classList.add('md-theme-' + themeName);
- this.currentTheme = themeName;
- },
- setCurrentTheme(themeName) {
- if (registeredThemes.indexOf(themeName) >= 0) {
- this.applyCurrentTheme(themeName);
- } else {
- if (registeredThemes.indexOf('default') === -1) {
- this.registerTheme('default', DEFAULT_THEME_COLORS);
- } else {
- console.warn(`The theme '${themeName}' doesn't exists. You need to register it first in order to use.`);
- }
+ const prefix = this.prefix;
- this.applyCurrentTheme('default');
+ this.useTheme(name);
+
+ if (changeHtmlMetaColor) {
+ changeHtmlMetaColor(
+ registeredPrimaryColor[name],
+ prefix + this.currentTheme,
+ prefix + name
+ );
}
+
+ this.currentTheme = name;
}
}
});
diff --git a/src/core/components/mdTheme/mdTheme.vue b/src/core/components/mdTheme/mdTheme.vue
index e2438fc..793d04c 100644
--- a/src/core/components/mdTheme/mdTheme.vue
+++ b/src/core/components/mdTheme/mdTheme.vue
@@ -8,17 +8,26 @@
default: 'default'
}
},
- data: () => ({
- name: 'md-theme'
- }),
- render(render) {
+ render(createElement) {
if (this.mdTag || this.$slots.default.length > 1) {
- return render(this.mdTag || 'div', {
- staticClass: 'md-theme'
+ return createElement(this.mdTag || 'div', {
+ staticClass: this.$material.prefix + this.mdName
}, this.$slots.default);
}
return this.$slots.default[0];
+ },
+ watch: {
+ mdName(value) {
+ this.$material.useTheme(value);
+ }
+ },
+ beforeMount() {
+ const localTheme = this.mdName;
+
+ if (localTheme) {
+ this.$material.useTheme(localTheme);
+ }
}
};
diff --git a/src/core/components/mdTheme/mixin.js b/src/core/components/mdTheme/mixin.js
index 77db9d2..dc745f0 100644
--- a/src/core/components/mdTheme/mixin.js
+++ b/src/core/components/mdTheme/mixin.js
@@ -1,47 +1,43 @@
+// Theme mixin
+
+// Grab the closest ancestor component's `md-theme` attribute OR grab the
+// `md-name` attribute from an `
` component.
+function getAncestorThemeName(component) {
+ if (!component) {
+ return null;
+ }
+
+ let name = component.mdTheme;
+
+ if (!name && component.$options._componentTag === 'md-theme') {
+ name = component.mdName;
+ }
+
+ return name || getAncestorThemeName(component.$parent);
+}
+
export default {
props: {
mdTheme: String
},
- data: () => ({
- closestThemedParent: false
- }),
- methods: {
- getClosestThemedParent($parent) {
- if (!$parent || !$parent.$el || $parent._uid === 0) {
- return false;
- }
-
- if ($parent.mdTheme || $parent.mdName) {
- return $parent;
- }
-
- return this.getClosestThemedParent($parent.$parent);
- }
- },
computed: {
+ mdEffectiveTheme() {
+ return getAncestorThemeName(this) || this.$material.currentTheme;
+ },
themeClass() {
- if (this.mdTheme) {
- return 'md-theme-' + this.mdTheme;
- }
-
- let theme = this.closestThemedParent.mdTheme;
-
- if (!theme) {
- if (this.closestThemedParent) {
- theme = this.closestThemedParent.mdName;
- } else {
- theme = this.$material.currentTheme;
- }
- }
-
- return 'md-theme-' + theme;
+ return this.$material.prefix + this.mdEffectiveTheme;
}
},
- mounted() {
- this.closestThemedParent = this.getClosestThemedParent(this.$parent);
+ watch: {
+ mdTheme(value) {
+ this.$material.useTheme(value);
+ }
+ },
+ beforeMount() {
+ const localTheme = this.mdTheme;
- if (!this.$material.currentTheme) {
- this.$material.setCurrentTheme('default');
+ if (localTheme) {
+ this.$material.useTheme(localTheme);
}
}
};
diff --git a/src/core/stylesheets/base.scss b/src/core/stylesheets/base.scss
index 3ef8d44..f9df9b9 100644
--- a/src/core/stylesheets/base.scss
+++ b/src/core/stylesheets/base.scss
@@ -1,3 +1,6 @@
+@import 'variables.scss';
+@import 'typography.scss';
+
/* Structure
========================================================================== */
diff --git a/src/core/stylesheets/scrollbar.scss b/src/core/stylesheets/scrollbar.scss
index 6d8b914..acbcd55 100644
--- a/src/core/stylesheets/scrollbar.scss
+++ b/src/core/stylesheets/scrollbar.scss
@@ -1,3 +1,5 @@
+@import 'variables.scss';
+
.md-scrollbar {
&::-webkit-scrollbar,
::-webkit-scrollbar {