Update screen components hierarchy to use new common component styles
This commit is contained in:
parent
350083025d
commit
8e6b4f1aeb
|
@ -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>
|
|
@ -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">
|
||||
<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} />
|
||||
</div>
|
||||
</div>
|
||||
</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>
|
||||
|
|
|
@ -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">
|
||||
text={isScreenslot(component._component) ? 'Screenslot' : component._instanceName}
|
||||
withArrow
|
||||
indentLevel={level + 1}
|
||||
selected={currentComponent === component}>
|
||||
<ComponentDropdownMenu {component} />
|
||||
</div>
|
||||
</div>
|
||||
</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>
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue