Update screen components hierarchy to use new common component styles

This commit is contained in:
Andrew Kingston 2020-10-22 17:42:03 +01:00
parent 350083025d
commit 8e6b4f1aeb
4 changed files with 159 additions and 213 deletions

View File

@ -0,0 +1,108 @@
<script>
export let icon
export let withArrow = false
export let withActions = true
export let indentLevel = 0
export let text
export let border = true
export let selected = false
export let opened = false
export let draggable = false
</script>
<div
class="container"
class:border
class:selected
style={`padding-left: ${indentLevel * 18}px`}
{draggable}
on:dragend
on:dragstart
on:dragover
on:drop
on:click
ondragover="return false"
ondragenter="return false">
<div class="content">
{#if withArrow}
<div class:opened class="icon arrow">
<i class="ri-arrow-right-s-fill" />
</div>
{/if}
{#if icon}
<div class="icon"><i class={icon} /></div>
{/if}
<div class="text">{text}</div>
{#if withActions}
<div class="actions">
<slot />
</div>
{/if}
</div>
</div>
<style>
.container {
border-radius: var(--border-radius-m);
cursor: pointer;
color: var(--grey-7);
}
.container.border {
border-top: 1px solid var(--grey-1);
}
.container.selected {
background-color: var(--grey-2);
color: var(--ink);
}
.container:hover {
background-color: var(--grey-1);
}
.container:hover .actions {
display: flex;
}
.content {
padding: 0 var(--spacing-m);
height: 32px;
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
gap: var(--spacing-xs);
}
.icon {
font-size: 16px;
flex: 0 0 20px;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
.icon.arrow {
margin: 0 -2px 0 -6px;
}
.icon.arrow.opened {
transform: rotate(90deg);
}
.icon + .icon {
margin-left: -4px;
}
.text {
flex: 1 1 auto;
font-weight: 500;
font-size: var(--font-size-xs);
}
.actions {
display: none;
width: 20px;
height: 20px;
cursor: pointer;
position: relative;
flex-direction: row;
justify-content: center;
align-items: center;
}
</style>

View File

@ -1,13 +1,12 @@
<script>
import { params, goto } from "@sveltech/routify"
import { goto } from "@sveltech/routify"
import ComponentsHierarchyChildren from "./ComponentsHierarchyChildren.svelte"
import { last, sortBy, map, trimCharsStart, trimChars, join } from "lodash/fp"
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
import { trimCharsStart, trimChars } from "lodash/fp"
import { pipe } from "components/common/core"
import { store } from "builderStore"
import { ArrowDownIcon, ShapeIcon } from "components/common/Icons/"
import ScreenDropdownMenu from "./ScreenDropdownMenu.svelte"
import { writable } from "svelte/store"
import NavItem from "components/common/NavItem.svelte"
export let screens = []
@ -24,9 +23,7 @@
let confirmDeleteDialog
let componentToDelete = ""
const joinPath = join("/")
const normalizedName = name =>
const normalizedName = (name) =>
pipe(name, [
trimCharsStart("./"),
trimCharsStart("~/"),
@ -34,7 +31,7 @@
trimChars(" "),
])
const changeScreen = screen => {
const changeScreen = (screen) => {
store.setCurrentScreen(screen.props._instanceName)
$goto(`./:page/${screen.props._instanceName}`)
}
@ -42,26 +39,15 @@
<div class="root">
{#each sortedScreens as screen}
<div
class="budibase__nav-item screen-header-row"
class:selected={$store.currentComponentInfo._id === screen.props._id}
on:click|stopPropagation={() => changeScreen(screen)}>
<span
class="icon"
class:rotate={$store.currentPreviewItem.name !== screen.props._instanceName}>
{#if screen.props._children.length}
<ArrowDownIcon />
{/if}
</span>
<i class="ri-artboard-2-fill icon" />
<span class="title">{screen.props._instanceName}</span>
<div class="dropdown-menu">
<ScreenDropdownMenu {screen} />
</div>
</div>
<NavItem
icon="ri-artboard-2-line"
text={screen.props._instanceName}
withArrow={screen.props._children.length}
selected={$store.currentComponentInfo._id === screen.props._id}
opened={$store.currentPreviewItem.name !== screen.props._id}
on:click={() => changeScreen(screen)}>
<ScreenDropdownMenu {screen} />
</NavItem>
{#if $store.currentPreviewItem.props._instanceName && $store.currentPreviewItem.props._instanceName === screen.props._instanceName && screen.props._children}
<ComponentsHierarchyChildren
@ -71,55 +57,3 @@
{/if}
{/each}
</div>
<style>
.root {
font-weight: 400;
color: var(--ink);
}
.screen-header-row {
display: flex;
flex-direction: row;
}
.title {
margin-left: 14px;
font-size: 14px;
font-weight: 400;
flex: 1;
}
.icon {
display: inline-block;
transition: 0.2s;
font-size: 24px;
width: 18px;
color: var(--grey-7);
}
.icon:nth-of-type(2) {
width: 14px;
margin: 0 0 0 5px;
}
.rotate :global(svg) {
transform: rotate(-90deg);
}
.dropdown-menu {
display: none;
color: var(--ink);
padding: 0 5px;
width: 24px;
height: 24px;
border-style: none;
background: rgba(0, 0, 0, 0);
cursor: pointer;
position: relative;
}
.budibase__nav-item:hover .dropdown-menu {
display: block;
}
</style>

View File

@ -4,12 +4,7 @@
import { last } from "lodash/fp"
import { pipe } from "components/common/core"
import ComponentDropdownMenu from "./ComponentDropdownMenu.svelte"
import {
XCircleIcon,
ChevronUpIcon,
ChevronDownIcon,
CopyIcon,
} from "../common/Icons"
import NavItem from "components/common/NavItem.svelte"
import { getComponentDefinition } from "builderStore/storeUtils"
export let components = []
@ -38,13 +33,12 @@
let dropUnderComponent
let componentToDrop
const capitalise = s => s.substring(0, 1).toUpperCase() + s.substring(1)
const get_name = s => (!s ? "" : last(s.split("/")))
const capitalise = (s) => s.substring(0, 1).toUpperCase() + s.substring(1)
const get_name = (s) => (!s ? "" : last(s.split("/")))
const get_capitalised_name = (name) => pipe(name, [get_name, capitalise])
const isScreenslot = (name) => name === "##builtin/screenslot"
const get_capitalised_name = name => pipe(name, [get_name, capitalise])
const isScreenslot = name => name === "##builtin/screenslot"
const selectComponent = component => {
const selectComponent = (component) => {
// Set current component
store.selectComponent(component)
@ -55,21 +49,21 @@
$goto(`./:page/:screen/${path}`)
}
const dragstart = component => e => {
const dragstart = (component) => (e) => {
e.dataTransfer.dropEffect = "move"
dragDropStore.update(s => {
dragDropStore.update((s) => {
s.componentToDrop = component
return s
})
}
const dragover = (component, index) => e => {
const dragover = (component, index) => (e) => {
const canHaveChildrenButIsEmpty =
getComponentDefinition($store, component._component).children &&
component._children.length === 0
e.dataTransfer.dropEffect = "copy"
dragDropStore.update(s => {
dragDropStore.update((s) => {
const isBottomHalf = e.offsetY > e.currentTarget.offsetHeight / 2
s.targetComponent = component
// only allow dropping inside when container type
@ -108,7 +102,7 @@
$dragDropStore.dropPosition
)
}
dragDropStore.update(s => {
dragDropStore.update((s) => {
s.dropPosition = ""
s.targetComponent = null
s.componentToDrop = null
@ -117,7 +111,7 @@
}
const dragend = () => {
dragDropStore.update(s => {
dragDropStore.update((s) => {
s.dropPosition = ""
s.targetComponent = null
s.componentToDrop = null
@ -134,29 +128,22 @@
on:drop={drop}
ondragover="return false"
ondragenter="return false"
class="budibase__nav-item item drop-item"
style="margin-left: {level * 20 + 40}px" />
class="drop-item"
style="margin-left: {(level + 1) * 18}px" />
{/if}
<div
class="budibase__nav-item item"
class:selected={currentComponent === component}
style="padding-left: {level * 20 + 40}px"
draggable={true}
<NavItem
draggable
on:dragend={dragend}
on:dragstart={dragstart(component)}
on:dragover={dragover(component, index)}
on:drop={drop}
ondragover="return false"
ondragenter="return false">
<div class="nav-item">
<i class="icon ri-arrow-right-circle-line" />
{isScreenslot(component._component) ? 'Screenslot' : component._instanceName}
</div>
<div class="actions">
<ComponentDropdownMenu {component} />
</div>
</div>
text={isScreenslot(component._component) ? 'Screenslot' : component._instanceName}
withArrow
indentLevel={level + 1}
selected={currentComponent === component}>
<ComponentDropdownMenu {component} />
</NavItem>
{#if component._children}
<svelte:self
@ -172,8 +159,8 @@
on:drop={drop}
ondragover="return false"
ondragenter="return false"
class="budibase__nav-item item drop-item"
style="margin-left: {(level + ($dragDropStore.dropPosition === 'inside' ? 2 : 0)) * 20 + 40}px" />
class="drop-item"
style="margin-left: {(level + ($dragDropStore.dropPosition === 'inside' ? 3 : 1)) * 18}px" />
{/if}
</li>
{/each}
@ -186,47 +173,9 @@
margin: 0;
}
.item {
display: grid;
grid-template-columns: 1fr auto auto auto;
padding: 0 var(--spacing-m);
margin: 0;
border-radius: var(--border-radius-m);
height: 36px;
align-items: center;
}
.drop-item {
border-radius: var(--border-radius-m);
height: 32px;
background: var(--blue-light);
height: 36px;
}
.actions {
display: none;
color: var(--ink);
border-style: none;
background: rgba(0, 0, 0, 0);
cursor: pointer;
position: relative;
}
.item:hover {
background: var(--grey-1);
cursor: pointer;
}
.item:hover .actions {
display: block;
}
.nav-item {
display: flex;
align-items: center;
font-size: 14px;
color: var(--ink);
}
.icon {
color: var(--grey-7);
margin-right: 8px;
}
</style>

View File

@ -1,21 +1,9 @@
<script>
import { goto } from "@sveltech/routify"
// import { tick } from "svelte"
import ComponentsHierarchyChildren from "./ComponentsHierarchyChildren.svelte"
import {
last,
sortBy,
map,
trimCharsStart,
trimChars,
join,
compose,
} from "lodash/fp"
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
import { pipe } from "components/common/core"
import NavItem from "components/common/NavItem.svelte"
import { last } from "lodash/fp"
import { store } from "builderStore"
import { ArrowDownIcon, GridIcon } from "components/common/Icons/"
import { writable } from "svelte/store"
export let layout
@ -24,13 +12,10 @@
let componentToDelete = ""
const dragDropStore = writable({})
const joinPath = join("/")
const lastPartOfName = c =>
const lastPartOfName = (c) =>
c && last(c.name ? c.name.split("/") : c._component.split("/"))
const isComponentSelected = (current, comp) => current === comp
$: _layout = {
component: layout,
title: lastPartOfName(layout),
@ -42,18 +27,14 @@
}
</script>
<div
class="budibase__nav-item root"
class:selected={$store.currentComponentInfo._id === _layout.component.props._id}
on:click|stopPropagation={setCurrentScreenToLayout}>
<span
class="icon"
class:rotate={$store.currentPreviewItem.name !== _layout.title}>
<ArrowDownIcon />
</span>
<i class="ri-layout-3-fill icon-big" />
<span class="title">Master Screen</span>
</div>
<NavItem
border={false}
icon="ri-layout-3-line"
text="Master Screen"
withArrow
selected={$store.currentComponentInfo._id === _layout.component.props._id}
opened={$store.currentPreviewItem.name === _layout.title}
on:click={setCurrentScreenToLayout} />
{#if $store.currentPreviewItem.name === _layout.title && _layout.component.props._children}
<ComponentsHierarchyChildren
@ -62,29 +43,3 @@
currentComponent={$store.currentComponentInfo}
{dragDropStore} />
{/if}
<style>
.title {
margin-left: 10px;
font-size: 14px;
font-weight: 400;
color: var(--ink);
}
.icon {
width: 24px;
display: inline-block;
transition: 0.2s;
width: 20px;
color: var(--grey-7);
}
.icon-big {
font-size: 20px;
color: var(--grey-7);
}
.rotate :global(svg) {
transform: rotate(-90deg);
}
</style>