refactor(utils): move store utils to state
* set z index on edge * extend edgeVisibleParams by dimensions of target and node edge Signed-off-by: Braks <78412429+bcakmakoglu@users.noreply.github.com>
This commit is contained in:
+53
-6
@@ -1,7 +1,7 @@
|
||||
import { rectToBox } from './graph'
|
||||
import { EdgePositions, GraphNode, HandleElement, Position, Rect, Transform, XYPosition } from '~/types'
|
||||
import { EdgePositions, GraphEdge, GraphNode, HandleElement, Position, Rect, Transform, XYPosition } from '~/types'
|
||||
|
||||
export function getHandlePosition(position: Position, rect: Rect, handle?: HandleElement): XYPosition {
|
||||
export const getHandlePosition = (position: Position, rect: Rect, handle?: HandleElement): XYPosition => {
|
||||
const x = (handle?.x ?? 0) + rect.x
|
||||
const y = (handle?.y ?? 0) + rect.y
|
||||
const width = handle?.width ?? rect.width
|
||||
@@ -31,7 +31,7 @@ export function getHandlePosition(position: Position, rect: Rect, handle?: Handl
|
||||
}
|
||||
}
|
||||
|
||||
export function getHandle(bounds?: HandleElement[], handleId?: string): HandleElement | undefined {
|
||||
export const getHandle = (bounds?: HandleElement[], handleId?: string): HandleElement | undefined => {
|
||||
if (!bounds) return undefined
|
||||
|
||||
// there is no handleId when there are no multiple handles/ handles with ids
|
||||
@@ -79,17 +79,31 @@ export const getEdgePositions = (
|
||||
interface IsEdgeVisibleParams {
|
||||
sourcePos: XYPosition
|
||||
targetPos: XYPosition
|
||||
sourceWidth: number
|
||||
sourceHeight: number
|
||||
targetWidth: number
|
||||
targetHeight: number
|
||||
width: number
|
||||
height: number
|
||||
transform: Transform
|
||||
}
|
||||
|
||||
export function isEdgeVisible({ sourcePos, targetPos, width, height, transform }: IsEdgeVisibleParams): boolean {
|
||||
export function isEdgeVisible({
|
||||
sourcePos,
|
||||
targetPos,
|
||||
sourceWidth,
|
||||
sourceHeight,
|
||||
targetWidth,
|
||||
targetHeight,
|
||||
width,
|
||||
height,
|
||||
transform,
|
||||
}: IsEdgeVisibleParams): boolean {
|
||||
const edgeBox = {
|
||||
x: Math.min(sourcePos.x, targetPos.x),
|
||||
y: Math.min(sourcePos.y, targetPos.y),
|
||||
x2: Math.max(sourcePos.x, targetPos.x),
|
||||
y2: Math.max(sourcePos.y, targetPos.y),
|
||||
x2: Math.max(sourcePos.x + sourceWidth, targetPos.x + targetWidth),
|
||||
y2: Math.max(sourcePos.y + sourceHeight, targetPos.y + targetHeight),
|
||||
}
|
||||
|
||||
if (edgeBox.x === edgeBox.x2) {
|
||||
@@ -113,3 +127,36 @@ export function isEdgeVisible({ sourcePos, targetPos, width, height, transform }
|
||||
|
||||
return overlappingArea > 0
|
||||
}
|
||||
|
||||
export const groupEdgesByZLevel = (edges: GraphEdge[], nodes: GraphNode[]) => {
|
||||
let maxLevel = -1
|
||||
const nodeIds = nodes.map((n) => n.id)
|
||||
|
||||
const levelLookup = edges.reduce<Record<string, GraphEdge[]>>((tree, edge) => {
|
||||
const z = edge.z
|
||||
? edge.z
|
||||
: Math.max(
|
||||
nodes[nodeIds.indexOf(edge.source)].computedPosition.z || 0,
|
||||
nodes[nodeIds.indexOf(edge.target)].computedPosition.z || 0,
|
||||
)
|
||||
if (tree[z]) {
|
||||
tree[z].push(edge)
|
||||
} else {
|
||||
tree[z] = [edge]
|
||||
}
|
||||
|
||||
maxLevel = z > maxLevel ? z : maxLevel
|
||||
|
||||
return tree
|
||||
}, {})
|
||||
|
||||
return Object.entries(levelLookup).map(([key, edges]) => {
|
||||
const level = +key
|
||||
|
||||
return {
|
||||
edges,
|
||||
level,
|
||||
isMaxLevel: level === maxLevel,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
+32
-17
@@ -4,6 +4,7 @@ import {
|
||||
CoordinateExtent,
|
||||
Dimensions,
|
||||
Edge,
|
||||
EdgeMarkerType,
|
||||
Elements,
|
||||
FlowElements,
|
||||
FlowExportObject,
|
||||
@@ -184,6 +185,7 @@ export const parseNode = (node: Node, nodeExtent: CoordinateExtent, defaults?: P
|
||||
...defaults,
|
||||
}
|
||||
: defaults
|
||||
|
||||
return {
|
||||
...node,
|
||||
...(defaults as GraphNode),
|
||||
@@ -202,9 +204,11 @@ export const parseEdge = (
|
||||
type: edge.type ?? 'default',
|
||||
source: edge.source.toString(),
|
||||
target: edge.target.toString(),
|
||||
z: typeof edge.style?.zIndex === 'string' ? parseInt(edge.style?.zIndex) : edge.style?.zIndex ?? 0,
|
||||
...defaults,
|
||||
}
|
||||
: defaults
|
||||
|
||||
return {
|
||||
...edge,
|
||||
...defaults,
|
||||
@@ -266,24 +270,21 @@ export const getNodesInside = (nodes: GraphNode[], rect: Rect, [tx, ty, tScale]:
|
||||
|
||||
return nodes.filter((node) => {
|
||||
if (!node || node.selectable === false) return false
|
||||
const { position = { x: 0, y: 0 }, dimensions = { width: 0, height: 0 }, dragging = false } = node
|
||||
const nBox = rectToBox({ ...position, ...dimensions })
|
||||
const { computedPosition = { x: 0, y: 0 }, dimensions = { width: 0, height: 0 }, dragging = false } = node
|
||||
const nBox = rectToBox({ ...computedPosition, ...dimensions })
|
||||
const xOverlap = Math.max(0, Math.min(rBox.x2, nBox.x2) - Math.max(rBox.x, nBox.x))
|
||||
const yOverlap = Math.max(0, Math.min(rBox.y2, nBox.y2) - Math.max(rBox.y, nBox.y))
|
||||
const overlappingArea = Math.ceil(xOverlap * yOverlap)
|
||||
const notInitialized =
|
||||
typeof dimensions.width === 'undefined' ||
|
||||
typeof dimensions.height === 'undefined' ||
|
||||
dimensions.width === 0 ||
|
||||
dimensions.height === 0 ||
|
||||
dragging
|
||||
|
||||
if (dimensions.width === null || dimensions.height === null || dragging) {
|
||||
// nodes are initialized with width and height = null
|
||||
return true
|
||||
}
|
||||
|
||||
if (partially) {
|
||||
return overlappingArea > 0
|
||||
}
|
||||
|
||||
const partiallyVisible = partially && overlappingArea > 0
|
||||
const area = dimensions.width * dimensions.height
|
||||
|
||||
return overlappingArea >= area
|
||||
return notInitialized || partiallyVisible || overlappingArea >= area
|
||||
})
|
||||
}
|
||||
|
||||
@@ -331,9 +332,9 @@ export const getTransformForBounds = (
|
||||
return [x, y, clampedZoom]
|
||||
}
|
||||
|
||||
export function calculateXYZPosition(node: GraphNode, result: XYZPosition): XYZPosition {
|
||||
export const getXYZPos = (node: GraphNode, result: XYZPosition): XYZPosition => {
|
||||
if (!node.parentNode) return result
|
||||
return calculateXYZPosition(node.parentNode, {
|
||||
return getXYZPos(node.parentNode, {
|
||||
x: result.x + node.parentNode.position.x,
|
||||
y: result.y + node.parentNode.position.y,
|
||||
z:
|
||||
@@ -341,9 +342,23 @@ export function calculateXYZPosition(node: GraphNode, result: XYZPosition): XYZP
|
||||
})
|
||||
}
|
||||
|
||||
export function isParentSelected(node: GraphNode): boolean {
|
||||
if (!node.parentNode) return false
|
||||
export const isParentSelected = (node: GraphNode): boolean => {
|
||||
if (!node.parentNode) return false
|
||||
if (node.parentNode.selected) return true
|
||||
return isParentSelected(node.parentNode)
|
||||
}
|
||||
|
||||
export const getMarkerId = (marker: EdgeMarkerType | undefined): string => {
|
||||
if (typeof marker === 'undefined') {
|
||||
return ''
|
||||
}
|
||||
|
||||
if (typeof marker === 'string') {
|
||||
return marker
|
||||
}
|
||||
|
||||
return Object.keys(marker)
|
||||
.sort()
|
||||
.map((key: string) => `${key}=${(marker as any)[key]}`)
|
||||
.join('&')
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
export * from './edge'
|
||||
export * from './graph'
|
||||
export * from './node'
|
||||
export * from './store'
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
import { ConnectionMode, FlowState, PanOnScrollMode, DefaultNodeTypes, DefaultEdgeTypes, ConnectionLineType } from '~/types'
|
||||
import { DefaultNode, InputNode, OutputNode, BezierEdge, SmoothStepEdge, StepEdge, StraightEdge } from '~/components'
|
||||
import { createHooks } from '~/composables'
|
||||
|
||||
export const defaultNodeTypes: DefaultNodeTypes = {
|
||||
input: InputNode,
|
||||
default: DefaultNode,
|
||||
output: OutputNode,
|
||||
}
|
||||
|
||||
export const defaultEdgeTypes: DefaultEdgeTypes = {
|
||||
default: BezierEdge,
|
||||
straight: StraightEdge,
|
||||
step: StepEdge,
|
||||
smoothstep: SmoothStepEdge,
|
||||
}
|
||||
|
||||
export const initialState = (): FlowState => ({
|
||||
elements: [],
|
||||
nodes: [],
|
||||
edges: [],
|
||||
nodeTypes: [],
|
||||
edgeTypes: [],
|
||||
|
||||
isReady: false,
|
||||
instance: undefined,
|
||||
|
||||
dimensions: {
|
||||
width: 0,
|
||||
height: 0,
|
||||
},
|
||||
transform: [0, 0, 1],
|
||||
selectedElements: undefined,
|
||||
selectedNodesBbox: { x: 0, y: 0, width: 0, height: 0 },
|
||||
|
||||
d3Zoom: undefined,
|
||||
d3Selection: undefined,
|
||||
d3ZoomHandler: undefined,
|
||||
minZoom: 0.5,
|
||||
maxZoom: 2,
|
||||
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],
|
||||
],
|
||||
preventScrolling: true,
|
||||
zoomOnScroll: true,
|
||||
zoomOnPinch: true,
|
||||
zoomOnDoubleClick: true,
|
||||
panOnScroll: false,
|
||||
panOnScrollSpeed: 0.5,
|
||||
panOnScrollMode: PanOnScrollMode.Free,
|
||||
paneMoveable: true,
|
||||
edgeUpdaterRadius: 10,
|
||||
onlyRenderVisibleElements: false,
|
||||
defaultZoom: 1,
|
||||
defaultPosition: [0, 0],
|
||||
|
||||
nodesSelectionActive: false,
|
||||
selectionActive: false,
|
||||
|
||||
userSelectionRect: {
|
||||
startX: 0,
|
||||
startY: 0,
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 0,
|
||||
height: 0,
|
||||
draw: false,
|
||||
},
|
||||
|
||||
arrowHeadColor: '#b1b1b7',
|
||||
connectionLineStyle: {},
|
||||
connectionLineType: ConnectionLineType.Bezier,
|
||||
connectionNodeId: undefined,
|
||||
connectionHandleId: undefined,
|
||||
connectionHandleType: 'source',
|
||||
connectionPosition: { x: NaN, y: NaN },
|
||||
connectionMode: ConnectionMode.Loose,
|
||||
|
||||
snapGrid: [15, 15],
|
||||
snapToGrid: false,
|
||||
|
||||
edgesUpdatable: false,
|
||||
nodesConnectable: true,
|
||||
nodesDraggable: true,
|
||||
elementsSelectable: true,
|
||||
selectNodesOnDrag: true,
|
||||
multiSelectionActive: false,
|
||||
selectionKeyCode: 'Shift',
|
||||
multiSelectionKeyCode: 'Meta',
|
||||
zoomActivationKeyCode: 'Meta',
|
||||
deleteKeyCode: 'Backspace',
|
||||
|
||||
hooks: createHooks(),
|
||||
loading: undefined,
|
||||
|
||||
markerEndId: undefined,
|
||||
storageKey: undefined,
|
||||
|
||||
vueFlowVersion: typeof __VUE_FLOW_VERSION__ !== 'undefined' ? __VUE_FLOW_VERSION__ : '-',
|
||||
})
|
||||
Reference in New Issue
Block a user