feat: implement workspaces
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
<script lang="ts" setup>
|
||||
import EdgeWrapper from '../../components/Edges/EdgeWrapper.vue'
|
||||
import ConnectionLine from '../../components/ConnectionLine/ConnectionLine.vue'
|
||||
import { useVueFlow } from '../../composables'
|
||||
import { groupEdgesByZLevel } from '../../utils'
|
||||
import MarkerDefinitions from './MarkerDefinitions.vue'
|
||||
|
||||
const { store } = useVueFlow()
|
||||
|
||||
const sourceNode = controlledComputed(
|
||||
() => store.connectionNodeId,
|
||||
() => {
|
||||
if (store.connectionNodeId) return store.getNodes[store.getNodes.map((n) => n.id).indexOf(store.connectionNodeId)]
|
||||
},
|
||||
)
|
||||
const connectionLineVisible = controlledComputed(
|
||||
() => store.connectionNodeId,
|
||||
() =>
|
||||
!!(
|
||||
sourceNode.value &&
|
||||
(typeof sourceNode.value.connectable === 'undefined' ? store.nodesConnectable : sourceNode.value.connectable) &&
|
||||
store.connectionNodeId &&
|
||||
store.connectionHandleType
|
||||
),
|
||||
)
|
||||
const groups = computed(() => groupEdgesByZLevel(store.getEdges, store.getNodes))
|
||||
</script>
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'Edges',
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<svg
|
||||
v-for="group of groups"
|
||||
:key="group.level"
|
||||
:width="store.dimensions.width"
|
||||
:height="store.dimensions.height"
|
||||
class="vue-flow__edges vue-flow__container"
|
||||
:style="`z-index: ${group.level}`"
|
||||
>
|
||||
<MarkerDefinitions v-if="group.isMaxLevel" :default-color="store.defaultMarkerColor" />
|
||||
<g>
|
||||
<EdgeWrapper
|
||||
v-for="edge of group.edges"
|
||||
:id="edge.id"
|
||||
:key="edge.id"
|
||||
:selectable="typeof edge.selectable === 'undefined' ? store.elementsSelectable : edge.selectable"
|
||||
:updatable="typeof edge.updatable === 'undefined' ? store.edgesUpdatable : edge.updatable"
|
||||
>
|
||||
<template #default="edgeProps">
|
||||
<slot v-if="edge.type" :name="`edge-${edge.type}`" v-bind="edgeProps"></slot>
|
||||
</template>
|
||||
</EdgeWrapper>
|
||||
<ConnectionLine v-if="connectionLineVisible && sourceNode" :source-node="sourceNode">
|
||||
<template #default="customConnectionLineProps">
|
||||
<slot name="connection-line" v-bind="customConnectionLineProps"></slot>
|
||||
</template>
|
||||
</ConnectionLine>
|
||||
</g>
|
||||
</svg>
|
||||
</template>
|
||||
@@ -0,0 +1,49 @@
|
||||
<script lang="ts" setup>
|
||||
import type { MarkerProps } from '../../types/edge'
|
||||
|
||||
const props = withDefaults(defineProps<MarkerProps>(), {
|
||||
width: 12.5,
|
||||
height: 12.5,
|
||||
markerUnits: 'strokeWidth',
|
||||
orient: 'auto',
|
||||
strokeWidth: 1,
|
||||
color: 'none',
|
||||
})
|
||||
</script>
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'Marker',
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<marker
|
||||
:id="props.id"
|
||||
class="vue-flow__arrowhead"
|
||||
viewBox="-10 -10 20 20"
|
||||
refX="0"
|
||||
refY="0"
|
||||
:markerWidth="`${props.width}`"
|
||||
:markerHeight="`${props.height}`"
|
||||
:markerUnits="props.markerUnits"
|
||||
:orient="props.orient"
|
||||
>
|
||||
<polyline
|
||||
v-if="props.type === 'arrowclosed'"
|
||||
:stroke="props.color"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
:stroke-width="props.strokeWidth"
|
||||
:fill="props.color"
|
||||
points="-5,-4 0,0 -5,4 -5,-4"
|
||||
/>
|
||||
<polyline
|
||||
v-if="props.type === 'arrow'"
|
||||
:stroke="props.color"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
:stroke-width="props.strokeWidth"
|
||||
fill="none"
|
||||
points="-5,-4 0,0 -5,4"
|
||||
/>
|
||||
</marker>
|
||||
</template>
|
||||
@@ -0,0 +1,55 @@
|
||||
<script lang="ts" setup>
|
||||
import { useVueFlow } from '../../composables'
|
||||
import type { MarkerProps } from '../../types/edge'
|
||||
import { getMarkerId } from '../../utils'
|
||||
import { MarkerType } from '../../types/edge'
|
||||
import Marker from './Marker.vue'
|
||||
|
||||
interface MarkerDefinitionsProps {
|
||||
defaultColor: string
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<MarkerDefinitionsProps>(), {
|
||||
defaultColor: '',
|
||||
})
|
||||
const { store } = useVueFlow()
|
||||
|
||||
const markers = computed(() => {
|
||||
const ids: string[] = []
|
||||
|
||||
return store.edges.reduce<MarkerProps[]>((markers, edge) => {
|
||||
;[edge.markerStart, edge.markerEnd].forEach((marker) => {
|
||||
if (marker) {
|
||||
const markerId = getMarkerId(marker)
|
||||
if (!ids.includes(markerId)) {
|
||||
if (typeof marker === 'object') markers.push({ ...marker, id: markerId, color: marker.color || props.defaultColor })
|
||||
else markers.push({ id: markerId, color: props.defaultColor, type: marker as MarkerType })
|
||||
ids.push(markerId)
|
||||
}
|
||||
}
|
||||
})
|
||||
return markers.sort((a, b) => a.id.localeCompare(b.id))
|
||||
}, [])
|
||||
})
|
||||
</script>
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'MarkerDefinitions',
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<defs>
|
||||
<Marker
|
||||
v-for="marker of markers"
|
||||
:id="marker.id"
|
||||
:key="marker.id"
|
||||
:type="marker.type"
|
||||
:color="marker.color"
|
||||
:width="marker.width"
|
||||
:height="marker.height"
|
||||
:markerUnits="marker.markerUnits"
|
||||
:stroke-width="marker.strokeWidth"
|
||||
:orient="marker.orient"
|
||||
/>
|
||||
</defs>
|
||||
</template>
|
||||
Reference in New Issue
Block a user