Skip to content

Commit d658c1d

Browse files
committed
refactor(core): replace arr reduce methods (#1467)
* refactor(core): replace arr reduce methods * chore(core): cleanup
1 parent 70b39cc commit d658c1d

File tree

10 files changed

+68
-65
lines changed

10 files changed

+68
-65
lines changed

packages/core/src/components/Nodes/NodeWrapper.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ const NodeWrapper = defineComponent({
172172
})
173173
}
174174
},
175-
{ immediate: true, flush: 'post' },
175+
{ immediate: true, flush: 'pre' },
176176
)
177177
})
178178

packages/core/src/composables/useKeyPress.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ function useKeyOrCode(code: string, keysToWatch: string | string[]) {
7575
* @internal
7676
* @param keyFilter - Can be a boolean, a string or an array of strings. If it's a boolean, it will always return that value. If it's a string, it will return true if the key is pressed. If it's an array of strings, it will return true if any of the keys are pressed, or a combination is pressed (e.g. ['ctrl+a', 'ctrl+b'])
7777
* @param onChange - Callback function that will be called when the key state changes
78+
* @param options - Options object
7879
*/
7980
export function useKeyPress(
8081
keyFilter: MaybeRefOrGetter<KeyFilter | null>,

packages/core/src/container/EdgeRenderer/MarkerDefinitions.vue

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,28 @@
11
<script lang="ts" setup>
22
import { computed } from 'vue'
3-
import type { EdgeMarkerType, MarkerProps, MarkerType } from '../../types/edge'
3+
import type { EdgeMarkerType, MarkerProps, MarkerType } from '../../types'
44
import { useVueFlow } from '../../composables'
55
import { getMarkerId } from '../../utils'
66
import MarkerSymbols from './MarkerSymbols.vue'
77
88
const { id: vueFlowId, edges, connectionLineOptions, defaultMarkerColor: defaultColor } = useVueFlow()
99
1010
const markers = computed(() => {
11-
const ids: string[] = []
11+
const ids: Set<string> = new Set()
1212
const markers: MarkerProps[] = []
1313
1414
const createMarkers = (marker?: EdgeMarkerType) => {
1515
if (marker) {
1616
const markerId = getMarkerId(marker, vueFlowId)
17-
if (!ids.includes(markerId)) {
17+
18+
if (!ids.has(markerId)) {
1819
if (typeof marker === 'object') {
1920
markers.push({ ...marker, id: markerId, color: marker.color || defaultColor.value })
2021
} else {
2122
markers.push({ id: markerId, color: defaultColor.value, type: marker as MarkerType })
2223
}
2324
24-
ids.push(markerId)
25+
ids.add(markerId)
2526
}
2627
}
2728
}
@@ -30,15 +31,13 @@ const markers = computed(() => {
3031
createMarkers(marker)
3132
}
3233
33-
edges.value.reduce<MarkerProps[]>((markers, edge) => {
34+
for (const edge of edges.value) {
3435
for (const marker of [edge.markerStart, edge.markerEnd]) {
3536
createMarkers(marker)
3637
}
38+
}
3739
38-
return markers.sort((a, b) => a.id.localeCompare(b.id))
39-
}, markers)
40-
41-
return markers
40+
return markers.sort((a, b) => a.id.localeCompare(b.id))
4241
})
4342
</script>
4443

packages/core/src/container/Pane/Pane.vue

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,14 @@ useKeyPress(
5050
return
5151
}
5252
53-
const nodesToRemove = getNodes.value.reduce<GraphNode[]>((res, node) => {
54-
if (!node.selected && node.parentNode && res.find((n) => n.id === node.parentNode)) {
55-
res.push(node)
53+
const nodesToRemove: GraphNode[] = []
54+
for (const node of getNodes.value) {
55+
if (!node.selected && node.parentNode && nodesToRemove.some((n) => n.id === node.parentNode)) {
56+
nodesToRemove.push(node)
5657
} else if (node.selected) {
57-
res.push(node)
58+
nodesToRemove.push(node)
5859
}
59-
60-
return res
61-
}, [])
60+
}
6261
6362
if (nodesToRemove || getSelectedEdges.value) {
6463
if (getSelectedEdges.value.length > 0) {

packages/core/src/store/actions.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ export function useActions(
141141
const style = window.getComputedStyle(viewportNode)
142142
const { m22: zoom } = new window.DOMMatrixReadOnly(style.transform)
143143

144-
const changes: NodeDimensionChange[] = Array.from({ length: updates.length })
144+
const changes: NodeDimensionChange[] = []
145145

146146
for (let i = 0; i < updates.length; ++i) {
147147
const update = updates[i]
@@ -378,7 +378,7 @@ export function useActions(
378378
return
379379
}
380380

381-
state.nodes = createGraphNodes(nextNodes, state.nodes, findNode, state.hooks.error.trigger)
381+
state.nodes = createGraphNodes(nextNodes, findNode, state.hooks.error.trigger)
382382
}
383383

384384
const setEdges: Actions['setEdges'] = (edges) => {
@@ -419,7 +419,7 @@ export function useActions(
419419
let nextNodes = nodes instanceof Function ? nodes(state.nodes) : nodes
420420
nextNodes = Array.isArray(nextNodes) ? nextNodes : [nextNodes]
421421

422-
const graphNodes = createGraphNodes(nextNodes, state.nodes, findNode, state.hooks.error.trigger)
422+
const graphNodes = createGraphNodes(nextNodes, findNode, state.hooks.error.trigger)
423423

424424
const changes: NodeAddChange<any>[] = []
425425
for (const node of graphNodes) {
@@ -665,7 +665,6 @@ export function useActions(
665665
return [nodeRect, node, isRectObj]
666666
}
667667

668-
// todo: rename to `findIntersectingNodes`
669668
const getIntersectingNodes: Actions['getIntersectingNodes'] = (nodeOrRect, partially = true, nodes = state.nodes) => {
670669
const [nodeRect, node, isRect] = getNodeRect(nodeOrRect)
671670

packages/core/src/store/state.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,7 @@ export function useState(): State {
88
return {
99
vueFlowRef: null,
1010
viewportRef: null,
11-
// todo: change this to a Set
1211
nodes: [],
13-
// todo: change this to a Set
1412
edges: [],
1513
connectionLookup: new Map(),
1614
nodeTypes: {},

packages/core/src/types/flow.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,21 @@ import type { VueFlowStore } from './store'
2323
// todo: should be object type
2424
export type ElementData = any
2525

26-
/** A flow element (after parsing into state) */
26+
/**
27+
* @deprecated - will be removed in the next major version
28+
* A flow element (after parsing into state)
29+
*/
2730
export type FlowElement<
2831
NodeData = ElementData,
2932
EdgeData = ElementData,
3033
NodeEvents extends Record<string, CustomEvent> = any,
3134
EdgeEvents extends Record<string, CustomEvent> = any,
3235
> = GraphNode<NodeData, NodeEvents> | GraphEdge<EdgeData, EdgeEvents>
3336

37+
/**
38+
* @deprecated - will be removed in the next major version
39+
* An array of flow elements (after parsing into state)
40+
*/
3441
export type FlowElements<
3542
NodeData = ElementData,
3643
EdgeData = ElementData,
@@ -54,6 +61,7 @@ export type Elements<
5461
> = Element<NodeData, EdgeData, NodeEvents, EdgeEvents>[]
5562

5663
export type MaybeElement = Node | Edge | Connection | FlowElement | Element
64+
5765
export interface CustomThemeVars {
5866
[key: string]: string | number | undefined
5967
}
@@ -82,13 +90,11 @@ export enum Position {
8290
Bottom = 'bottom',
8391
}
8492

85-
// todo: Rename to `Point`
8693
export interface XYPosition {
8794
x: number
8895
y: number
8996
}
9097

91-
// todo: Rename to `AbsolutePoint`
9298
export type XYZPosition = XYPosition & { z: number }
9399

94100
export interface Dimensions {

packages/core/src/utils/graph.ts

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -69,22 +69,18 @@ export function getHostForElement(element: HTMLElement): Document {
6969
return window.document
7070
}
7171

72-
// todo: refactor generic to use MaybeElement
7372
export function isEdge<Data = ElementData>(element: MaybeElement): element is Edge<Data> {
7473
return element && typeof element === 'object' && 'id' in element && 'source' in element && 'target' in element
7574
}
7675

77-
// todo: refactor generic to use MaybeElement
7876
export function isGraphEdge<Data = ElementData>(element: MaybeElement): element is GraphEdge<Data> {
7977
return isEdge(element) && 'sourceNode' in element && 'targetNode' in element
8078
}
8179

82-
// todo: refactor generic to use MaybeElement
8380
export function isNode<Data = ElementData>(element: MaybeElement): element is Node<Data> {
8481
return element && typeof element === 'object' && 'id' in element && 'position' in element && !isEdge(element)
8582
}
8683

87-
// todo: refactor generic to use MaybeElement
8884
export function isGraphNode<Data = ElementData>(element: MaybeElement): element is GraphNode<Data> {
8985
return isNode(element) && 'computedPosition' in element
9086
}
@@ -105,15 +101,15 @@ export function parseNode(node: Node, existingNode?: GraphNode, parentNode?: str
105101
width: 0,
106102
height: 0,
107103
}),
104+
computedPosition: markRaw({
105+
z: 0,
106+
...node.position,
107+
}),
108108
// todo: shouldn't be defined initially, as we want to use handleBounds to check if a node was actually initialized or not
109109
handleBounds: {
110110
source: [],
111111
target: [],
112112
},
113-
computedPosition: markRaw({
114-
z: 0,
115-
...node.position,
116-
}),
117113
draggable: undefined,
118114
selectable: undefined,
119115
connectable: undefined,
@@ -356,17 +352,23 @@ export function getBoundsofRects(rect1: Rect, rect2: Rect) {
356352
}
357353

358354
export function getRectOfNodes(nodes: GraphNode[]) {
359-
const box = nodes.reduce(
360-
(currBox, { computedPosition = { x: 0, y: 0 }, dimensions = { width: 0, height: 0 } } = {} as any) =>
361-
getBoundsOfBoxes(
362-
currBox,
363-
rectToBox({
364-
...computedPosition,
365-
...dimensions,
366-
} as Rect),
367-
),
368-
{ x: Number.POSITIVE_INFINITY, y: Number.POSITIVE_INFINITY, x2: Number.NEGATIVE_INFINITY, y2: Number.NEGATIVE_INFINITY },
369-
)
355+
let box: Box = {
356+
x: Number.POSITIVE_INFINITY,
357+
y: Number.POSITIVE_INFINITY,
358+
x2: Number.NEGATIVE_INFINITY,
359+
y2: Number.NEGATIVE_INFINITY,
360+
}
361+
362+
for (let i = 0; i < nodes.length; i++) {
363+
const node = nodes[i]
364+
box = getBoundsOfBoxes(
365+
box,
366+
rectToBox({
367+
...node.computedPosition,
368+
...node.dimensions,
369+
} as Rect),
370+
)
371+
}
370372

371373
return boxToRect(box)
372374
}

packages/core/src/utils/handle.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -222,8 +222,12 @@ interface GetHandleLookupParams {
222222
}
223223

224224
export function getHandleLookup({ nodes, nodeId, handleId, handleType }: GetHandleLookupParams) {
225-
return nodes.reduce<ConnectionHandle[]>((res, node) => {
225+
const handleLookup: ConnectionHandle[] = []
226+
for (let i = 0; i < nodes.length; i++) {
227+
const node = nodes[i]
228+
226229
const { handleBounds } = node
230+
227231
let sourceHandles: ConnectionHandle[] = []
228232
let targetHandles: ConnectionHandle[] = []
229233

@@ -232,9 +236,10 @@ export function getHandleLookup({ nodes, nodeId, handleId, handleType }: GetHand
232236
targetHandles = getHandles(node, handleBounds, 'target', `${nodeId}-${handleId}-${handleType}`)
233237
}
234238

235-
res.push(...sourceHandles, ...targetHandles)
236-
return res
237-
}, [])
239+
handleLookup.push(...sourceHandles, ...targetHandles)
240+
}
241+
242+
return handleLookup
238243
}
239244

240245
export function getHandleType(edgeUpdaterType: HandleType | undefined, handleDomNode: Element | null): HandleType | null {

packages/core/src/utils/store.ts

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -89,22 +89,18 @@ export function updateEdgeAction(
8989
return newEdge
9090
}
9191

92-
export function createGraphNodes(
93-
nodes: Node[],
94-
currGraphNodes: GraphNode[],
95-
findNode: Actions['findNode'],
96-
triggerError: State['hooks']['error']['trigger'],
97-
) {
92+
export function createGraphNodes(nodes: Node[], findNode: Actions['findNode'], triggerError: State['hooks']['error']['trigger']) {
9893
const parentNodes: Record<string, true> = {}
9994

100-
const nextNodes = nodes.reduce((nextNodes, node, currentIndex) => {
101-
// make sure we don't try to add invalid nodes
95+
const nextNodes: GraphNode[] = []
96+
for (let i = 0; i < nodes.length; ++i) {
97+
const node = nodes[i]
98+
10299
if (!isNode(node)) {
103100
triggerError(
104-
new VueFlowError(ErrorCode.NODE_INVALID, (node as undefined | Record<any, any>)?.id) ||
105-
`[ID UNKNOWN|INDEX ${currentIndex}]`,
101+
new VueFlowError(ErrorCode.NODE_INVALID, (node as undefined | Record<any, any>)?.id) || `[ID UNKNOWN|INDEX ${i}]`,
106102
)
107-
return nextNodes
103+
continue
108104
}
109105

110106
const parsed = parseNode(node, findNode(node.id), node.parentNode)
@@ -113,13 +109,11 @@ export function createGraphNodes(
113109
parentNodes[node.parentNode] = true
114110
}
115111

116-
return nextNodes.concat(parsed)
117-
}, [] as GraphNode[])
118-
119-
const allNodes = [...nextNodes, ...currGraphNodes]
112+
nextNodes[i] = parsed
113+
}
120114

121115
for (const node of nextNodes) {
122-
const parentNode = allNodes.find((n) => n.id === node.parentNode)
116+
const parentNode = findNode(node.parentNode) || nextNodes.find((n) => n.id === node.parentNode)
123117

124118
if (node.parentNode && !parentNode) {
125119
triggerError(new VueFlowError(ErrorCode.NODE_MISSING_PARENT, node.id, node.parentNode))

0 commit comments

Comments
 (0)