From 97da31fb63c51e2f8216c0afa199d6240aa98106 Mon Sep 17 00:00:00 2001 From: Conor_Mack <36074859+Conor-Mack@users.noreply.github.com> Date: Mon, 10 Feb 2020 10:04:20 +0000 Subject: [PATCH] New feature and refactor of Classbuilder along with some bug fixes (#85) --- .../src/Button/Button.svelte | 66 +++++++------- .../src/ClassBuilder.js | 87 ++++++++++++------- .../src/Test/props.js | 9 +- .../src/Textfield/Textfield.svelte | 26 +++--- .../src/Textfield/_mixins.scss | 5 +- 5 files changed, 111 insertions(+), 82 deletions(-) diff --git a/packages/materialdesign-components/src/Button/Button.svelte b/packages/materialdesign-components/src/Button/Button.svelte index eee93cac6d..c0c9ceb7e2 100644 --- a/packages/materialdesign-components/src/Button/Button.svelte +++ b/packages/materialdesign-components/src/Button/Button.svelte @@ -1,40 +1,50 @@ - + + {#if href} - {text} + {text} {:else} {/if} - - diff --git a/packages/materialdesign-components/src/ClassBuilder.js b/packages/materialdesign-components/src/ClassBuilder.js index 2f11edd49b..6b54666559 100644 --- a/packages/materialdesign-components/src/ClassBuilder.js +++ b/packages/materialdesign-components/src/ClassBuilder.js @@ -1,43 +1,70 @@ export default class ClassBuilder { - constructor(block, customDefaults) { + constructor(block, defaultIgnoreList) { this.block = `mdc-${block}`; - this.customDefaults = customDefaults; //will be ignored when building custom classes + this.defaultIgnoreList = defaultIgnoreList; //will be ignored when building custom classes } - // classParams: {modifiers:[] (mdc), custom:[] (bbmd), extra:[] (any)} - blocks(classParams) { - let base = this.block; - if (classParams == undefined) return base; - return this.buildClass(base, classParams); + /* + 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); } - //elementName: string, classParams: {} - elements(elementName, classParams) { - let base = `${this.block}__${elementName}`; - if (classParams == undefined) return base; - return this.buildClass(base, classParams); + //Easily grab a simple element class + elem(elementName) { + return this.build({ elementName }); } - //TODO: Classparams modifier and custom could take an object. Booleans or numbers use key value for classes, strings use property value for classes. Extras to stay as is - buildClass(base, classParams) { + //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 } = classParams; - if (!!modifiers) - cls += modifiers.map(m => (!!m ? ` ${base}--${m}` : "")).join(" "); - if (!!customs) - cls += Object.entries(customs) - .map(([property, value]) => { - //disregard falsy and values set by customDefaults constructor param - if ( - !!value && - (!this.customDefaults || !this.customDefaults.includes(value)) - ) { - //custom scss name convention = bbmd-[block | element]--[property]-[value] - return ` bbmd-${base}--${property}-${value}`; - } - }) - .join(""); + 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}--${property}-${value}` + : ` ${classBase}--${value}`; + } else if (valueType == "boolean") { + return ` ${classBase}--${property}`; + } + } + }) + .join(""); + } } diff --git a/packages/materialdesign-components/src/Test/props.js b/packages/materialdesign-components/src/Test/props.js index 700f611694..70145635ec 100644 --- a/packages/materialdesign-components/src/Test/props.js +++ b/packages/materialdesign-components/src/Test/props.js @@ -1,5 +1,6 @@ const getComponent = comp => `@budibase//materialdesign-components/${comp}`; + export const props = { justAnH1: { _component: "@budibase/materialdesign-components/h1", @@ -27,11 +28,11 @@ export const props = { textfield: { _component: "@budibase/materialdesign-components/textfield", _children: [], - label: "Surname", - icon: "alarm_on", - variant: "outlined", - helperText: "Add Surname", + label: "First", + colour: "secondary", textarea: true, + fullwidth:true, + helperText: "Add Surname", useCharCounter: true } }; diff --git a/packages/materialdesign-components/src/Textfield/Textfield.svelte b/packages/materialdesign-components/src/Textfield/Textfield.svelte index fd03dca37f..54a207c33d 100644 --- a/packages/materialdesign-components/src/Textfield/Textfield.svelte +++ b/packages/materialdesign-components/src/Textfield/Textfield.svelte @@ -44,15 +44,14 @@ export let persistent = false let id = `${label}-${variant}` - let helperClasses = `${cb.block}-helper-text` - let modifiers = [] + let modifiers = { fullwidth, disabled, textarea } let customs = { colour } if (variant == "standard" || fullwidth) { customs = { ...customs, variant } } else { - modifiers.push(variant) + modifiers = { ...modifiers, variant } } if (!textarea && size !== "medium") { @@ -60,15 +59,12 @@ } if (!label || fullwidth) { - modifiers.push("no-label") + modifiers = { ...modifiers, noLabel: "no-label" } } - //TODO: Refactor - this could be handled better using an object as modifier instead of an array - if (fullwidth) modifiers.push("fullwidth") - if (disabled) modifiers.push("disabled") - if (textarea) modifiers.push("textarea") - if (persistent) helperClasses += ` ${cb.block}-helper-text--persistent` - if (validation) helperClasses += ` ${cb.block}-helper-text--validation` + let helperClasses = cb.debase(`${cb.block}-helper-text`, { + modifiers: { persistent, validation }, + }) let useLabel = !!label && (!fullwidth || (fullwidth && textarea)) let useIcon = !!icon && (!textarea && !fullwidth) @@ -77,16 +73,16 @@ if (useIcon) { setContext("BBMD:icon:context", "text-field") - trailingIcon - ? modifiers.push("with-trailing-icon") - : modifiers.push("with-leading-icon") + let iconClass = trailingIcon ? "with-trailing-icon" : "with-leading-icon" + modifiers = { ...modifiers, iconClass } } $: renderLeadingIcon = useIcon && !trailingIcon $: renderTrailingIcon = useIcon && trailingIcon - const blockClasses = cb.blocks({ modifiers, customs }) - const inputClasses = cb.elements("input") + let props = { modifiers, customs } + const blockClasses = cb.build({ props }) + const inputClasses = cb.elem("input") let renderMaxLength = !!maxLength ? `0 / ${maxLength}` : "0" diff --git a/packages/materialdesign-components/src/Textfield/_mixins.scss b/packages/materialdesign-components/src/Textfield/_mixins.scss index b9ddfdc662..e589d9d2c9 100644 --- a/packages/materialdesign-components/src/Textfield/_mixins.scss +++ b/packages/materialdesign-components/src/Textfield/_mixins.scss @@ -16,11 +16,12 @@ &.bbmd-mdc-text-field--colour-secondary { &.mdc-text-field--focused { .mdc-floating-label--float-above { - color: var(--mdc-theme-secondary); + @include mdc-floating-label-ink-color(secondary) + } } .mdc-line-ripple--active { - background-color: var(--mdc-theme-secondary); + @include mdc-line-ripple-color(secondary); } &.mdc-text-field--outlined,