|
<script lang="ts"> |
|
import { getContext } from "svelte"; |
|
|
|
import type { Editor } from "@graphite/editor"; |
|
import { isWidgetSpanRow, isWidgetSpanColumn, isWidgetSection, type WidgetSection as WidgetSectionFromJsMessages } from "@graphite/messages"; |
|
|
|
import LayoutCol from "@graphite/components/layout/LayoutCol.svelte"; |
|
import IconButton from "@graphite/components/widgets/buttons/IconButton.svelte"; |
|
import TextLabel from "@graphite/components/widgets/labels/TextLabel.svelte"; |
|
import WidgetSpan from "@graphite/components/widgets/WidgetSpan.svelte"; |
|
|
|
export let widgetData: WidgetSectionFromJsMessages; |
|
|
|
export let layoutTarget: any; |
|
|
|
let className = ""; |
|
export { className as class }; |
|
export let classes: Record<string, boolean> = {}; |
|
|
|
let expanded = true; |
|
|
|
const editor = getContext<Editor>("editor"); |
|
</script> |
|
|
|
|
|
<LayoutCol class={`widget-section ${className}`.trim()} {classes}> |
|
<button class="header" class:expanded on:click|stopPropagation={() => (expanded = !expanded)} tabindex="0"> |
|
<div class="expand-arrow" /> |
|
<TextLabel tooltip={widgetData.description} bold={true}>{widgetData.name}</TextLabel> |
|
<IconButton |
|
icon={widgetData.pinned ? "PinActive" : "PinInactive"} |
|
tooltip={widgetData.pinned ? "Unpin this node so it's no longer shown here when nothing is selected" : "Pin this node so it's shown here when nothing is selected"} |
|
size={24} |
|
action={(e) => { |
|
editor.handle.setNodePinned(widgetData.id, !widgetData.pinned); |
|
e?.stopPropagation(); |
|
}} |
|
class={"show-only-on-hover"} |
|
/> |
|
<IconButton |
|
icon={"Trash"} |
|
tooltip={"Delete this node from the layer chain"} |
|
size={24} |
|
action={(e) => { |
|
editor.handle.deleteNode(widgetData.id); |
|
e?.stopPropagation(); |
|
}} |
|
class={"show-only-on-hover"} |
|
/> |
|
<IconButton |
|
icon={widgetData.visible ? "EyeVisible" : "EyeHidden"} |
|
hoverIcon={widgetData.visible ? "EyeHide" : "EyeShow"} |
|
tooltip={widgetData.visible ? "Hide this node" : "Show this node"} |
|
size={24} |
|
action={(e) => { |
|
editor.handle.toggleNodeVisibilityLayerPanel(widgetData.id); |
|
e?.stopPropagation(); |
|
}} |
|
class={widgetData.visible ? "show-only-on-hover" : ""} |
|
/> |
|
</button> |
|
{#if expanded} |
|
<LayoutCol class="body"> |
|
{#each widgetData.layout as layoutGroup} |
|
{#if isWidgetSpanRow(layoutGroup)} |
|
<WidgetSpan widgetData={layoutGroup} {layoutTarget} /> |
|
{:else if isWidgetSpanColumn(layoutGroup)} |
|
<TextLabel styles={{ color: "#d6536e" }}>Error: The WidgetSpan used here should be a row not a column</TextLabel> |
|
{:else if isWidgetSection(layoutGroup)} |
|
<svelte:self widgetData={layoutGroup} {layoutTarget} /> |
|
{:else} |
|
<TextLabel styles={{ color: "#d6536e" }}>Error: The widget that belongs here has an invalid layout group type</TextLabel> |
|
{/if} |
|
{/each} |
|
</LayoutCol> |
|
{/if} |
|
</LayoutCol> |
|
|
|
<style lang="scss" global> |
|
.widget-section { |
|
flex: 0 0 auto; |
|
margin: 0 4px; |
|
margin-top: 4px; |
|
|
|
.header { |
|
text-align: left; |
|
align-items: center; |
|
display: flex; |
|
flex: 0 0 24px; |
|
padding-left: 8px; |
|
padding-right: 0; |
|
margin-bottom: 4px; |
|
border: 0; |
|
border-radius: 4px; |
|
background: var(--color-2-mildblack); |
|
|
|
&.expanded { |
|
border-radius: 4px 4px 0 0; |
|
margin-bottom: 0; |
|
|
|
.expand-arrow::after { |
|
transform: rotate(90deg); |
|
} |
|
} |
|
|
|
&:hover { |
|
background: var(--color-4-dimgray); |
|
|
|
.expand-arrow::after { |
|
background: var(--icon-expand-collapse-arrow-hover); |
|
} |
|
|
|
+ .body { |
|
border: 1px solid var(--color-4-dimgray); |
|
} |
|
} |
|
|
|
.expand-arrow { |
|
width: 8px; |
|
height: 8px; |
|
margin: 0; |
|
padding: 0; |
|
position: relative; |
|
flex: 0 0 auto; |
|
display: flex; |
|
align-items: center; |
|
justify-content: center; |
|
|
|
&::after { |
|
content: ""; |
|
position: absolute; |
|
width: 8px; |
|
height: 8px; |
|
background: var(--icon-expand-collapse-arrow); |
|
} |
|
} |
|
|
|
.text-label { |
|
height: 18px; |
|
margin-left: 8px; |
|
flex: 1 1 100%; |
|
} |
|
} |
|
|
|
&:not |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|