Merge pull request #128 from Conor-Mack/feature/menu
Completed MD Menu component
This commit is contained in:
commit
f8aae4883c
|
@ -45,6 +45,7 @@
|
||||||
"@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/list": "4.0.0",
|
||||||
|
"@material/menu": "4.0.0",
|
||||||
"@material/radio": "^4.0.0",
|
"@material/radio": "^4.0.0",
|
||||||
"@material/textfield": "^4.0.0"
|
"@material/textfield": "^4.0.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,64 +1,71 @@
|
||||||
<script>
|
<script>
|
||||||
import { onMount } from "svelte"
|
import { onMount, getContext } from "svelte";
|
||||||
import { MDCList } from "@material/list"
|
import { MDCList } from "@material/list";
|
||||||
import { MDCRipple } from "@material/ripple"
|
import { MDCRipple } from "@material/ripple";
|
||||||
import ListItem from "./ListItem.svelte"
|
import ListItem from "./ListItem.svelte";
|
||||||
import ClassBuilder from "../ClassBuilder.js"
|
import ClassBuilder from "../ClassBuilder.js";
|
||||||
|
|
||||||
const cb = new ClassBuilder("list")
|
const cb = new ClassBuilder("list", ["one-line"]);
|
||||||
|
|
||||||
let list = null
|
let list = null;
|
||||||
let instance = null
|
let instance = null;
|
||||||
|
|
||||||
export let onSelect = selectedItems => {}
|
export let onSelect = selectedItems => {};
|
||||||
|
|
||||||
export let variant = ""
|
export let variant = "one-line";
|
||||||
//items: [{text: string | {primary: string, secondary: string}, value: any, selected: bool}...n]
|
//items: [{text: string | {primary: string, secondary: string}, value: any, selected: bool}...n]
|
||||||
export let items = []
|
export let items = [];
|
||||||
export let singleSelection = false
|
export let singleSelection = false;
|
||||||
export let inputElement = null
|
export let inputElement = null;
|
||||||
|
|
||||||
|
let role = "listbox";
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
if (!!list) {
|
if (!!list) {
|
||||||
instance = new MDCList(list)
|
instance = new MDCList(list);
|
||||||
instance.singleSelection = singleSelection
|
instance.singleSelection = singleSelection;
|
||||||
instance.listElements.map(element => new MDCRipple(element))
|
instance.listElements.map(element => new MDCRipple(element));
|
||||||
|
}
|
||||||
|
|
||||||
|
let context = getContext("BBMD:list:context");
|
||||||
|
if (context === "menu") {
|
||||||
|
role = "menu";
|
||||||
}
|
}
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
instance && instance.destroy()
|
instance && instance.destroy();
|
||||||
instance = null
|
instance = null;
|
||||||
}
|
};
|
||||||
})
|
});
|
||||||
|
|
||||||
function handleSelectedItem(item) {
|
function handleSelectedItem(item) {
|
||||||
if (!item.disabled) {
|
if (!item.disabled) {
|
||||||
if (singleSelection || inputElement === "radiobutton") {
|
if (singleSelection || inputElement === "radiobutton") {
|
||||||
items.forEach(i => {
|
items.forEach(i => {
|
||||||
if (i.selected) i.selected = false
|
if (i.selected) i.selected = false;
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let idx = items.indexOf(item)
|
let idx = items.indexOf(item);
|
||||||
if (!!item.selected) {
|
if (!!item.selected) {
|
||||||
items[idx].selected = !item.selected
|
items[idx].selected = !item.selected;
|
||||||
} else {
|
} else {
|
||||||
items[idx].selected = true
|
items[idx].selected = true;
|
||||||
}
|
}
|
||||||
onSelect(items.filter(item => item.selected))
|
onSelect(items.filter(item => item.selected));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$: useDoubleLine =
|
$: useDoubleLine =
|
||||||
variant == "two-line" &&
|
variant == "two-line" &&
|
||||||
items.every(i => typeof i.text == "object" && "primary" in i.text)
|
items.every(i => typeof i.text == "object" && "primary" in i.text);
|
||||||
|
|
||||||
$: modifiers = { variant }
|
$: modifiers = { variant };
|
||||||
$: props = { modifiers }
|
$: props = { modifiers };
|
||||||
$: listClass = cb.build({ props })
|
$: listClass = cb.build({ props });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class={listClass} role="listbox">
|
<ul class={listClass} {role}>
|
||||||
{#each items as item, i}
|
{#each items as item, i}
|
||||||
<ListItem
|
<ListItem
|
||||||
{item}
|
{item}
|
||||||
|
@ -69,4 +76,4 @@
|
||||||
<li role="separator" class="mdc-list-divider" />
|
<li role="separator" class="mdc-list-divider" />
|
||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</ul>
|
||||||
|
|
|
@ -1,30 +1,39 @@
|
||||||
<script>
|
<script>
|
||||||
import { setContext } from "svelte"
|
import { onMount, getContext } from "svelte";
|
||||||
import { Radiobutton } from "../Radiobutton"
|
import { Radiobutton } from "../Radiobutton";
|
||||||
import { Checkbox } from "../Checkbox"
|
import { Checkbox } from "../Checkbox";
|
||||||
import ClassBuilder from "../ClassBuilder.js"
|
import ClassBuilder from "../ClassBuilder.js";
|
||||||
|
|
||||||
const cb = new ClassBuilder("list-item")
|
const cb = new ClassBuilder("list-item");
|
||||||
|
|
||||||
export let onClick = item => {}
|
export let onClick = item => {};
|
||||||
|
|
||||||
export let item = null
|
export let item = null;
|
||||||
export let useDoubleLine = false
|
export let useDoubleLine = false;
|
||||||
export let inputElement = null //radiobutton or checkbox
|
export let inputElement = null; //radiobutton or checkbox
|
||||||
|
|
||||||
|
let role = "option";
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
let context = getContext("BBMD:list:context");
|
||||||
|
if (context === "menu") {
|
||||||
|
role = "menuitem";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
$: if (!!inputElement) {
|
$: if (!!inputElement) {
|
||||||
setContext("BBMD:input:context", "list-item")
|
setContext("BBMD:input:context", "list-item");
|
||||||
}
|
}
|
||||||
|
|
||||||
$: modifiers = {
|
$: modifiers = {
|
||||||
selected: !inputElement ? item.selected : null,
|
selected: !inputElement ? item.selected : null,
|
||||||
disabled: item.disabled,
|
disabled: item.disabled
|
||||||
}
|
};
|
||||||
$: props = { modifiers }
|
$: props = { modifiers };
|
||||||
$: listItemClass = cb.build({ props })
|
$: listItemClass = cb.build({ props });
|
||||||
|
|
||||||
$: useSecondaryText =
|
$: useSecondaryText =
|
||||||
typeof item.text === "object" && "secondary" in item.text
|
typeof item.text === "object" && "secondary" in item.text;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<li
|
<li
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
<script>
|
||||||
|
import { List } from "../List";
|
||||||
|
import { MDCMenu } from "@material/menu";
|
||||||
|
import { onMount, setContext } from "svelte";
|
||||||
|
export let items = [];
|
||||||
|
export let singleSelection = true;
|
||||||
|
export let width = "400px";
|
||||||
|
export let open = true;
|
||||||
|
export let useFixedPosition = false;
|
||||||
|
export let useAbsolutePosition = false;
|
||||||
|
//{x: number, y: number}
|
||||||
|
export let absolutePositionCoords = null;
|
||||||
|
|
||||||
|
let menu = null;
|
||||||
|
let instance = null;
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
if (!!menu) {
|
||||||
|
instance = new MDCMenu(menu);
|
||||||
|
instance.open = open;
|
||||||
|
if (useFixedPosition) {
|
||||||
|
instance.setFixedPosition(true);
|
||||||
|
} else if (useAbsolutePosition) {
|
||||||
|
let { x, y } = absolutePositionCoords;
|
||||||
|
instance.setAbsolutePosition(x | 0, y | 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setContext("BBMD:list:context", "menu");
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if useFixedPosition || useAbsolutePosition}
|
||||||
|
<div
|
||||||
|
bind:this={menu}
|
||||||
|
class="mdc-menu mdc-menu-surface"
|
||||||
|
style={`width: ${width}`}>
|
||||||
|
<List {items} {singleSelection} />
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<div class="mdc-menu-surface--anchor">
|
||||||
|
<!-- Will automatically anchor to slotted element -->
|
||||||
|
<slot />
|
||||||
|
<div
|
||||||
|
bind:this={menu}
|
||||||
|
class="mdc-menu mdc-menu-surface"
|
||||||
|
style={`width: ${width}`}>
|
||||||
|
<List {items} {singleSelection} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
|
@ -0,0 +1,2 @@
|
||||||
|
@import "@material/menu-surface/mdc-menu-surface.scss";
|
||||||
|
@import "@material/menu/mdc-menu.scss";
|
|
@ -0,0 +1,2 @@
|
||||||
|
import "./_styles.scss";
|
||||||
|
export { default as Menu } from "./Menu.svelte";
|
Loading…
Reference in New Issue