budibase/packages/materialdesign-components/src/ClassBuilder.js

75 lines
2.5 KiB
JavaScript

export default class ClassBuilder {
constructor(block, defaultIgnoreList) {
this.block = `mdc-${block}`;
this.defaultIgnoreList = defaultIgnoreList; //will be ignored when building custom classes
}
/*
handles both blocks and elementss (BEM MD Notation)
params = {elementName: string, props: {modifiers{}, customs:{}, extras: []}}
All are optional
*/
build(params) {
if (!params) return this.block; //return block if nothing passed
const { props, elementName } = params;
let base = !!elementName ? `${this.block}__${elementName}` : this.block;
if (!props) return base;
return this._handleProps(base, props);
}
//Easily grab a simple element class
elem(elementName) {
return this.build({ elementName });
}
//use if a different base is needed than whats defined by this.block
debase(base, elementProps) {
if (!elementProps) return base;
return this._handleProps(base, elementProps);
}
//proxies bindProps and checks for which elementProps exist before binding
_handleProps(base, elementProps) {
let cls = base;
const { modifiers, customs, extras } = elementProps;
if (!!modifiers) cls += this._bindProps(modifiers, base);
if (!!customs) cls += this._bindProps(customs, base, true);
if (!!extras) cls += ` ${extras.join(" ")}`;
return cls.trim();
}
/*
Handles both modifiers and customs. Use property, value or both depending
on whether it is passsed props for custom or modifiers
if custom uses the following convention for scss mixins:
bbmd-{this.block}--{property}-{value}
bbmd-mdc-button--size-large
*/
_bindProps(elementProps, base, isCustom = false) {
return Object.entries(elementProps)
.map(([property, value]) => {
//disregard falsy and values set by defaultIgnoreList constructor param
if (
!!value &&
(!this.defaultIgnoreList || !this.defaultIgnoreList.includes(value))
) {
let classBase = isCustom ? `bbmd-${base}` : `${base}`;
let valueType = typeof value;
if (valueType == "string" || valueType == "number") {
return isCustom
? ` ${classBase}--${this._convertCamel(property)}-${value}`
: ` ${classBase}--${value}`;
} else if (valueType == "boolean") {
return ` ${classBase}--${this._convertCamel(property)}`;
}
}
})
.join("");
}
_convertCamel(str) {
return str.replace(/[A-Z]/g, match => `-${match.toLowerCase()}`);
}
}