67 lines
3.1 KiB
Vue
67 lines
3.1 KiB
Vue
<template>
|
|
<div class="absolute overflow-visible h-px w-px">
|
|
<div v-if="edge.label" :style="{ transform: labelPos }" class="relative bg-light-20 dark:bg-dark-20 border border-light-35 dark:border-dark-35 px-4 py-2 -translate-x-[50%] -translate-y-[50%]">{{ edge.label }}</div>
|
|
<input v-else-if="editing" @click="e => e.stopImmediatePropagation()" :style="{ transform: `${labelPos} translate(-50%, -50%)` }" class="relative bg-light-20 dark:bg-dark-20 border border-light-35 dark:border-dark-35 px-4 py-2 z-20" :v-model="edge.label" />
|
|
<svg ref="dom" class="absolute top-0 overflow-visible h-px w-px" @click="select" @dblclick="edit">
|
|
<g :style="{'--canvas-color': edge.color?.hex}" class="z-0">
|
|
<path :style="`stroke-linecap: butt; stroke-width: calc(3px * var(--zoom-multiplier));`" :class="[edge.color?.class ? `stroke-light-${edge.color.class} dark:stroke-dark-${edge.color.class}` : ((edge.color && edge.color?.hex !== undefined) ? 'stroke-[color:var(--canvas-color)]' : 'stroke-light-40 dark:stroke-dark-40'), { 'outline-4': focusing }]" class="fill-none stroke-[4px]" :d="path!.path"></path>
|
|
<g :style="`transform: translate(${path!.to.x}px, ${path!.to.y}px) scale(var(--zoom-multiplier)) rotate(${rotation[path!.side]}deg);`">
|
|
<polygon :class="edge.color?.class ? `fill-light-${edge.color.class} dark:fill-dark-${edge.color.class}` : ((edge.color && edge.color?.hex !== undefined) ? 'fill-[color:var(--canvas-color)]' : 'fill-light-40 dark:fill-dark-40')" points="0,0 6.5,10.4 -6.5,10.4"></polygon>
|
|
</g>
|
|
</g>
|
|
</svg>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { getPath, labelCenter, type Direction } from '#shared/canvas.util';
|
|
import type { Element } from '../CanvasEditor.vue';
|
|
import type { CanvasEdge, CanvasNode } from '~/types/canvas';
|
|
|
|
const rotation: Record<Direction, string> = {
|
|
top: "180",
|
|
bottom: "0",
|
|
left: "90",
|
|
right: "270"
|
|
};
|
|
|
|
const { edge, nodes } = defineProps<{
|
|
edge: CanvasEdge
|
|
nodes: CanvasNode[]
|
|
}>();
|
|
|
|
const emit = defineEmits<{
|
|
(e: 'select', id: Element): void,
|
|
(e: 'edit', id: Element): void,
|
|
(e: 'move', id: string, from: string, to: string): void,
|
|
}>();
|
|
|
|
const dom = useTemplateRef('dom');
|
|
const focusing = ref(false), editing = ref(false);
|
|
|
|
const from = computed(() => nodes!.find(f => f.id === edge.fromNode))
|
|
const to = computed(() => nodes!.find(f => f.id === edge.toNode));
|
|
const path = computed(() => getPath(from.value!, edge.fromSide, to.value!, edge.toSide));
|
|
const labelPos = computed(() => labelCenter(from.value!, edge.fromSide, to.value!, edge.toSide));
|
|
|
|
function select(e: Event) {
|
|
if(editing.value)
|
|
return;
|
|
|
|
focusing.value = true;
|
|
emit('select', { type: 'edge', id: edge.id });
|
|
}
|
|
function edit(e: Event) {
|
|
focusing.value = true;
|
|
editing.value = true;
|
|
|
|
e.stopImmediatePropagation();
|
|
emit('edit', { type: 'edge', id: edge.id });
|
|
}
|
|
function unselect() {
|
|
focusing.value = false;
|
|
editing.value = false;
|
|
}
|
|
|
|
defineExpose({ unselect, dom, id: edge.id });
|
|
</script> |