mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 10:47:04 +02:00
feat: name draggable
This commit is contained in:
1 parent
ca111510f6
commit
ea07d2646d
2 files changed
+48
-46
No files matched your search
@@ -2,21 +2,15 @@ import { LoopIcon, TrashIcon } from '@radix-ui/react-icons';
|
|||||||
import { Dialog, Flex, IconButton } from '@radix-ui/themes';
|
import { Dialog, Flex, IconButton } from '@radix-ui/themes';
|
||||||
import { use, useState } from 'react';
|
import { use, useState } from 'react';
|
||||||
import { provisionDefinitions } from '../../../../core/blitzkrieg/provisionDefinitions';
|
import { provisionDefinitions } from '../../../../core/blitzkrieg/provisionDefinitions';
|
||||||
import { TankDefinition } from '../../../../core/blitzkrieg/tankDefinitions';
|
|
||||||
import { tankToCompareMember } from '../../../../core/blitzkrieg/tankToCompareMember';
|
import { tankToCompareMember } from '../../../../core/blitzkrieg/tankToCompareMember';
|
||||||
import {
|
import { mutateCompareTemporary } from '../../../../stores/compare';
|
||||||
CompareMember,
|
|
||||||
mutateCompareTemporary,
|
|
||||||
} from '../../../../stores/compare';
|
|
||||||
import { TankSearch } from '../../tankopedia/components/TankSearch';
|
import { TankSearch } from '../../tankopedia/components/TankSearch';
|
||||||
|
|
||||||
interface TankControlProps {
|
interface TankControlProps {
|
||||||
index: number;
|
index: number;
|
||||||
tank: TankDefinition;
|
|
||||||
members: CompareMember[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function TankControl({ index, tank, members }: TankControlProps) {
|
export function TankControl({ index }: TankControlProps) {
|
||||||
const awaitedProvisionDefinitions = use(provisionDefinitions);
|
const awaitedProvisionDefinitions = use(provisionDefinitions);
|
||||||
const [switchTankDialogOpen, setSwitchTankDialogOpen] = useState(false);
|
const [switchTankDialogOpen, setSwitchTankDialogOpen] = useState(false);
|
||||||
|
|
||||||
|
|||||||
@@ -331,20 +331,20 @@ export default function Page() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function TankCard({ index, tank }: { index: number; tank: TankDefinition }) {
|
function TankCard({ index, tank }: { index: number; tank: TankDefinition }) {
|
||||||
const image = useRef<HTMLImageElement>(null);
|
const draggable = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const initial = new Vector2();
|
const initial = new Vector2();
|
||||||
const current = new Vector2();
|
const current = new Vector2();
|
||||||
const delta = new Vector2();
|
const delta = new Vector2();
|
||||||
const marker = new Vector2();
|
const marker = new Vector2();
|
||||||
let initialRect = image.current!.getBoundingClientRect();
|
let initialRect = draggable.current!.getBoundingClientRect();
|
||||||
let dropIndex = -1;
|
let dropIndex = -1;
|
||||||
|
|
||||||
function handlePointerDown(event: PointerEvent) {
|
function handlePointerDown(event: PointerEvent) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
initialRect = image.current!.getBoundingClientRect();
|
initialRect = draggable.current!.getBoundingClientRect();
|
||||||
|
|
||||||
delta.set(0, 0);
|
delta.set(0, 0);
|
||||||
current.copy(initial.set(event.clientX, event.clientY));
|
current.copy(initial.set(event.clientX, event.clientY));
|
||||||
@@ -375,18 +375,18 @@ export default function Page() {
|
|||||||
|
|
||||||
dropIndex = closest.index;
|
dropIndex = closest.index;
|
||||||
closest.element.style.opacity = '1';
|
closest.element.style.opacity = '1';
|
||||||
image.current!.style.position = 'fixed';
|
draggable.current!.style.position = 'fixed';
|
||||||
image.current!.style.cursor = 'grabbing';
|
draggable.current!.style.cursor = 'grabbing';
|
||||||
image.current!.style.zIndex = '1';
|
draggable.current!.style.zIndex = '1';
|
||||||
image.current!.style.left = `${initialRect.left + delta.x}px`;
|
draggable.current!.style.left = `${initialRect.left + delta.x}px`;
|
||||||
image.current!.style.top = `${initialRect.top + delta.y}px`;
|
draggable.current!.style.top = `${initialRect.top + delta.y}px`;
|
||||||
}
|
}
|
||||||
function handlePointerUp(event: PointerEvent) {
|
function handlePointerUp(event: PointerEvent) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
image.current!.style.position = 'static';
|
draggable.current!.style.position = 'static';
|
||||||
image.current!.style.zIndex = 'unset';
|
draggable.current!.style.zIndex = 'unset';
|
||||||
image.current!.style.cursor = 'grab';
|
draggable.current!.style.cursor = 'grab';
|
||||||
|
|
||||||
insertionMarkers.forEach(({ element }) => {
|
insertionMarkers.forEach(({ element }) => {
|
||||||
element.style.opacity = '0';
|
element.style.opacity = '0';
|
||||||
@@ -409,10 +409,13 @@ export default function Page() {
|
|||||||
dropIndex = -1;
|
dropIndex = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
image.current?.addEventListener('pointerdown', handlePointerDown);
|
draggable.current?.addEventListener('pointerdown', handlePointerDown);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
image.current?.removeEventListener('pointerdown', handlePointerDown);
|
draggable.current?.removeEventListener(
|
||||||
|
'pointerdown',
|
||||||
|
handlePointerDown,
|
||||||
|
);
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@@ -428,37 +431,42 @@ export default function Page() {
|
|||||||
gap="2"
|
gap="2"
|
||||||
style={{ height: '100%' }}
|
style={{ height: '100%' }}
|
||||||
>
|
>
|
||||||
<TankControl
|
<TankControl index={index} key={tank.id} />
|
||||||
index={index}
|
|
||||||
key={tank.id}
|
<Flex
|
||||||
tank={tank}
|
ref={draggable}
|
||||||
members={members}
|
direction="column"
|
||||||
/>
|
align="center"
|
||||||
<img
|
justify="between"
|
||||||
ref={image}
|
gap="2"
|
||||||
alt={tank.name}
|
|
||||||
src={tankIcon(tank.id)}
|
|
||||||
width={64}
|
|
||||||
height={64}
|
|
||||||
draggable={false}
|
|
||||||
style={{
|
style={{
|
||||||
userSelect: 'none',
|
userSelect: 'none',
|
||||||
touchAction: 'none',
|
touchAction: 'none',
|
||||||
cursor: 'grab',
|
cursor: 'grab',
|
||||||
objectFit: 'contain',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Text
|
|
||||||
style={{
|
|
||||||
whiteSpace: 'nowrap',
|
|
||||||
maxWidth: 128,
|
|
||||||
overflow: 'hidden',
|
|
||||||
textOverflow: 'ellipsis',
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{tank.name}
|
<img
|
||||||
</Text>
|
alt={tank.name}
|
||||||
|
src={tankIcon(tank.id)}
|
||||||
|
width={64}
|
||||||
|
height={64}
|
||||||
|
draggable={false}
|
||||||
|
style={{
|
||||||
|
objectFit: 'contain',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
whiteSpace: 'nowrap',
|
||||||
|
maxWidth: 128,
|
||||||
|
overflow: 'hidden',
|
||||||
|
textOverflow: 'ellipsis',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{tank.name}
|
||||||
|
</Text>
|
||||||
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
<InsertionMarker index={index + 1} />
|
<InsertionMarker index={index + 1} />
|
||||||
|
|||||||
Reference in new issue
Block a user