refactor(additional-components): move additional components into separate pkg

This commit is contained in:
braks
2022-10-08 23:25:34 +02:00
committed by Braks
parent 8567e3733b
commit c1bcc02797
82 changed files with 934 additions and 222 deletions
@@ -0,0 +1,165 @@
<script lang="ts" setup>
import type { GraphNode } from '@vue-flow/core'
import { getBoundsofRects, getConnectedEdges, getRectOfNodes, useVueFlow } from '@vue-flow/core'
import type { MiniMapNodeFunc, MiniMapProps, ShapeRendering } from './types'
import MiniMapNode from './MiniMapNode'
const {
width,
height,
nodeStrokeColor = '#555',
nodeColor = '#fff',
nodeClassName,
nodeBorderRadius = 5,
nodeStrokeWidth = 2,
maskColor = 'rgb(240, 242, 243, 0.7)',
} = defineProps<MiniMapProps>()
const emit = defineEmits(['nodeClick', 'nodeDblclick', 'nodeMouseenter', 'nodeMousemove', 'nodeMouseleave'])
const attrs: Record<string, any> = useAttrs()
const defaultWidth = 200
const defaultHeight = 150
const { edges, viewport, dimensions, emits, getNodes } = useVueFlow()
const elementWidth = $computed(() => width ?? attrs.style?.width ?? defaultWidth)
const elementHeight = $computed(() => height ?? attrs.style?.height ?? defaultHeight)
const nodeColorFunc: MiniMapNodeFunc = nodeColor instanceof Function ? nodeColor : () => nodeColor as string
const nodeStrokeColorFunc: MiniMapNodeFunc =
nodeStrokeColor instanceof Function ? nodeStrokeColor : () => nodeStrokeColor as string
const nodeClassNameFunc = nodeClassName instanceof Function ? nodeClassName : ((() => nodeClassName) as MiniMapNodeFunc)
const shapeRendering: ShapeRendering = typeof window === 'undefined' || !!window.chrome ? 'crispEdges' : 'geometricPrecision'
const bb = $computed(() => getRectOfNodes(getNodes.value))
const viewBB = $computed(() => ({
x: -viewport.value.x / viewport.value.zoom,
y: -viewport.value.y / viewport.value.zoom,
width: dimensions.value.width / viewport.value.zoom,
height: dimensions.value.height / viewport.value.zoom,
}))
const viewBox = $(
controlledComputed($$(viewBB), () => {
const boundingRect = getNodes && getNodes.value.length ? getBoundsofRects(bb, viewBB) : viewBB
const scaledWidth = boundingRect.width / elementWidth
const scaledHeight = boundingRect.height / elementHeight
const viewScale = Math.max(scaledWidth, scaledHeight)
const viewWidth = viewScale * elementWidth
const viewHeight = viewScale * elementHeight
const offset = 5 * viewScale
return {
offset,
x: boundingRect.x - (viewWidth - boundingRect.width) / 2 - offset,
y: boundingRect.y - (viewHeight - boundingRect.height) / 2 - offset,
width: viewWidth + offset * 2,
height: viewHeight + offset * 2,
}
}),
)
const d = controlledComputed($$(viewBox), () => {
if (viewBox.x && viewBox.y) {
return `
M${viewBox.x - viewBox.offset},${viewBox.y - viewBox.offset}
h${viewBox.width + viewBox.offset * 2}
v${viewBox.height + viewBox.offset * 2}
h${-viewBox.width - viewBox.offset * 2}z
M${viewBB.x},${viewBB.y}
h${viewBB.width}
v${viewBB.height}
h${-viewBB.width}z`
} else {
return ''
}
})
const onNodeClick = (event: MouseEvent, node: GraphNode) => {
const param = { event, node, connectedEdges: getConnectedEdges([node], edges.value) }
emits.miniMapNodeClick(param)
emit('nodeClick', param)
}
const onNodeDblClick = (event: MouseEvent, node: GraphNode) => {
const param = { event, node, connectedEdges: getConnectedEdges([node], edges.value) }
emits.miniMapNodeDoubleClick(param)
emit('nodeDblclick', param)
}
const onNodeMouseEnter = (event: MouseEvent, node: GraphNode) => {
const param = { event, node, connectedEdges: getConnectedEdges([node], edges.value) }
emits.miniMapNodeMouseEnter(param)
emit('nodeMouseenter', param)
}
const onNodeMouseMove = (event: MouseEvent, node: GraphNode) => {
const param = { event, node, connectedEdges: getConnectedEdges([node], edges.value) }
emits.miniMapNodeMouseMove(param)
emit('nodeMousemove', param)
}
const onNodeMouseLeave = (event: MouseEvent, node: GraphNode) => {
const param = { event, node, connectedEdges: getConnectedEdges([node], edges.value) }
emits.miniMapNodeMouseLeave(param)
emit('nodeMouseleave', param)
}
</script>
<script lang="ts">
export default {
name: 'MiniMap',
}
</script>
<template>
<svg
:width="elementWidth"
:height="elementHeight"
:viewBox="[viewBox.x, viewBox.y, viewBox.width, viewBox.height].join(' ')"
class="vue-flow__minimap"
>
<MiniMapNode
v-for="node of getNodes"
:id="node.id"
:key="node.id"
:position="node.computedPosition"
:dimensions="node.dimensions"
:style="node.style"
:class="nodeClassNameFunc(node)"
:color="nodeColorFunc(node)"
:border-radius="nodeBorderRadius"
:stroke-color="nodeStrokeColorFunc(node)"
:stroke-width="nodeStrokeWidth"
:shape-rendering="shapeRendering"
@click="onNodeClick($event, node)"
@dblclick="onNodeDblClick($event, node)"
@mouseenter="onNodeMouseEnter($event, node)"
@mousemove="onNodeMouseMove($event, node)"
@mouseleave="onNodeMouseLeave($event, node)"
>
<slot
:id="node.id"
:name="`node-${node.type}`"
:parent-node="node.parentNode"
:selected="node.selected"
:position="node.computedPosition"
:dimensions="node.dimensions"
:style="node.style"
:class="nodeClassNameFunc(node)"
:color="nodeColorFunc(node)"
:border-radius="nodeBorderRadius"
:stroke-color="nodeStrokeColorFunc(node)"
:stroke-width="nodeStrokeWidth"
:shape-rendering="shapeRendering"
/>
</MiniMapNode>
<path class="vue-flow__minimap-mask" :d="d" :fill="maskColor" fill-rule="evenodd" />
</svg>
</template>
@@ -0,0 +1,46 @@
import type { CSSProperties, FunctionalComponent } from 'vue'
import type { MiniMapNodeProps } from './types'
const MiniMapNode: FunctionalComponent<MiniMapNodeProps> = function (
{
position: { x, y },
dimensions: { height, width },
strokeWidth,
strokeColor,
borderRadius,
color,
shapeRendering = 'geometricPrecision',
},
{ attrs, emit, slots },
) {
const style = (attrs.style ?? {}) as CSSProperties
return [
h('rect', {
class: ['vue-flow__minimap-node', attrs.class].join(' '),
style,
x,
y,
rx: borderRadius,
ry: borderRadius,
width,
height,
fill: color || (style.background as string) || style.backgroundColor,
stroke: strokeColor,
strokeWidth,
shapeRendering,
onClick: (e: MouseEvent) => emit('click', e),
onDblClick: (e: MouseEvent) => emit('dblclick', e),
onMouseenter: (e: MouseEvent) => emit('mouseenter', e),
onMousemove: (e: MouseEvent) => emit('mousemove', e),
onMouseleave: (e: MouseEvent) => emit('mouseleave', e),
}),
slots?.default?.(),
]
}
MiniMapNode.props = ['position', 'dimensions', 'strokeWidth', 'strokeColor', 'borderRadius', 'color', 'shapeRendering']
MiniMapNode.emits = ['click', 'dblclick', 'mouseenter', 'mousemove', 'mouseleave']
export default MiniMapNode
@@ -0,0 +1,4 @@
export { default as MiniMap } from './MiniMap.vue'
export { default as MiniMapNode } from './MiniMapNode'
export * from './types'
@@ -0,0 +1,43 @@
import type { Dimensions, GraphNode, XYPosition } from '@vue-flow/core'
import type { CSSProperties } from 'vue'
/** expects a node and returns a color value */
export type MiniMapNodeFunc = (node: GraphNode) => string
// hack for vue-type imports
type MiniMapNodeFunc2 = (node: GraphNode) => string
type MiniMapNodeFunc3 = (node: GraphNode) => string
export type ShapeRendering = CSSProperties['shapeRendering']
export interface MiniMapProps {
/** Node color, can be either a string or a string func that receives the current node */
nodeColor?: string | MiniMapNodeFunc
/** Node stroke color, can be either a string or a string func that receives the current node */
nodeStrokeColor?: string | MiniMapNodeFunc2
/** Additional node class name, can be either a string or a string func that receives the current node */
nodeClassName?: string | MiniMapNodeFunc3
/** Node border radius */
nodeBorderRadius?: number
/** Node stroke width */
nodeStrokeWidth?: number
/** Background color of minimap */
maskColor?: string
width?: number
height?: number
}
/** these props are passed to mini map node slots */
export interface MiniMapNodeProps {
id: string
parentNode?: string
selected?: boolean
dragging?: boolean
position: XYPosition
dimensions: Dimensions
borderRadius?: number
color?: string
shapeRendering?: ShapeRendering
strokeColor?: string
strokeWidth?: number
}