Add sub link drawer
This commit is contained in:
parent
26c4e504bf
commit
fdc757029a
|
@ -78,7 +78,12 @@
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Drawer bind:this={bindingDrawer} title={title ?? placeholder ?? "Bindings"}>
|
<Drawer
|
||||||
|
bind:this={bindingDrawer}
|
||||||
|
title={title ?? placeholder ?? "Bindings"}
|
||||||
|
on:drawerHide
|
||||||
|
on:drawerShow
|
||||||
|
>
|
||||||
<Button cta slot="buttons" on:click={handleClose}>Save</Button>
|
<Button cta slot="buttons" on:click={handleClose}>Save</Button>
|
||||||
<svelte:component
|
<svelte:component
|
||||||
this={panel}
|
this={panel}
|
||||||
|
|
|
@ -20,8 +20,8 @@
|
||||||
]
|
]
|
||||||
|
|
||||||
let popover
|
let popover
|
||||||
let drawers = []
|
|
||||||
let open = false
|
let open = false
|
||||||
|
let drawerCount = 0
|
||||||
|
|
||||||
$: urlOptions = $screenStore.screens
|
$: urlOptions = $screenStore.screens
|
||||||
.map(screen => screen.routing?.route)
|
.map(screen => screen.routing?.route)
|
||||||
|
@ -52,7 +52,7 @@
|
||||||
<Popover
|
<Popover
|
||||||
bind:this={popover}
|
bind:this={popover}
|
||||||
on:open={() => {
|
on:open={() => {
|
||||||
drawers = []
|
open = true
|
||||||
$draggable.actions.select(navItem.id)
|
$draggable.actions.select(navItem.id)
|
||||||
}}
|
}}
|
||||||
on:close={() => {
|
on:close={() => {
|
||||||
|
@ -63,8 +63,8 @@
|
||||||
}}
|
}}
|
||||||
{anchor}
|
{anchor}
|
||||||
align="left-outside"
|
align="left-outside"
|
||||||
showPopover={drawers.length === 0}
|
showPopover={drawerCount === 0}
|
||||||
clickOutsideOverride={drawers.length > 0}
|
clickOutsideOverride={drawerCount > 0}
|
||||||
maxHeight={600}
|
maxHeight={600}
|
||||||
offset={18}
|
offset={18}
|
||||||
>
|
>
|
||||||
|
@ -87,6 +87,8 @@
|
||||||
props={{
|
props={{
|
||||||
updateOnChange: false,
|
updateOnChange: false,
|
||||||
}}
|
}}
|
||||||
|
on:drawerShow={() => drawerCount++}
|
||||||
|
on:drawerHide={() => drawerCount--}
|
||||||
/>
|
/>
|
||||||
{#if navItem.type === "sublinks"}
|
{#if navItem.type === "sublinks"}
|
||||||
<PropertyControl
|
<PropertyControl
|
||||||
|
@ -94,6 +96,12 @@
|
||||||
control={SubLinksDrawer}
|
control={SubLinksDrawer}
|
||||||
value={navItem.subLinks}
|
value={navItem.subLinks}
|
||||||
onChange={update("subLinks")}
|
onChange={update("subLinks")}
|
||||||
|
{bindings}
|
||||||
|
props={{
|
||||||
|
navItem,
|
||||||
|
}}
|
||||||
|
on:drawerShow={() => drawerCount++}
|
||||||
|
on:drawerHide={() => drawerCount--}
|
||||||
/>
|
/>
|
||||||
{:else}
|
{:else}
|
||||||
<PropertyControl
|
<PropertyControl
|
||||||
|
@ -107,6 +115,8 @@
|
||||||
appendBindingsAsOptions: false,
|
appendBindingsAsOptions: false,
|
||||||
placeholder: null,
|
placeholder: null,
|
||||||
}}
|
}}
|
||||||
|
on:drawerShow={() => drawerCount++}
|
||||||
|
on:drawerHide={() => drawerCount--}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
<PropertyControl
|
<PropertyControl
|
||||||
|
|
|
@ -6,99 +6,96 @@
|
||||||
DrawerContent,
|
DrawerContent,
|
||||||
Layout,
|
Layout,
|
||||||
Input,
|
Input,
|
||||||
Combobox,
|
|
||||||
Drawer,
|
Drawer,
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
import { flip } from "svelte/animate"
|
import { flip } from "svelte/animate"
|
||||||
import { dndzone } from "svelte-dnd-action"
|
import { dndzone } from "svelte-dnd-action"
|
||||||
import { generate } from "shortid"
|
import { generate } from "shortid"
|
||||||
import { screenStore } from "stores/builder"
|
import { screenStore } from "stores/builder"
|
||||||
import RoleSelect from "components/design/settings/controls/RoleSelect.svelte"
|
import DrawerBindableCombobox from "components/common/bindings/DrawerBindableCombobox.svelte"
|
||||||
|
|
||||||
export let value = []
|
export let value = []
|
||||||
|
export let onChange
|
||||||
|
export let navItem
|
||||||
|
export let bindings
|
||||||
|
|
||||||
const flipDurationMs = 150
|
const flipDurationMs = 150
|
||||||
|
|
||||||
let dragDisabled = true
|
|
||||||
let drawer
|
let drawer
|
||||||
|
let subLinks = value?.slice() || []
|
||||||
|
|
||||||
$: links = value || []
|
$: count = value?.length ?? 0
|
||||||
$: links.forEach(link => {
|
$: buttonText = `${count || "No"} sub link${count === 1 ? "" : "s"}`
|
||||||
if (!link.id) {
|
$: drawerTitle = navItem.text ? `${navItem.text} sub links` : "Sub links"
|
||||||
link.id = generate()
|
$: subLinks.forEach(subLink => {
|
||||||
|
if (!subLink.id) {
|
||||||
|
subLink.id = generate()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
$: urlOptions = $screenStore.screens
|
$: urlOptions = $screenStore.screens
|
||||||
.map(screen => screen.routing?.route)
|
.map(screen => screen.routing?.route)
|
||||||
.filter(x => x != null)
|
.filter(x => x != null)
|
||||||
|
.sort()
|
||||||
|
|
||||||
const addLink = () => {
|
const addSubLink = () => {
|
||||||
links = [...links, {}]
|
subLinks = [...subLinks, {}]
|
||||||
}
|
}
|
||||||
|
|
||||||
const removeLink = id => {
|
const removeSubLink = id => {
|
||||||
links = links.filter(link => link.id !== id)
|
subLinks = subLinks.filter(link => link.id !== id)
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateLinks = e => {
|
const saveSubLinks = () => {
|
||||||
links = e.detail.items
|
onChange(subLinks)
|
||||||
|
drawer.hide()
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleFinalize = e => {
|
const updateSubLinks = e => {
|
||||||
updateLinks(e)
|
subLinks = e.detail.items
|
||||||
dragDisabled = true
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
<Drawer bind:this={drawer} title={drawerTitle} on:drawerShow on:drawerHide>
|
||||||
<Drawer bind:this={drawer}>
|
<Button cta slot="buttons" on:click={saveSubLinks}>Save</Button>
|
||||||
<DrawerContent>
|
<DrawerContent slot="body">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<Layout noPadding gap="S">
|
<Layout noPadding gap="S">
|
||||||
{#if links?.length}
|
{#if subLinks?.length}
|
||||||
<div
|
<div
|
||||||
class="links"
|
class="subLinks"
|
||||||
use:dndzone={{
|
use:dndzone={{
|
||||||
items: links,
|
items: subLinks,
|
||||||
flipDurationMs,
|
flipDurationMs,
|
||||||
dropTargetStyle: { outline: "none" },
|
dropTargetStyle: { outline: "none" },
|
||||||
dragDisabled,
|
|
||||||
}}
|
}}
|
||||||
on:finalize={handleFinalize}
|
on:consider={updateSubLinks}
|
||||||
on:consider={updateLinks}
|
on:finalize={updateSubLinks}
|
||||||
>
|
>
|
||||||
{#each links as link (link.id)}
|
{#each subLinks as subLink (subLink.id)}
|
||||||
<div class="link" animate:flip={{ duration: flipDurationMs }}>
|
<div class="subLink" animate:flip={{ duration: flipDurationMs }}>
|
||||||
<div
|
<Icon name="DragHandle" size="XL" />
|
||||||
class="handle"
|
<Input bind:value={subLink.text} placeholder="Text" />
|
||||||
aria-label="drag-handle"
|
<DrawerBindableCombobox
|
||||||
style={dragDisabled ? "cursor: grab" : "cursor: grabbing"}
|
value={subLink.url}
|
||||||
on:mousedown={() => (dragDisabled = false)}
|
on:change={e => (subLink.url = e.detail)}
|
||||||
>
|
placeholder="Link"
|
||||||
<Icon name="DragHandle" size="XL" />
|
|
||||||
</div>
|
|
||||||
<Input bind:value={link.text} placeholder="Text" />
|
|
||||||
<Combobox
|
|
||||||
bind:value={link.url}
|
|
||||||
placeholder="URL"
|
|
||||||
options={urlOptions}
|
options={urlOptions}
|
||||||
/>
|
{bindings}
|
||||||
<RoleSelect
|
|
||||||
bind:value={link.roleId}
|
|
||||||
placeholder="Minimum role"
|
|
||||||
/>
|
/>
|
||||||
<Icon
|
<Icon
|
||||||
name="Close"
|
name="Close"
|
||||||
hoverable
|
hoverable
|
||||||
size="S"
|
size="S"
|
||||||
on:click={() => removeLink(link.id)}
|
on:click={() => removeSubLink(subLink.id)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<div>
|
<div>
|
||||||
<Button secondary icon="Add" on:click={addLink}>Add Link</Button>
|
<ActionButton quiet icon="Add" on:click={addSubLink}>
|
||||||
|
Add link
|
||||||
|
</ActionButton>
|
||||||
</div>
|
</div>
|
||||||
</Layout>
|
</Layout>
|
||||||
</div>
|
</div>
|
||||||
|
@ -106,7 +103,7 @@
|
||||||
</Drawer>
|
</Drawer>
|
||||||
|
|
||||||
<div class="button">
|
<div class="button">
|
||||||
<ActionButton>No sub links</ActionButton>
|
<ActionButton on:click={drawer.show}>{buttonText}</ActionButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -118,14 +115,14 @@
|
||||||
max-width: 800px;
|
max-width: 800px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
.links {
|
.subLinks {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
gap: var(--spacing-m);
|
gap: var(--spacing-m);
|
||||||
}
|
}
|
||||||
.link {
|
.subLink {
|
||||||
gap: var(--spacing-l);
|
gap: var(--spacing-l);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
@ -134,15 +131,11 @@
|
||||||
border-radius: var(--border-radius-s);
|
border-radius: var(--border-radius-s);
|
||||||
transition: background-color ease-in-out 130ms;
|
transition: background-color ease-in-out 130ms;
|
||||||
}
|
}
|
||||||
.link:hover {
|
.subLink:hover {
|
||||||
background-color: var(--spectrum-global-color-gray-100);
|
background-color: var(--spectrum-global-color-gray-100);
|
||||||
}
|
}
|
||||||
.link > :global(.spectrum-Form-item) {
|
.subLink > :global(.spectrum-Form-item) {
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
width: 0;
|
width: 0;
|
||||||
}
|
}
|
||||||
.handle {
|
|
||||||
display: grid;
|
|
||||||
place-items: center;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Reference in New Issue