forked from tsai/budibase
committed by
GitHub
11 changed files with 244 additions and 32 deletions
@ -0,0 +1,67 @@ |
|||||
|
<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)} /> |
||||
|
{/each} |
||||
|
</div> |
||||
@ -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> |
||||
@ -0,0 +1 @@ |
|||||
|
@import "@material/list/mdc-list.scss"; |
||||
@ -0,0 +1,2 @@ |
|||||
|
import "./_style.scss"; |
||||
|
export { default as List } from "./List.svelte"; |
||||
Loading…
Reference in new issue