New feature and refactor of Classbuilder along with some bug fixes (#85)
This commit is contained in:
parent
7fe09780a4
commit
52c0e3b066
|
@ -1,40 +1,50 @@
|
|||
<script>
|
||||
import { setContext, getContext } from "svelte"
|
||||
import Icon from "../Icon.svelte"
|
||||
import ripple from "../Ripple.js"
|
||||
import ClassBuilder from "../ClassBuilder.js"
|
||||
import { setContext, getContext } from "svelte";
|
||||
import Icon from "../Icon.svelte";
|
||||
import ripple from "../Ripple.js";
|
||||
import ClassBuilder from "../ClassBuilder.js";
|
||||
|
||||
const cb = new ClassBuilder("button", ["primary", "medium"])
|
||||
const cb = new ClassBuilder("button", ["primary", "medium"]);
|
||||
|
||||
export let variant = "raised"
|
||||
export let colour = "primary"
|
||||
export let size = "medium"
|
||||
export let variant = "raised";
|
||||
export let colour = "primary";
|
||||
export let size = "medium";
|
||||
|
||||
export let href = ""
|
||||
export let icon = ""
|
||||
export let trailingIcon = false
|
||||
export let fullwidth = false
|
||||
export let href = "";
|
||||
export let icon = "";
|
||||
export let trailingIcon = false;
|
||||
export let fullwidth = false;
|
||||
|
||||
export let text = ""
|
||||
export let disabled = false
|
||||
export let text = "";
|
||||
export let disabled = false;
|
||||
|
||||
let modifiers = {};
|
||||
let customs = { size, colour };
|
||||
|
||||
if (!href) modifiers = { variant };
|
||||
|
||||
let props = { modifiers, customs };
|
||||
|
||||
let blockClasses = cb.build({ props });
|
||||
const labelClass = cb.elem("label");
|
||||
|
||||
$: if (icon) {
|
||||
setContext("BBMD:icon:context", "button")
|
||||
setContext("BBMD:icon:context", "button");
|
||||
}
|
||||
|
||||
$: renderLeadingIcon = !!icon && !trailingIcon
|
||||
$: renderTrailingIcon = !!icon && trailingIcon
|
||||
|
||||
let blockClasses = cb.blocks({
|
||||
modifiers: !href ? [variant] : null,
|
||||
customs: { size, colour },
|
||||
})
|
||||
$: renderLeadingIcon = !!icon && !trailingIcon;
|
||||
$: renderTrailingIcon = !!icon && trailingIcon;
|
||||
</script>
|
||||
|
||||
<!-- TODO: Activated colour on primary elevated buttons seems to be rendering weird -->
|
||||
<style>
|
||||
.fullwidth {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
{#if href}
|
||||
<a class={blockClasses} {href} on:click>
|
||||
<span class={cb.elements('label')}>{text}</span>
|
||||
<span class={labelClass}>{text}</span>
|
||||
</a>
|
||||
{:else}
|
||||
<button
|
||||
|
@ -46,15 +56,9 @@
|
|||
{#if renderLeadingIcon}
|
||||
<Icon {icon} />
|
||||
{/if}
|
||||
<span class={cb.elements('label')}>{text}</span>
|
||||
<span class={labelClass}>{text}</span>
|
||||
{#if renderTrailingIcon}
|
||||
<Icon {icon} />
|
||||
{/if}
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
.fullwidth {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -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("");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue