mirror of
https://github.com/stan-smith/FossFLOW.git
synced 2025-12-24 06:58:48 -05:00
feat: enables dragging of connector anchors
This commit is contained in:
@@ -28,7 +28,7 @@
|
||||
"react/no-unused-prop-types": ["warn"],
|
||||
"react/require-default-props": [0],
|
||||
"react/prop-types": [0],
|
||||
"no-param-reassign": ["error", { "props": true, "ignorePropertyModificationsFor": ["draftState", "draft"] }],
|
||||
"no-param-reassign": ["error", { "props": true, "ignorePropertyModificationsFor": ["draft"] }],
|
||||
"arrow-body-style": ["error", "always"]
|
||||
},
|
||||
"ignorePatterns": [
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
setWindowCursor,
|
||||
getAllAnchors
|
||||
} from 'src/utils';
|
||||
import { ModeActions } from 'src/types';
|
||||
import { ModeActions, SceneItemTypeEnum } from 'src/types';
|
||||
|
||||
export const Connector: ModeActions = {
|
||||
entry: () => {
|
||||
@@ -34,37 +34,35 @@ export const Connector: ModeActions = {
|
||||
});
|
||||
|
||||
if (itemAtTile && itemAtTile.type === 'NODE') {
|
||||
const newMode = produce(uiState.mode, (draftState) => {
|
||||
if (!draftState.connector) return;
|
||||
const newMode = produce(uiState.mode, (draft) => {
|
||||
if (!draft.connector) return;
|
||||
|
||||
draftState.connector.anchors[1] = {
|
||||
draft.connector.anchors[1] = {
|
||||
id: generateId(),
|
||||
type: SceneItemTypeEnum.CONNECTOR_ANCHOR,
|
||||
ref: {
|
||||
type: 'NODE',
|
||||
id: itemAtTile.id
|
||||
}
|
||||
};
|
||||
|
||||
draftState.connector.path = getConnectorPath({
|
||||
anchors: draftState.connector.anchors,
|
||||
nodes: scene.nodes,
|
||||
allAnchors: getAllAnchors(scene.connectors)
|
||||
});
|
||||
});
|
||||
|
||||
uiState.actions.setMode(newMode);
|
||||
} else {
|
||||
const newMode = produce(uiState.mode, (draftState) => {
|
||||
if (!draftState.connector) return;
|
||||
const newMode = produce(uiState.mode, (draft) => {
|
||||
if (!draft.connector) return;
|
||||
|
||||
draftState.connector.anchors[1] = {
|
||||
draft.connector.anchors[1] = {
|
||||
id: generateId(),
|
||||
type: SceneItemTypeEnum.CONNECTOR_ANCHOR,
|
||||
ref: {
|
||||
type: 'TILE',
|
||||
coords: uiState.mouse.position.tile
|
||||
}
|
||||
};
|
||||
|
||||
draftState.connector.path = getConnectorPath({
|
||||
anchors: draftState.connector.anchors,
|
||||
draft.connector.path = getConnectorPath({
|
||||
anchors: draft.connector.anchors,
|
||||
nodes: scene.nodes,
|
||||
allAnchors: getAllAnchors(scene.connectors)
|
||||
});
|
||||
@@ -82,8 +80,8 @@ export const Connector: ModeActions = {
|
||||
});
|
||||
|
||||
if (itemAtTile && itemAtTile.type === 'NODE') {
|
||||
const newMode = produce(uiState.mode, (draftState) => {
|
||||
draftState.connector = connectorInputToConnector(
|
||||
const newMode = produce(uiState.mode, (draft) => {
|
||||
draft.connector = connectorInputToConnector(
|
||||
{
|
||||
id: generateId(),
|
||||
anchors: [
|
||||
@@ -98,8 +96,8 @@ export const Connector: ModeActions = {
|
||||
|
||||
uiState.actions.setMode(newMode);
|
||||
} else {
|
||||
const newMode = produce(uiState.mode, (draftState) => {
|
||||
draftState.connector = connectorInputToConnector(
|
||||
const newMode = produce(uiState.mode, (draft) => {
|
||||
draft.connector = connectorInputToConnector(
|
||||
{
|
||||
id: generateId(),
|
||||
anchors: [
|
||||
|
||||
@@ -1,6 +1,42 @@
|
||||
import { produce } from 'immer';
|
||||
import { ModeActions, ModeActionsAction } from 'src/types';
|
||||
import { getItemAtTile, hasMovedTile } from 'src/utils';
|
||||
import {
|
||||
ConnectorAnchor,
|
||||
ModeActions,
|
||||
ModeActionsAction,
|
||||
SceneItemTypeEnum,
|
||||
SceneStore,
|
||||
Coords
|
||||
} from 'src/types';
|
||||
import {
|
||||
getItemAtTile,
|
||||
hasMovedTile,
|
||||
getAnchorAtTile,
|
||||
getItemById,
|
||||
generateId,
|
||||
CoordsUtils
|
||||
} from 'src/utils';
|
||||
|
||||
const getAnchor = (connectorId: string, tile: Coords, scene: SceneStore) => {
|
||||
const connector = getItemById(scene.connectors, connectorId).item;
|
||||
const anchor = getAnchorAtTile(tile, connector.anchors);
|
||||
|
||||
if (!anchor) {
|
||||
const newAnchor: ConnectorAnchor = {
|
||||
id: generateId(),
|
||||
type: SceneItemTypeEnum.CONNECTOR_ANCHOR,
|
||||
ref: { type: 'TILE', coords: tile }
|
||||
};
|
||||
|
||||
const newConnector = produce(connector, (draft) => {
|
||||
draft.anchors.push(newAnchor);
|
||||
});
|
||||
|
||||
scene.actions.updateConnector(connector.id, newConnector);
|
||||
return newAnchor;
|
||||
}
|
||||
|
||||
return anchor;
|
||||
};
|
||||
|
||||
const mousedown: ModeActionsAction = ({
|
||||
uiState,
|
||||
@@ -9,26 +45,23 @@ const mousedown: ModeActionsAction = ({
|
||||
}) => {
|
||||
if (uiState.mode.type !== 'CURSOR' || !isRendererInteraction) return;
|
||||
|
||||
const itemAtTile = getItemAtTile({
|
||||
const item = getItemAtTile({
|
||||
tile: uiState.mouse.position.tile,
|
||||
scene
|
||||
});
|
||||
|
||||
if (itemAtTile) {
|
||||
if (item) {
|
||||
uiState.actions.setMode(
|
||||
produce(uiState.mode, (draftState) => {
|
||||
draftState.mousedownItem = {
|
||||
type: itemAtTile.type,
|
||||
id: itemAtTile.id
|
||||
};
|
||||
produce(uiState.mode, (draft) => {
|
||||
draft.mousedownItem = item;
|
||||
})
|
||||
);
|
||||
|
||||
uiState.actions.setItemControls(itemAtTile);
|
||||
uiState.actions.setItemControls(item);
|
||||
} else {
|
||||
uiState.actions.setMode(
|
||||
produce(uiState.mode, (draftState) => {
|
||||
draftState.mousedownItem = null;
|
||||
produce(uiState.mode, (draft) => {
|
||||
draft.mousedownItem = null;
|
||||
})
|
||||
);
|
||||
|
||||
@@ -46,23 +79,32 @@ export const Cursor: ModeActions = {
|
||||
mousedown(state);
|
||||
}
|
||||
},
|
||||
mousemove: ({ uiState }) => {
|
||||
mousemove: ({ scene, uiState }) => {
|
||||
if (uiState.mode.type !== 'CURSOR' || !hasMovedTile(uiState.mouse)) return;
|
||||
|
||||
const { mousedownItem } = uiState.mode;
|
||||
let item = uiState.mode.mousedownItem;
|
||||
|
||||
if (mousedownItem) {
|
||||
if (item?.type === 'CONNECTOR') {
|
||||
const prevTile = uiState.mouse.delta
|
||||
? CoordsUtils.subtract(
|
||||
uiState.mouse.position.tile,
|
||||
uiState.mouse.delta.tile
|
||||
)
|
||||
: CoordsUtils.zero();
|
||||
const anchor = getAnchor(item.id, prevTile, scene);
|
||||
item = anchor;
|
||||
}
|
||||
|
||||
if (item) {
|
||||
uiState.actions.setMode({
|
||||
type: 'DRAG_ITEMS',
|
||||
showCursor: true,
|
||||
items: [mousedownItem],
|
||||
items: [item],
|
||||
isInitialMovement: true
|
||||
});
|
||||
}
|
||||
},
|
||||
mousedown: (state) => {
|
||||
mousedown(state);
|
||||
},
|
||||
mousedown,
|
||||
mouseup: ({ uiState, isRendererInteraction }) => {
|
||||
if (uiState.mode.type !== 'CURSOR' || !isRendererInteraction) return;
|
||||
|
||||
@@ -102,8 +144,8 @@ export const Cursor: ModeActions = {
|
||||
}
|
||||
|
||||
uiState.actions.setMode(
|
||||
produce(uiState.mode, (draftState) => {
|
||||
draftState.mousedownItem = null;
|
||||
produce(uiState.mode, (draft) => {
|
||||
draft.mousedownItem = null;
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
import { produce } from 'immer';
|
||||
import { ModeActions, Coords, SceneItemReference, SceneStore } from 'src/types';
|
||||
import { getItemById, CoordsUtils, hasMovedTile } from 'src/utils';
|
||||
import {
|
||||
getItemById,
|
||||
CoordsUtils,
|
||||
hasMovedTile,
|
||||
getAnchorParent
|
||||
} from 'src/utils';
|
||||
|
||||
const dragItems = (
|
||||
items: SceneItemReference[],
|
||||
tile: Coords,
|
||||
delta: Coords,
|
||||
scene: SceneStore
|
||||
) => {
|
||||
@@ -26,6 +32,27 @@ const dragItems = (
|
||||
scene.actions.updateTextBox(item.id, {
|
||||
tile: CoordsUtils.add(textBox.tile, delta)
|
||||
});
|
||||
} else if (item.type === 'CONNECTOR_ANCHOR') {
|
||||
const connector = getAnchorParent(item.id, scene.connectors);
|
||||
|
||||
const newConnector = produce(connector, (draft) => {
|
||||
const { item: anchor, index: anchorIndex } = getItemById(
|
||||
connector.anchors,
|
||||
item.id
|
||||
);
|
||||
|
||||
if (anchor.ref.type !== 'TILE') return;
|
||||
|
||||
draft.anchors[anchorIndex] = {
|
||||
...anchor,
|
||||
ref: {
|
||||
type: 'TILE',
|
||||
coords: tile
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
scene.actions.updateConnector(connector.id, newConnector);
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -50,11 +77,11 @@ export const DragItems: ModeActions = {
|
||||
uiState.mouse.mousedown.tile
|
||||
);
|
||||
|
||||
dragItems(uiState.mode.items, delta, scene);
|
||||
dragItems(uiState.mode.items, uiState.mouse.position.tile, delta, scene);
|
||||
|
||||
uiState.actions.setMode(
|
||||
produce(uiState.mode, (draftState) => {
|
||||
draftState.isInitialMovement = false;
|
||||
produce(uiState.mode, (draft) => {
|
||||
draft.isInitialMovement = false;
|
||||
})
|
||||
);
|
||||
|
||||
@@ -65,7 +92,7 @@ export const DragItems: ModeActions = {
|
||||
|
||||
const delta = uiState.mouse.delta.tile;
|
||||
|
||||
dragItems(uiState.mode.items, delta, scene);
|
||||
dragItems(uiState.mode.items, uiState.mouse.position.tile, delta, scene);
|
||||
},
|
||||
mouseup: ({ uiState }) => {
|
||||
uiState.actions.setMode({
|
||||
|
||||
@@ -44,17 +44,17 @@
|
||||
// );
|
||||
// }
|
||||
// },
|
||||
// mousedown: (draftState) => {
|
||||
// if (draftState.mode.type !== 'LASSO') return;
|
||||
// mousedown: (draft) => {
|
||||
// if (draft.mode.type !== 'LASSO') return;
|
||||
|
||||
// if (draftState.mode.selection) {
|
||||
// const isWithinSelection = isWithinBounds(draftState.mouse.position.tile, [
|
||||
// draftState.mode.selection.startTile,
|
||||
// draftState.mode.selection.endTile
|
||||
// if (draft.mode.selection) {
|
||||
// const isWithinSelection = isWithinBounds(draft.mouse.position.tile, [
|
||||
// draft.mode.selection.startTile,
|
||||
// draft.mode.selection.endTile
|
||||
// ]);
|
||||
|
||||
// if (!isWithinSelection) {
|
||||
// draftState.mode = {
|
||||
// draft.mode = {
|
||||
// type: 'CURSOR',
|
||||
// showCursor: true,
|
||||
// mousedown: null
|
||||
@@ -64,13 +64,13 @@
|
||||
// }
|
||||
|
||||
// if (isWithinSelection) {
|
||||
// draftState.mode.isDragging = true;
|
||||
// draft.mode.isDragging = true;
|
||||
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
|
||||
// draftState.mode = {
|
||||
// draft.mode = {
|
||||
// type: 'CURSOR',
|
||||
// showCursor: true,
|
||||
// mousedown: null
|
||||
|
||||
@@ -13,10 +13,10 @@ export const Pan: ModeActions = {
|
||||
if (uiState.mode.type !== 'PAN') return;
|
||||
|
||||
if (uiState.mouse.mousedown !== null) {
|
||||
const newScroll = produce(uiState.scroll, (draftState) => {
|
||||
draftState.position = uiState.mouse.delta?.screen
|
||||
? CoordsUtils.add(draftState.position, uiState.mouse.delta.screen)
|
||||
: draftState.position;
|
||||
const newScroll = produce(uiState.scroll, (draft) => {
|
||||
draft.position = uiState.mouse.delta?.screen
|
||||
? CoordsUtils.add(draft.position, uiState.mouse.delta.screen)
|
||||
: draft.position;
|
||||
});
|
||||
|
||||
uiState.actions.setScroll(newScroll);
|
||||
|
||||
@@ -34,8 +34,8 @@ export const PlaceElement: ModeActions = {
|
||||
}
|
||||
|
||||
uiState.actions.setMode(
|
||||
produce(uiState.mode, (draftState) => {
|
||||
draftState.icon = null;
|
||||
produce(uiState.mode, (draft) => {
|
||||
draft.icon = null;
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -19,10 +19,10 @@ export const DrawRectangle: ModeActions = {
|
||||
)
|
||||
return;
|
||||
|
||||
const newMode = produce(uiState.mode, (draftState) => {
|
||||
if (!draftState.area) return;
|
||||
const newMode = produce(uiState.mode, (draft) => {
|
||||
if (!draft.area) return;
|
||||
|
||||
draftState.area.to = uiState.mouse.position.tile;
|
||||
draft.area.to = uiState.mouse.position.tile;
|
||||
});
|
||||
|
||||
uiState.actions.setMode(newMode);
|
||||
@@ -30,8 +30,8 @@ export const DrawRectangle: ModeActions = {
|
||||
mousedown: ({ uiState }) => {
|
||||
if (uiState.mode.type !== 'RECTANGLE.DRAW') return;
|
||||
|
||||
const newMode = produce(uiState.mode, (draftState) => {
|
||||
draftState.area = {
|
||||
const newMode = produce(uiState.mode, (draft) => {
|
||||
draft.area = {
|
||||
from: uiState.mouse.position.tile,
|
||||
to: uiState.mouse.position.tile
|
||||
};
|
||||
|
||||
@@ -100,8 +100,8 @@ export const TransformRectangle: ModeActions = {
|
||||
Object.values(AnchorPositionsEnum)[activeAnchorIndex];
|
||||
|
||||
uiState.actions.setMode(
|
||||
produce(uiState.mode, (draftState) => {
|
||||
draftState.selectedAnchor = activeAnchor;
|
||||
produce(uiState.mode, (draft) => {
|
||||
draft.selectedAnchor = activeAnchor;
|
||||
})
|
||||
);
|
||||
return;
|
||||
@@ -139,8 +139,8 @@ export const TransformRectangle: ModeActions = {
|
||||
|
||||
if (uiState.mode.selectedAnchor) {
|
||||
uiState.actions.setMode(
|
||||
produce(uiState.mode, (draftState) => {
|
||||
draftState.selectedAnchor = null;
|
||||
produce(uiState.mode, (draft) => {
|
||||
draft.selectedAnchor = null;
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -48,32 +48,32 @@ const initialState = () => {
|
||||
},
|
||||
|
||||
createNode: (node) => {
|
||||
const newScene = produce(get(), (draftState) => {
|
||||
draftState.nodes.push(nodeInputToNode(node));
|
||||
const newScene = produce(get(), (draft) => {
|
||||
draft.nodes.push(nodeInputToNode(node));
|
||||
});
|
||||
|
||||
set({ nodes: newScene.nodes });
|
||||
},
|
||||
|
||||
updateNode: (id, updates) => {
|
||||
const newScene = produce(get(), (draftState) => {
|
||||
const { item: node, index } = getItemById(draftState.nodes, id);
|
||||
const newScene = produce(get(), (draft) => {
|
||||
const { item: node, index } = getItemById(draft.nodes, id);
|
||||
|
||||
draftState.nodes[index] = {
|
||||
draft.nodes[index] = {
|
||||
...node,
|
||||
...updates
|
||||
};
|
||||
|
||||
draftState.connectors.forEach((connector, i) => {
|
||||
draft.connectors.forEach((connector, i) => {
|
||||
const needsUpdate = connector.anchors.find((anchor) => {
|
||||
return anchor.ref.type === 'NODE' && anchor.ref.id === id;
|
||||
});
|
||||
|
||||
if (needsUpdate) {
|
||||
draftState.connectors[i].path = getConnectorPath({
|
||||
draft.connectors[i].path = getConnectorPath({
|
||||
anchors: connector.anchors,
|
||||
nodes: draftState.nodes,
|
||||
allAnchors: getAllAnchors(draftState.connectors)
|
||||
nodes: draft.nodes,
|
||||
allAnchors: getAllAnchors(draft.connectors)
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -83,12 +83,12 @@ const initialState = () => {
|
||||
},
|
||||
|
||||
deleteNode: (id: string) => {
|
||||
const newScene = produce(get(), (draftState) => {
|
||||
const { index } = getItemById(draftState.nodes, id);
|
||||
const newScene = produce(get(), (draft) => {
|
||||
const { index } = getItemById(draft.nodes, id);
|
||||
|
||||
draftState.nodes.splice(index, 1);
|
||||
draft.nodes.splice(index, 1);
|
||||
|
||||
draftState.connectors = draftState.connectors.filter(
|
||||
draft.connectors = draft.connectors.filter(
|
||||
(connector) => {
|
||||
return !connector.anchors.find((anchor) => {
|
||||
return anchor.ref.type === 'NODE' && anchor.ref.id === id;
|
||||
@@ -101,12 +101,12 @@ const initialState = () => {
|
||||
},
|
||||
|
||||
createConnector: (connector) => {
|
||||
const newScene = produce(get(), (draftState) => {
|
||||
draftState.connectors.push(
|
||||
const newScene = produce(get(), (draft) => {
|
||||
draft.connectors.push(
|
||||
connectorInputToConnector(
|
||||
connector,
|
||||
draftState.nodes,
|
||||
getAllAnchors(draftState.connectors)
|
||||
draft.nodes,
|
||||
getAllAnchors(draft.connectors)
|
||||
)
|
||||
);
|
||||
});
|
||||
@@ -115,56 +115,63 @@ const initialState = () => {
|
||||
},
|
||||
|
||||
updateConnector: (id, updates) => {
|
||||
const newScene = produce(get(), (draftState) => {
|
||||
const { item: connector, index } = getItemById(
|
||||
draftState.connectors,
|
||||
id
|
||||
);
|
||||
const scene = get();
|
||||
const { item: connector, index } = getItemById(scene.connectors, id);
|
||||
|
||||
draftState.connectors[index] = {
|
||||
const newScene = produce(scene, (draft) => {
|
||||
draft.connectors[index] = {
|
||||
...connector,
|
||||
...updates
|
||||
};
|
||||
|
||||
if (updates.anchors) {
|
||||
draft.connectors[index].path = getConnectorPath({
|
||||
anchors: updates.anchors,
|
||||
nodes: scene.nodes,
|
||||
allAnchors: getAllAnchors(scene.connectors)
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
set({ connectors: newScene.connectors });
|
||||
console.log(newScene.connectors)
|
||||
},
|
||||
|
||||
deleteConnector: (id: string) => {
|
||||
const newScene = produce(get(), (draftState) => {
|
||||
const { index } = getItemById(draftState.connectors, id);
|
||||
const newScene = produce(get(), (draft) => {
|
||||
const { index } = getItemById(draft.connectors, id);
|
||||
|
||||
draftState.connectors.splice(index, 1);
|
||||
draft.connectors.splice(index, 1);
|
||||
});
|
||||
|
||||
set({ connectors: newScene.connectors });
|
||||
},
|
||||
|
||||
createRectangle: (rectangle) => {
|
||||
const newScene = produce(get(), (draftState) => {
|
||||
draftState.rectangles.push(rectangleInputToRectangle(rectangle));
|
||||
const newScene = produce(get(), (draft) => {
|
||||
draft.rectangles.push(rectangleInputToRectangle(rectangle));
|
||||
});
|
||||
|
||||
set({ rectangles: newScene.rectangles });
|
||||
},
|
||||
|
||||
createTextBox: (textBox) => {
|
||||
const newScene = produce(get(), (draftState) => {
|
||||
draftState.textBoxes.push(textBoxInputToTextBox(textBox));
|
||||
const newScene = produce(get(), (draft) => {
|
||||
draft.textBoxes.push(textBoxInputToTextBox(textBox));
|
||||
});
|
||||
|
||||
set({ textBoxes: newScene.textBoxes });
|
||||
},
|
||||
|
||||
updateTextBox: (id, updates) => {
|
||||
const newScene = produce(get(), (draftState) => {
|
||||
const newScene = produce(get(), (draft) => {
|
||||
const { item: textBox, index } = getItemById(
|
||||
draftState.textBoxes,
|
||||
draft.textBoxes,
|
||||
id
|
||||
);
|
||||
|
||||
if (updates.text !== undefined || updates.fontSize !== undefined) {
|
||||
draftState.textBoxes[index].size = {
|
||||
draft.textBoxes[index].size = {
|
||||
width: getTextWidth(updates.text ?? textBox.text, {
|
||||
fontSize: updates.fontSize ?? textBox.fontSize,
|
||||
fontFamily: DEFAULT_FONT_FAMILY,
|
||||
@@ -174,7 +181,7 @@ const initialState = () => {
|
||||
};
|
||||
}
|
||||
|
||||
draftState.textBoxes[index] = {
|
||||
draft.textBoxes[index] = {
|
||||
...textBox,
|
||||
...updates
|
||||
};
|
||||
@@ -184,23 +191,23 @@ const initialState = () => {
|
||||
},
|
||||
|
||||
deleteTextBox: (id: string) => {
|
||||
const newScene = produce(get(), (draftState) => {
|
||||
const { index } = getItemById(draftState.textBoxes, id);
|
||||
const newScene = produce(get(), (draft) => {
|
||||
const { index } = getItemById(draft.textBoxes, id);
|
||||
|
||||
draftState.textBoxes.splice(index, 1);
|
||||
draft.textBoxes.splice(index, 1);
|
||||
});
|
||||
|
||||
set({ textBoxes: newScene.textBoxes });
|
||||
},
|
||||
|
||||
updateRectangle: (id, updates) => {
|
||||
const newScene = produce(get(), (draftState) => {
|
||||
const newScene = produce(get(), (draft) => {
|
||||
const { item: rectangle, index } = getItemById(
|
||||
draftState.rectangles,
|
||||
draft.rectangles,
|
||||
id
|
||||
);
|
||||
|
||||
draftState.rectangles[index] = {
|
||||
draft.rectangles[index] = {
|
||||
...rectangle,
|
||||
...updates
|
||||
};
|
||||
@@ -210,10 +217,10 @@ const initialState = () => {
|
||||
},
|
||||
|
||||
deleteRectangle: (id: string) => {
|
||||
const newScene = produce(get(), (draftState) => {
|
||||
const { index } = getItemById(draftState.rectangles, id);
|
||||
const newScene = produce(get(), (draft) => {
|
||||
const { index } = getItemById(draft.rectangles, id);
|
||||
|
||||
draftState.rectangles.splice(index, 1);
|
||||
draft.rectangles.splice(index, 1);
|
||||
});
|
||||
|
||||
set({ rectangles: newScene.rectangles });
|
||||
|
||||
@@ -20,6 +20,7 @@ export enum TileOriginEnum {
|
||||
export enum SceneItemTypeEnum {
|
||||
NODE = 'NODE',
|
||||
CONNECTOR = 'CONNECTOR',
|
||||
CONNECTOR_ANCHOR = 'CONNECTOR_ANCHOR',
|
||||
TEXTBOX = 'TEXTBOX',
|
||||
RECTANGLE = 'RECTANGLE'
|
||||
}
|
||||
@@ -49,7 +50,8 @@ export type ConnectorAnchorRef =
|
||||
};
|
||||
|
||||
export type ConnectorAnchor = {
|
||||
id?: string;
|
||||
id: string;
|
||||
type: SceneItemTypeEnum.CONNECTOR_ANCHOR;
|
||||
ref: ConnectorAnchorRef;
|
||||
};
|
||||
|
||||
@@ -84,7 +86,7 @@ export interface Rectangle {
|
||||
to: Coords;
|
||||
}
|
||||
|
||||
export type SceneItem = Node | Connector | TextBox | Rectangle;
|
||||
export type SceneItem = Node | Connector | TextBox | Rectangle | ConnectorAnchor;
|
||||
export type SceneItemReference = {
|
||||
type: SceneItemTypeEnum;
|
||||
id: string;
|
||||
|
||||
@@ -17,6 +17,11 @@ interface TextBoxControls {
|
||||
id: string;
|
||||
}
|
||||
|
||||
interface ConnectorAnchorControls {
|
||||
type: 'CONNECTOR_ANCHOR';
|
||||
id: string;
|
||||
}
|
||||
|
||||
interface RectangleControls {
|
||||
type: 'RECTANGLE';
|
||||
id: string;
|
||||
@@ -32,6 +37,7 @@ export type ItemControls =
|
||||
| RectangleControls
|
||||
| AddItemControls
|
||||
| TextBoxControls
|
||||
| ConnectorAnchorControls
|
||||
| null;
|
||||
|
||||
export interface Mouse {
|
||||
|
||||
@@ -23,7 +23,7 @@ import {
|
||||
TEXTBOX_DEFAULTS,
|
||||
DEFAULT_FONT_FAMILY
|
||||
} from 'src/config';
|
||||
import { getConnectorPath, getTextWidth } from 'src/utils';
|
||||
import { getConnectorPath, getTextWidth, generateId } from 'src/utils';
|
||||
|
||||
export const iconInputToIcon = (iconInput: IconInput): Icon => {
|
||||
return {
|
||||
@@ -62,9 +62,14 @@ export const rectangleInputToRectangle = (
|
||||
const connectorAnchorInputToConnectorAnchor = (
|
||||
anchor: ConnectorAnchorInput
|
||||
): ConnectorAnchor => {
|
||||
const anchorBase: Required<Pick<ConnectorAnchor, 'id' | 'type'>> = {
|
||||
id: anchor.id ?? generateId(),
|
||||
type: SceneItemTypeEnum.CONNECTOR_ANCHOR
|
||||
};
|
||||
|
||||
if (anchor.ref.node) {
|
||||
return {
|
||||
id: anchor.id,
|
||||
...anchorBase,
|
||||
ref: {
|
||||
type: 'NODE',
|
||||
id: anchor.ref.node
|
||||
@@ -74,7 +79,7 @@ const connectorAnchorInputToConnectorAnchor = (
|
||||
|
||||
if (anchor.ref.tile) {
|
||||
return {
|
||||
id: anchor.id,
|
||||
...anchorBase,
|
||||
ref: {
|
||||
type: 'TILE',
|
||||
coords: anchor.ref.tile
|
||||
@@ -84,7 +89,7 @@ const connectorAnchorInputToConnectorAnchor = (
|
||||
|
||||
if (anchor.ref.anchor) {
|
||||
return {
|
||||
id: anchor.id,
|
||||
...anchorBase,
|
||||
ref: {
|
||||
type: 'ANCHOR',
|
||||
id: anchor.ref.anchor
|
||||
|
||||
@@ -211,9 +211,9 @@ const isoProjectionBaseValues = [0.707, -0.409, 0.707, 0.409, 0, -0.816];
|
||||
export const getIsoMatrix = (orientation?: ProjectionOrientationEnum) => {
|
||||
switch (orientation) {
|
||||
case ProjectionOrientationEnum.Y:
|
||||
return produce(isoProjectionBaseValues, (draftState) => {
|
||||
draftState[1] = -draftState[1];
|
||||
draftState[2] = -draftState[2];
|
||||
return produce(isoProjectionBaseValues, (draft) => {
|
||||
draft[1] = -draft[1];
|
||||
draft[2] = -draft[2];
|
||||
});
|
||||
case ProjectionOrientationEnum.X:
|
||||
default:
|
||||
@@ -568,3 +568,25 @@ export const convertBoundsToNamedAnchors = (boundingBox: BoundingBox) => {
|
||||
[AnchorPositionsEnum.TOP_LEFT]: boundingBox[3]
|
||||
};
|
||||
};
|
||||
|
||||
export const getAnchorAtTile = (tile: Coords, anchors: ConnectorAnchor[]) => {
|
||||
return anchors.find((anchor) => {
|
||||
return (
|
||||
anchor.ref.type === 'TILE' && CoordsUtils.isEqual(anchor.ref.coords, tile)
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
export const getAnchorParent = (anchorId: string, connectors: Connector[]) => {
|
||||
const connector = connectors.find((con) => {
|
||||
return con.anchors.find((anchor) => {
|
||||
return anchor.id === anchorId;
|
||||
});
|
||||
});
|
||||
|
||||
if (!connector) {
|
||||
throw new Error(`Could not find connector with anchor id ${anchorId}`);
|
||||
}
|
||||
|
||||
return connector;
|
||||
};
|
||||
|
||||
@@ -19,8 +19,8 @@ describe('Tests immer', () => {
|
||||
|
||||
test('Array equivalence with immer', () => {
|
||||
const arr = [createItem(0, 0), createItem(1, 1)];
|
||||
const newArr = produce(arr, (draftState) => {
|
||||
draftState[1] = createItem(2, 2);
|
||||
const newArr = produce(arr, (draft) => {
|
||||
draft[1] = createItem(2, 2);
|
||||
});
|
||||
|
||||
expect(arr[0]).toBe(newArr[0]);
|
||||
|
||||
Reference in New Issue
Block a user