Merge branch 'master' of github.com:Budibase/budibase

This commit is contained in:
Michael Shanks 2020-02-21 21:28:00 +00:00
commit 5ce9bf5040
13 changed files with 285 additions and 43 deletions

View File

@ -28,9 +28,21 @@
"description": "A Material Design button with different variations. It renders as an anchor if href is passed to it.", "description": "A Material Design button with different variations. It renders as an anchor if href is passed to it.",
"props": { "props": {
"onClick": "event", "onClick": "event",
"variant": "string", "variant": {
"colour": "string", "type": "options",
"size": "string", "options": ["text", "raised", "unelevated", "outlined"],
"default": "text"
},
"colour": {
"type": "options",
"options": ["primary", "secondary"],
"default": "primary"
},
"size": {
"type": "options",
"options": ["small", "medium", "large"],
"default": "medium"
},
"href": "string", "href": "string",
"icon": "string", "icon": "string",
"trailingIcon": "bool", "trailingIcon": "bool",
@ -159,7 +171,6 @@
"onClick": "event", "onClick": "event",
"id": "string", "id": "string",
"label": "string", "label": "string",
"names": "string",
"name": "string", "name": "string",
"checked": "bool", "checked": "bool",
"disabled": "bool", "disabled": "bool",
@ -190,12 +201,28 @@
"onChange": "event", "onChange": "event",
"value": "string", "value": "string",
"label": "string", "label": "string",
"variant": "string", "variant": {
"type": "options",
"options": ["standard", "outlined", "filled"],
"default": "standard"
},
"disabled": "bool", "disabled": "bool",
"fullwidth": "bool", "fullwidth": "bool",
"colour":"string", "colour": {
"size":"string", "type": "options",
"type": "string", "options": ["primary", "secondary"],
"default": "primary"
},
"size":{
"type": "options",
"options": ["small", "medium", "large"],
"default": "medium"
},
"type": {
"type": "options",
"options": ["text", "password"],
"default": "text"
},
"required": "bool", "required": "bool",
"minLength": "number", "minLength": "number",
"maxLength": "number", "maxLength": "number",

View File

@ -44,6 +44,7 @@
"@material/checkbox": "^4.0.0", "@material/checkbox": "^4.0.0",
"@material/data-table": "4.0.0", "@material/data-table": "4.0.0",
"@material/form-field": "^4.0.0", "@material/form-field": "^4.0.0",
"@material/list": "4.0.0",
"@material/radio": "^4.0.0", "@material/radio": "^4.0.0",
"@material/textfield": "^4.0.0" "@material/textfield": "^4.0.0"
} }

View File

@ -4,11 +4,11 @@
import ripple from "../Common/Ripple.js" import ripple from "../Common/Ripple.js"
import ClassBuilder from "../ClassBuilder.js" import ClassBuilder from "../ClassBuilder.js"
const cb = new ClassBuilder("button", ["primary", "medium"]) const cb = new ClassBuilder("button", ["primary", "medium", "text"])
export let onClick = () => {} export let onClick = () => {}
export let variant = "raised" export let variant = "text"
export let colour = "primary" export let colour = "primary"
export let size = "medium" export let size = "medium"

View File

