Skip to content

Commit

Permalink
editor drag cells
Browse files Browse the repository at this point in the history
  • Loading branch information
k2xl committed Jan 2, 2025
1 parent 196fe67 commit 3ee904c
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 15 deletions.
2 changes: 1 addition & 1 deletion components/editor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ export default function Editor({ isDirty, level, setIsDirty, setLevel }: EditorP
}
}

function onClick(index: number, rightClick: boolean) {
function onClick(index: number, rightClick: boolean, isDragging?: boolean) {
setIsDirty(true);
setLevel(prevLevel => {
if (!prevLevel) {
Expand Down
4 changes: 2 additions & 2 deletions components/level/basicLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ interface BasicLayoutProps {
hideText?: boolean;
id: string;
level: Level;
onClick?: (index: number, rightClick: boolean) => void;
onClick?: (index: number, rightClick: boolean, isDragging?: boolean) => void;
}

export default function BasicLayout({ cellClassName, cellStyle, controls, hideText, id, level, onClick }: BasicLayoutProps) {
Expand All @@ -28,7 +28,7 @@ export default function BasicLayout({ cellClassName, cellStyle, controls, hideTe
hideText={hideText}
id={id}
leastMoves={level.leastMoves}
onCellClick={(x, y, rightClick) => onClick ? onClick(y * (level.width + 1) + x, rightClick) : undefined}
onCellClick={(x, y, rightClick, isDragging) => onClick ? onClick(y * (level.width + 1) + x, rightClick, isDragging) : undefined}
/>
{!controls ? null : <Controls controls={controls} />}
</>
Expand Down
54 changes: 42 additions & 12 deletions components/level/grid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { teko } from '@root/helpers/getFont';
import Position from '@root/models/position';
import classNames from 'classnames';
import { useTheme } from 'next-themes';
import React, { useCallback, useContext, useEffect, useState } from 'react';
import React, { useCallback, useContext, useEffect, useRef, useState } from 'react';
import Theme from '../../constants/theme';
import Tile from './tile/tile';

Expand All @@ -20,7 +20,7 @@ interface GridProps {
hideText?: boolean;
id: string;
leastMoves: number;
onCellClick?: (x: number, y: number, rightClick: boolean) => void;
onCellClick?: (x: number, y: number, rightClick: boolean, isDragging?: boolean) => void;
optimizeDom?: boolean;
themeOverride?: Theme;
}
Expand Down Expand Up @@ -88,7 +88,7 @@ export default function Grid({ cellClassName, cellStyle, disableAnimation, gameO
className={cellClassName ? cellClassName(x, y) : undefined}
disableAnimation={disableAnimation}
game={game}
handleClick={onCellClick ? (rightClick: boolean) => onCellClick(x, y, rightClick) : undefined}
handleClick={onCellClick ? (rightClick: boolean) => onCellClick(x, y, rightClick, isDragging) : undefined}
key={`tile-${y}-${x}`}
pos={new Position(x, y)}
style={cellStyle ? cellStyle(x, y) : undefined}
Expand All @@ -108,7 +108,7 @@ export default function Grid({ cellClassName, cellStyle, disableAnimation, gameO
className={cellClassName ? cellClassName(x, y) : undefined}
disableAnimation={disableAnimation}
game={game}
handleClick={onCellClick ? (rightClick: boolean) => onCellClick(x, y, rightClick) : undefined}
handleClick={onCellClick ? (rightClick: boolean) => onCellClick(x, y, rightClick, isDragging) : undefined}
key={`block-${tileState.block.id}`}
onTopOf={tileAtPosition.tileType}
pos={new Position(x, y)}
Expand All @@ -125,7 +125,7 @@ export default function Grid({ cellClassName, cellStyle, disableAnimation, gameO
className={cellClassName ? cellClassName(x, y) : undefined}
disableAnimation={disableAnimation}
game={game}
handleClick={onCellClick ? (rightClick: boolean) => onCellClick(x, y, rightClick) : undefined}
handleClick={onCellClick ? (rightClick: boolean, isDragging?: boolean) => onCellClick(x, y, rightClick, isDragging) : undefined}
inHole={true}
key={`block-${tileState.blockInHole.id}`}
pos={new Position(x, y)}
Expand All @@ -138,6 +138,8 @@ export default function Grid({ cellClassName, cellStyle, disableAnimation, gameO
}
}

const [isDragging, setIsDragging] = useState(false);

const getBackground = useCallback(() => {
if (!optimizeDom) {
return null;
Expand All @@ -147,7 +149,7 @@ export default function Grid({ cellClassName, cellStyle, disableAnimation, gameO
const x = Math.floor(offsetX / tileSize);
const y = Math.floor(offsetY / tileSize);

onCellClick && onCellClick(x, y, rightClick);
onCellClick && onCellClick(x, y, rightClick, isDragging);
};

const onBgClick = (e: React.MouseEvent<HTMLDivElement>) => {
Expand Down Expand Up @@ -188,7 +190,7 @@ export default function Grid({ cellClassName, cellStyle, disableAnimation, gameO
}}
/>
);
}, [borderWidth, height, onCellClick, optimizeDom, tileSize, width]);
}, [borderWidth, height, isDragging, onCellClick, optimizeDom, tileSize, width]);

// Prevent hydration mismatch by not rendering theme class until mounted
const [mounted, setMounted] = useState(false);
Expand All @@ -197,12 +199,31 @@ export default function Grid({ cellClassName, cellStyle, disableAnimation, gameO
setMounted(true);
}, []);

const lastTileDragged = useRef<Position | undefined>(undefined);
const onMouseMove = (e: React.MouseEvent<HTMLDivElement> | React.TouchEvent<HTMLDivElement>) => {
if (isDragging) {
const rect = e.currentTarget.getBoundingClientRect();
const clientX = 'touches' in e ? e.touches[0].clientX : e.clientX;
const clientY = 'touches' in e ? e.touches[0].clientY : e.clientY;
const tileX = Math.floor((clientX - rect.left) / tileSize);
const tileY = Math.floor((clientY - rect.top) / tileSize);

if (tileX === lastTileDragged.current?.x && tileY === lastTileDragged.current?.y) {
return;
}

lastTileDragged.current = new Position(tileX, tileY);
onCellClick && onCellClick(tileX, tileY, false, isDragging);
}
};

return (
<div className={classNames(
'grow flex items-center justify-center overflow-hidden',
mounted ? theme : undefined,
{ [teko.className]: classic }
)} id={gridId}>
<div
className={classNames(
'grow flex items-center justify-center overflow-hidden',
mounted ? theme : undefined,
{ [teko.className]: classic }
)} id={gridId}>
{tileSize !== 0 &&
<GridContext.Provider value={{
borderWidth: borderWidth,
Expand All @@ -217,6 +238,15 @@ export default function Grid({ cellClassName, cellStyle, disableAnimation, gameO
height: tileSize * height,
width: tileSize * width,
}}

onMouseDown={() => setIsDragging(true)}
onMouseUp={() => setIsDragging(false)}
onTouchStart={() => setIsDragging(true)}
onTouchEnd={() => setIsDragging(false)}
onTouchMove={onMouseMove}
onMouseMove={(e) => {
onMouseMove(e);
}}
>
{getBackground()}
{tiles}
Expand Down

0 comments on commit 3ee904c

Please sign in to comment.