Hover component tree preview (#12465)
* wip * wip * linting * remove console log * highlighting a selected component in nav * PR feeddback * wip * pr feedback --------- Co-authored-by: Andrew Kingston <andrew@kingston.dev>
This commit is contained in:
parent
e7f1692cd5
commit
56cb92aa34
|
@ -85,6 +85,7 @@ const INITIAL_FRONTEND_STATE = {
|
||||||
selectedScreenId: null,
|
selectedScreenId: null,
|
||||||
selectedComponentId: null,
|
selectedComponentId: null,
|
||||||
selectedLayoutId: null,
|
selectedLayoutId: null,
|
||||||
|
hoverComponentId: null,
|
||||||
|
|
||||||
// Client state
|
// Client state
|
||||||
selectedComponentInstance: null,
|
selectedComponentInstance: null,
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
export let showTooltip = false
|
export let showTooltip = false
|
||||||
export let selectedBy = null
|
export let selectedBy = null
|
||||||
export let compact = false
|
export let compact = false
|
||||||
|
export let hovering = false
|
||||||
|
|
||||||
const scrollApi = getContext("scroll")
|
const scrollApi = getContext("scroll")
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
|
@ -61,6 +62,7 @@
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="nav-item"
|
class="nav-item"
|
||||||
|
class:hovering
|
||||||
class:border
|
class:border
|
||||||
class:selected
|
class:selected
|
||||||
class:withActions
|
class:withActions
|
||||||
|
@ -71,6 +73,8 @@
|
||||||
on:dragstart
|
on:dragstart
|
||||||
on:dragover
|
on:dragover
|
||||||
on:drop
|
on:drop
|
||||||
|
on:mouseenter
|
||||||
|
on:mouseleave
|
||||||
on:click={onClick}
|
on:click={onClick}
|
||||||
ondragover="return false"
|
ondragover="return false"
|
||||||
ondragenter="return false"
|
ondragenter="return false"
|
||||||
|
@ -152,15 +156,17 @@
|
||||||
--avatars-background: var(--spectrum-global-color-gray-200);
|
--avatars-background: var(--spectrum-global-color-gray-200);
|
||||||
}
|
}
|
||||||
.nav-item.selected {
|
.nav-item.selected {
|
||||||
background-color: var(--spectrum-global-color-gray-300);
|
background-color: var(--spectrum-global-color-gray-300) !important;
|
||||||
--avatars-background: var(--spectrum-global-color-gray-300);
|
--avatars-background: var(--spectrum-global-color-gray-300);
|
||||||
color: var(--ink);
|
color: var(--ink);
|
||||||
}
|
}
|
||||||
.nav-item:hover {
|
.nav-item:hover,
|
||||||
background-color: var(--spectrum-global-color-gray-300);
|
.hovering {
|
||||||
|
background-color: var(--spectrum-global-color-gray-200);
|
||||||
--avatars-background: var(--spectrum-global-color-gray-300);
|
--avatars-background: var(--spectrum-global-color-gray-300);
|
||||||
}
|
}
|
||||||
.nav-item:hover .actions {
|
.nav-item:hover .actions,
|
||||||
|
.hovering .actions {
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
}
|
}
|
||||||
.nav-item-content {
|
.nav-item-content {
|
||||||
|
|
|
@ -36,12 +36,14 @@
|
||||||
|
|
||||||
// Determine selected component ID
|
// Determine selected component ID
|
||||||
$: selectedComponentId = $store.selectedComponentId
|
$: selectedComponentId = $store.selectedComponentId
|
||||||
|
$: hoverComponentId = $store.hoverComponentId
|
||||||
|
|
||||||
$: previewData = {
|
$: previewData = {
|
||||||
appId: $store.appId,
|
appId: $store.appId,
|
||||||
layout,
|
layout,
|
||||||
screen,
|
screen,
|
||||||
selectedComponentId,
|
selectedComponentId,
|
||||||
|
hoverComponentId,
|
||||||
theme: $store.theme,
|
theme: $store.theme,
|
||||||
customTheme: $store.customTheme,
|
customTheme: $store.customTheme,
|
||||||
previewDevice: $store.previewDevice,
|
previewDevice: $store.previewDevice,
|
||||||
|
@ -117,6 +119,8 @@
|
||||||
error = event.error || "An unknown error occurred"
|
error = event.error || "An unknown error occurred"
|
||||||
} else if (type === "select-component" && data.id) {
|
} else if (type === "select-component" && data.id) {
|
||||||
$store.selectedComponentId = data.id
|
$store.selectedComponentId = data.id
|
||||||
|
} else if (type === "hover-component" && data.id) {
|
||||||
|
$store.hoverComponentId = data.id
|
||||||
} else if (type === "update-prop") {
|
} else if (type === "update-prop") {
|
||||||
await store.actions.components.updateSetting(data.prop, data.value)
|
await store.actions.components.updateSetting(data.prop, data.value)
|
||||||
} else if (type === "update-styles") {
|
} else if (type === "update-styles") {
|
||||||
|
|
|
@ -89,6 +89,17 @@
|
||||||
}
|
}
|
||||||
return findComponentPath($selectedComponent, component._id)?.length > 0
|
return findComponentPath($selectedComponent, component._id)?.length > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleMouseover = componentId => {
|
||||||
|
if ($store.hoverComponentId !== componentId) {
|
||||||
|
$store.hoverComponentId = componentId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const handleMouseout = componentId => {
|
||||||
|
if ($store.hoverComponentId === componentId) {
|
||||||
|
$store.hoverComponentId = null
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
@ -109,6 +120,9 @@
|
||||||
on:dragover={dragover(component, index)}
|
on:dragover={dragover(component, index)}
|
||||||
on:iconClick={() => toggleNodeOpen(component._id)}
|
on:iconClick={() => toggleNodeOpen(component._id)}
|
||||||
on:drop={onDrop}
|
on:drop={onDrop}
|
||||||
|
hovering={$store.hoverComponentId === component._id}
|
||||||
|
on:mouseenter={() => handleMouseover(component._id)}
|
||||||
|
on:mouseleave={() => handleMouseout(component._id)}
|
||||||
text={getComponentText(component)}
|
text={getComponentText(component)}
|
||||||
icon={getComponentIcon(component)}
|
icon={getComponentIcon(component)}
|
||||||
iconTooltip={getComponentName(component)}
|
iconTooltip={getComponentName(component)}
|
||||||
|
|
|
@ -32,6 +32,17 @@
|
||||||
const handleScroll = e => {
|
const handleScroll = e => {
|
||||||
scrolling = e.target.scrollTop !== 0
|
scrolling = e.target.scrollTop !== 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleMouseover = componentId => {
|
||||||
|
if ($store.hoverComponentId !== componentId) {
|
||||||
|
$store.hoverComponentId = componentId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const handleMouseout = componentId => {
|
||||||
|
if ($store.hoverComponentId === componentId) {
|
||||||
|
$store.hoverComponentId = null
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="components">
|
<div class="components">
|
||||||
|
@ -57,6 +68,12 @@
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
$store.selectedComponentId = `${$store.selectedScreenId}-screen`
|
$store.selectedComponentId = `${$store.selectedScreenId}-screen`
|
||||||
}}
|
}}
|
||||||
|
hovering={$store.hoverComponentId ===
|
||||||
|
`${$store.selectedScreenId}-screen`}
|
||||||
|
on:mouseenter={() =>
|
||||||
|
handleMouseover(`${$store.selectedScreenId}-screen`)}
|
||||||
|
on:mouseleave={() =>
|
||||||
|
handleMouseout(`${$store.selectedScreenId}-screen`)}
|
||||||
id={`component-screen`}
|
id={`component-screen`}
|
||||||
selectedBy={$userSelectedResourceMap[
|
selectedBy={$userSelectedResourceMap[
|
||||||
`${$store.selectedScreenId}-screen`
|
`${$store.selectedScreenId}-screen`
|
||||||
|
@ -78,6 +95,12 @@
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
$store.selectedComponentId = `${$store.selectedScreenId}-navigation`
|
$store.selectedComponentId = `${$store.selectedScreenId}-navigation`
|
||||||
}}
|
}}
|
||||||
|
hovering={$store.hoverComponentId ===
|
||||||
|
`${$store.selectedScreenId}-navigation`}
|
||||||
|
on:mouseenter={() =>
|
||||||
|
handleMouseover(`${$store.selectedScreenId}-navigation`)}
|
||||||
|
on:mouseleave={() =>
|
||||||
|
handleMouseout(`${$store.selectedScreenId}-navigation`)}
|
||||||
id={`component-nav`}
|
id={`component-nav`}
|
||||||
selectedBy={$userSelectedResourceMap[
|
selectedBy={$userSelectedResourceMap[
|
||||||
`${$store.selectedScreenId}-navigation`
|
`${$store.selectedScreenId}-navigation`
|
||||||
|
|
|
@ -3,8 +3,7 @@
|
||||||
import IndicatorSet from "./IndicatorSet.svelte"
|
import IndicatorSet from "./IndicatorSet.svelte"
|
||||||
import { builderStore, dndIsDragging } from "stores"
|
import { builderStore, dndIsDragging } from "stores"
|
||||||
|
|
||||||
let componentId
|
$: componentId = $builderStore.hoverComponentId
|
||||||
|
|
||||||
$: zIndex = componentId === $builderStore.selectedComponentId ? 900 : 920
|
$: zIndex = componentId === $builderStore.selectedComponentId ? 900 : 920
|
||||||
|
|
||||||
const onMouseOver = e => {
|
const onMouseOver = e => {
|
||||||
|
@ -24,12 +23,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newId !== componentId) {
|
if (newId !== componentId) {
|
||||||
componentId = newId
|
builderStore.actions.hoverComponent(newId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const onMouseLeave = () => {
|
const onMouseLeave = () => {
|
||||||
componentId = null
|
builderStore.actions.hoverComponent(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
|
|
|
@ -32,6 +32,7 @@ const loadBudibase = async () => {
|
||||||
layout: window["##BUDIBASE_PREVIEW_LAYOUT##"],
|
layout: window["##BUDIBASE_PREVIEW_LAYOUT##"],
|
||||||
screen: window["##BUDIBASE_PREVIEW_SCREEN##"],
|
screen: window["##BUDIBASE_PREVIEW_SCREEN##"],
|
||||||
selectedComponentId: window["##BUDIBASE_SELECTED_COMPONENT_ID##"],
|
selectedComponentId: window["##BUDIBASE_SELECTED_COMPONENT_ID##"],
|
||||||
|
hoverComponentId: window["##BUDIBASE_HOVER_COMPONENT_ID##"],
|
||||||
previewId: window["##BUDIBASE_PREVIEW_ID##"],
|
previewId: window["##BUDIBASE_PREVIEW_ID##"],
|
||||||
theme: window["##BUDIBASE_PREVIEW_THEME##"],
|
theme: window["##BUDIBASE_PREVIEW_THEME##"],
|
||||||
customTheme: window["##BUDIBASE_PREVIEW_CUSTOM_THEME##"],
|
customTheme: window["##BUDIBASE_PREVIEW_CUSTOM_THEME##"],
|
||||||
|
|
|
@ -8,6 +8,7 @@ const createBuilderStore = () => {
|
||||||
inBuilder: false,
|
inBuilder: false,
|
||||||
screen: null,
|
screen: null,
|
||||||
selectedComponentId: null,
|
selectedComponentId: null,
|
||||||
|
hoverComponentId: null,
|
||||||
editMode: false,
|
editMode: false,
|
||||||
previewId: null,
|
previewId: null,
|
||||||
theme: null,
|
theme: null,
|
||||||
|
@ -23,6 +24,16 @@ const createBuilderStore = () => {
|
||||||
}
|
}
|
||||||
const store = writable(initialState)
|
const store = writable(initialState)
|
||||||
const actions = {
|
const actions = {
|
||||||
|
hoverComponent: id => {
|
||||||
|
if (id === get(store).hoverComponentId) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
store.update(state => ({
|
||||||
|
...state,
|
||||||
|
hoverComponentId: id,
|
||||||
|
}))
|
||||||
|
eventStore.actions.dispatchEvent("hover-component", { id })
|
||||||
|
},
|
||||||
selectComponent: id => {
|
selectComponent: id => {
|
||||||
if (id === get(store).selectedComponentId) {
|
if (id === get(store).selectedComponentId) {
|
||||||
return
|
return
|
||||||
|
|
|
@ -63,6 +63,7 @@
|
||||||
// Extract data from message
|
// Extract data from message
|
||||||
const {
|
const {
|
||||||
selectedComponentId,
|
selectedComponentId,
|
||||||
|
hoverComponentId,
|
||||||
layout,
|
layout,
|
||||||
screen,
|
screen,
|
||||||
appId,
|
appId,
|
||||||
|
@ -81,6 +82,7 @@
|
||||||
window["##BUDIBASE_PREVIEW_LAYOUT##"] = layout
|
window["##BUDIBASE_PREVIEW_LAYOUT##"] = layout
|
||||||
window["##BUDIBASE_PREVIEW_SCREEN##"] = screen
|
window["##BUDIBASE_PREVIEW_SCREEN##"] = screen
|
||||||
window["##BUDIBASE_SELECTED_COMPONENT_ID##"] = selectedComponentId
|
window["##BUDIBASE_SELECTED_COMPONENT_ID##"] = selectedComponentId
|
||||||
|
window["##BUDIBASE_HOVER_COMPONENT_ID##"] = hoverComponentId
|
||||||
window["##BUDIBASE_PREVIEW_ID##"] = Math.random()
|
window["##BUDIBASE_PREVIEW_ID##"] = Math.random()
|
||||||
window["##BUDIBASE_PREVIEW_THEME##"] = theme
|
window["##BUDIBASE_PREVIEW_THEME##"] = theme
|
||||||
window["##BUDIBASE_PREVIEW_CUSTOM_THEME##"] = customTheme
|
window["##BUDIBASE_PREVIEW_CUSTOM_THEME##"] = customTheme
|
||||||
|
|
Loading…
Reference in New Issue