update(script-setup): Refactor remaining files to script setup style

This commit is contained in:
Braks
2021-10-20 22:39:54 +02:00
parent 9b2f4b7406
commit 560bdc203b
62 changed files with 1683 additions and 1425 deletions
+44 -21
View File
@@ -1,49 +1,72 @@
<script lang="ts" setup>
import { CSSProperties } from 'vue'
import Edge from '~/components/Edges/Edge'
import { ConnectionLineComponent, ConnectionLineType, ConnectionMode, Dimensions, Edge as TEdge, Transform } from '~/types'
import { getSourceTargetNodes } from '~/container/EdgeRenderer/utils'
import Edge from '~/components/Edges/Edge.vue'
import ConnectionLine from '~/components/ConnectionLine/ConnectionLine.vue'
import {
ConnectionLineType,
ConnectionMode,
CustomConnectionLine,
Dimensions,
EdgeType,
RevueFlowStore,
Transform,
} from '~/types'
import MarkerDefinitions from '~/container/MarkerDefinitions.vue'
interface EdgeRendererProps {
edges: TEdge[]
edgeTypes: any
transform: Transform
connectionLineType: ConnectionLineType
connectionLineStyle?: CSSProperties
connectionLineComponent?: ConnectionLineComponent
connectionMode?: ConnectionMode
arrowHeadColor: string
markerEndId?: string
onlyRenderVisibleElements: boolean
edgeUpdaterRadius?: number
edgeTypes: Record<string, EdgeType>
dimensions: Dimensions
transform: Transform
connectionLineType?: ConnectionLineType
connectionLineStyle?: CSSProperties
customConnectionLine?: CustomConnectionLine
connectionMode?: ConnectionMode
arrowHeadColor?: string
markerEndId?: string
onlyRenderVisibleElements?: boolean
}
const props = withDefaults(defineProps<EdgeRendererProps>(), {
transform: () => [0, 0, 1],
edges: () => [],
arrowHeadColor: '#fff',
arrowHeadColor: '#b1b1b7',
dimensions: () => ({ width: 0, height: 0 }),
onlyRenderVisibleElements: false,
connectionMode: ConnectionMode.Strict,
connectionLineType: ConnectionLineType.Bezier,
})
const store = inject<RevueFlowStore>('store')!
const sourceNode = computed(() => store.nodes.find((n) => n.id === store.connectionNodeId))
const connectionLineVisible = computed(
() => store.nodesConnectable && sourceNode.value && store.connectionNodeId && store.connectionHandleType,
)
</script>
<template>
<svg :width="props.dimensions.width" :height="props.dimensions.height" class="revue-flow__edges">
<MarkerDefinitions :color="props.arrowHeadColor" />
<g
:transform="
props.transform &&
props.transform.length &&
`translate(${props.transform[0]},${props.transform[1]}) scale(${props.transform[2]})`
"
:transform="props.transform.length && `translate(${props.transform[0]},${props.transform[1]}) scale(${props.transform[2]})`"
>
<template v-for="(edge, i) of props.edges" :key="`edge-${i}`">
<template v-for="(edge, i) of store.edges" :key="`edge-${i}`">
<Edge
:edge="edge"
:nodes="getSourceTargetNodes(edge, store.nodes)"
:type="props.edgeTypes[edge.type || 'default']"
:dimensions="props.dimensions"
:transform="props.transform"
:only-render-visible-elements="props.onlyRenderVisibleElements"
:marker-end-id="props.markerEndId"
/>
</template>
<ConnectionLine
v-if="connectionLineVisible"
:source-node="sourceNode"
:connection-line-style="props.connectionLineStyle"
:connection-line-type="props.connectionLineType"
:custom-connection-line="props.customConnectionLine"
/>
</g>
</svg>
</template>
+14 -14
View File
@@ -1,8 +1,8 @@
import { CSSProperties, defineComponent, inject, PropType } from 'vue'
import { ConnectionLineType, ConnectionLineComponent, ConnectionMode, RevueFlowStore } from '../../types'
import ConnectionLine from '../../components/ConnectionLine'
import Edge from '../../components/Edges/EdgeDepr'
import MarkerDefinitions from './MarkerDefinitions'
import Edge from '../../components/Edges/Edge'
interface EdgeRendererProps {
edgeTypes: any
@@ -21,59 +21,59 @@ export default defineComponent({
components: {
Edge,
ConnectionLine,
MarkerDefinitions
MarkerDefinitions,
},
props: {
edgeTypes: {
type: Object,
required: true
required: true,
},
connectionLineType: {
type: String as PropType<EdgeRendererProps['connectionLineType']>,
required: false,
default: undefined
default: undefined,
},
connectionLineStyle: {
type: Object as PropType<EdgeRendererProps['connectionLineStyle']>,
required: false,
default: undefined
default: undefined,
},
connectionLineComponent: {
type: Object as PropType<EdgeRendererProps['connectionLineComponent']>,
required: false,
default: undefined
default: undefined,
},
connectionMode: {
type: String as PropType<EdgeRendererProps['connectionMode']>,
required: false,
default: undefined
default: undefined,
},
arrowHeadColor: {
type: String as PropType<EdgeRendererProps['arrowHeadColor']>,
required: false,
default: undefined
default: undefined,
},
markerEndId: {
type: String as PropType<EdgeRendererProps['markerEndId']>,
required: false,
default: undefined
default: undefined,
},
onlyRenderVisibleElements: {
type: Boolean as PropType<EdgeRendererProps['onlyRenderVisibleElements']>,
required: false,
default: undefined
default: undefined,
},
edgeUpdaterRadius: {
type: Number as PropType<EdgeRendererProps['edgeUpdaterRadius']>,
required: false,
default: undefined
}
default: undefined,
},
},
setup(props) {
const store = inject<RevueFlowStore>('store')!
return () => (
<svg width={store.width} height={store.height} class="revue-flow__edges">
<svg width={store.width} height={store.height} className="revue-flow__edges">
<MarkerDefinitions color={props.arrowHeadColor} />
<g transform={`translate(${store.transform[0]},${store.transform[1]}) scale(${store.transform[2]})`}>
{store.edges.map((edge, i) => (
@@ -95,5 +95,5 @@ export default defineComponent({
</g>
</svg>
)
}
},
})
+8 -5
View File
@@ -1,3 +1,4 @@
import { Ref } from 'vue'
import { BezierEdge, StepEdge, SmoothStepEdge, StraightEdge } from '~/components/Edges'
import { rectToBox } from '~/utils/graph'
import { Position, Node, XYPosition, ElementId, HandleElement, Transform, Edge, EdgeType } from '~/types'
@@ -137,12 +138,12 @@ export function isEdgeVisible({ sourcePos, targetPos, width, height, transform }
}
type SourceTargetNode = {
sourceNode: Node | null
targetNode: Node | null
sourceNode: Node
targetNode: Node
}
export const getSourceTargetNodes = (edge: Edge, nodes: Node[]): SourceTargetNode => {
return nodes.reduce(
export const getSourceTargetNodes = (edge: Edge, nodes: Node[]): Ref<SourceTargetNode> => {
const sourceTargetNode: SourceTargetNode = nodes.reduce(
(res, node) => {
if (node.id === edge.source) {
res.sourceNode = node
@@ -152,6 +153,8 @@ export const getSourceTargetNodes = (edge: Edge, nodes: Node[]): SourceTargetNod
}
return res
},
{ sourceNode: null, targetNode: null } as SourceTargetNode,
{ sourceNode: null, targetNode: null } as any,
)
return ref(sourceTargetNode)
}
+50 -96
View File
@@ -1,7 +1,7 @@
<script lang="ts" setup>
import '~/style.css'
import '~/theme-default.css'
import { CSSProperties } from 'vue'
import { CSSProperties, onBeforeUnmount } from 'vue'
import ZoomPane from './ZoomPane.vue'
import SelectionPane from './SelectionPane.vue'
import NodeRenderer from '~/container/NodeRenderer.vue'
@@ -12,11 +12,9 @@ import {
Elements,
PanOnScrollMode,
RevueFlowStore,
Node,
Edge,
NodeType,
EdgeType,
ConnectionLineComponent,
CustomConnectionLine,
KeyCode,
TranslateExtent,
NodeExtent,
@@ -25,21 +23,18 @@ import { RevueFlowHooks, useRevueFlow } from '~/hooks/RevueFlowHooks'
import configureStore from '~/store/configure-store'
import { initialState } from '~/store'
import { createNodeTypes } from '~/container/NodeRenderer/utils'
import InputNode from '~/components/Nodes/InputNode'
import DefaultNode from '~/components/Nodes/DefaultNode'
import OutputNode from '~/components/Nodes/OutputNode'
import { DefaultNode, InputNode, OutputNode } from '~/components/Nodes'
import { BezierEdge, SmoothStepEdge, StepEdge, StraightEdge } from '~/components/Edges'
import { createEdgeTypes } from '~/container/EdgeRenderer/utils'
import { isEdge, isNode, parseEdge, parseNode } from '~/utils/graph'
interface RevueFlowProps {
modelValue: Elements
elements: Elements
nodeTypes?: Record<string, NodeType>
edgeTypes?: Record<string, EdgeType>
connectionMode?: ConnectionMode
connectionLineType?: ConnectionLineType
connectionLineStyle?: CSSProperties
connectionLineComponent?: ConnectionLineComponent
connectionLineComponent?: CustomConnectionLine
deleteKeyCode?: KeyCode
selectionKeyCode?: KeyCode
multiSelectionKeyCode?: KeyCode
@@ -69,11 +64,6 @@ interface RevueFlowProps {
edgeUpdaterRadius?: number
}
type NextElements = {
nextNodes: Node[]
nextEdges: Edge[]
}
const props = withDefaults(defineProps<RevueFlowProps>(), {
modelValue: () => [] as Elements,
connectionMode: ConnectionMode.Strict,
@@ -86,6 +76,7 @@ const props = withDefaults(defineProps<RevueFlowProps>(), {
snapGrid: () => [15, 15],
onlyRenderVisibleElements: false,
nodesConnectable: true,
nodesDraggable: true,
elementsSelectable: true,
selectNodesOnDrag: true,
minZoom: 0.5,
@@ -112,102 +103,65 @@ const props = withDefaults(defineProps<RevueFlowProps>(), {
})
const emit = defineEmits(Object.keys(useRevueFlow()))
const store = configureStore(initialState)()
provide<RevueFlowStore>('store', store)
const defaultNodeTypes: Record<string, NodeType> = {
input: InputNode as NodeType,
default: DefaultNode as NodeType,
output: OutputNode as NodeType,
}
const defaultEdgeTypes: Record<string, EdgeType> = {
default: BezierEdge as EdgeType,
straight: StraightEdge as EdgeType,
step: StepEdge as EdgeType,
smoothstep: SmoothStepEdge as EdgeType,
}
let store = inject<RevueFlowStore>('store')
if (!store) {
store = configureStore({
...initialState,
...props,
})()
provide<RevueFlowStore>('store', store)
}
onBeforeUnmount(() => store?.$dispose())
store.setElements(props.elements)
store.setMinZoom(props.minZoom)
store.setMaxZoom(props.maxZoom)
store.setTranslateExtent(props.translateExtent)
store.setNodeExtent(props.nodeExtent)
const hooks = useRevueFlow().bind(emit)
provide<RevueFlowHooks>('hooks', hooks)
const elements = useVModel(props, 'modelValue', emit)
const defaultNodeTypes = {
input: InputNode,
default: DefaultNode,
output: OutputNode,
}
const defaultEdgeTypes = {
default: BezierEdge,
straight: StraightEdge,
step: StepEdge,
smoothstep: SmoothStepEdge,
}
const nodeTypes = createNodeTypes({ ...defaultNodeTypes, ...props.nodeTypes })
const edgeTypes = createEdgeTypes({ ...defaultEdgeTypes, ...props.edgeTypes })
const nodes = ref<Node[]>([])
const edges = ref<Edge[]>([])
const setElements = (elements: Elements) => {
const propElements = elements
const nextElements: NextElements = {
nextNodes: [],
nextEdges: [],
}
const { nextNodes, nextEdges } = propElements.reduce((res, propElement): NextElements => {
if (isNode(propElement)) {
const storeNode = nodes.value.find((node) => node.id === propElement.id)
if (storeNode) {
const updatedNode: Node = {
...storeNode,
...propElement,
}
if (storeNode.position.x !== propElement.position.x || storeNode.position.y !== propElement.position.y) {
updatedNode.__rf.position = propElement.position
}
if (typeof propElement.type !== 'undefined' && propElement.type !== storeNode.type) {
// we reset the elements dimensions here in order to force a re-calculation of the bounds.
// When the type of a node changes it is possible that the number or positions of handles changes too.
updatedNode.__rf.width = null
}
res.nextNodes.push(updatedNode)
} else {
res.nextNodes.push(parseNode(propElement, props.nodeExtent))
}
} else if (isEdge(propElement)) {
const storeEdge = edges.value.find((se) => se.id === propElement.id)
if (storeEdge) {
res.nextEdges.push({
...storeEdge,
...propElement,
})
} else {
res.nextEdges.push(parseEdge(propElement))
}
}
return res
}, nextElements)
nodes.value = nextNodes
edges.value = nextEdges
}
setElements(elements.value)
</script>
<template>
<div class="revue-flow">
<ZoomPane>
<ZoomPane
:selection-key-code="props.selectionKeyCode"
:zoom-activation-key-code="props.zoomActivationKeyCode"
:default-zoom="props.defaultZoom"
:default-position="props.defaultPosition"
:zoom-on-scroll="props.zoomOnScroll"
:zoom-on-pinch="props.zoomOnPinch"
:zoom-on-double-click="props.zoomOnDoubleClick"
:pan-on-scroll="props.panOnScroll"
:pan-on-scroll-speed="props.panOnScrollSpeed"
:pan-on-scroll-mode="props.panOnScrollMode"
:pane-moveable="props.paneMoveable"
>
<template #default="{ transform, dimensions }">
<SelectionPane
:delete-key-code="props.deleteKeyCode"
:multi-selection-key-code="props.multiSelectionKeyCode"
:selection-key-code="props.selectionKeyCode"
>
<NodeRenderer v-bind="props" :node-types="nodeTypes" :nodes="nodes" :transform="transform" :dimensions="dimensions" />
<EdgeRenderer
v-if="false"
v-bind="props"
:edge-types="edgeTypes"
:edges="edges"
:transform="transform"
:dimensions="dimensions"
/>
<NodeRenderer :node-types="nodeTypes" :transform="transform" :dimensions="dimensions" />
<EdgeRenderer :edge-types="edgeTypes" :transform="transform" :dimensions="dimensions" />
</SelectionPane>
</template>
</ZoomPane>
+19 -73
View File
@@ -1,37 +1,26 @@
<script lang="ts" setup>
import Node from '~/components/Node.vue'
import { NodeType, Node as TNode, Transform, Dimensions, NodeDimensionUpdate } from '~/types'
import Node from '~/components/Nodes/Node.vue'
import { NodeType, Node as TNode, Transform, Dimensions, RevueFlowStore } from '~/types'
import { getNodesInside } from '~/utils/graph'
import { getDimensions } from '~/utils'
import { getHandleBounds } from '~/components/Nodes/utils'
interface NodeRendererProps {
nodes: TNode[]
transform: Transform
nodeTypes: Record<string, NodeType>
selectNodesOnDrag: boolean
snapToGrid: boolean
snapGrid: [number, number]
onlyRenderVisibleElements: boolean
dimensions: Dimensions
transform: Transform
}
const props = withDefaults(defineProps<NodeRendererProps>(), {
selectNodesOnDrag: true,
snapGrid: () => [15, 15],
snapToGrid: false,
onlyRenderVisibleElements: false,
transform: () => [0, 0, 1],
nodes: () => [],
dimensions: () => ({ width: 0, height: 0 }),
})
const nodes = ref(props.nodes)
const getNodes = () =>
props.onlyRenderVisibleElements
? nodes.value &&
const store = inject<RevueFlowStore>('store')!
const getNodes = computed(() =>
store.onlyRenderVisibleElements
? store.nodes &&
getNodesInside(
nodes.value,
store.nodes,
{
x: 0,
y: 0,
@@ -41,9 +30,8 @@ const getNodes = () =>
props.transform,
true,
)
: nodes.value
const cNodes = computed(() => getNodes())
: store.nodes,
)
const type = (node: TNode) => {
const nodeType = node.type || 'default'
@@ -54,65 +42,23 @@ const type = (node: TNode) => {
return type
}
const updateNodeDimensions = (updates: NodeDimensionUpdate[]) => {
nodes.value = nodes.value.map((node) => {
const update = updates.find((u) => u.id === node.id)
if (update) {
const dimensions = getDimensions(update.nodeElement)
const doUpdate =
dimensions.width &&
dimensions.height &&
(node.__rf.width !== dimensions.width || node.__rf.height !== dimensions.height || update.forceUpdate)
if (doUpdate) {
const handleBounds = getHandleBounds(update.nodeElement, props.transform[2])
return {
...node,
__rf: {
...node.__rf,
...dimensions,
handleBounds,
},
}
}
}
return node
})
}
const selected = (nodeId: string) => store.selectedElements?.some(({ id }) => id === nodeId)
</script>
<template>
<div
class="revue-flow__nodes"
:style="{ transform: `translate(${props.transform[0]}px,${props.transform[1]}px) scale(${props.transform[2]})` }"
>
<template v-for="(node, i) of cNodes" :key="`node-${i}`">
<template v-for="(node, i) of getNodes" :key="`node-${i}`">
<Node
:node="node"
:snap-grid="props.snapGrid"
:snap-to-grid="props.snapToGrid"
:select-nodes-on-drag="props.selectNodesOnDrag"
:type="type(node)"
:scale="props.transform[2]"
@updateNodeDimensions="updateNodeDimensions"
>
<template #default="{ selected, isConnectable }">
<component
:is="type(node)"
v-bind="{
data: node.data,
type: node.type,
xPos: node.__rf.position.x,
yPos: node.__rf.position.y,
selected: selected,
isConnectable: isConnectable,
sourcePosition: node.sourcePosition,
targetPosition: node.targetPosition,
isDragging: node.__rf.isDragging,
}"
/>
</template>
</Node>
:selected="selected(node.id)"
:selectable="node.selectable || store.elementsSelectable"
:connectable="node.connectable || store.nodesConnectable"
:draggable="node.draggable || store.nodesDraggable"
/>
</template>
</div>
</template>
+12 -12
View File
@@ -1,5 +1,5 @@
import { defineComponent, inject, PropType } from 'vue'
import Node from '../../components/Nodes/Node'
import Node from '../../components/Nodes/NodeDepr'
import { getNodesInside } from '../../utils/graph'
import { NodeType, RevueFlowStore } from '../../types'
@@ -18,28 +18,28 @@ export default defineComponent({
nodeTypes: {
type: Object as PropType<NodeRendererProps['nodeTypes']>,
required: false,
default: undefined
default: undefined,
},
selectNodesOnDrag: {
type: Boolean as PropType<NodeRendererProps['selectNodesOnDrag']>,
required: false,
default: undefined
default: undefined,
},
snapToGrid: {
type: Boolean as PropType<NodeRendererProps['snapToGrid']>,
required: false,
default: undefined
default: undefined,
},
snapGrid: {
type: Array as unknown as PropType<NodeRendererProps['snapGrid']>,
required: false,
default: undefined
default: undefined,
},
onlyRenderVisibleElements: {
type: Boolean as PropType<NodeRendererProps['onlyRenderVisibleElements']>,
required: false,
default: undefined
}
default: undefined,
},
},
setup(props) {
const store = inject<RevueFlowStore>('store')!
@@ -53,19 +53,19 @@ export default defineComponent({
x: 0,
y: 0,
width: store?.width,
height: store?.height
height: store?.height,
},
store.transform,
true
true,
)
: store.nodes
}
return () => (
<div
class="revue-flow__nodes"
className="revue-flow__nodes"
style={{
transform: `translate(${store.transform[0]}px,${store.transform[1]}px) scale(${store.transform[2]})`
transform: `translate(${store.transform[0]}px,${store.transform[1]}px) scale(${store.transform[2]})`,
}}
>
{getNodes().map((node, i) => {
@@ -90,5 +90,5 @@ export default defineComponent({
})}
</div>
)
}
},
})
+1 -3
View File
@@ -1,6 +1,4 @@
import DefaultNode from '~/components/Nodes/DefaultNode'
import InputNode from '~/components/Nodes/InputNode'
import OutputNode from '~/components/Nodes/OutputNode'
import { DefaultNode, InputNode, OutputNode } from '~/components/Nodes'
import { NodeType } from '~/types'
export function createNodeTypes(nodeTypes: Record<string, NodeType>): Record<string, NodeType> {
+46 -46
View File
@@ -2,9 +2,9 @@ import { PropType } from 'vue'
import '../../style.css'
import '../../theme-default.css'
import GraphView from '../GraphView'
import DefaultNode from '../../components/Nodes/DefaultNode'
import InputNode from '../../components/Nodes/InputNode'
import OutputNode from '../../components/Nodes/OutputNode'
import DefaultNode from '../../components/Nodes/DefaultNodeDepr'
import InputNode from '../../components/Nodes/InputNodeDepr'
import OutputNode from '../../components/Nodes/OutputNodeDepr'
import { createNodeTypes } from '../NodeRenderer/utils'
import { BezierEdge, StepEdge, SmoothStepEdge, StraightEdge } from '../../components/Edges'
import { createEdgeTypes } from '../EdgeRenderer/utils'
@@ -16,14 +16,14 @@ import { RevueFlowHooks, useRevueFlow } from '../../hooks/RevueFlowHooks'
const defaultNodeTypes = {
input: InputNode,
default: DefaultNode,
output: OutputNode
output: OutputNode,
}
const defaultEdgeTypes = {
default: BezierEdge,
straight: StraightEdge,
step: StepEdge,
smoothstep: SmoothStepEdge
smoothstep: SmoothStepEdge,
}
export default defineComponent({
@@ -33,189 +33,189 @@ export default defineComponent({
modelValue: {
type: Array as PropType<RevueFlowProps['modelValue']>,
required: false,
default: () => []
default: () => [],
},
nodeTypesId: {
type: String as PropType<RevueFlowProps['nodeTypesId']>,
required: false,
default: '1'
default: '1',
},
edgeTypesId: {
type: String as PropType<RevueFlowProps['edgeTypesId']>,
required: false,
default: '1'
default: '1',
},
nodeTypes: {
type: Object as PropType<RevueFlowProps['nodeTypes']>,
required: false,
default: () => defaultNodeTypes
default: () => defaultNodeTypes,
},
edgeTypes: {
type: Object as PropType<RevueFlowProps['edgeTypes']>,
required: false,
default: () => defaultEdgeTypes
default: () => defaultEdgeTypes,
},
connectionMode: {
type: String as PropType<RevueFlowProps['connectionMode']>,
required: false,
default: ConnectionMode.Strict
default: ConnectionMode.Strict,
},
connectionLineType: {
type: String as PropType<RevueFlowProps['connectionLineType']>,
required: false,
default: ConnectionLineType.Bezier
default: ConnectionLineType.Bezier,
},
connectionLineStyle: {
type: Object as PropType<RevueFlowProps['connectionLineStyle']>,
required: false,
default: undefined
default: undefined,
},
connectionLineComponent: {
type: Object as PropType<RevueFlowProps['connectionLineComponent']>,
required: false,
default: undefined
default: undefined,
},
selectionKeyCode: {
type: [Number, String] as PropType<RevueFlowProps['selectionKeyCode']>,
required: false,
default: 'Shift'
default: 'Shift',
},
multiSelectionKeyCode: {
type: [Number, String] as PropType<RevueFlowProps['multiSelectionKeyCode']>,
required: false,
default: 'Meta'
default: 'Meta',
},
zoomActivationKeyCode: {
type: [Number, String] as PropType<RevueFlowProps['zoomActivationKeyCode']>,
required: false,
default: 'Meta'
default: 'Meta',
},
deleteKeyCode: {
type: [Number, String] as PropType<RevueFlowProps['deleteKeyCode']>,
required: false,
default: 'Backspace'
default: 'Backspace',
},
snapToGrid: {
type: Boolean as PropType<RevueFlowProps['snapToGrid']>,
required: false,
default: false
default: false,
},
snapGrid: {
type: Array as unknown as PropType<RevueFlowProps['snapGrid']>,
required: false,
default: () => [15, 15]
default: () => [15, 15],
},
onlyRenderVisibleElements: {
type: Boolean as PropType<RevueFlowProps['onlyRenderVisibleElements']>,
required: false,
default: false
default: false,
},
nodesDraggable: {
type: Boolean as PropType<RevueFlowProps['nodesDraggable']>,
required: false,
default: undefined
default: undefined,
},
nodesConnectable: {
type: Boolean as PropType<RevueFlowProps['nodesConnectable']>,
required: false,
default: true
default: true,
},
elementsSelectable: {
type: Boolean as PropType<RevueFlowProps['elementsSelectable']>,
required: false,
default: true
default: true,
},
selectNodesOnDrag: {
type: Boolean as PropType<RevueFlowProps['selectNodesOnDrag']>,
required: false,
default: true
default: true,
},
minZoom: {
type: Number as PropType<RevueFlowProps['minZoom']>,
required: false,
default: 0.5
default: 0.5,
},
maxZoom: {
type: Number as PropType<RevueFlowProps['maxZoom']>,
required: false,
default: 2
default: 2,
},
defaultZoom: {
type: Number as PropType<RevueFlowProps['defaultZoom']>,
required: false,
default: 1
default: 1,
},
defaultPosition: {
type: Array as unknown as PropType<RevueFlowProps['defaultPosition']>,
required: false,
default: () => [0, 0]
default: () => [0, 0],
},
translateExtent: {
type: Array as unknown as PropType<RevueFlowProps['translateExtent']>,
required: false,
default: () => [
[Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY],
[Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY]
]
[Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY],
],
},
nodeExtent: {
type: Array as unknown as PropType<RevueFlowProps['nodeExtent']>,
required: false,
default: () => [
[Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY],
[Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY]
]
[Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY],
],
},
arrowHeadColor: {
type: String as PropType<RevueFlowProps['arrowHeadColor']>,
required: false,
default: '#b1b1b7'
default: '#b1b1b7',
},
markerEndId: {
type: String as PropType<RevueFlowProps['markerEndId']>,
required: false,
default: undefined
default: undefined,
},
zoomOnScroll: {
type: Boolean as PropType<RevueFlowProps['zoomOnScroll']>,
required: false,
default: true
default: true,
},
zoomOnPinch: {
type: Boolean as PropType<RevueFlowProps['zoomOnPinch']>,
required: false,
default: true
default: true,
},
panOnScroll: {
type: Boolean as PropType<RevueFlowProps['panOnScroll']>,
required: false,
default: false
default: false,
},
panOnScrollSpeed: {
type: Number as PropType<RevueFlowProps['panOnScrollSpeed']>,
required: false,
default: 0.5
default: 0.5,
},
panOnScrollMode: {
type: String as PropType<RevueFlowProps['panOnScrollMode']>,
required: false,
default: PanOnScrollMode.Free
default: PanOnScrollMode.Free,
},
zoomOnDoubleClick: {
type: Boolean as PropType<RevueFlowProps['zoomOnDoubleClick']>,
required: false,
default: true
default: true,
},
paneMoveable: {
type: Boolean as PropType<RevueFlowProps['paneMoveable']>,
required: false,
default: true
default: true,
},
edgeUpdaterRadius: {
type: Number as PropType<RevueFlowProps['edgeUpdaterRadius']>,
required: false,
default: 10
}
default: 10,
},
},
emits: Object.keys(useRevueFlow()),
setup(props, { emit, slots }) {
@@ -240,7 +240,7 @@ export default defineComponent({
})
return () => (
<div class="revue-flow">
<div className="revue-flow">
<GraphView
nodeTypes={createNodeTypes({ ...defaultNodeTypes, ...props.nodeTypes })}
edgeTypes={createEdgeTypes({ ...defaultEdgeTypes, ...props.edgeTypes })}
@@ -279,5 +279,5 @@ export default defineComponent({
{slots.default ? slots.default() : ''}
</div>
)
}
},
})
+21 -20
View File
@@ -1,31 +1,29 @@
<script lang="ts" setup>
import { inject } from 'vue'
import { RevueFlowHooks } from '~/hooks/RevueFlowHooks'
import useKeyPress from '~/hooks/useKeyPress'
import { KeyCode } from '~/types'
import { KeyCode, RevueFlowStore } from '~/types'
import useGlobalKeyHandler from '~/hooks/useGlobalKeyHandler'
import NodesSelection from '~/components/NodesSelection/NodesSelection.vue'
import UserSelection from '~/components/UserSelection/UserSelection.vue'
const props = withDefaults(
defineProps<{
selectionKeyCode: KeyCode
deleteKeyCode: KeyCode
multiSelectionKeyCode: KeyCode
}>(),
{
selectionKeyCode: 'Shift',
deleteKeyCode: 'Backspace',
multiSelectionKeyCode: 'Meta',
},
)
interface SelectionPaneProps {
selectionKeyCode?: KeyCode
deleteKeyCode?: KeyCode
multiSelectionKeyCode?: KeyCode
}
const props = withDefaults(defineProps<SelectionPaneProps>(), {
selectionKeyCode: 'Shift',
deleteKeyCode: 'Backspace',
multiSelectionKeyCode: 'Meta',
})
const store = inject<RevueFlowStore>('store')!
const hooks = inject<RevueFlowHooks>('hooks')!
const keyPressed = useKeyPress(props.selectionKeyCode)
const nodeSelectionActive = ref(false)
const selectedElements = ref([])
const onClick = (event: MouseEvent) => {
hooks.paneClick.trigger(event)
nodeSelectionActive.value = false
selectedElements.value = []
store.unsetNodesSelection()
store.resetSelectedElements()
}
const onContextMenu = (event: MouseEvent) => hooks.paneContextMenu.trigger(event)
@@ -37,10 +35,13 @@ useGlobalKeyHandler({
deleteKeyCode: props.deleteKeyCode,
multiSelectionKeyCode: props.multiSelectionKeyCode,
})
const userSelectionVisible = computed(() => keyPressed.value && (store.selectionActive || store.elementsSelectable))
const nodesSelectionVisible = computed(() => store.nodesSelectionActive)
</script>
<template>
<slot></slot>
<div v-if="keyPressed" id="user-selection">User Selection</div>
<div v-if="nodeSelectionActive" id="nodes-selection">Nodes Selection</div>
<UserSelection v-if="userSelectionVisible" id="user-selection" />
<NodesSelection v-if="nodesSelectionVisible" id="nodes-selection" />
<div class="revue-flow__pane" @click="onClick" @contextmenu="onContextMenu" @wheel="onWheel" />
</template>
+35 -30
View File
@@ -1,39 +1,28 @@
<script lang="ts" setup>
import { RevueFlowOptions, ConnectionLineType, ConnectionMode, Elements, PanOnScrollMode } from '~/types'
import { KeyCode, PanOnScrollMode, RevueFlowStore } from '~/types'
import useZoom from '~/composables/useZoom'
import useResizeHandler from '~/hooks/useResizeHandler'
import useZoomPanHelper from '~/hooks/useZoomPanHelper'
interface RevueFlowProps extends RevueFlowOptions {
modelValue: Elements
interface ZoomPaneProps {
selectionKeyCode?: KeyCode
zoomActivationKeyCode?: KeyCode
paneMoveable?: boolean
defaultZoom?: number
defaultPosition?: [number, number]
zoomOnScroll?: boolean
zoomOnPinch?: boolean
panOnScroll?: boolean
panOnScrollSpeed?: number
panOnScrollMode?: PanOnScrollMode
zoomOnDoubleClick?: boolean
}
const props = withDefaults(defineProps<RevueFlowProps>(), {
modelValue: () => [] as Elements,
connectionMode: ConnectionMode.Strict,
connectionLineType: ConnectionLineType.Bezier,
const props = withDefaults(defineProps<ZoomPaneProps>(), {
selectionKeyCode: 'Shift',
multiSelectionKeyCode: 'Meta',
zoomActivationKeyCode: 'Meta',
deleteKeyCode: 'Backspace',
snapToGrid: false,
snapGrid: () => [15, 15],
onlyRenderVisibleElements: false,
nodesConnectable: true,
elementsSelectable: true,
selectNodesOnDrag: true,
minZoom: 0.5,
maxZoom: 2,
defaultZoom: 1,
defaultPosition: () => [0, 0],
translateExtent: () => [
[Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY],
[Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY],
],
nodeExtent: () => [
[Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY],
[Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY],
],
arrowHeadColor: '#b1b1b7',
zoomOnScroll: true,
zoomOnPinch: true,
zoomOnDoubleClick: true,
@@ -41,11 +30,27 @@ const props = withDefaults(defineProps<RevueFlowProps>(), {
panOnScrollSpeed: 0.5,
panOnScrollMode: PanOnScrollMode.Free,
paneMoveable: true,
edgeUpdaterRadius: 10,
})
const zoomPane = templateRef<HTMLDivElement>('zoom-pane', null)
const transform = useZoom(zoomPane, props)
const dimensions = useResizeHandler(zoomPane)
const store = inject<RevueFlowStore>('store')!
const zoomPaneEl = templateRef<HTMLDivElement>('zoom-pane', null)
const { transform, d3Selection, d3Zoom } = useZoom(zoomPaneEl, props, (initD3ZoomPayload) => store.initD3Zoom(initD3ZoomPayload))
watch(transform, (val) => (store.transform = val), { flush: 'post' })
const dimensions = useResizeHandler(zoomPaneEl)
watch(dimensions, (val) => (store.dimensions = val), { flush: 'post' })
const getZoomPanHelper = reactify(useZoomPanHelper)
const zoomPanHelper = getZoomPanHelper(
d3Zoom,
d3Selection,
store.nodes,
transform,
dimensions,
store.minZoom,
store.maxZoom,
store.snapToGrid,
store.snapGrid,
)
</script>
<template>
<div ref="zoom-pane" class="revue-flow__renderer revue-flow__zoompane">