Add selection drag overlay
This commit is contained in:
parent
19139dec82
commit
ed64294855
@ -30,6 +30,8 @@ type SelectionProps = {
|
||||
onSelectionChange: (selection: SelectionType | null) => void;
|
||||
onSelectionItemsChange: SelectionItemsChangeEventHandler;
|
||||
onPreventSelectionChange: (preventSelection: boolean) => void;
|
||||
onSelectionDragStart: () => void;
|
||||
onSelectionDragEnd: () => void;
|
||||
} & Konva.ShapeConfig;
|
||||
|
||||
function Selection({
|
||||
@ -37,6 +39,8 @@ function Selection({
|
||||
onSelectionChange,
|
||||
onSelectionItemsChange,
|
||||
onPreventSelectionChange,
|
||||
onSelectionDragStart,
|
||||
onSelectionDragEnd,
|
||||
...props
|
||||
}: SelectionProps) {
|
||||
const userId = useUserId();
|
||||
@ -75,6 +79,7 @@ function Selection({
|
||||
}
|
||||
}
|
||||
}
|
||||
onSelectionDragStart();
|
||||
}
|
||||
|
||||
function handleDragMove(event: Konva.KonvaEventObject<DragEvent>) {
|
||||
@ -119,6 +124,7 @@ function Selection({
|
||||
});
|
||||
intersectingNodesRef.current = [];
|
||||
onPreventSelectionChange(false);
|
||||
onSelectionDragEnd();
|
||||
}
|
||||
|
||||
function handlePointerDown() {
|
||||
|
@ -38,6 +38,7 @@ import {
|
||||
TokenStateChangeEventHandler,
|
||||
NoteCreateEventHander,
|
||||
SelectionItemsChangeEventHandler,
|
||||
SelectionItemsRemoveEventHandler,
|
||||
} from "../../types/Events";
|
||||
|
||||
import useMapTokens from "../../hooks/useMapTokens";
|
||||
@ -52,6 +53,7 @@ type MapProps = {
|
||||
onMapTokenStateChange: TokenStateChangeEventHandler;
|
||||
onMapTokenStateRemove: TokenStateRemoveHandler;
|
||||
onSelectionItemsChange: SelectionItemsChangeEventHandler;
|
||||
onSelectionItemsRemove: SelectionItemsRemoveEventHandler;
|
||||
onMapChange: MapChangeEventHandler;
|
||||
onMapReset: MapResetEventHandler;
|
||||
onMapDraw: (action: Action<DrawingState>) => void;
|
||||
@ -72,6 +74,7 @@ function Map({
|
||||
onMapTokenStateChange,
|
||||
onMapTokenStateRemove,
|
||||
onSelectionItemsChange,
|
||||
onSelectionItemsRemove,
|
||||
onMapChange,
|
||||
onMapReset,
|
||||
onMapDraw,
|
||||
@ -149,13 +152,15 @@ function Map({
|
||||
!!(map?.owner === userId || mapState?.editFlags.includes("notes"))
|
||||
);
|
||||
|
||||
const { selectionTool, selectionMenu } = useMapSelection(
|
||||
map,
|
||||
mapState,
|
||||
onSelectionItemsChange,
|
||||
selectedToolId,
|
||||
settings.select
|
||||
);
|
||||
const { selectionTool, selectionMenu, selectionDragOverlay } =
|
||||
useMapSelection(
|
||||
map,
|
||||
mapState,
|
||||
onSelectionItemsChange,
|
||||
onSelectionItemsRemove,
|
||||
selectedToolId,
|
||||
settings.select
|
||||
);
|
||||
|
||||
return (
|
||||
<Box sx={{ flexGrow: 1 }}>
|
||||
@ -184,6 +189,7 @@ function Map({
|
||||
{selectionMenu}
|
||||
{tokenDragOverlay}
|
||||
{noteDragOverlay}
|
||||
{selectionDragOverlay}
|
||||
</>
|
||||
}
|
||||
selectedToolId={selectedToolId}
|
||||
|
@ -1,4 +1,3 @@
|
||||
import Konva from "konva";
|
||||
import { NoteRemoveEventHander } from "../../types/Events";
|
||||
|
||||
import DragOverlay from "../map/DragOverlay";
|
||||
@ -6,27 +5,19 @@ import DragOverlay from "../map/DragOverlay";
|
||||
type NoteDragOverlayProps = {
|
||||
onNoteRemove: NoteRemoveEventHander;
|
||||
noteId: string;
|
||||
noteGroup: Konva.Node;
|
||||
dragging: boolean;
|
||||
};
|
||||
|
||||
function NoteDragOverlay({
|
||||
onNoteRemove,
|
||||
noteId,
|
||||
noteGroup,
|
||||
dragging,
|
||||
}: NoteDragOverlayProps) {
|
||||
function handleNoteRemove() {
|
||||
onNoteRemove([noteId]);
|
||||
}
|
||||
|
||||
return (
|
||||
<DragOverlay
|
||||
dragging={dragging}
|
||||
onRemove={handleNoteRemove}
|
||||
node={noteGroup}
|
||||
/>
|
||||
);
|
||||
return <DragOverlay dragging={dragging} onRemove={handleNoteRemove} />;
|
||||
}
|
||||
|
||||
export default NoteDragOverlay;
|
||||
|
33
src/components/selection/SelectionDragOverlay.tsx
Normal file
33
src/components/selection/SelectionDragOverlay.tsx
Normal file
@ -0,0 +1,33 @@
|
||||
import { SelectionItemsRemoveEventHandler } from "../../types/Events";
|
||||
import { Selection } from "../../types/Select";
|
||||
|
||||
import DragOverlay from "../map/DragOverlay";
|
||||
|
||||
type NoteDragOverlayProps = {
|
||||
onSelectionItemsRemove: SelectionItemsRemoveEventHandler;
|
||||
selection: Selection;
|
||||
dragging: boolean;
|
||||
};
|
||||
|
||||
function NoteDragOverlay({
|
||||
onSelectionItemsRemove,
|
||||
selection,
|
||||
dragging,
|
||||
}: NoteDragOverlayProps) {
|
||||
function handleNoteRemove() {
|
||||
const tokenIds: string[] = [];
|
||||
const noteIds: string[] = [];
|
||||
for (let item of selection.items) {
|
||||
if (item.type === "token") {
|
||||
tokenIds.push(item.id);
|
||||
} else {
|
||||
noteIds.push(item.id);
|
||||
}
|
||||
}
|
||||
onSelectionItemsRemove(tokenIds, noteIds);
|
||||
}
|
||||
|
||||
return <DragOverlay dragging={dragging} onRemove={handleNoteRemove} />;
|
||||
}
|
||||
|
||||
export default NoteDragOverlay;
|
@ -40,6 +40,8 @@ type MapSelectProps = {
|
||||
selection: SelectionType | null;
|
||||
onSelectionChange: React.Dispatch<React.SetStateAction<SelectionType | null>>;
|
||||
onSelectionMenuOpen: (open: boolean) => void;
|
||||
onSelectionDragStart: () => void;
|
||||
onSelectionDragEnd: () => void;
|
||||
};
|
||||
|
||||
function SelectTool({
|
||||
@ -49,6 +51,8 @@ function SelectTool({
|
||||
selection,
|
||||
onSelectionChange,
|
||||
onSelectionMenuOpen,
|
||||
onSelectionDragStart,
|
||||
onSelectionDragEnd,
|
||||
}: MapSelectProps) {
|
||||
const stageScale = useDebouncedStageScale();
|
||||
const mapWidth = useMapWidth();
|
||||
@ -255,6 +259,8 @@ function SelectTool({
|
||||
onPreventSelectionChange={(prevent: boolean) =>
|
||||
(preventSelectionRef.current = prevent)
|
||||
}
|
||||
onSelectionDragStart={onSelectionDragStart}
|
||||
onSelectionDragEnd={onSelectionDragEnd}
|
||||
/>
|
||||
)}
|
||||
</Group>
|
||||
|
@ -1,7 +1,11 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import SelectionDragOverlay from "../components/selection/SelectionDragOverlay";
|
||||
import SelectionMenu from "../components/selection/SelectionMenu";
|
||||
import SelectTool from "../components/tools/SelectTool";
|
||||
import { SelectionItemsChangeEventHandler } from "../types/Events";
|
||||
import {
|
||||
SelectionItemsChangeEventHandler,
|
||||
SelectionItemsRemoveEventHandler,
|
||||
} from "../types/Events";
|
||||
import { Map, MapToolId } from "../types/Map";
|
||||
import { MapState } from "../types/MapState";
|
||||
import { Selection } from "../types/Select";
|
||||
@ -11,11 +15,13 @@ function useMapSelection(
|
||||
map: Map | null,
|
||||
mapState: MapState | null,
|
||||
onSelectionItemsChange: SelectionItemsChangeEventHandler,
|
||||
onSelectionItemsRemove: SelectionItemsRemoveEventHandler,
|
||||
selectedToolId: MapToolId,
|
||||
settings: SelectToolSettings
|
||||
) {
|
||||
const [isSelectionMenuOpen, setIsSelectionMenuOpen] =
|
||||
useState<boolean>(false);
|
||||
const [isSelectionDragging, setIsSelectionDragging] = useState(false);
|
||||
const [selection, setSelection] = useState<Selection | null>(null);
|
||||
|
||||
function handleSelectionMenuOpen(open: boolean) {
|
||||
@ -31,6 +37,22 @@ function useMapSelection(
|
||||
}
|
||||
}, [active]);
|
||||
|
||||
function handleSelectionDragStart() {
|
||||
setIsSelectionDragging(true);
|
||||
}
|
||||
|
||||
function handleSelectionDragEnd() {
|
||||
setIsSelectionDragging(false);
|
||||
}
|
||||
|
||||
function handleSelectionItemsRemove(
|
||||
tokenStateIds: string[],
|
||||
noteIds: string[]
|
||||
) {
|
||||
setSelection(null);
|
||||
onSelectionItemsRemove(tokenStateIds, noteIds);
|
||||
}
|
||||
|
||||
const selectionTool = (
|
||||
<SelectTool
|
||||
active={active}
|
||||
@ -39,6 +61,8 @@ function useMapSelection(
|
||||
selection={selection}
|
||||
onSelectionChange={setSelection}
|
||||
onSelectionMenuOpen={handleSelectionMenuOpen}
|
||||
onSelectionDragStart={handleSelectionDragStart}
|
||||
onSelectionDragEnd={handleSelectionDragEnd}
|
||||
/>
|
||||
);
|
||||
|
||||
@ -53,7 +77,15 @@ function useMapSelection(
|
||||
/>
|
||||
);
|
||||
|
||||
return { selectionTool, selectionMenu };
|
||||
const selectionDragOverlay = selection ? (
|
||||
<SelectionDragOverlay
|
||||
dragging={isSelectionDragging}
|
||||
selection={selection}
|
||||
onSelectionItemsRemove={handleSelectionItemsRemove}
|
||||
/>
|
||||
) : null;
|
||||
|
||||
return { selectionTool, selectionMenu, selectionDragOverlay };
|
||||
}
|
||||
|
||||
export default useMapSelection;
|
||||
|
@ -330,6 +330,18 @@ function NetworkedMapAndTokens({ session }: { session: Session }) {
|
||||
]);
|
||||
}
|
||||
|
||||
function handleSelectionItemsRemove(
|
||||
tokenStateIds: string[],
|
||||
noteIds: string[]
|
||||
) {
|
||||
const tokenAction = new RemoveStatesAction<TokenState>(tokenStateIds);
|
||||
const noteAction = new RemoveStatesAction<Note>(noteIds);
|
||||
addActions([
|
||||
{ type: "tokens", action: tokenAction },
|
||||
{ type: "notes", action: noteAction },
|
||||
]);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
async function handlePeerData({ id, data, reply }: PeerDataEvent) {
|
||||
if (id === "assetRequest") {
|
||||
@ -394,6 +406,7 @@ function NetworkedMapAndTokens({ session }: { session: Session }) {
|
||||
onMapTokenStateChange={handleMapTokenStateChange}
|
||||
onMapTokenStateRemove={handleMapTokenStateRemove}
|
||||
onSelectionItemsChange={handleSelectionItemsChange}
|
||||
onSelectionItemsRemove={handleSelectionItemsRemove}
|
||||
onMapChange={handleMapChange}
|
||||
onMapReset={handleMapReset}
|
||||
onMapDraw={handleMapDraw}
|
||||
|
@ -63,3 +63,7 @@ export type SelectionItemsChangeEventHandler = (
|
||||
tokenChanges: Record<string, Partial<TokenState>>,
|
||||
noteChanges: Record<string, Partial<Note>>
|
||||
) => void;
|
||||
export type SelectionItemsRemoveEventHandler = (
|
||||
tokenStateIds: string[],
|
||||
noteIds: string[]
|
||||
) => void;
|
||||
|
Loading…
Reference in New Issue
Block a user