139 lines
3.5 KiB
Svelte
139 lines
3.5 KiB
Svelte
<script lang="ts">
|
|
import { createEventDispatcher } from "svelte";
|
|
|
|
import { currentDraggingElement } from "@graphite/io-managers/drag";
|
|
|
|
import type { LayerType, LayerTypeData } from "@graphite/wasm-communication/messages";
|
|
import { layerTypeData } from "@graphite/wasm-communication/messages";
|
|
|
|
import LayoutRow from "@graphite/components/layout/LayoutRow.svelte";
|
|
import IconButton from "@graphite/components/widgets/buttons/IconButton.svelte";
|
|
import IconLabel from "@graphite/components/widgets/labels/IconLabel.svelte";
|
|
import TextLabel from "@graphite/components/widgets/labels/TextLabel.svelte";
|
|
|
|
// emits: ["update:value"],
|
|
const dispatch = createEventDispatcher<{ value: string | undefined }>();
|
|
|
|
export let value: string | undefined = undefined;
|
|
export let layerName: string | undefined = undefined;
|
|
export let layerType: LayerType | undefined = undefined;
|
|
export let disabled = false;
|
|
export let tooltip: string | undefined = undefined;
|
|
export let sharpRightCorners = false;
|
|
|
|
let hoveringDrop = false;
|
|
|
|
$: droppable = hoveringDrop && Boolean(currentDraggingElement());
|
|
|
|
function dragOver(e: DragEvent): void {
|
|
hoveringDrop = true;
|
|
|
|
e.preventDefault();
|
|
}
|
|
|
|
function drop(e: DragEvent): void {
|
|
hoveringDrop = false;
|
|
|
|
const element = currentDraggingElement();
|
|
const layerPath = element?.getAttribute("data-layer") || undefined;
|
|
|
|
if (layerPath) {
|
|
e.preventDefault();
|
|
|
|
dispatch("value", layerPath);
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<LayoutRow
|
|
class="layer-reference-input"
|
|
classes={{ disabled, droppable, "sharp-right-corners": sharpRightCorners }}
|
|
{tooltip}
|
|
on:dragover={(e) => !disabled && dragOver(e)}
|
|
on:dragleave={() => !disabled && (hoveringDrop = false)}
|
|
on:drop={(e) => !disabled && drop(e)}
|
|
>
|
|
{#if value === undefined || droppable}
|
|
<LayoutRow class="drop-zone" />
|
|
<TextLabel italic={true}>{droppable ? "Drop" : "Drag"} Layer Here</TextLabel>
|
|
{:else}
|
|
{#if layerName !== undefined && layerType}
|
|
<IconLabel icon={layerTypeData(layerType).icon} class="layer-icon" />
|
|
<TextLabel italic={layerName === ""} class="layer-name">{layerName || `Untitled ${layerTypeData(layerType).name}`}</TextLabel>
|
|
{:else}
|
|
<TextLabel bold={true} italic={true} class="missing">Layer Missing</TextLabel>
|
|
{/if}
|
|
<IconButton icon="CloseX" size={16} {disabled} action={() => dispatch("value", undefined)} />
|
|
{/if}
|
|
</LayoutRow>
|
|
|
|
<style lang="scss" global>
|
|
.layer-reference-input {
|
|
position: relative;
|
|
flex: 1 0 auto;
|
|
height: 24px;
|
|
border-radius: 2px;
|
|
background: var(--color-1-nearblack);
|
|
|
|
.drop-zone {
|
|
pointer-events: none;
|
|
border: 1px dashed var(--color-4-dimgray);
|
|
border-radius: 1px;
|
|
position: absolute;
|
|
top: 2px;
|
|
bottom: 2px;
|
|
left: 2px;
|
|
right: 2px;
|
|
}
|
|
|
|
&.droppable .drop-zone {
|
|
border: 1px dashed var(--color-e-nearwhite);
|
|
}
|
|
|
|
.layer-icon {
|
|
margin: 4px 8px;
|
|
|
|
+ .text-label {
|
|
padding-left: 0;
|
|
}
|
|
}
|
|
|
|
.text-label {
|
|
line-height: 18px;
|
|
padding: 3px calc(8px + 2px);
|
|
width: 100%;
|
|
text-align: center;
|
|
|
|
&.missing {
|
|
// TODO: Define this as a permanent color palette choice (search the project for all uses of this hex code)
|
|
color: #d6536e;
|
|
}
|
|
|
|
&.layer-name {
|
|
text-align: left;
|
|
}
|
|
}
|
|
|
|
.icon-button {
|
|
margin: 4px;
|
|
margin-left: 0;
|
|
}
|
|
|
|
&.disabled {
|
|
background: var(--color-2-mildblack);
|
|
|
|
.drop-zone {
|
|
border: 1px dashed var(--color-4-dimgray);
|
|
}
|
|
|
|
.text-label {
|
|
color: var(--color-8-uppergray);
|
|
}
|
|
|
|
.icon-label svg {
|
|
fill: var(--color-8-uppergray);
|
|
}
|
|
}
|
|
}
|
|
</style>
|