@dxos/react-ui-gameboard 0.8.4-main.b97322e → 0.8.4-main.f5c0578
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 +309 -274
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +309 -274
- 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.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 +19 -6
- 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/{Gameboard → 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/{Gameboard → components/Gameboard}/types.d.ts +1 -0
- 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 +14 -12
- package/src/{Chessboard → components/Chessboard}/Chessboard.stories.tsx +26 -25
- package/src/{Chessboard → components/Chessboard}/Chessboard.tsx +32 -35
- package/src/{Chessboard → components/Chessboard}/chess.ts +86 -26
- package/src/components/Gameboard/Gameboard.tsx +139 -0
- package/src/{Gameboard → components/Gameboard}/Piece.tsx +19 -20
- package/src/{Gameboard → components/Gameboard}/Square.tsx +4 -4
- package/src/{Gameboard → components/Gameboard}/index.ts +0 -3
- package/src/{Gameboard → components/Gameboard}/types.ts +2 -0
- package/src/components/index.ts +6 -0
- package/src/index.ts +1 -2
- 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/dist/types/src/Gameboard/Gameboard.d.ts +0 -23
- package/dist/types/src/Gameboard/Gameboard.d.ts.map +0 -1
- package/dist/types/src/Gameboard/Piece.d.ts.map +0 -1
- package/dist/types/src/Gameboard/Square.d.ts.map +0 -1
- package/dist/types/src/Gameboard/context.d.ts +0 -10
- package/dist/types/src/Gameboard/context.d.ts.map +0 -1
- package/dist/types/src/Gameboard/index.d.ts +0 -7
- package/dist/types/src/Gameboard/index.d.ts.map +0 -1
- package/dist/types/src/Gameboard/types.d.ts.map +0 -1
- package/dist/types/src/Gameboard/util.d.ts.map +0 -1
- package/src/Gameboard/Gameboard.tsx +0 -103
- package/src/Gameboard/context.ts +0 -22
- /package/dist/types/src/{Chessboard → components/Chessboard}/Chessboard.d.ts +0 -0
- /package/dist/types/src/{Chessboard → components/Chessboard}/index.d.ts +0 -0
- /package/dist/types/src/{Gameboard → components/Gameboard}/Square.d.ts +0 -0
- /package/dist/types/src/{Gameboard → components/Gameboard}/util.d.ts +0 -0
- /package/src/{Chessboard → components/Chessboard}/index.ts +0 -0
- /package/src/{Gameboard → components/Gameboard}/util.ts +0 -0
|
@@ -4,22 +4,14 @@ var __export = (target, all) => {
|
|
|
4
4
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
5
5
|
};
|
|
6
6
|
|
|
7
|
-
// src/Gameboard/
|
|
8
|
-
import { createContext, useContext } from "react";
|
|
9
|
-
import { raise } from "@dxos/debug";
|
|
10
|
-
var GameboardContext = createContext(void 0);
|
|
11
|
-
var useBoardContext = () => {
|
|
12
|
-
return useContext(GameboardContext) ?? raise(new Error("Missing BoardContext"));
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
// src/Gameboard/types.ts
|
|
7
|
+
// src/components/Gameboard/types.ts
|
|
16
8
|
var locationToString = (location) => location.join("-");
|
|
17
9
|
var stringToLocation = (str) => str.split("-").map(Number);
|
|
18
10
|
var isPiece = (piece) => piece != null && typeof piece === "object" && "id" in piece && "type" in piece && "location" in piece && isLocation(piece.location);
|
|
19
11
|
var isLocation = (token) => Array.isArray(token) && token.length === 2 && token.every((val) => typeof val === "number");
|
|
20
12
|
var isEqualLocation = (l1, l2) => l1[0] === l2[0] && l1[1] === l2[1];
|
|
21
13
|
|
|
22
|
-
// src/Gameboard/util.ts
|
|
14
|
+
// src/components/Gameboard/util.ts
|
|
23
15
|
var getRelativeBounds = (container, element) => {
|
|
24
16
|
const containerRect = container.getBoundingClientRect();
|
|
25
17
|
const elementRect = element.getBoundingClientRect();
|
|
@@ -31,133 +23,170 @@ var getRelativeBounds = (container, element) => {
|
|
|
31
23
|
};
|
|
32
24
|
};
|
|
33
25
|
|
|
34
|
-
// src/Gameboard/Gameboard.tsx
|
|
35
|
-
import { useSignals as
|
|
26
|
+
// src/components/Gameboard/Gameboard.tsx
|
|
27
|
+
import { useSignals as _useSignals3 } from "@preact-signals/safe-react/tracking";
|
|
36
28
|
import { monitorForElements } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
|
|
37
|
-
import
|
|
29
|
+
import { createContext } from "@radix-ui/react-context";
|
|
30
|
+
import React3, { forwardRef, useCallback, useEffect as useEffect3, useState as useState3 } from "react";
|
|
31
|
+
import { log as log3 } from "@dxos/log";
|
|
32
|
+
import { mx as mx3 } from "@dxos/react-ui-theme";
|
|
33
|
+
|
|
34
|
+
// src/components/Gameboard/Piece.tsx
|
|
35
|
+
import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
|
|
36
|
+
import { draggable } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
|
|
37
|
+
import { centerUnderPointer } from "@atlaskit/pragmatic-drag-and-drop/element/center-under-pointer";
|
|
38
|
+
import { setCustomNativeDragPreview } from "@atlaskit/pragmatic-drag-and-drop/element/set-custom-native-drag-preview";
|
|
39
|
+
import React, { memo, useEffect, useRef, useState } from "react";
|
|
40
|
+
import { createPortal } from "react-dom";
|
|
41
|
+
import { invariant } from "@dxos/invariant";
|
|
38
42
|
import { log } from "@dxos/log";
|
|
43
|
+
import { useDynamicRef, useTrackProps } from "@dxos/react-ui";
|
|
39
44
|
import { mx } from "@dxos/react-ui-theme";
|
|
40
|
-
var __dxlog_file = "/__w/dxos/dxos/packages/ui/react-ui-gameboard/src/Gameboard/
|
|
41
|
-
var
|
|
45
|
+
var __dxlog_file = "/__w/dxos/dxos/packages/ui/react-ui-gameboard/src/components/Gameboard/Piece.tsx";
|
|
46
|
+
var Piece = /* @__PURE__ */ memo(({ classNames, Component, piece, orientation, bounds, label, onClick }) => {
|
|
42
47
|
var _effect = _useSignals();
|
|
43
48
|
try {
|
|
49
|
+
useTrackProps({
|
|
50
|
+
classNames,
|
|
51
|
+
Component,
|
|
52
|
+
piece,
|
|
53
|
+
orientation,
|
|
54
|
+
bounds,
|
|
55
|
+
label
|
|
56
|
+
}, Piece.displayName, false);
|
|
57
|
+
const { model, dragging: isDragging, promoting } = useGameboardContext(Piece.displayName);
|
|
58
|
+
const promotingRef = useDynamicRef(promoting);
|
|
44
59
|
const [dragging, setDragging] = useState(false);
|
|
45
|
-
const [
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
60
|
+
const [preview, setPreview] = useState();
|
|
61
|
+
const [current, setCurrent] = useState({});
|
|
62
|
+
const ref = useRef(null);
|
|
63
|
+
useEffect(() => {
|
|
64
|
+
const el = ref.current;
|
|
65
|
+
invariant(el, void 0, {
|
|
50
66
|
F: __dxlog_file,
|
|
51
|
-
L:
|
|
67
|
+
L: 42,
|
|
52
68
|
S: void 0,
|
|
53
|
-
|
|
69
|
+
A: [
|
|
70
|
+
"el",
|
|
71
|
+
""
|
|
72
|
+
]
|
|
54
73
|
});
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
onDragStart: ({ source }) => {
|
|
64
|
-
log("onDragStart", {
|
|
65
|
-
source
|
|
74
|
+
return draggable({
|
|
75
|
+
element: el,
|
|
76
|
+
getInitialData: () => ({
|
|
77
|
+
piece
|
|
78
|
+
}),
|
|
79
|
+
onGenerateDragPreview: ({ nativeSetDragImage, source }) => {
|
|
80
|
+
log("onGenerateDragPreview", {
|
|
81
|
+
source: source.data
|
|
66
82
|
}, {
|
|
67
83
|
F: __dxlog_file,
|
|
68
|
-
L:
|
|
84
|
+
L: 48,
|
|
69
85
|
S: void 0,
|
|
70
86
|
C: (f, a) => f(...a)
|
|
71
87
|
});
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
88
|
+
setCustomNativeDragPreview({
|
|
89
|
+
getOffset: centerUnderPointer,
|
|
90
|
+
render: ({ container }) => {
|
|
91
|
+
setPreview(container);
|
|
92
|
+
const { width, height } = el.getBoundingClientRect();
|
|
93
|
+
container.style.width = width + "px";
|
|
94
|
+
container.style.height = height + "px";
|
|
95
|
+
return () => {
|
|
96
|
+
setPreview(void 0);
|
|
97
|
+
};
|
|
98
|
+
},
|
|
99
|
+
nativeSetDragImage
|
|
83
100
|
});
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
};
|
|
98
|
-
if (model.canPromote?.(move)) {
|
|
99
|
-
setPromoting({
|
|
100
|
-
...piece,
|
|
101
|
-
location: targetLocation
|
|
102
|
-
});
|
|
103
|
-
} else {
|
|
104
|
-
onDrop?.(move);
|
|
101
|
+
},
|
|
102
|
+
canDrag: () => !promotingRef.current && model?.turn === piece.side,
|
|
103
|
+
onDragStart: () => setDragging(true),
|
|
104
|
+
onDrop: ({ location: { current: current2 } }) => {
|
|
105
|
+
try {
|
|
106
|
+
const location = current2.dropTargets[0]?.data.location;
|
|
107
|
+
if (isLocation(location)) {
|
|
108
|
+
setCurrent((current3) => ({
|
|
109
|
+
...current3,
|
|
110
|
+
location
|
|
111
|
+
}));
|
|
112
|
+
}
|
|
113
|
+
} catch {
|
|
105
114
|
}
|
|
106
115
|
setDragging(false);
|
|
107
116
|
}
|
|
108
117
|
});
|
|
109
118
|
}, [
|
|
110
|
-
model
|
|
119
|
+
model,
|
|
120
|
+
piece
|
|
111
121
|
]);
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
122
|
+
useEffect(() => {
|
|
123
|
+
requestAnimationFrame(() => {
|
|
124
|
+
if (!ref.current || !bounds) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (!current.location || !isEqualLocation(current.location, piece.location)) {
|
|
128
|
+
ref.current.style.transition = "top 400ms ease-out, left 400ms ease-out";
|
|
129
|
+
ref.current.style.top = bounds.top + "px";
|
|
130
|
+
ref.current.style.left = bounds.left + "px";
|
|
131
|
+
setCurrent({
|
|
132
|
+
location: piece.location,
|
|
133
|
+
bounds
|
|
134
|
+
});
|
|
135
|
+
} else if (current.bounds !== bounds) {
|
|
136
|
+
ref.current.style.transition = "none";
|
|
137
|
+
ref.current.style.top = bounds.top + "px";
|
|
138
|
+
ref.current.style.left = bounds.left + "px";
|
|
139
|
+
setCurrent({
|
|
140
|
+
location: piece.location,
|
|
141
|
+
bounds
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
}, [
|
|
146
|
+
current,
|
|
147
|
+
piece.location,
|
|
148
|
+
bounds
|
|
149
|
+
]);
|
|
150
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", {
|
|
151
|
+
ref,
|
|
152
|
+
style: {
|
|
153
|
+
width: bounds?.width,
|
|
154
|
+
height: bounds?.height
|
|
155
|
+
},
|
|
156
|
+
className: mx("absolute", classNames, dragging && "opacity-20", isDragging && "pointer-events-none"),
|
|
157
|
+
onClick
|
|
158
|
+
}, /* @__PURE__ */ React.createElement(Component, {
|
|
159
|
+
className: "grow"
|
|
160
|
+
}), label && /* @__PURE__ */ React.createElement("div", {
|
|
161
|
+
className: "absolute inset-1 text-xs text-black"
|
|
162
|
+
}, label)), preview && /* @__PURE__ */ createPortal(/* @__PURE__ */ React.createElement("div", {
|
|
163
|
+
className: mx(classNames)
|
|
164
|
+
}, /* @__PURE__ */ React.createElement(Component, {
|
|
165
|
+
className: "grow"
|
|
166
|
+
})), preview));
|
|
135
167
|
} finally {
|
|
136
168
|
_effect.f();
|
|
137
169
|
}
|
|
138
170
|
});
|
|
139
|
-
|
|
140
|
-
Root: GameboardRoot,
|
|
141
|
-
Content: GameboardContent
|
|
142
|
-
};
|
|
171
|
+
Piece.displayName = "Piece";
|
|
143
172
|
|
|
144
|
-
// src/Gameboard/Square.tsx
|
|
173
|
+
// src/components/Gameboard/Square.tsx
|
|
145
174
|
import { useSignals as _useSignals2 } from "@preact-signals/safe-react/tracking";
|
|
146
175
|
import { dropTargetForElements } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
|
|
147
|
-
import React2, {
|
|
148
|
-
import { invariant } from "@dxos/invariant";
|
|
176
|
+
import React2, { memo as memo2, useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
|
|
177
|
+
import { invariant as invariant2 } from "@dxos/invariant";
|
|
149
178
|
import { log as log2 } from "@dxos/log";
|
|
150
179
|
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
151
|
-
var __dxlog_file2 = "/__w/dxos/dxos/packages/ui/react-ui-gameboard/src/Gameboard/Square.tsx";
|
|
152
|
-
var Square = /* @__PURE__ */
|
|
180
|
+
var __dxlog_file2 = "/__w/dxos/dxos/packages/ui/react-ui-gameboard/src/components/Gameboard/Square.tsx";
|
|
181
|
+
var Square = /* @__PURE__ */ memo2(({ location, bounds, label, classNames }) => {
|
|
153
182
|
var _effect = _useSignals2();
|
|
154
183
|
try {
|
|
155
|
-
const ref =
|
|
184
|
+
const ref = useRef2(null);
|
|
156
185
|
const [state, setState] = useState2("idle");
|
|
157
|
-
const { model } =
|
|
186
|
+
const { model } = useGameboardContext(Square.displayName);
|
|
158
187
|
useEffect2(() => {
|
|
159
188
|
const el = ref.current;
|
|
160
|
-
|
|
189
|
+
invariant2(el, void 0, {
|
|
161
190
|
F: __dxlog_file2,
|
|
162
191
|
L: 32,
|
|
163
192
|
S: void 0,
|
|
@@ -225,155 +254,121 @@ var Square = /* @__PURE__ */ memo(({ location, bounds, label, classNames }) => {
|
|
|
225
254
|
});
|
|
226
255
|
Square.displayName = "Square";
|
|
227
256
|
|
|
228
|
-
// src/Gameboard/
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
import { invariant as invariant2 } from "@dxos/invariant";
|
|
236
|
-
import { log as log3 } from "@dxos/log";
|
|
237
|
-
import { useDynamicRef, useTrackProps } from "@dxos/react-ui";
|
|
238
|
-
import { mx as mx3 } from "@dxos/react-ui-theme";
|
|
239
|
-
var __dxlog_file3 = "/__w/dxos/dxos/packages/ui/react-ui-gameboard/src/Gameboard/Piece.tsx";
|
|
240
|
-
var Piece = /* @__PURE__ */ memo2(({ classNames, piece, orientation, bounds, label, Component }) => {
|
|
257
|
+
// src/components/Gameboard/Gameboard.tsx
|
|
258
|
+
var __dxlog_file3 = "/__w/dxos/dxos/packages/ui/react-ui-gameboard/src/components/Gameboard/Gameboard.tsx";
|
|
259
|
+
var [GameboardContextProvider, useRadixGameboardContext] = createContext("Gameboard");
|
|
260
|
+
var useGameboardContext = (consumerName) => {
|
|
261
|
+
return useRadixGameboardContext(consumerName);
|
|
262
|
+
};
|
|
263
|
+
var GameboardRoot = ({ children, model, onDrop }) => {
|
|
241
264
|
var _effect = _useSignals3();
|
|
242
265
|
try {
|
|
243
|
-
useTrackProps({
|
|
244
|
-
classNames,
|
|
245
|
-
piece,
|
|
246
|
-
orientation,
|
|
247
|
-
bounds,
|
|
248
|
-
label,
|
|
249
|
-
Component
|
|
250
|
-
}, Piece.displayName, false);
|
|
251
|
-
const { model } = useBoardContext();
|
|
252
|
-
const { dragging: isDragging, promoting } = useBoardContext();
|
|
253
|
-
const promotingRef = useDynamicRef(promoting);
|
|
254
266
|
const [dragging, setDragging] = useState3(false);
|
|
255
|
-
const [
|
|
256
|
-
const
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
invariant2(el, void 0, {
|
|
267
|
+
const [promoting, setPromoting] = useState3();
|
|
268
|
+
const handlePromotion = useCallback((move) => {
|
|
269
|
+
log3("onPromotion", {
|
|
270
|
+
move
|
|
271
|
+
}, {
|
|
261
272
|
F: __dxlog_file3,
|
|
262
|
-
L:
|
|
273
|
+
L: 47,
|
|
263
274
|
S: void 0,
|
|
264
|
-
|
|
265
|
-
"el",
|
|
266
|
-
""
|
|
267
|
-
]
|
|
275
|
+
C: (f, a) => f(...a)
|
|
268
276
|
});
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
+
setPromoting(void 0);
|
|
278
|
+
onDrop?.(move);
|
|
279
|
+
}, []);
|
|
280
|
+
useEffect3(() => {
|
|
281
|
+
if (!model) {
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
return monitorForElements({
|
|
285
|
+
onDragStart: ({ source }) => {
|
|
286
|
+
log3("onDragStart", {
|
|
287
|
+
source
|
|
277
288
|
}, {
|
|
278
289
|
F: __dxlog_file3,
|
|
279
|
-
L:
|
|
290
|
+
L: 60,
|
|
280
291
|
S: void 0,
|
|
281
292
|
C: (f, a) => f(...a)
|
|
282
293
|
});
|
|
283
|
-
|
|
284
|
-
getOffset: centerUnderPointer,
|
|
285
|
-
// getOffset: preserveOffsetOnSource({
|
|
286
|
-
// element: source.element,
|
|
287
|
-
// input: location.current.input,
|
|
288
|
-
// }),
|
|
289
|
-
render: ({ container }) => {
|
|
290
|
-
setPreview(container);
|
|
291
|
-
const { width, height } = el.getBoundingClientRect();
|
|
292
|
-
container.style.width = width + "px";
|
|
293
|
-
container.style.height = height + "px";
|
|
294
|
-
return () => {
|
|
295
|
-
setPreview(void 0);
|
|
296
|
-
};
|
|
297
|
-
},
|
|
298
|
-
nativeSetDragImage
|
|
299
|
-
});
|
|
294
|
+
setDragging(true);
|
|
300
295
|
},
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
296
|
+
onDrop: ({ source, location }) => {
|
|
297
|
+
log3("onDrop", {
|
|
298
|
+
source,
|
|
299
|
+
location
|
|
300
|
+
}, {
|
|
301
|
+
F: __dxlog_file3,
|
|
302
|
+
L: 64,
|
|
303
|
+
S: void 0,
|
|
304
|
+
C: (f, a) => f(...a)
|
|
305
|
+
});
|
|
306
|
+
const target = location.current.dropTargets[0];
|
|
307
|
+
if (!target) {
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
const targetLocation = target.data.location;
|
|
311
|
+
const piece = source.data.piece;
|
|
312
|
+
if (!isLocation(targetLocation) || !isPiece(piece)) {
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
const move = {
|
|
316
|
+
from: piece.location,
|
|
317
|
+
to: targetLocation,
|
|
318
|
+
piece: piece.type
|
|
319
|
+
};
|
|
320
|
+
if (model.isValidMove(move)) {
|
|
321
|
+
if (model.canPromote?.(move)) {
|
|
322
|
+
setPromoting({
|
|
323
|
+
...piece,
|
|
324
|
+
location: targetLocation
|
|
325
|
+
});
|
|
326
|
+
} else {
|
|
327
|
+
onDrop?.(move);
|
|
328
|
+
}
|
|
310
329
|
}
|
|
311
330
|
setDragging(false);
|
|
312
331
|
}
|
|
313
332
|
});
|
|
314
333
|
}, [
|
|
315
|
-
model
|
|
316
|
-
piece
|
|
317
|
-
]);
|
|
318
|
-
useEffect3(() => {
|
|
319
|
-
requestAnimationFrame(() => {
|
|
320
|
-
if (!ref.current || !bounds) {
|
|
321
|
-
return;
|
|
322
|
-
}
|
|
323
|
-
if (!current.location || !isEqualLocation(current.location, piece.location)) {
|
|
324
|
-
ref.current.style.transition = "top 400ms ease-out, left 400ms ease-out";
|
|
325
|
-
ref.current.style.top = bounds.top + "px";
|
|
326
|
-
ref.current.style.left = bounds.left + "px";
|
|
327
|
-
setCurrent({
|
|
328
|
-
location: piece.location,
|
|
329
|
-
bounds
|
|
330
|
-
});
|
|
331
|
-
} else if (current.bounds !== bounds) {
|
|
332
|
-
ref.current.style.transition = "none";
|
|
333
|
-
ref.current.style.top = bounds.top + "px";
|
|
334
|
-
ref.current.style.left = bounds.left + "px";
|
|
335
|
-
setCurrent({
|
|
336
|
-
location: piece.location,
|
|
337
|
-
bounds
|
|
338
|
-
});
|
|
339
|
-
}
|
|
340
|
-
});
|
|
341
|
-
}, [
|
|
342
|
-
current,
|
|
343
|
-
piece.location,
|
|
344
|
-
bounds
|
|
334
|
+
model
|
|
345
335
|
]);
|
|
346
|
-
return /* @__PURE__ */ React3.createElement(
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
className: "
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
})), preview));
|
|
336
|
+
return /* @__PURE__ */ React3.createElement(GameboardContextProvider, {
|
|
337
|
+
model,
|
|
338
|
+
dragging,
|
|
339
|
+
promoting,
|
|
340
|
+
onPromotion: handlePromotion
|
|
341
|
+
}, children);
|
|
342
|
+
} finally {
|
|
343
|
+
_effect.f();
|
|
344
|
+
}
|
|
345
|
+
};
|
|
346
|
+
GameboardRoot.displayName = "Gameboard.Root";
|
|
347
|
+
var GameboardContent = /* @__PURE__ */ forwardRef(({ children, classNames, grow, contain }, forwardedRef) => {
|
|
348
|
+
var _effect = _useSignals3();
|
|
349
|
+
try {
|
|
350
|
+
return /* @__PURE__ */ React3.createElement("div", {
|
|
351
|
+
role: "none",
|
|
352
|
+
className: mx3(grow && "grid is-full bs-full size-container place-content-center", classNames),
|
|
353
|
+
ref: forwardedRef
|
|
354
|
+
}, contain ? /* @__PURE__ */ React3.createElement("div", {
|
|
355
|
+
className: "is-[min(100cqw,100cqh)] bs-[min(100cqw,100cqh)]"
|
|
356
|
+
}, children) : children);
|
|
368
357
|
} finally {
|
|
369
358
|
_effect.f();
|
|
370
359
|
}
|
|
371
360
|
});
|
|
372
|
-
|
|
361
|
+
GameboardContent.displayName = "Gameboard.Content";
|
|
362
|
+
var Gameboard = {
|
|
363
|
+
Root: GameboardRoot,
|
|
364
|
+
Content: GameboardContent,
|
|
365
|
+
Piece,
|
|
366
|
+
Square
|
|
367
|
+
};
|
|
373
368
|
|
|
374
|
-
// src/Chessboard/chess.ts
|
|
369
|
+
// src/components/Chessboard/chess.ts
|
|
375
370
|
import { signal } from "@preact/signals-core";
|
|
376
|
-
import { Chess
|
|
371
|
+
import { Chess as ChessJS } from "chess.js";
|
|
377
372
|
import { log as log4 } from "@dxos/log";
|
|
378
373
|
|
|
379
374
|
// src/gen/pieces/chess/alpha/index.ts
|
|
@@ -666,8 +661,8 @@ var SvgWR = (props) => {
|
|
|
666
661
|
};
|
|
667
662
|
var wR_default = SvgWR;
|
|
668
663
|
|
|
669
|
-
// src/Chessboard/chess.ts
|
|
670
|
-
var __dxlog_file4 = "/__w/dxos/dxos/packages/ui/react-ui-gameboard/src/Chessboard/chess.ts";
|
|
664
|
+
// src/components/Chessboard/chess.ts
|
|
665
|
+
var __dxlog_file4 = "/__w/dxos/dxos/packages/ui/react-ui-gameboard/src/components/Chessboard/chess.ts";
|
|
671
666
|
var ChessPieces = alpha_exports;
|
|
672
667
|
var posToLocation = (pos) => {
|
|
673
668
|
const col = pos.charCodeAt(0) - "a".charCodeAt(0);
|
|
@@ -706,55 +701,88 @@ var boardStyles = styles.original;
|
|
|
706
701
|
var getSquareColor = ([row, col]) => {
|
|
707
702
|
return (col + row) % 2 === 0 ? boardStyles.black : boardStyles.white;
|
|
708
703
|
};
|
|
709
|
-
var
|
|
704
|
+
var createChess = (pgn) => {
|
|
705
|
+
const chess = new ChessJS();
|
|
706
|
+
if (pgn) {
|
|
707
|
+
try {
|
|
708
|
+
chess.loadPgn(pgn);
|
|
709
|
+
} catch {
|
|
710
|
+
log4.warn(pgn, void 0, {
|
|
711
|
+
F: __dxlog_file4,
|
|
712
|
+
L: 71,
|
|
713
|
+
S: void 0,
|
|
714
|
+
C: (f, a) => f(...a)
|
|
715
|
+
});
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
return chess;
|
|
719
|
+
};
|
|
720
|
+
var tryMove = (chess, move) => {
|
|
710
721
|
const from = locationToPos(move.from);
|
|
711
722
|
const to = locationToPos(move.to);
|
|
712
723
|
try {
|
|
713
|
-
log4("makeMove", {
|
|
714
|
-
move
|
|
715
|
-
}, {
|
|
716
|
-
F: __dxlog_file4,
|
|
717
|
-
L: 72,
|
|
718
|
-
S: void 0,
|
|
719
|
-
C: (f, a) => f(...a)
|
|
720
|
-
});
|
|
721
724
|
const promotion = move.promotion ? move.promotion[1].toLowerCase() : "q";
|
|
722
|
-
|
|
725
|
+
chess.move({
|
|
723
726
|
from,
|
|
724
727
|
to,
|
|
725
728
|
promotion
|
|
726
729
|
}, {
|
|
727
730
|
strict: false
|
|
728
731
|
});
|
|
729
|
-
return
|
|
730
|
-
} catch
|
|
732
|
+
return chess;
|
|
733
|
+
} catch {
|
|
731
734
|
return null;
|
|
732
735
|
}
|
|
733
736
|
};
|
|
734
737
|
var ChessModel = class {
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
+
_chess = new ChessJS();
|
|
739
|
+
_pieces = signal({});
|
|
740
|
+
constructor(pgn) {
|
|
741
|
+
this.update(pgn);
|
|
738
742
|
}
|
|
739
743
|
get turn() {
|
|
740
|
-
return this.
|
|
744
|
+
return this._chess.turn() === "w" ? "white" : "black";
|
|
741
745
|
}
|
|
742
746
|
get pieces() {
|
|
743
747
|
return this._pieces;
|
|
744
748
|
}
|
|
745
749
|
get game() {
|
|
746
|
-
return this.
|
|
750
|
+
return this._chess;
|
|
751
|
+
}
|
|
752
|
+
/**
|
|
753
|
+
* PGN with headers.
|
|
754
|
+
*
|
|
755
|
+
* [Event "?"]
|
|
756
|
+
* [Site "?"]
|
|
757
|
+
* [Date "2025.08.05"]
|
|
758
|
+
* [Round "?"]
|
|
759
|
+
* [White "?"]
|
|
760
|
+
* [Black "?"]
|
|
761
|
+
* [Result "*"]
|
|
762
|
+
*/
|
|
763
|
+
// TODO(burdon): Update headers.
|
|
764
|
+
get pgn() {
|
|
765
|
+
return this._chess.pgn();
|
|
747
766
|
}
|
|
748
767
|
get fen() {
|
|
749
|
-
return this.
|
|
768
|
+
return this._chess.fen();
|
|
750
769
|
}
|
|
751
|
-
|
|
752
|
-
this.
|
|
753
|
-
|
|
770
|
+
update(pgn = "") {
|
|
771
|
+
const previous = this._chess.history();
|
|
772
|
+
try {
|
|
773
|
+
this._chess.loadPgn(pgn);
|
|
774
|
+
this._chess.setHeader("Date", createDate());
|
|
775
|
+
this._chess.setHeader("Site", "dxos.org");
|
|
776
|
+
} catch {
|
|
777
|
+
}
|
|
778
|
+
const current = this._chess.history();
|
|
779
|
+
if (!isValidNextMove(previous, current)) {
|
|
780
|
+
this._pieces.value = {};
|
|
781
|
+
}
|
|
754
782
|
this._update();
|
|
755
783
|
}
|
|
756
784
|
isValidMove(move) {
|
|
757
|
-
return
|
|
785
|
+
return tryMove(new ChessJS(this._chess.fen()), move) !== null;
|
|
758
786
|
}
|
|
759
787
|
canPromote(move) {
|
|
760
788
|
const isPawnMove = move.piece === "BP" || move.piece === "WP";
|
|
@@ -762,21 +790,20 @@ var ChessModel = class {
|
|
|
762
790
|
return isPawnMove && isToLastRank;
|
|
763
791
|
}
|
|
764
792
|
makeMove(move) {
|
|
765
|
-
const game =
|
|
793
|
+
const game = tryMove(this._chess, move);
|
|
766
794
|
if (!game) {
|
|
767
795
|
return false;
|
|
768
796
|
}
|
|
769
|
-
this._game = game;
|
|
770
797
|
this._update();
|
|
771
798
|
return true;
|
|
772
799
|
}
|
|
773
800
|
makeRandomMove() {
|
|
774
|
-
const moves = this.
|
|
801
|
+
const moves = this._chess.moves();
|
|
775
802
|
if (!moves.length) {
|
|
776
803
|
return false;
|
|
777
804
|
}
|
|
778
805
|
const move = moves[Math.floor(Math.random() * moves.length)];
|
|
779
|
-
this.
|
|
806
|
+
this._chess.move(move);
|
|
780
807
|
this._update();
|
|
781
808
|
return true;
|
|
782
809
|
}
|
|
@@ -785,7 +812,7 @@ var ChessModel = class {
|
|
|
785
812
|
*/
|
|
786
813
|
_update() {
|
|
787
814
|
const pieces = {};
|
|
788
|
-
this.
|
|
815
|
+
this._chess.board().flatMap((row) => row.forEach((record) => {
|
|
789
816
|
if (!record) {
|
|
790
817
|
return;
|
|
791
818
|
}
|
|
@@ -802,6 +829,17 @@ var ChessModel = class {
|
|
|
802
829
|
this._pieces.value = mapPieces(this._pieces.value, pieces);
|
|
803
830
|
}
|
|
804
831
|
};
|
|
832
|
+
var isValidNextMove = (previous, current) => {
|
|
833
|
+
if (current.length > previous.length + 1) {
|
|
834
|
+
return false;
|
|
835
|
+
}
|
|
836
|
+
for (let i = 0; i < previous.length; i++) {
|
|
837
|
+
if (previous[i] !== current[i]) {
|
|
838
|
+
return false;
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
return true;
|
|
842
|
+
};
|
|
805
843
|
var mapPieces = (before, after) => {
|
|
806
844
|
const difference = {
|
|
807
845
|
removed: {},
|
|
@@ -832,16 +870,17 @@ var mapPieces = (before, after) => {
|
|
|
832
870
|
added: Object.keys(difference.added).length
|
|
833
871
|
}, {
|
|
834
872
|
F: __dxlog_file4,
|
|
835
|
-
L:
|
|
873
|
+
L: 263,
|
|
836
874
|
S: void 0,
|
|
837
875
|
C: (f, a) => f(...a)
|
|
838
876
|
});
|
|
839
877
|
return after;
|
|
840
878
|
};
|
|
879
|
+
var createDate = (date = /* @__PURE__ */ new Date()) => date.toISOString().slice(0, 10).replace(/-/g, ".");
|
|
841
880
|
|
|
842
|
-
// src/Chessboard/Chessboard.tsx
|
|
881
|
+
// src/components/Chessboard/Chessboard.tsx
|
|
843
882
|
import { useSignals as _useSignals16 } from "@preact-signals/safe-react/tracking";
|
|
844
|
-
import React16, {
|
|
883
|
+
import React16, { memo as memo3, useEffect as useEffect4, useMemo, useRef as useRef3, useState as useState4 } from "react";
|
|
845
884
|
import { useResizeDetector } from "react-resize-detector";
|
|
846
885
|
import { useTrackProps as useTrackProps2 } from "@dxos/react-ui";
|
|
847
886
|
import { mx as mx4 } from "@dxos/react-ui-theme";
|
|
@@ -857,7 +896,7 @@ var Chessboard = /* @__PURE__ */ memo3(({ orientation, showLabels, debug, rows =
|
|
|
857
896
|
const { ref: containerRef, width, height } = useResizeDetector({
|
|
858
897
|
refreshRate: 200
|
|
859
898
|
});
|
|
860
|
-
const { model, promoting, onPromotion } =
|
|
899
|
+
const { model, promoting, onPromotion } = useGameboardContext(Chessboard.displayName);
|
|
861
900
|
const locations = useMemo(() => {
|
|
862
901
|
return Array.from({
|
|
863
902
|
length: rows
|
|
@@ -923,7 +962,7 @@ var Chessboard = /* @__PURE__ */ memo3(({ orientation, showLabels, debug, rows =
|
|
|
923
962
|
}, /* @__PURE__ */ React16.createElement("div", {
|
|
924
963
|
ref: gridRef,
|
|
925
964
|
className: "grid grid-rows-8 grid-cols-8 aspect-square select-none"
|
|
926
|
-
}, layout), /* @__PURE__ */ React16.createElement("div", null, locations.map((location) => /* @__PURE__ */ React16.createElement(Square, {
|
|
965
|
+
}, layout), /* @__PURE__ */ React16.createElement("div", null, locations.map((location) => /* @__PURE__ */ React16.createElement(Gameboard.Square, {
|
|
927
966
|
key: locationToString(location),
|
|
928
967
|
location,
|
|
929
968
|
label: showLabels ? locationToPos(location) : void 0,
|
|
@@ -931,14 +970,14 @@ var Chessboard = /* @__PURE__ */ memo3(({ orientation, showLabels, debug, rows =
|
|
|
931
970
|
classNames: getSquareColor(location)
|
|
932
971
|
}))), /* @__PURE__ */ React16.createElement("div", {
|
|
933
972
|
className: mx4(promoting && "opacity-50")
|
|
934
|
-
}, positions.map(({ bounds, piece }) => /* @__PURE__ */ React16.createElement(Piece, {
|
|
973
|
+
}, positions.map(({ bounds, piece }) => /* @__PURE__ */ React16.createElement(Gameboard.Piece, {
|
|
935
974
|
key: piece.id,
|
|
936
975
|
piece,
|
|
937
976
|
bounds,
|
|
938
977
|
label: debug ? piece.id : void 0,
|
|
939
978
|
orientation,
|
|
940
979
|
Component: ChessPieces[piece.type]
|
|
941
|
-
}))),
|
|
980
|
+
}))), promoting && /* @__PURE__ */ React16.createElement(PromotionSelector, {
|
|
942
981
|
grid,
|
|
943
982
|
piece: promoting,
|
|
944
983
|
onSelect: (piece) => {
|
|
@@ -949,7 +988,7 @@ var Chessboard = /* @__PURE__ */ memo3(({ orientation, showLabels, debug, rows =
|
|
|
949
988
|
promotion: piece.type
|
|
950
989
|
});
|
|
951
990
|
}
|
|
952
|
-
}))
|
|
991
|
+
}));
|
|
953
992
|
} finally {
|
|
954
993
|
_effect.f();
|
|
955
994
|
}
|
|
@@ -987,16 +1026,14 @@ var PromotionSelector = ({ grid, piece, onSelect }) => {
|
|
|
987
1026
|
type: selected.type
|
|
988
1027
|
});
|
|
989
1028
|
};
|
|
990
|
-
return /* @__PURE__ */ React16.createElement(
|
|
1029
|
+
return /* @__PURE__ */ React16.createElement(React16.Fragment, null, positions.map(({ piece: piece2, bounds }) => /* @__PURE__ */ React16.createElement(Gameboard.Piece, {
|
|
991
1030
|
key: piece2.id,
|
|
992
|
-
style: bounds,
|
|
993
|
-
onClick: () => handleSelect(piece2)
|
|
994
|
-
}, /* @__PURE__ */ React16.createElement(Piece, {
|
|
995
1031
|
piece: piece2,
|
|
996
1032
|
bounds,
|
|
997
1033
|
Component: ChessPieces[piece2.type],
|
|
998
|
-
classNames: mx4("border-2 border-neutral-700 rounded-full", boardStyles.promotion)
|
|
999
|
-
|
|
1034
|
+
classNames: mx4("border-2 border-neutral-700 rounded-full", boardStyles.promotion),
|
|
1035
|
+
onClick: () => handleSelect(piece2)
|
|
1036
|
+
})));
|
|
1000
1037
|
} finally {
|
|
1001
1038
|
_effect.f();
|
|
1002
1039
|
}
|
|
@@ -1006,10 +1043,8 @@ export {
|
|
|
1006
1043
|
ChessPieces,
|
|
1007
1044
|
Chessboard,
|
|
1008
1045
|
Gameboard,
|
|
1009
|
-
GameboardContext,
|
|
1010
|
-
Piece,
|
|
1011
|
-
Square,
|
|
1012
1046
|
boardStyles,
|
|
1047
|
+
createChess,
|
|
1013
1048
|
getRelativeBounds,
|
|
1014
1049
|
getSquareColor,
|
|
1015
1050
|
isEqualLocation,
|
|
@@ -1020,6 +1055,6 @@ export {
|
|
|
1020
1055
|
mapPieces,
|
|
1021
1056
|
posToLocation,
|
|
1022
1057
|
stringToLocation,
|
|
1023
|
-
|
|
1058
|
+
useGameboardContext
|
|
1024
1059
|
};
|
|
1025
1060
|
//# sourceMappingURL=index.mjs.map
|