preact-material-components
Version:
preact wrapper for "Material Components for the web"
145 lines • 5.34 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { MDCRipple } from '@material/ripple';
import { bind } from 'bind-decorator';
import { Component } from 'preact';
const doNotRemoveProps = ['disabled'];
/**
* Base class for every Material component in this package
* NOTE: every component should add a ref by the name of `control` to its root dom for autoInit Properties
*
* @export
* @class MaterialComponent
* @extends {Component}
*/
export class MaterialComponent extends Component {
render(props) {
if (!this.classText) {
this.classText = this.buildClassName(props);
}
// Fetch a VNode
const componentProps = props;
const userDefinedClasses = componentProps.className || componentProps.class || '';
// We delete class props and add them later in the final
// step so every component does not need to handle user specified classes.
if (componentProps.class) {
delete componentProps.class;
}
if (componentProps.className) {
delete componentProps.className;
}
const element = this.materialDom(componentProps);
let propName = 'attributes';
if ('props' in element) {
propName = 'props';
// @ts-ignore
element.props = element.props || {};
}
else {
element.attributes = element.attributes || {};
}
// @ts-ignore
element[propName].className = `${userDefinedClasses} ${this.getClassName(element)}`
.split(' ')
.filter((value, index, self) => self.indexOf(value) === index && value !== '') // Unique + exclude empty class names
.join(' ');
// Clean this shit of proxy attributes
this.mdcProps.forEach(prop => {
// TODO: Fix this better
if (prop in doNotRemoveProps) {
return;
}
// @ts-ignore
delete element[propName][prop];
});
return element;
}
/** Attach the ripple effect */
componentDidMount() {
if (this.props.ripple && this.control) {
this.ripple = new MDCRipple(this.control);
}
}
componentWillReceiveProps(nextProps) {
if (this.MDComponent && this.mdcNotifyProps) {
for (const prop of this.mdcNotifyProps) {
if (this.props[prop] !== nextProps[prop]) {
this.MDComponent[prop] = nextProps[prop];
}
}
}
for (const prop of this.mdcProps) {
if (this.props[prop] !== nextProps[prop]) {
this.classText = this.buildClassName(nextProps);
break;
}
}
}
componentWillUnmount() {
if (this.ripple) {
this.ripple.destroy();
}
}
afterComponentDidMount() {
if (this.MDComponent && this.mdcNotifyProps) {
for (const prop of this.mdcNotifyProps) {
this.MDComponent[prop] = this.props[prop];
}
}
}
// Shared setter for the root element ref
setControlRef(control) {
this.control = control;
}
/** Build the className based on component names and mdc props */
buildClassName(props) {
// Class name based on component name
let classText = 'mdc-' + this.componentName;
// Loop over mdcProps to turn them into classNames
for (const propKey in props) {
if (props.hasOwnProperty(propKey)) {
const prop = props[propKey];
if (typeof prop === 'boolean' && prop) {
if (this.mdcProps.indexOf(propKey) !== -1) {
classText += ` mdc-${this.componentName}--${propKey}`;
}
}
}
}
return classText;
}
/** Returns the class name for element */
getClassName(element) {
if (!element) {
return '';
}
let propName = 'attributes';
if ('props' in element) {
propName = 'props';
// @ts-ignore
element.props = element.props || {};
}
else {
element.attributes = element.attributes || {};
}
// @ts-ignore
const attrs = (element[propName] = element[propName] || {});
let classText = this.classText;
if (attrs.class) {
classText += ' ' + attrs.class;
}
if (attrs.className && attrs.className !== attrs.class) {
classText += ' ' + attrs.className;
}
return classText;
}
}
__decorate([
bind
], MaterialComponent.prototype, "setControlRef", null);
export default MaterialComponent;
//# sourceMappingURL=MaterialComponent.js.map