mirror of
https://github.com/wanderer-industries/wanderer
synced 2025-12-12 10:45:54 +00:00
chore: release version v1.19.1
This commit is contained in:
@@ -12,8 +12,6 @@ import ReactFlow, {
|
|||||||
OnSelectionChangeFunc,
|
OnSelectionChangeFunc,
|
||||||
SelectionDragHandler,
|
SelectionDragHandler,
|
||||||
SelectionMode,
|
SelectionMode,
|
||||||
useEdgesState,
|
|
||||||
useNodesState,
|
|
||||||
useReactFlow,
|
useReactFlow,
|
||||||
} from 'reactflow';
|
} from 'reactflow';
|
||||||
import 'reactflow/dist/style.css';
|
import 'reactflow/dist/style.css';
|
||||||
@@ -21,7 +19,7 @@ import classes from './Map.module.scss';
|
|||||||
import './styles/neon-theme.scss';
|
import './styles/neon-theme.scss';
|
||||||
import './styles/eve-common.scss';
|
import './styles/eve-common.scss';
|
||||||
import { MapProvider, useMapState } from './MapProvider';
|
import { MapProvider, useMapState } from './MapProvider';
|
||||||
import { useMapHandlers, useUpdateNodes } from './hooks';
|
import { useNodesState, useEdgesState, useMapHandlers, useUpdateNodes } from './hooks';
|
||||||
import { MapHandlers, OutCommand, OutCommandHandler } from '@/hooks/Mapper/types/mapHandlers.ts';
|
import { MapHandlers, OutCommand, OutCommandHandler } from '@/hooks/Mapper/types/mapHandlers.ts';
|
||||||
import {
|
import {
|
||||||
ContextMenuConnection,
|
ContextMenuConnection,
|
||||||
@@ -115,8 +113,8 @@ const MapComp = ({
|
|||||||
isThickConnections,
|
isThickConnections,
|
||||||
}: MapCompProps) => {
|
}: MapCompProps) => {
|
||||||
const { getNode } = useReactFlow();
|
const { getNode } = useReactFlow();
|
||||||
const [nodes, , onNodesChange] = useNodesState<SolarSystemRawType>(initialNodes);
|
const [nodes, , onNodesChange] = useNodesState<Node<SolarSystemRawType>>(initialNodes);
|
||||||
const [edges, , onEdgesChange] = useEdgesState<Edge<SolarSystemConnection>[]>(initialEdges);
|
const [edges, , onEdgesChange] = useEdgesState<Edge<SolarSystemConnection>>(initialEdges);
|
||||||
|
|
||||||
useMapHandlers(refn, onSelectionChange);
|
useMapHandlers(refn, onSelectionChange);
|
||||||
useUpdateNodes(nodes);
|
useUpdateNodes(nodes);
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
export * from './useMapHandlers';
|
export * from './useMapHandlers';
|
||||||
export * from './useUpdateNodes';
|
export * from './useUpdateNodes';
|
||||||
|
export * from './useNodesEdgesState';
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import { useState, useCallback, type Dispatch, type SetStateAction } from 'react';
|
||||||
|
|
||||||
|
import { applyNodeChanges, applyEdgeChanges } from '../utils/changes';
|
||||||
|
import { OnNodesChange, Edge, OnEdgesChange, Node } from 'reactflow';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook for managing the state of nodes - should only be used for prototyping / simple use cases.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
* @param initialNodes
|
||||||
|
* @returns an array [nodes, setNodes, onNodesChange]
|
||||||
|
*/
|
||||||
|
export function useNodesState<NodeType extends Node>(
|
||||||
|
initialNodes: NodeType[],
|
||||||
|
): [NodeType[], Dispatch<SetStateAction<NodeType[]>>, OnNodesChange] {
|
||||||
|
const [nodes, setNodes] = useState(initialNodes);
|
||||||
|
const onNodesChange: OnNodesChange = useCallback(changes => setNodes(nds => applyNodeChanges(changes, nds)), []);
|
||||||
|
|
||||||
|
return [nodes, setNodes, onNodesChange];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook for managing the state of edges - should only be used for prototyping / simple use cases.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
* @param initialEdges
|
||||||
|
* @returns an array [edges, setEdges, onEdgesChange]
|
||||||
|
*/
|
||||||
|
export function useEdgesState<EdgeType extends Edge = Edge>(
|
||||||
|
initialEdges: EdgeType[],
|
||||||
|
): [EdgeType[], Dispatch<SetStateAction<EdgeType[]>>, OnEdgesChange] {
|
||||||
|
const [edges, setEdges] = useState(initialEdges);
|
||||||
|
const onEdgesChange: OnEdgesChange = useCallback(changes => setEdges(eds => applyEdgeChanges(changes, eds)), []);
|
||||||
|
|
||||||
|
return [edges, setEdges, onEdgesChange];
|
||||||
|
}
|
||||||
174
assets/js/hooks/Mapper/components/map/utils/changes.ts
Normal file
174
assets/js/hooks/Mapper/components/map/utils/changes.ts
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
import { EdgeChange, NodeChange, Node, Edge } from 'reactflow';
|
||||||
|
|
||||||
|
// This function applies changes to nodes or edges that are triggered by React Flow internally.
|
||||||
|
// When you drag a node for example, React Flow will send a position change update.
|
||||||
|
// This function then applies the changes and returns the updated elements.
|
||||||
|
function applyChanges(changes: any[], elements: any[]): any[] {
|
||||||
|
// we need this hack to handle the setNodes and setEdges function of the useReactFlow hook for controlled flows
|
||||||
|
if (changes.some(c => c.type === 'reset')) {
|
||||||
|
return changes.filter(c => c.type === 'reset').map(c => c.item);
|
||||||
|
}
|
||||||
|
|
||||||
|
const updatedElements: any[] = [];
|
||||||
|
// By storing a map of changes for each element, we can a quick lookup as we
|
||||||
|
// iterate over the elements array!
|
||||||
|
const changesMap = new Map<any, any[]>();
|
||||||
|
const addItemChanges: any[] = [];
|
||||||
|
|
||||||
|
for (const change of changes) {
|
||||||
|
if (change.type === 'add') {
|
||||||
|
addItemChanges.push(change);
|
||||||
|
continue;
|
||||||
|
} else if (change.type === 'remove' || change.type === 'replace') {
|
||||||
|
// For a 'remove' change we can safely ignore any other changes queued for
|
||||||
|
// the same element, it's going to be removed anyway!
|
||||||
|
changesMap.set(change.id, [change]);
|
||||||
|
} else {
|
||||||
|
const elementChanges = changesMap.get(change.id);
|
||||||
|
|
||||||
|
if (elementChanges) {
|
||||||
|
// If we have some changes queued already, we can do a mutable update of
|
||||||
|
// that array and save ourselves some copying.
|
||||||
|
elementChanges.push(change);
|
||||||
|
} else {
|
||||||
|
changesMap.set(change.id, [change]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const element of elements) {
|
||||||
|
const changes = changesMap.get(element.id);
|
||||||
|
|
||||||
|
// When there are no changes for an element we can just push it unmodified,
|
||||||
|
// no need to copy it.
|
||||||
|
if (!changes) {
|
||||||
|
updatedElements.push(element);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have a 'remove' change queued, it'll be the only change in the array
|
||||||
|
if (changes[0].type === 'remove') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changes[0].type === 'replace') {
|
||||||
|
updatedElements.push({ ...changes[0].item });
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For other types of changes, we want to start with a shallow copy of the
|
||||||
|
// object so React knows this element has changed. Sequential changes will
|
||||||
|
/// each _mutate_ this object, so there's only ever one copy.
|
||||||
|
const updatedElement = { ...element };
|
||||||
|
|
||||||
|
for (const change of changes) {
|
||||||
|
applyChange(change, updatedElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
updatedElements.push(updatedElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
// we need to wait for all changes to be applied before adding new items
|
||||||
|
// to be able to add them at the correct index
|
||||||
|
if (addItemChanges.length) {
|
||||||
|
addItemChanges.forEach(change => {
|
||||||
|
if (change.index !== undefined) {
|
||||||
|
updatedElements.splice(change.index, 0, { ...change.item });
|
||||||
|
} else {
|
||||||
|
updatedElements.push({ ...change.item });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return updatedElements;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Applies a single change to an element. This is a *mutable* update.
|
||||||
|
function applyChange(change: any, element: any): any {
|
||||||
|
switch (change.type) {
|
||||||
|
case 'select': {
|
||||||
|
element.selected = change.selected;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'position': {
|
||||||
|
if (typeof change.position !== 'undefined') {
|
||||||
|
element.position = change.position;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof change.dragging !== 'undefined') {
|
||||||
|
element.dragging = change.dragging;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'dimensions': {
|
||||||
|
if (typeof change.dimensions !== 'undefined') {
|
||||||
|
element.measured ??= {};
|
||||||
|
element.measured.width = change.dimensions.width;
|
||||||
|
element.measured.height = change.dimensions.height;
|
||||||
|
|
||||||
|
if (change.setAttributes) {
|
||||||
|
element.width = change.dimensions.width;
|
||||||
|
element.height = change.dimensions.height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof change.resizing === 'boolean') {
|
||||||
|
element.resizing = change.resizing;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Drop in function that applies node changes to an array of nodes.
|
||||||
|
* @public
|
||||||
|
* @remarks Various events on the <ReactFlow /> component can produce an {@link NodeChange} that describes how to update the edges of your flow in some way.
|
||||||
|
If you don't need any custom behaviour, this util can be used to take an array of these changes and apply them to your edges.
|
||||||
|
* @param changes - Array of changes to apply
|
||||||
|
* @param nodes - Array of nodes to apply the changes to
|
||||||
|
* @returns Array of updated nodes
|
||||||
|
* @example
|
||||||
|
* const onNodesChange = useCallback(
|
||||||
|
(changes) => {
|
||||||
|
setNodes((oldNodes) => applyNodeChanges(changes, oldNodes));
|
||||||
|
},
|
||||||
|
[setNodes],
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ReactFLow nodes={nodes} edges={edges} onNodesChange={onNodesChange} />
|
||||||
|
);
|
||||||
|
*/
|
||||||
|
export function applyNodeChanges<NodeType extends Node = Node>(changes: NodeChange[], nodes: NodeType[]): NodeType[] {
|
||||||
|
return applyChanges(changes, nodes) as NodeType[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Drop in function that applies edge changes to an array of edges.
|
||||||
|
* @public
|
||||||
|
* @remarks Various events on the <ReactFlow /> component can produce an {@link EdgeChange} that describes how to update the edges of your flow in some way.
|
||||||
|
If you don't need any custom behaviour, this util can be used to take an array of these changes and apply them to your edges.
|
||||||
|
* @param changes - Array of changes to apply
|
||||||
|
* @param edges - Array of edge to apply the changes to
|
||||||
|
* @returns Array of updated edges
|
||||||
|
* @example
|
||||||
|
* const onEdgesChange = useCallback(
|
||||||
|
(changes) => {
|
||||||
|
setEdges((oldEdges) => applyEdgeChanges(changes, oldEdges));
|
||||||
|
},
|
||||||
|
[setEdges],
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ReactFlow nodes={nodes} edges={edges} onEdgesChange={onEdgesChange} />
|
||||||
|
);
|
||||||
|
*/
|
||||||
|
export function applyEdgeChanges<EdgeType extends Edge = Edge>(changes: EdgeChange[], edges: EdgeType[]): EdgeType[] {
|
||||||
|
return applyChanges(changes, edges) as EdgeType[];
|
||||||
|
}
|
||||||
@@ -11,33 +11,41 @@ export const useCommandsSystems = () => {
|
|||||||
|
|
||||||
const { addSystemStatic } = useLoadSystemStatic({ systems: [] });
|
const { addSystemStatic } = useLoadSystemStatic({ systems: [] });
|
||||||
|
|
||||||
const ref = useRef({ systems, update });
|
const ref = useRef({ systems, update, addSystemStatic });
|
||||||
ref.current = { systems, update };
|
ref.current = { systems, update, addSystemStatic };
|
||||||
|
|
||||||
const addSystems = useCallback(
|
const addSystems = useCallback((systemsToAdd: CommandAddSystems) => {
|
||||||
(addSystems: CommandAddSystems) => {
|
const { update, addSystemStatic, systems } = ref.current;
|
||||||
addSystems.forEach(sys => {
|
|
||||||
|
systemsToAdd.forEach(sys => {
|
||||||
|
if (sys.system_static_info) {
|
||||||
addSystemStatic(sys.system_static_info);
|
addSystemStatic(sys.system_static_info);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
update({
|
update(
|
||||||
systems: [...ref.current.systems.filter(sys => !addSystems.some(x => sys.id === x.id)), ...addSystems],
|
{
|
||||||
});
|
systems: [...systems.filter(sys => !systemsToAdd.some(x => sys.id === x.id)), ...systemsToAdd],
|
||||||
},
|
},
|
||||||
[addSystemStatic, update],
|
true,
|
||||||
);
|
);
|
||||||
|
}, []);
|
||||||
|
|
||||||
const removeSystems = useCallback((toRemove: CommandRemoveSystems) => {
|
const removeSystems = useCallback((toRemove: CommandRemoveSystems) => {
|
||||||
const { update, systems } = ref.current;
|
const { update, systems } = ref.current;
|
||||||
update({
|
update(
|
||||||
|
{
|
||||||
systems: systems.filter(x => !toRemove.includes(parseInt(x.id))),
|
systems: systems.filter(x => !toRemove.includes(parseInt(x.id))),
|
||||||
});
|
},
|
||||||
|
true,
|
||||||
|
);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const updateSystems = useCallback(
|
const updateSystems = useCallback((updatedSystems: CommandUpdateSystems) => {
|
||||||
(systems: CommandUpdateSystems) => {
|
const { update, systems } = ref.current;
|
||||||
const out = ref.current.systems.map(current => {
|
|
||||||
const newSystem = systems.find(x => current.id === x.id);
|
const out = systems.map(current => {
|
||||||
|
const newSystem = updatedSystems.find(x => current.id === x.id);
|
||||||
if (!newSystem) {
|
if (!newSystem) {
|
||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
@@ -45,10 +53,8 @@ export const useCommandsSystems = () => {
|
|||||||
return newSystem;
|
return newSystem;
|
||||||
});
|
});
|
||||||
|
|
||||||
update({ systems: out });
|
update({ systems: out }, true);
|
||||||
},
|
}, []);
|
||||||
[update],
|
|
||||||
);
|
|
||||||
|
|
||||||
return { addSystems, removeSystems, updateSystems };
|
return { addSystems, removeSystems, updateSystems };
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user