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