@dxos/react-ui-gameboard 0.8.4-main.f9ba587 → 0.8.4-main.fd6878d
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/browser/index.mjs +400 -374
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +400 -374
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/components/Chessboard/Chessboard.d.ts +15 -0
- package/dist/types/src/components/Chessboard/Chessboard.d.ts.map +1 -0
- package/dist/types/src/components/Chessboard/Chessboard.stories.d.ts +28 -0
- package/dist/types/src/components/Chessboard/Chessboard.stories.d.ts.map +1 -0
- package/dist/types/src/{Chessboard → components/Chessboard}/chess.d.ts +20 -7
- package/dist/types/src/components/Chessboard/chess.d.ts.map +1 -0
- package/dist/types/src/components/Chessboard/index.d.ts.map +1 -0
- package/dist/types/src/components/Gameboard/Gameboard.d.ts +37 -0
- package/dist/types/src/components/Gameboard/Gameboard.d.ts.map +1 -0
- package/dist/types/src/{Board → components/Gameboard}/Piece.d.ts +3 -2
- package/dist/types/src/components/Gameboard/Piece.d.ts.map +1 -0
- package/dist/types/src/components/Gameboard/Square.d.ts.map +1 -0
- package/dist/types/src/components/Gameboard/index.d.ts +4 -0
- package/dist/types/src/components/Gameboard/index.d.ts.map +1 -0
- package/dist/types/src/{Board → components/Gameboard}/types.d.ts +2 -1
- package/dist/types/src/components/Gameboard/types.d.ts.map +1 -0
- package/dist/types/src/components/Gameboard/util.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +3 -0
- package/dist/types/src/components/index.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +1 -2
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +16 -14
- package/src/{Chessboard → components/Chessboard}/Chessboard.stories.tsx +32 -29
- package/src/components/Chessboard/Chessboard.tsx +191 -0
- package/src/{Chessboard → components/Chessboard}/chess.ts +88 -28
- package/src/components/Gameboard/Gameboard.tsx +139 -0
- package/src/{Board → components/Gameboard}/Piece.tsx +19 -20
- package/src/{Board → components/Gameboard}/Square.tsx +4 -4
- package/src/components/Gameboard/index.ts +8 -0
- package/src/{Board → components/Gameboard}/types.ts +3 -1
- package/src/components/index.ts +6 -0
- package/src/index.ts +1 -2
- package/dist/types/src/Board/Board.d.ts +0 -15
- package/dist/types/src/Board/Board.d.ts.map +0 -1
- package/dist/types/src/Board/Container.d.ts +0 -14
- package/dist/types/src/Board/Container.d.ts.map +0 -1
- package/dist/types/src/Board/Piece.d.ts.map +0 -1
- package/dist/types/src/Board/Square.d.ts.map +0 -1
- package/dist/types/src/Board/context.d.ts +0 -10
- package/dist/types/src/Board/context.d.ts.map +0 -1
- package/dist/types/src/Board/index.d.ts +0 -8
- package/dist/types/src/Board/index.d.ts.map +0 -1
- package/dist/types/src/Board/types.d.ts.map +0 -1
- package/dist/types/src/Board/util.d.ts.map +0 -1
- package/dist/types/src/Chessboard/Chessboard.d.ts +0 -14
- package/dist/types/src/Chessboard/Chessboard.d.ts.map +0 -1
- package/dist/types/src/Chessboard/Chessboard.stories.d.ts +0 -16
- package/dist/types/src/Chessboard/Chessboard.stories.d.ts.map +0 -1
- package/dist/types/src/Chessboard/chess.d.ts.map +0 -1
- package/dist/types/src/Chessboard/index.d.ts.map +0 -1
- package/src/Board/Board.tsx +0 -86
- package/src/Board/Container.tsx +0 -25
- package/src/Board/context.ts +0 -22
- package/src/Board/index.ts +0 -12
- package/src/Chessboard/Chessboard.tsx +0 -190
- /package/dist/types/src/{Chessboard → components/Chessboard}/index.d.ts +0 -0
- /package/dist/types/src/{Board → components/Gameboard}/Square.d.ts +0 -0
- /package/dist/types/src/{Board → components/Gameboard}/util.d.ts +0 -0
- /package/src/{Chessboard → components/Chessboard}/index.ts +0 -0
- /package/src/{Board → components/Gameboard}/util.ts +0 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
6
|
+
import { createContext } from '@radix-ui/react-context';
|
|
7
|
+
import React, { type PropsWithChildren, forwardRef, useCallback, useEffect, useState } from 'react';
|
|
8
|
+
|
|
9
|
+
import { log } from '@dxos/log';
|
|
10
|
+
import { type ThemedClassName } from '@dxos/react-ui';
|
|
11
|
+
import { mx } from '@dxos/react-ui-theme';
|
|
12
|
+
|
|
13
|
+
import { Piece, type PieceProps } from './Piece';
|
|
14
|
+
import { Square, type SquareProps } from './Square';
|
|
15
|
+
import { type GameboardModel, type Move, type PieceRecord, isLocation, isPiece } from './types';
|
|
16
|
+
|
|
17
|
+
export type GameboardContextValue<M extends GameboardModel> = {
|
|
18
|
+
model: M;
|
|
19
|
+
dragging?: boolean; // TODO(burdon): Change to PieceRecord.
|
|
20
|
+
promoting?: PieceRecord;
|
|
21
|
+
onPromotion: (move: Move) => void;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const [GameboardContextProvider, useRadixGameboardContext] = createContext<GameboardContextValue<any>>('Gameboard');
|
|
25
|
+
|
|
26
|
+
const useGameboardContext = <M extends GameboardModel>(consumerName: string): GameboardContextValue<M> => {
|
|
27
|
+
return useRadixGameboardContext(consumerName);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
//
|
|
31
|
+
// Root
|
|
32
|
+
//
|
|
33
|
+
|
|
34
|
+
type GameboardRootProps<M extends GameboardModel> = PropsWithChildren<{
|
|
35
|
+
model?: M;
|
|
36
|
+
onDrop?: (move: Move) => boolean;
|
|
37
|
+
}>;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Generic board container.
|
|
41
|
+
*/
|
|
42
|
+
const GameboardRoot = <M extends GameboardModel>({ children, model, onDrop }: GameboardRootProps<M>) => {
|
|
43
|
+
const [dragging, setDragging] = useState(false);
|
|
44
|
+
const [promoting, setPromoting] = useState<PieceRecord | undefined>();
|
|
45
|
+
|
|
46
|
+
const handlePromotion = useCallback<GameboardContextValue<M>['onPromotion']>((move) => {
|
|
47
|
+
log('onPromotion', { move });
|
|
48
|
+
setPromoting(undefined);
|
|
49
|
+
onDrop?.(move);
|
|
50
|
+
}, []);
|
|
51
|
+
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
if (!model) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// TODO(burdon): Should target specific container.
|
|
58
|
+
return monitorForElements({
|
|
59
|
+
onDragStart: ({ source }) => {
|
|
60
|
+
log('onDragStart', { source });
|
|
61
|
+
setDragging(true);
|
|
62
|
+
},
|
|
63
|
+
onDrop: ({ source, location }) => {
|
|
64
|
+
log('onDrop', { source, location });
|
|
65
|
+
const target = location.current.dropTargets[0];
|
|
66
|
+
if (!target) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const targetLocation = target.data.location;
|
|
71
|
+
const piece = source.data.piece;
|
|
72
|
+
if (!isLocation(targetLocation) || !isPiece(piece)) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const move: Move = { from: piece.location, to: targetLocation, piece: piece.type };
|
|
77
|
+
if (model.isValidMove(move)) {
|
|
78
|
+
if (model.canPromote?.(move)) {
|
|
79
|
+
setPromoting({ ...piece, location: targetLocation });
|
|
80
|
+
} else {
|
|
81
|
+
onDrop?.(move);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
setDragging(false);
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
}, [model]);
|
|
89
|
+
|
|
90
|
+
return (
|
|
91
|
+
<GameboardContextProvider model={model} dragging={dragging} promoting={promoting} onPromotion={handlePromotion}>
|
|
92
|
+
{children}
|
|
93
|
+
</GameboardContextProvider>
|
|
94
|
+
);
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
GameboardRoot.displayName = 'Gameboard.Root';
|
|
98
|
+
|
|
99
|
+
//
|
|
100
|
+
// Content
|
|
101
|
+
//
|
|
102
|
+
|
|
103
|
+
type GameboardContentProps = ThemedClassName<PropsWithChildren<{ grow?: boolean; contain?: boolean }>>;
|
|
104
|
+
|
|
105
|
+
const GameboardContent = forwardRef<HTMLDivElement, GameboardContentProps>(
|
|
106
|
+
({ children, classNames, grow, contain }, forwardedRef) => {
|
|
107
|
+
return (
|
|
108
|
+
<div
|
|
109
|
+
role='none'
|
|
110
|
+
className={mx(grow && 'grid is-full bs-full size-container place-content-center', classNames)}
|
|
111
|
+
ref={forwardedRef}
|
|
112
|
+
>
|
|
113
|
+
{contain ? <div className='is-[min(100cqw,100cqh)] bs-[min(100cqw,100cqh)]'>{children}</div> : children}
|
|
114
|
+
</div>
|
|
115
|
+
);
|
|
116
|
+
},
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
GameboardContent.displayName = 'Gameboard.Content';
|
|
120
|
+
|
|
121
|
+
//
|
|
122
|
+
// Gameboard
|
|
123
|
+
//
|
|
124
|
+
|
|
125
|
+
export const Gameboard = {
|
|
126
|
+
Root: GameboardRoot,
|
|
127
|
+
Content: GameboardContent,
|
|
128
|
+
Piece,
|
|
129
|
+
Square,
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
export { useGameboardContext };
|
|
133
|
+
|
|
134
|
+
export type {
|
|
135
|
+
GameboardRootProps,
|
|
136
|
+
GameboardContentProps,
|
|
137
|
+
PieceProps as GameboardPieceProps,
|
|
138
|
+
SquareProps as GameboardSquareProps,
|
|
139
|
+
};
|
|
@@ -3,34 +3,32 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { draggable } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
6
|
-
// import { preserveOffsetOnSource } from '@atlaskit/pragmatic-drag-and-drop/element/preserve-offset-on-source';
|
|
7
6
|
import { centerUnderPointer } from '@atlaskit/pragmatic-drag-and-drop/element/center-under-pointer';
|
|
8
7
|
import { setCustomNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/element/set-custom-native-drag-preview';
|
|
9
|
-
import React, {
|
|
8
|
+
import React, { type FC, type SVGProps, memo, useEffect, useRef, useState } from 'react';
|
|
10
9
|
import { createPortal } from 'react-dom';
|
|
11
10
|
|
|
12
11
|
import { invariant } from '@dxos/invariant';
|
|
13
12
|
import { log } from '@dxos/log';
|
|
14
|
-
import { useDynamicRef, useTrackProps
|
|
13
|
+
import { type ThemedClassName, useDynamicRef, useTrackProps } from '@dxos/react-ui';
|
|
15
14
|
import { mx } from '@dxos/react-ui-theme';
|
|
16
15
|
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
16
|
+
import { useGameboardContext } from './Gameboard';
|
|
17
|
+
import { type Location, type PieceRecord, type Player, isEqualLocation, isLocation } from './types';
|
|
19
18
|
import { type DOMRectBounds } from './util';
|
|
20
19
|
|
|
21
20
|
export type PieceProps = ThemedClassName<{
|
|
21
|
+
Component: FC<SVGProps<SVGSVGElement>>;
|
|
22
22
|
piece: PieceRecord;
|
|
23
23
|
bounds: DOMRectBounds;
|
|
24
24
|
label?: string;
|
|
25
25
|
orientation?: Player;
|
|
26
|
-
|
|
26
|
+
onClick?: () => void;
|
|
27
27
|
}>;
|
|
28
28
|
|
|
29
|
-
export const Piece = memo(({ classNames, piece, orientation, bounds, label,
|
|
30
|
-
useTrackProps({ classNames, piece, orientation, bounds, label
|
|
31
|
-
const { model } =
|
|
32
|
-
|
|
33
|
-
const { dragging: isDragging, promoting } = useBoardContext();
|
|
29
|
+
export const Piece = memo(({ classNames, Component, piece, orientation, bounds, label, onClick }: PieceProps) => {
|
|
30
|
+
useTrackProps({ classNames, Component, piece, orientation, bounds, label }, Piece.displayName, false);
|
|
31
|
+
const { model, dragging: isDragging, promoting } = useGameboardContext(Piece.displayName!);
|
|
34
32
|
const promotingRef = useDynamicRef(promoting);
|
|
35
33
|
const [dragging, setDragging] = useState(false);
|
|
36
34
|
const [preview, setPreview] = useState<HTMLElement>();
|
|
@@ -46,14 +44,10 @@ export const Piece = memo(({ classNames, piece, orientation, bounds, label, Comp
|
|
|
46
44
|
return draggable({
|
|
47
45
|
element: el,
|
|
48
46
|
getInitialData: () => ({ piece }),
|
|
49
|
-
onGenerateDragPreview: ({ nativeSetDragImage,
|
|
47
|
+
onGenerateDragPreview: ({ nativeSetDragImage, source }) => {
|
|
50
48
|
log('onGenerateDragPreview', { source: source.data });
|
|
51
49
|
setCustomNativeDragPreview({
|
|
52
50
|
getOffset: centerUnderPointer,
|
|
53
|
-
// getOffset: preserveOffsetOnSource({
|
|
54
|
-
// element: source.element,
|
|
55
|
-
// input: location.current.input,
|
|
56
|
-
// }),
|
|
57
51
|
render: ({ container }) => {
|
|
58
52
|
setPreview(container);
|
|
59
53
|
const { width, height } = el.getBoundingClientRect();
|
|
@@ -69,9 +63,14 @@ export const Piece = memo(({ classNames, piece, orientation, bounds, label, Comp
|
|
|
69
63
|
canDrag: () => !promotingRef.current && model?.turn === piece.side,
|
|
70
64
|
onDragStart: () => setDragging(true),
|
|
71
65
|
onDrop: ({ location: { current } }) => {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
66
|
+
// TODO(burdon): Create wrapper function to catch errors.
|
|
67
|
+
try {
|
|
68
|
+
const location = current.dropTargets[0]?.data.location;
|
|
69
|
+
if (isLocation(location)) {
|
|
70
|
+
setCurrent((current) => ({ ...current, location }));
|
|
71
|
+
}
|
|
72
|
+
} catch {
|
|
73
|
+
// Ignore.
|
|
75
74
|
}
|
|
76
75
|
|
|
77
76
|
setDragging(false);
|
|
@@ -112,10 +111,10 @@ export const Piece = memo(({ classNames, piece, orientation, bounds, label, Comp
|
|
|
112
111
|
className={mx(
|
|
113
112
|
'absolute',
|
|
114
113
|
classNames,
|
|
115
|
-
// orientation === 'black' && '_rotate-180',
|
|
116
114
|
dragging && 'opacity-20', // Must not unmount component while dragging.
|
|
117
115
|
isDragging && 'pointer-events-none', // Don't block the square's drop target.
|
|
118
116
|
)}
|
|
117
|
+
onClick={onClick}
|
|
119
118
|
>
|
|
120
119
|
<Component className='grow' />
|
|
121
120
|
{label && <div className='absolute inset-1 text-xs text-black'>{label}</div>}
|
|
@@ -3,15 +3,15 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { dropTargetForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
6
|
-
import React, {
|
|
6
|
+
import React, { memo, useEffect, useRef, useState } from 'react';
|
|
7
7
|
|
|
8
8
|
import { invariant } from '@dxos/invariant';
|
|
9
9
|
import { log } from '@dxos/log';
|
|
10
10
|
import { type ThemedClassName } from '@dxos/react-ui';
|
|
11
11
|
import { mx } from '@dxos/react-ui-theme';
|
|
12
12
|
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
13
|
+
import { useGameboardContext } from './Gameboard';
|
|
14
|
+
import { type Location, isPiece } from './types';
|
|
15
15
|
import { type DOMRectBounds } from './util';
|
|
16
16
|
|
|
17
17
|
type HoveredState = 'idle' | 'validMove' | 'invalidMove';
|
|
@@ -25,7 +25,7 @@ export type SquareProps = ThemedClassName<{
|
|
|
25
25
|
export const Square = memo(({ location, bounds, label, classNames }: SquareProps) => {
|
|
26
26
|
const ref = useRef<HTMLDivElement>(null);
|
|
27
27
|
const [state, setState] = useState<HoveredState>('idle');
|
|
28
|
-
const { model } =
|
|
28
|
+
const { model } = useGameboardContext(Square.displayName!);
|
|
29
29
|
|
|
30
30
|
useEffect(() => {
|
|
31
31
|
const el = ref.current;
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import { type ReadonlySignal } from '@preact/signals-core';
|
|
6
6
|
|
|
7
|
+
// TODO(burdon): Don't make this assumption.
|
|
7
8
|
export type Player = 'black' | 'white';
|
|
8
9
|
|
|
9
10
|
export type Location = [number, number];
|
|
@@ -50,8 +51,9 @@ export const isEqualLocation = (l1: Location, l2: Location): boolean => l1[0] ==
|
|
|
50
51
|
/**
|
|
51
52
|
* Generic board model.
|
|
52
53
|
*/
|
|
53
|
-
export interface
|
|
54
|
+
export interface GameboardModel<T extends PieceType = PieceType> {
|
|
54
55
|
turn: Player;
|
|
56
|
+
/** @reactive */
|
|
55
57
|
pieces: ReadonlySignal<PieceMap<T>>;
|
|
56
58
|
isValidMove: (move: Move) => boolean;
|
|
57
59
|
canPromote?: (move: Move) => boolean;
|
package/src/index.ts
CHANGED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import React, { type PropsWithChildren } from 'react';
|
|
2
|
-
import { type ThemedClassName } from '@dxos/react-ui';
|
|
3
|
-
import { type BoardModel, type Move } from './types';
|
|
4
|
-
type RootProps = ThemedClassName<PropsWithChildren<{
|
|
5
|
-
model?: BoardModel;
|
|
6
|
-
onDrop?: (move: Move) => boolean;
|
|
7
|
-
}>>;
|
|
8
|
-
export declare const Board: {
|
|
9
|
-
Root: {
|
|
10
|
-
({ children, classNames, model, onDrop }: RootProps): React.JSX.Element;
|
|
11
|
-
displayName: string;
|
|
12
|
-
};
|
|
13
|
-
};
|
|
14
|
-
export type { RootProps as BoardRootProps };
|
|
15
|
-
//# sourceMappingURL=Board.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Board.d.ts","sourceRoot":"","sources":["../../../../src/Board/Board.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,EAAE,KAAK,iBAAiB,EAAoC,MAAM,OAAO,CAAC;AAGxF,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAKtD,OAAO,EAAE,KAAK,UAAU,EAAuB,KAAK,IAAI,EAAoB,MAAM,SAAS,CAAC;AAE5F,KAAK,SAAS,GAAG,eAAe,CAC9B,iBAAiB,CAAC;IAChB,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC;CAClC,CAAC,CACH,CAAC;AA6DF,eAAO,MAAM,KAAK;;kDAxDqC,SAAS;;;CA0D/D,CAAC;AAEF,YAAY,EAAE,SAAS,IAAI,cAAc,EAAE,CAAC"}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import React, { type CSSProperties, type PropsWithChildren } from 'react';
|
|
2
|
-
import { type ThemedClassName } from '@dxos/react-ui';
|
|
3
|
-
export type ContainerProps = ThemedClassName<PropsWithChildren<{
|
|
4
|
-
style?: CSSProperties;
|
|
5
|
-
}>>;
|
|
6
|
-
/**
|
|
7
|
-
* Container centers the board.
|
|
8
|
-
*/
|
|
9
|
-
export declare const Container: React.ForwardRefExoticComponent<Omit<React.PropsWithChildren<{
|
|
10
|
-
style?: CSSProperties;
|
|
11
|
-
}>, "className"> & {
|
|
12
|
-
classNames?: import("@dxos/react-ui-types").ClassNameValue;
|
|
13
|
-
} & React.RefAttributes<HTMLDivElement>>;
|
|
14
|
-
//# sourceMappingURL=Container.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Container.d.ts","sourceRoot":"","sources":["../../../../src/Board/Container.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,EAAE,KAAK,aAAa,EAAc,KAAK,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAEtF,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGtD,MAAM,MAAM,cAAc,GAAG,eAAe,CAC1C,iBAAiB,CAAC;IAChB,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB,CAAC,CACH,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,SAAS;YAPV,aAAa;;;wCAavB,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Piece.d.ts","sourceRoot":"","sources":["../../../../src/Board/Piece.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,EAA+B,KAAK,EAAE,EAAE,KAAK,QAAQ,EAAQ,MAAM,OAAO,CAAC;AAKzF,OAAO,EAAgC,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAIpF,OAAO,EAA8C,KAAK,WAAW,EAAE,KAAK,MAAM,EAAE,MAAM,SAAS,CAAC;AACpG,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,QAAQ,CAAC;AAE5C,MAAM,MAAM,UAAU,GAAG,eAAe,CAAC;IACvC,KAAK,EAAE,WAAW,CAAC;IACnB,MAAM,EAAE,aAAa,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC;CACxC,CAAC,CAAC;AAEH,eAAO,MAAM,KAAK,2FAAuE,UAAU,uBAwGjG,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Square.d.ts","sourceRoot":"","sources":["../../../../src/Board/Square.tsx"],"names":[],"mappings":"AAKA,OAAO,KAA4C,MAAM,OAAO,CAAC;AAIjE,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAItD,OAAO,EAAW,KAAK,QAAQ,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,QAAQ,CAAC;AAI5C,MAAM,MAAM,WAAW,GAAG,eAAe,CAAC;IACxC,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,aAAa,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC,CAAC;AAEH,eAAO,MAAM,MAAM,sEAAkD,WAAW,uBA+C9E,CAAC"}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { type PieceRecord, type BoardModel, type Move } from './types';
|
|
2
|
-
export type BoardContextType = {
|
|
3
|
-
model?: BoardModel;
|
|
4
|
-
dragging?: boolean;
|
|
5
|
-
promoting?: PieceRecord;
|
|
6
|
-
onPromotion: (move: Move) => void;
|
|
7
|
-
};
|
|
8
|
-
export declare const BoardContext: import("react").Context<BoardContextType | undefined>;
|
|
9
|
-
export declare const useBoardContext: () => BoardContextType;
|
|
10
|
-
//# sourceMappingURL=context.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../../src/Board/context.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,KAAK,IAAI,EAAE,MAAM,SAAS,CAAC;AAEvE,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;CACnC,CAAC;AAEF,eAAO,MAAM,YAAY,uDAAyD,CAAC;AAEnF,eAAO,MAAM,eAAe,wBAE3B,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/Board/index.ts"],"names":[],"mappings":"AAIA,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AAEvB,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/Board/types.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,MAAM,MAAM,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AAEvC,MAAM,MAAM,QAAQ,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAExC,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC;AAE/B,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,IAAI;IACzD,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,CAAC,CAAC;IACR,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,QAAQ,CAAC;CACpB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,IAAI,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;AAEvF,MAAM,MAAM,IAAI,GAAG;IACjB,IAAI,EAAE,QAAQ,CAAC;IACf,EAAE,EAAE,QAAQ,CAAC;IACb,KAAK,EAAE,SAAS,CAAC;IACjB,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,UAAU,QAAQ,KAAG,MAA4B,CAAC;AACnF,eAAO,MAAM,gBAAgB,GAAI,KAAK,MAAM,KAAG,QAAkD,CAAC;AAGlG,eAAO,MAAM,OAAO,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,WAMtB,CAAC;AAG7B,eAAO,MAAM,UAAU,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,QACwC,CAAC;AAE9F,eAAO,MAAM,eAAe,GAAI,IAAI,QAAQ,EAAE,IAAI,QAAQ,KAAG,OAA6C,CAAC;AAE3G;;GAEG;AACH,MAAM,WAAW,UAAU,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IACpC,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC;IACrC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC;CACtC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../../../src/Board/util.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC,CAAC;AAE/E,eAAO,MAAM,iBAAiB,GAAI,WAAW,WAAW,EAAE,SAAS,WAAW,KAAG,aAShF,CAAC"}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import React, { type PropsWithChildren } from 'react';
|
|
2
|
-
import { type Player } from '../Board';
|
|
3
|
-
export type ChessboardProps = PropsWithChildren<{
|
|
4
|
-
orientation?: Player;
|
|
5
|
-
showLabels?: boolean;
|
|
6
|
-
debug?: boolean;
|
|
7
|
-
rows?: number;
|
|
8
|
-
cols?: number;
|
|
9
|
-
}>;
|
|
10
|
-
/**
|
|
11
|
-
* Chessboard layout.
|
|
12
|
-
*/
|
|
13
|
-
export declare const Chessboard: React.MemoExoticComponent<({ orientation, showLabels, debug, rows, cols }: ChessboardProps) => React.JSX.Element>;
|
|
14
|
-
//# sourceMappingURL=Chessboard.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Chessboard.d.ts","sourceRoot":"","sources":["../../../../src/Chessboard/Chessboard.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,EAAE,KAAK,iBAAiB,EAA8C,MAAM,OAAO,CAAC;AAQlG,OAAO,EAIL,KAAK,MAAM,EAKZ,MAAM,UAAU,CAAC;AAGlB,MAAM,MAAM,eAAe,GAAG,iBAAiB,CAAC;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,UAAU,6EAAiE,eAAe,uBAyGrG,CAAC"}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import '@dxos-theme';
|
|
2
|
-
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
3
|
-
import React from 'react';
|
|
4
|
-
import { type ChessboardProps } from './Chessboard';
|
|
5
|
-
type RenderProps = Pick<ChessboardProps, 'orientation' | 'showLabels' | 'debug'> & {
|
|
6
|
-
fen: string;
|
|
7
|
-
};
|
|
8
|
-
declare const DefaultStory: ({ fen, orientation: _orientation, ...props }: RenderProps) => React.JSX.Element;
|
|
9
|
-
declare const meta: Meta<typeof DefaultStory>;
|
|
10
|
-
export default meta;
|
|
11
|
-
type Story = StoryObj<typeof DefaultStory>;
|
|
12
|
-
export declare const Default: Story;
|
|
13
|
-
export declare const Promotion: Story;
|
|
14
|
-
export declare const Debug: Story;
|
|
15
|
-
export declare const Nine: Story;
|
|
16
|
-
//# sourceMappingURL=Chessboard.stories.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Chessboard.stories.d.ts","sourceRoot":"","sources":["../../../../src/Chessboard/Chessboard.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,aAAa,CAAC;AAErB,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAoD,MAAM,OAAO,CAAC;AAMzE,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AAIhE,KAAK,WAAW,GAAG,IAAI,CAAC,eAAe,EAAE,aAAa,GAAG,YAAY,GAAG,OAAO,CAAC,GAAG;IACjF,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,QAAA,MAAM,YAAY,GAAI,8CAA8C,WAAW,sBA6B9E,CAAC;AA2BF,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,YAAY,CAKnC,CAAC;AAEF,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,YAAY,CAAC,CAAC;AAE3C,eAAO,MAAM,OAAO,EAAE,KAAU,CAAC;AAEjC,eAAO,MAAM,SAAS,EAAE,KAIvB,CAAC;AAEF,eAAO,MAAM,KAAK,EAAE,KAOnB,CAAC;AAEF,eAAO,MAAM,IAAI,EAAE,KAElB,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"chess.d.ts","sourceRoot":"","sources":["../../../../src/Chessboard/chess.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,cAAc,EAAU,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,KAAK,EAAe,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,KAAK,EAAE,EAAE,KAAK,QAAQ,EAAE,MAAM,OAAO,CAAC;AAI/C,OAAO,EACL,KAAK,IAAI,EACT,KAAK,QAAQ,EACb,KAAK,QAAQ,EAEb,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,MAAM,EACZ,MAAM,UAAU,CAAC;AAGlB,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAE3G,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,UAAU,EAAE,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAS,CAAC;AAElF,eAAO,MAAM,aAAa,GAAI,KAAK,MAAM,KAAG,QAI3C,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,YAAY,QAAQ,KAAG,MAEpD,CAAC;AAyBF,eAAO,MAAM,WAAW;;;;CAAkB,CAAC;AAE3C,eAAO,MAAM,cAAc,GAAI,YAAY,QAAQ,WAElD,CAAC;AAmBF;;GAEG;AACH,qBAAa,UAAW,YAAW,UAAU,CAAC,UAAU,CAAC;IACvD,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoC;gBAEhD,GAAG,CAAC,EAAE,MAAM;IAIxB,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,IAAI,MAAM,IAAI,cAAc,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAEjD;IAED,IAAI,IAAI,IAAI,KAAK,CAEhB;IAED,IAAI,GAAG,IAAI,MAAM,CAEhB;IAED,UAAU,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI;IAM9B,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO;IAIhC,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO;IAM/B,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO;IAW7B,cAAc,IAAI,OAAO;IAYzB;;OAEG;IACH,OAAO,CAAC,OAAO;CAsBhB;AAED;;GAEG;AACH,eAAO,MAAM,SAAS,GAAI,CAAC,SAAS,SAAS,EAAE,QAAQ,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,QAAQ,CAAC,CAAC,CAAC,KAAG,QAAQ,CAAC,CAAC,CAmClG,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/Chessboard/index.ts"],"names":[],"mappings":"AAIA,cAAc,SAAS,CAAC;AAExB,cAAc,cAAc,CAAC"}
|
package/src/Board/Board.tsx
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2025 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
6
|
-
import React, { type PropsWithChildren, useCallback, useEffect, useState } from 'react';
|
|
7
|
-
|
|
8
|
-
import { log } from '@dxos/log';
|
|
9
|
-
import { type ThemedClassName } from '@dxos/react-ui';
|
|
10
|
-
import { mx } from '@dxos/react-ui-theme';
|
|
11
|
-
|
|
12
|
-
import { Container } from './Container';
|
|
13
|
-
import { BoardContext, type BoardContextType } from './context';
|
|
14
|
-
import { type BoardModel, isLocation, isPiece, type Move, type PieceRecord } from './types';
|
|
15
|
-
|
|
16
|
-
type RootProps = ThemedClassName<
|
|
17
|
-
PropsWithChildren<{
|
|
18
|
-
model?: BoardModel;
|
|
19
|
-
onDrop?: (move: Move) => boolean;
|
|
20
|
-
}>
|
|
21
|
-
>;
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Generic board container.
|
|
25
|
-
*/
|
|
26
|
-
const Root = ({ children, classNames, model, onDrop }: RootProps) => {
|
|
27
|
-
const [dragging, setDragging] = useState(false);
|
|
28
|
-
const [promoting, setPromoting] = useState<PieceRecord | undefined>();
|
|
29
|
-
|
|
30
|
-
// Handle promotion.
|
|
31
|
-
const onPromotion = useCallback<BoardContextType['onPromotion']>((move) => {
|
|
32
|
-
log('onPromotion', { move });
|
|
33
|
-
setPromoting(undefined);
|
|
34
|
-
onDrop?.(move);
|
|
35
|
-
}, []);
|
|
36
|
-
|
|
37
|
-
useEffect(() => {
|
|
38
|
-
if (!model) {
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// TODO(burdon): Should target specific container.
|
|
43
|
-
return monitorForElements({
|
|
44
|
-
onDragStart: ({ source }) => {
|
|
45
|
-
log('onDragStart', { source });
|
|
46
|
-
setDragging(true);
|
|
47
|
-
},
|
|
48
|
-
onDrop: ({ source, location }) => {
|
|
49
|
-
log('onDrop', { source, location });
|
|
50
|
-
const target = location.current.dropTargets[0];
|
|
51
|
-
if (!target) {
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const targetLocation = target.data.location;
|
|
56
|
-
const piece = source.data.piece;
|
|
57
|
-
if (!isLocation(targetLocation) || !isPiece(piece)) {
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const move: Move = { from: piece.location, to: targetLocation, piece: piece.type };
|
|
62
|
-
if (model.canPromote?.(move)) {
|
|
63
|
-
setPromoting({ ...piece, location: targetLocation });
|
|
64
|
-
} else {
|
|
65
|
-
onDrop?.(move);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
setDragging(false);
|
|
69
|
-
},
|
|
70
|
-
});
|
|
71
|
-
}, [model]);
|
|
72
|
-
|
|
73
|
-
return (
|
|
74
|
-
<BoardContext.Provider value={{ model, dragging, promoting, onPromotion }}>
|
|
75
|
-
<Container classNames={mx('aspect-square', classNames)}>{children}</Container>
|
|
76
|
-
</BoardContext.Provider>
|
|
77
|
-
);
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
Root.displayName = 'Board.Root';
|
|
81
|
-
|
|
82
|
-
export const Board = {
|
|
83
|
-
Root,
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
export type { RootProps as BoardRootProps };
|
package/src/Board/Container.tsx
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2025 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import React, { type CSSProperties, forwardRef, type PropsWithChildren } from 'react';
|
|
6
|
-
|
|
7
|
-
import { type ThemedClassName } from '@dxos/react-ui';
|
|
8
|
-
import { mx } from '@dxos/react-ui-theme';
|
|
9
|
-
|
|
10
|
-
export type ContainerProps = ThemedClassName<
|
|
11
|
-
PropsWithChildren<{
|
|
12
|
-
style?: CSSProperties;
|
|
13
|
-
}>
|
|
14
|
-
>;
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Container centers the board.
|
|
18
|
-
*/
|
|
19
|
-
export const Container = forwardRef<HTMLDivElement, ContainerProps>(({ children, classNames, style }, forwardedRef) => {
|
|
20
|
-
return (
|
|
21
|
-
<div ref={forwardedRef} style={style} className='flex w-full h-full justify-center overflow-hidden'>
|
|
22
|
-
<div className={mx('max-w-full max-h-full content-center', classNames)}>{children}</div>
|
|
23
|
-
</div>
|
|
24
|
-
);
|
|
25
|
-
});
|
package/src/Board/context.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2025 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { createContext, useContext } from 'react';
|
|
6
|
-
|
|
7
|
-
import { raise } from '@dxos/debug';
|
|
8
|
-
|
|
9
|
-
import { type PieceRecord, type BoardModel, type Move } from './types';
|
|
10
|
-
|
|
11
|
-
export type BoardContextType = {
|
|
12
|
-
model?: BoardModel;
|
|
13
|
-
dragging?: boolean; // TODO(burdon): Change to PieceRecord.
|
|
14
|
-
promoting?: PieceRecord;
|
|
15
|
-
onPromotion: (move: Move) => void;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export const BoardContext = createContext<BoardContextType | undefined>(undefined);
|
|
19
|
-
|
|
20
|
-
export const useBoardContext = () => {
|
|
21
|
-
return useContext(BoardContext) ?? raise(new Error('Missing BoardContext'));
|
|
22
|
-
};
|
package/src/Board/index.ts
DELETED