@ -1,40 +1,51 @@
<script> <script>
import { onMount, onDestroy, getContext } from "svelte"; import { onMount, onDestroy, getContext } from "svelte"
import Formfield from "../Common/Formfield.svelte"; import Formfield from "../Common/Formfield.svelte"
import { fieldStore } from "../Common/FormfieldStore.js"; import { fieldStore } from "../Common/FormfieldStore.js"
import ClassBuilder from "../ClassBuilder.js"; import ClassBuilder from "../ClassBuilder.js"
import { MDCCheckbox } from "@material/checkbox"; import { MDCCheckbox } from "@material/checkbox"
export let onClick = item => {}; export let onClick = item => {}
export let id = ""; export let id = ""
export let label = ""; export let label = ""
export let disabled = false; export let disabled = false
export let alignEnd = false; export let alignEnd = false
export let indeterminate = false; export let indeterminate = false
export let checked = false; export let checked = false
let instance = null; let instance = null
let checkbox = null; let checkbox = null
let context = getContext("BBMD:input:context")
onMount(() => { onMount(() => {
if (!!checkbox) { if (!!checkbox) {
instance = new MDCCheckbox(checkbox); instance = new MDCCheckbox(checkbox)
let fieldStore = getContext("BBMD:field-element"); instance.indeterminate = indeterminate
fieldStore.setInput(instance); if (context !== "list-item") {
instance.indeterminate = indeterminate; let fieldStore = getContext("BBMD:field-element")
fieldStore.setInput(instance)
} }
}); }
})
const cb = new ClassBuilder("checkbox"); let extras = null
let modifiers = { disabled };
let props = { modifiers };
const blockClass = cb.build({ props }); if (context === "list-item") {
extras = ["mdc-list-item__meta"]
}
const cb = new ClassBuilder("checkbox")
let modifiers = { disabled }
let props = { modifiers, extras }
const blockClass = cb.build({ props })
</script> </script>
<!-- TODO: Customizing Colour and Density - What level of customization for these things does Budibase need here? --> <!-- TODO: Customizing Colour and Density - What level of customization for these things does Budibase need here? -->
{#if context !== 'list-item'}
<Formfield {label} {id} {alignEnd}> <Formfield {label} {id} {alignEnd}>
<div bind:this={checkbox} class={blockClass}> <div bind:this={checkbox} class={blockClass}>
<input <input
@ -56,3 +67,24 @@
<div class={cb.elem`ripple`} /> <div class={cb.elem`ripple`} />
</div> </div>
</Formfield> </Formfield>
{:else}
<div bind:this={checkbox} class={blockClass}>
<input
type="checkbox"
class={cb.elem`native-control`}
{id}
{disabled}
{checked}
on:click={onClick} />
<div class={cb.elem`background`}>
<svg class={cb.elem`checkmark`} viewBox="0 0 24 24">
<path
class={cb.elem`checkmark-path`}
fill="none"
d="M1.73,12.91 8.1,19.28 22.79,4.59" />
</svg>
<div class={cb.elem`mixedmark`} />
</div>
<div class={cb.elem`ripple`} />
</div>
{/if}

View File

@ -0,0 +1,70 @@
<script>
import { onMount } from "svelte"
import { MDCList } from "@material/list"
import { MDCRipple } from "@material/ripple"
import ListItem from "./ListItem.svelte"
import ClassBuilder from "../ClassBuilder.js"
const cb = new ClassBuilder("list")
let list = null
let instance = null
export let onSelect = selectedItems => {}
export let variant = ""
//items: [{text: string | {primary: string, secondary: string}, value: any, selected: bool}...n]
export let items = []
export let singleSelection = false
export let inputElement = null
onMount(() => {
if (!!list) {
instance = new MDCList(list)
instance.singleSelection = singleSelection
instance.listElements.map(element => new MDCRipple(element))
}
return () => {
instance && instance.destroy()
instance = null
}
})
function handleSelectedItem(item) {
if (singleSelection || inputElement === "radiobutton") {
items.forEach(i => {
if (i.selected) i.selected = false
})
}
let idx = items.indexOf(item)
if (!!item.selected) {
items[idx].selected = !item.selected
} else {
items[idx].selected = true
}
onSelect(items.filter(item => item.selected))
}
$: useDoubleLine =
variant == "two-line" &&
items.every(i => typeof i.text == "object" && "primary" in i.text)
$: modifiers = { variant }
$: props = { modifiers }
$: listClass = cb.build({ props })
</script>
<div class={listClass} role="listbox">
{#each items as item, i}
<ListItem
{item}
{useDoubleLine}
{inputElement}
onClick={() => handleSelectedItem(item)} />
{#if item.divider}
<li role="separator" class="mdc-list-divider" />
{/if}
{/each}
</div>

View File

@ -0,0 +1,59 @@
<script>
import { setContext } from "svelte";
import { Radiobutton } from "../Radiobutton";
import { Checkbox } from "../Checkbox";
import ClassBuilder from "../ClassBuilder.js";
const cb = new ClassBuilder("list-item");
export let onClick = item => {};
export let item = null;
export let useDoubleLine = false;
export let inputElement = null; //radiobutton or checkbox
$: if (!!inputElement) {
setContext("BBMD:input:context", "list-item");
}
$: modifiers = { selected: !inputElement ? item.selected : null };
$: props = { modifiers };
$: listItemClass = cb.build({ props });
$: useSecondaryText =
typeof item.text === "object" && "secondary" in item.text;
</script>
<li
class={listItemClass}
role="option"
aria-selected={item.selected}
tabindex="0"
on:click={onClick}>
{#if item.leadingIcon}
<span class="mdc-list-item__graphic material-icons" aria-hidden="true">
{item.leadingIcon}
</span>
{/if}
<span class={cb.elem`text`}>
{#if useDoubleLine}
<span class={cb.elem`primary-text`}>{item.text.primary}</span>
{#if useSecondaryText}
<span class={cb.elem`secondary-text`}>{item.text.secondary}</span>
{/if}
{:else}{item.text}{/if}
</span>
{#if inputElement}
{#if inputElement === 'radiobutton'}
<Radiobutton checked={item.selected} />
{:else if inputElement === 'checkbox'}
<Checkbox checked={item.selected} />
{/if}
{:else if item.trailingIcon}
<!-- TODO: Adapt label to accept class prop to handle this. Context is insufficient -->
<span class="mdc-list-item__meta material-icons" aria-hidden="true">
{item.trailingIcon}
</span>
{/if}
</li>

View File

@ -0,0 +1 @@
@import "@material/list/mdc-list.scss";

View File

@ -0,0 +1,2 @@
import "./_style.scss";
export { default as List } from "./List.svelte";

View File

@ -16,21 +16,32 @@
let instance = null let instance = null
let radiobtn = null let radiobtn = null
let context = getContext("BBMD:input:context")
onMount(() => { onMount(() => {
if (!!radiobtn) { if (!!radiobtn) {
instance = new MDCRadio(radiobtn) instance = new MDCRadio(radiobtn)
if (context !== "list-item") {
let fieldStore = getContext("BBMD:field-element") let fieldStore = getContext("BBMD:field-element")
fieldStore.setInput(instance) fieldStore.setInput(instance)
} }
}
}) })
let extras = null
if (context === "list-item") {
extras = ["mdc-list-item__meta"]
}
const cb = new ClassBuilder("radio") const cb = new ClassBuilder("radio")
let modifiers = { disabled } let modifiers = { disabled }
let props = { modifiers } let props = { modifiers, extras }
const blockClass = cb.build({ props }) const blockClass = cb.build({ props })
</script> </script>
{#if context !== 'list-item'}
<Formfield {id} {label} {alignEnd}> <Formfield {id} {label} {alignEnd}>
<div class={blockClass}> <div class={blockClass}>
<input <input
@ -48,3 +59,20 @@
<div class={cb.elem`ripple`} /> <div class={cb.elem`ripple`} />
</div> </div>
</Formfield> </Formfield>
{:else}
<div class={blockClass}>
<input
{id}
class={cb.elem`native-control`}
type="radio"
{name}
{checked}
{disabled}
on:click={onClick} />
<div class={cb.elem`background`}>
<div class={cb.elem`outer-circle`} />
<div class={cb.elem`inner-circle`} />
</div>
<div class={cb.elem`ripple`} />
</div>
{/if}

View File

@ -37,7 +37,7 @@
{name} {name}
{alignEnd} {alignEnd}
label={item.label} label={item.label}
checked={item.checked} checked={item.checked || false}
onClick={() => handleOnClick(item)} /> onClick={() => handleOnClick(item)} />
</div> </div>
{/each} {/each}

View File

@ -13,6 +13,7 @@
Radiobuttongroup, Radiobuttongroup,
Datatable, Datatable,
CustomersIndexTable, CustomersIndexTable,
List,
} = props } = props
let currentComponent let currentComponent
@ -33,7 +34,8 @@
Radiobutton, Radiobutton,
Radiobuttongroup, Radiobuttongroup,
Datatable, Datatable,
CustomersIndexTable CustomersIndexTable,
List,
], ],
}, },
} }

View File

@ -103,4 +103,23 @@ export const props = {
}, },
CustomersIndexTable: indexDatatable(templateOptions)[0].props, CustomersIndexTable: indexDatatable(templateOptions)[0].props,
List: {
_component: "@budibase/materialdesign-components/List",
_children: [],
variant: "two-line",
singleSelection: true,
items: [
{
text: { primary: "Curry", secondary: "Chicken or Beef" },
value: 0,
divider: true,
},
{
text: { primary: "Pastie", secondary: "Bap with Mayo" },
value: 1,
},
{ text: { primary: "Fish", secondary: "Salmon or Cod" }, value: 2 },
],
onSelect: selected => console.log(selected),
},
} }

View File

@ -15,3 +15,4 @@ export {
DatatableRow, DatatableRow,
} from "./Datatable" } from "./Datatable"
export { default as indexDatatable } from "./Templates/indexDatatable" export { default as indexDatatable } from "./Templates/indexDatatable"
export { List } from "./List"