@mirasen/chessboard 1.0.3 → 1.0.5
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/CHANGELOG.md +15 -0
- package/README.md +119 -100
- package/dist/extensions/build/index.d.ts +1 -0
- package/dist/extensions/build/index.js +1 -0
- package/dist/extensions/first-party/promotion/normalize.js +6 -4
- package/dist/extensions/types/wrapper.d.ts +0 -3
- package/dist/extensions/types/wrapper.js +0 -3
- package/dist/index.d.ts +3 -1
- package/dist/runtime/factory/input.js +6 -7
- package/dist/runtime/mutation/interaction.js +1 -1
- package/dist/runtime/mutation/types.d.ts +3 -2
- package/dist/wrapper/factory.d.ts +1 -1
- package/dist/wrapper/factory.js +8 -0
- package/dist/wrapper/types.d.ts +15 -5
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# @mirasen/chessboard
|
|
2
2
|
|
|
3
|
+
## 1.0.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 0422020: Fix fast drag-and-drop sometimes leaving a stale drag visual due to an unsynced target square.
|
|
8
|
+
- 0422020: Update dependencies
|
|
9
|
+
- 0422020: Fix promotion extension to accept renderer-compatible piece URL maps without throwing on extra entries.
|
|
10
|
+
- 0422020: Allow createBoard options to configure built-in extensions without direct factory calls.
|
|
11
|
+
|
|
12
|
+
## 1.0.4
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- f586eea: Update README integration examples and export move-related public types.
|
|
17
|
+
|
|
3
18
|
## 1.0.3
|
|
4
19
|
|
|
5
20
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@ This is not just a board renderer. It is a chessboard platform designed for real
|
|
|
24
24
|
|
|
25
25
|
## What you get out of the box
|
|
26
26
|
|
|
27
|
-
The
|
|
27
|
+
The default first-party extension baseline includes rendering, events, selection, active target feedback, legal move hints, last move feedback, promotion UI, and optional auto-promotion.
|
|
28
28
|
|
|
29
29
|
- `renderer` — the first-party rendering extension that validates the same extension architecture used for board features
|
|
30
30
|
- `events`
|
|
@@ -78,44 +78,48 @@ if (!element) {
|
|
|
78
78
|
const board = createBoard({
|
|
79
79
|
element
|
|
80
80
|
});
|
|
81
|
-
|
|
81
|
+
|
|
82
|
+
// User moves are disabled by default.
|
|
83
|
+
// Enable free movement when you want unconstrained UI moves.
|
|
82
84
|
board.setMovability({
|
|
83
85
|
mode: 'free'
|
|
84
86
|
});
|
|
85
87
|
```
|
|
86
88
|
|
|
87
|
-
###
|
|
88
|
-
|
|
89
|
-
```ts
|
|
90
|
-
import { createBoard, type Chessboard, type ChessboardExtensionInput } from '@mirasen/chessboard';
|
|
91
|
-
|
|
92
|
-
const extensionList = [
|
|
93
|
-
// Always add renderer first, otherwise nothing will be rendered
|
|
94
|
-
'renderer',
|
|
95
|
-
'lastMove',
|
|
96
|
-
// Keep autoPromote before promotion, otherwise promotion may defer the move first
|
|
97
|
-
'autoPromote',
|
|
98
|
-
'promotion'
|
|
99
|
-
// customExtensionDefinition
|
|
100
|
-
] as const satisfies readonly ChessboardExtensionInput[];
|
|
101
|
-
let board: Chessboard<typeof extensionList> | null = null;
|
|
102
|
-
|
|
103
|
-
const element = document.getElementById('board');
|
|
104
|
-
|
|
105
|
-
if (!element) {
|
|
106
|
-
throw new Error('Missing board element');
|
|
107
|
-
}
|
|
89
|
+
### Connect to a game/rules layer
|
|
108
90
|
|
|
109
|
-
board
|
|
110
|
-
element,
|
|
111
|
-
extensions: extensionList
|
|
112
|
-
});
|
|
113
|
-
```
|
|
91
|
+
`@mirasen/chessboard` handles board interaction and move intent. Your application can keep chess rules and game state in its own game/rules layer.
|
|
114
92
|
|
|
115
|
-
|
|
93
|
+
A typical integration uses a small adapter between your game move format and the board move format. The `game` object below represents your own chess rules layer, such as chess.js, a server-backed game model, or a custom engine.
|
|
116
94
|
|
|
117
95
|
```ts
|
|
118
|
-
import {
|
|
96
|
+
import {
|
|
97
|
+
createBoard,
|
|
98
|
+
type MoveDestinationInput,
|
|
99
|
+
type MoveOutput,
|
|
100
|
+
type MoveRequestInput
|
|
101
|
+
} from '@mirasen/chessboard';
|
|
102
|
+
|
|
103
|
+
type GameMove = {
|
|
104
|
+
from: string;
|
|
105
|
+
to: string;
|
|
106
|
+
capturedSquare?: string;
|
|
107
|
+
secondary?: {
|
|
108
|
+
from: string;
|
|
109
|
+
to: string;
|
|
110
|
+
};
|
|
111
|
+
promotedTo?: 'queen' | 'rook' | 'bishop' | 'knight';
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
type GameDestination = {
|
|
115
|
+
to: string;
|
|
116
|
+
capturedSquare?: string;
|
|
117
|
+
secondary?: {
|
|
118
|
+
from: string;
|
|
119
|
+
to: string;
|
|
120
|
+
};
|
|
121
|
+
promotedTo?: ('queen' | 'rook' | 'bishop' | 'knight')[];
|
|
122
|
+
};
|
|
119
123
|
|
|
120
124
|
const element = document.getElementById('board');
|
|
121
125
|
|
|
@@ -123,95 +127,72 @@ if (!element) {
|
|
|
123
127
|
throw new Error('Missing board element');
|
|
124
128
|
}
|
|
125
129
|
|
|
130
|
+
const game = createYourGameEngine(); // Your app/game layer.
|
|
126
131
|
const board = createBoard({
|
|
127
|
-
element
|
|
128
|
-
state: {
|
|
129
|
-
board: 'start',
|
|
130
|
-
interaction: {
|
|
131
|
-
movability: {
|
|
132
|
-
mode: 'free'
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
board.extensions.events.setOnUIMove((move) => {
|
|
139
|
-
console.log('UI move:', move);
|
|
132
|
+
element
|
|
140
133
|
});
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
### setMovability - strict with explicit destinations
|
|
144
134
|
|
|
145
|
-
|
|
146
|
-
import { createBoard } from '@mirasen/chessboard';
|
|
135
|
+
board.setPosition(game.getPosition());
|
|
147
136
|
|
|
148
|
-
|
|
137
|
+
function toBoardDestination(gameDestination: GameDestination): MoveDestinationInput {
|
|
138
|
+
return {
|
|
139
|
+
to: gameDestination.to,
|
|
140
|
+
capturedSquare: gameDestination.capturedSquare,
|
|
141
|
+
secondary: gameDestination.secondary, // e.g. castling.
|
|
142
|
+
promotedTo: gameDestination.promotedTo
|
|
143
|
+
};
|
|
144
|
+
}
|
|
149
145
|
|
|
150
|
-
|
|
151
|
-
|
|
146
|
+
function toBoardMoveRequest(gameMove: GameMove): MoveRequestInput {
|
|
147
|
+
return {
|
|
148
|
+
from: gameMove.from,
|
|
149
|
+
to: gameMove.to,
|
|
150
|
+
capturedSquare: gameMove.capturedSquare,
|
|
151
|
+
secondary: gameMove.secondary,
|
|
152
|
+
promotedTo: gameMove.promotedTo
|
|
153
|
+
};
|
|
152
154
|
}
|
|
153
155
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
156
|
+
function toGameMove(move: MoveOutput): GameMove {
|
|
157
|
+
return {
|
|
158
|
+
from: move.from,
|
|
159
|
+
to: move.to,
|
|
160
|
+
capturedSquare: move.capturedSquare,
|
|
161
|
+
secondary: move.secondary,
|
|
162
|
+
promotedTo: move.promotedTo
|
|
163
|
+
};
|
|
164
|
+
}
|
|
157
165
|
|
|
158
166
|
board.setMovability({
|
|
159
167
|
mode: 'strict',
|
|
160
|
-
destinations: {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
{ to: 'd8', promotedTo: ['queen', 'rook', 'bishop', 'knight'] }
|
|
165
|
-
],
|
|
166
|
-
g1: [{ to: 'f3' }, { to: 'h3' }]
|
|
168
|
+
destinations: (source): MoveDestinationInput[] | undefined => {
|
|
169
|
+
const gameDestinations = game.getDestinationsFor(source);
|
|
170
|
+
|
|
171
|
+
return gameDestinations.length > 0 ? gameDestinations.map(toBoardDestination) : undefined;
|
|
167
172
|
}
|
|
168
173
|
});
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
### setMovability - strict with a resolver
|
|
172
174
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
+
board.extensions.events.setOnUIMove((move) => {
|
|
176
|
+
// The board accepted and applied this UI move.
|
|
177
|
+
// Keep your game/rules layer in sync.
|
|
178
|
+
game.move(toGameMove(move));
|
|
179
|
+
});
|
|
175
180
|
|
|
176
|
-
|
|
181
|
+
function applyExternalMove(gameMove: GameMove) {
|
|
182
|
+
// Apply moves that come from outside the board UI:
|
|
183
|
+
// server, engine, opponent, imported game, replay, etc.
|
|
184
|
+
game.move(gameMove);
|
|
177
185
|
|
|
178
|
-
|
|
179
|
-
|
|
186
|
+
// Then animate/apply the same move on the board.
|
|
187
|
+
board.move(toBoardMoveRequest(gameMove));
|
|
180
188
|
}
|
|
189
|
+
```
|
|
181
190
|
|
|
182
|
-
|
|
183
|
-
element
|
|
184
|
-
});
|
|
191
|
+
`MoveDestinationInput` can describe more than a target square. For example, `secondary` can represent paired piece movement (e.g. castling), `capturedSquare` can represent captures away from the destination square (e.g. en passant), and `promotedTo` can represent promotion choices.
|
|
185
192
|
|
|
186
|
-
board.
|
|
187
|
-
mode: 'strict',
|
|
188
|
-
destinations: (source) => {
|
|
189
|
-
if (source === 'e2')
|
|
190
|
-
return [
|
|
191
|
-
{ to: 'e8', promotedTo: ['bishop', 'queen'] },
|
|
192
|
-
{ to: 'd8', promotedTo: ['rook', 'knight', 'queen'] }
|
|
193
|
-
];
|
|
194
|
-
if (source === 'f7')
|
|
195
|
-
return [
|
|
196
|
-
{ to: 'f8', promotedTo: ['bishop', 'rook', 'knight', 'queen'] },
|
|
197
|
-
{ to: 'g8', promotedTo: ['bishop', 'rook', 'knight', 'queen'] }
|
|
198
|
-
];
|
|
199
|
-
if (source === 'd7')
|
|
200
|
-
return [
|
|
201
|
-
{ to: 'd1', promotedTo: ['bishop', 'knight'] },
|
|
202
|
-
{ to: 'e1', promotedTo: ['rook', 'knight', 'queen'] }
|
|
203
|
-
];
|
|
204
|
-
if (source === 'c2')
|
|
205
|
-
return [
|
|
206
|
-
{ to: 'c1', promotedTo: ['bishop', 'rook', 'knight', 'queen'] },
|
|
207
|
-
{ to: 'b1', promotedTo: ['bishop', 'rook', 'knight', 'queen'] }
|
|
208
|
-
];
|
|
209
|
-
return undefined;
|
|
210
|
-
}
|
|
211
|
-
});
|
|
212
|
-
```
|
|
193
|
+
This lets your game/rules layer own chess legality and game state while the board owns interaction, selection, targeting, visual feedback, promotion UI, animation, and its own displayed position.
|
|
213
194
|
|
|
214
|
-
|
|
195
|
+
### Promotion and auto-promotion
|
|
215
196
|
|
|
216
197
|
Promotion is handled inside the board interaction pipeline through a natural deferred move flow.
|
|
217
198
|
|
|
@@ -249,6 +230,44 @@ const board = createBoard({
|
|
|
249
230
|
board.extensions.autoPromote.toQueen = true;
|
|
250
231
|
```
|
|
251
232
|
|
|
233
|
+
### Movability modes
|
|
234
|
+
|
|
235
|
+
Movability controls how the board accepts user-initiated moves.
|
|
236
|
+
|
|
237
|
+
- `disabled` — user moves are ignored
|
|
238
|
+
- `free` — user moves are accepted without legal destination filtering
|
|
239
|
+
- `strict` — user moves are accepted only when the target is allowed by the destinations provided by your app/rules layer
|
|
240
|
+
|
|
241
|
+
### Advanced: explicit extension lists
|
|
242
|
+
|
|
243
|
+
Most users can rely on the default first-party extension baseline. Use an explicit extension list only when you want to control which built-in or custom extensions are installed.
|
|
244
|
+
|
|
245
|
+
```ts
|
|
246
|
+
import { createBoard, type Chessboard, type ChessboardExtensionInput } from '@mirasen/chessboard';
|
|
247
|
+
|
|
248
|
+
const extensionList = [
|
|
249
|
+
// Always add renderer first, otherwise nothing will be rendered
|
|
250
|
+
'renderer',
|
|
251
|
+
'lastMove',
|
|
252
|
+
// Keep autoPromote before promotion, otherwise promotion may defer the move first
|
|
253
|
+
'autoPromote',
|
|
254
|
+
'promotion'
|
|
255
|
+
// customExtensionDefinition
|
|
256
|
+
] as const satisfies readonly ChessboardExtensionInput[];
|
|
257
|
+
let board: Chessboard<typeof extensionList> | null = null;
|
|
258
|
+
|
|
259
|
+
const element = document.getElementById('board');
|
|
260
|
+
|
|
261
|
+
if (!element) {
|
|
262
|
+
throw new Error('Missing board element');
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
board = createBoard({
|
|
266
|
+
element,
|
|
267
|
+
extensions: extensionList
|
|
268
|
+
});
|
|
269
|
+
```
|
|
270
|
+
|
|
252
271
|
## Architecture
|
|
253
272
|
|
|
254
273
|
`@mirasen/chessboard` is built around explicit boundaries:
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { cleanAnimationPlan, prepareAnimationPlan, renderAnimationPlan } from '../../animation/render/plan.js';
|
|
1
2
|
export { clearElementChildren, createSvgElement, updateElementAttributes } from '../../render/svg/helpers.js';
|
|
2
3
|
export type { RuntimeReadonlyMutationSession } from '../../runtime/mutation/types.js';
|
|
3
4
|
export { isNonEmptyPieceCode } from '../../state/board/check.js';
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { cleanAnimationPlan, prepareAnimationPlan, renderAnimationPlan } from '../../animation/render/plan.js';
|
|
1
2
|
export { clearElementChildren, createSvgElement, updateElementAttributes } from '../../render/svg/helpers.js';
|
|
2
3
|
export { isNonEmptyPieceCode } from '../../state/board/check.js';
|
|
3
4
|
export { fileOf, rankOf, squareOf } from '../../state/board/coords.js';
|
|
@@ -6,21 +6,23 @@ function assertPieceUrlsComplete(pieceUrls) {
|
|
|
6
6
|
assert(pieceCode in pieceUrls, `Missing URL for piece code: ${pieceCode}`);
|
|
7
7
|
}
|
|
8
8
|
}
|
|
9
|
-
function
|
|
10
|
-
|
|
9
|
+
function isPromotionPieceCode(pieceCode) {
|
|
10
|
+
return (pieceCode === 5 /* PieceCode.WhiteQueen */ ||
|
|
11
11
|
pieceCode === 4 /* PieceCode.WhiteRook */ ||
|
|
12
12
|
pieceCode === 3 /* PieceCode.WhiteBishop */ ||
|
|
13
13
|
pieceCode === 2 /* PieceCode.WhiteKnight */ ||
|
|
14
14
|
pieceCode === 13 /* PieceCode.BlackQueen */ ||
|
|
15
15
|
pieceCode === 12 /* PieceCode.BlackRook */ ||
|
|
16
16
|
pieceCode === 11 /* PieceCode.BlackBishop */ ||
|
|
17
|
-
pieceCode === 10 /* PieceCode.BlackKnight
|
|
17
|
+
pieceCode === 10 /* PieceCode.BlackKnight */);
|
|
18
18
|
}
|
|
19
19
|
function normalizePromotionPieceUrls(input) {
|
|
20
20
|
const normalized = {};
|
|
21
21
|
for (const [key, url] of Object.entries(input)) {
|
|
22
22
|
const pieceCode = normalizePiece(key);
|
|
23
|
-
|
|
23
|
+
if (!isPromotionPieceCode(pieceCode)) {
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
24
26
|
normalized[pieceCode] = url;
|
|
25
27
|
}
|
|
26
28
|
assertPieceUrlsComplete(normalized);
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Public built-in extension ids accepted by createBoard({ extensions })
|
|
3
|
-
*/
|
|
4
1
|
import { createActiveTarget } from '../first-party/active-target/factory.js';
|
|
5
2
|
import { createAutoPromote } from '../first-party/auto-promote/factory.js';
|
|
6
3
|
import { createBoardEvents } from '../first-party/board-events/factory.js';
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Public built-in extension ids accepted by createBoard({ extensions })
|
|
3
|
-
*/
|
|
4
1
|
import { createActiveTarget } from '../first-party/active-target/factory.js';
|
|
5
2
|
import { EXTENSION_ID as EXTENSION_ID_ACTIVE_TARGET } from '../first-party/active-target/types.js';
|
|
6
3
|
import { createAutoPromote } from '../first-party/auto-promote/factory.js';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export type { MoveOutput } from './extensions/build/index.js';
|
|
2
|
+
export type { MoveRequestInput, PiecePositionRecordString } from './state/board/types/input.js';
|
|
3
|
+
export type { MoveDestinationInput } from './state/interaction/types/input.js';
|
|
1
4
|
export { createBoard } from './wrapper/factory.js';
|
|
2
5
|
export type { Chessboard, ChessboardExtensionInput, ChessboardInitOptions } from './wrapper/types.js';
|
|
3
|
-
export type { MoveRequestInput, PiecePositionRecordString } from './state/board/types/input.js';
|
|
@@ -42,23 +42,24 @@ export function createRuntimeInteractionSurface(state) {
|
|
|
42
42
|
const internalState = state();
|
|
43
43
|
const mutationSession = internalState.mutation.getSession();
|
|
44
44
|
const interaction = internalState.state.interaction;
|
|
45
|
+
interaction.updateDragSessionCurrentTarget(target, mutationSession);
|
|
45
46
|
const dragSession = interaction.dragSession;
|
|
46
|
-
assert(dragSession !== null, 'completeDragTo requires an active drag session');
|
|
47
47
|
assert(isDragSessionCoreOwned(dragSession), 'completeDragTo can only be called for core-owned drag sessions');
|
|
48
48
|
uiMoveCompleteTo(internalState, target);
|
|
49
|
-
mutationSession.addMutation('runtime.interaction.
|
|
49
|
+
mutationSession.addMutation('runtime.interaction.completeCoreDragTo', true, dragSession);
|
|
50
50
|
runtimeRunMutationPipeline(internalState);
|
|
51
51
|
},
|
|
52
52
|
completeExtensionDrag(target) {
|
|
53
53
|
const internalState = state();
|
|
54
54
|
const mutationSession = internalState.mutation.getSession();
|
|
55
55
|
const interaction = internalState.state.interaction;
|
|
56
|
+
interaction.updateDragSessionCurrentTarget(target, mutationSession);
|
|
56
57
|
const dragSession = interaction.dragSession;
|
|
57
|
-
assert(dragSession !== null, 'completeExtensionDrag requires an active drag session');
|
|
58
58
|
assert(!isDragSessionCoreOwned(dragSession), 'completeExtensionDrag can only be called for extension-owned drag sessions');
|
|
59
|
-
assert(dragSession.targetSquare === target, 'The target square in completeExtensionDrag must match the current target square of the drag session');
|
|
60
59
|
internalState.extensionSystem.completeDrag(dragSession);
|
|
61
60
|
internalState.state.interaction.setDragSession(null, mutationSession);
|
|
61
|
+
mutationSession.addMutation('runtime.interaction.completeExtensionDragTo', true, dragSession);
|
|
62
|
+
runtimeRunMutationPipeline(internalState);
|
|
62
63
|
},
|
|
63
64
|
startReleaseTargetingDrag(source, target) {
|
|
64
65
|
const internalState = state();
|
|
@@ -92,9 +93,7 @@ export function createRuntimeInteractionSurface(state) {
|
|
|
92
93
|
const internalState = state();
|
|
93
94
|
const interactionMutationSession = internalState.mutation.getSession();
|
|
94
95
|
const interaction = internalState.state.interaction;
|
|
95
|
-
|
|
96
|
-
assert(currentDragSession !== null, 'No active drag session to update');
|
|
97
|
-
internalState.state.interaction.updateDragSessionCurrentTarget(target, interactionMutationSession);
|
|
96
|
+
interaction.updateDragSessionCurrentTarget(target, interactionMutationSession);
|
|
98
97
|
runtimeRunMutationPipeline(internalState);
|
|
99
98
|
},
|
|
100
99
|
onEvent(context) {
|
|
@@ -4,7 +4,7 @@ export const reconcileInteractionSelectionAfterBoardStateChange = (context, muta
|
|
|
4
4
|
const { current } = context;
|
|
5
5
|
if (!mutationSession.hasMutation({ prefixes: ['state.board.'] }) ||
|
|
6
6
|
mutationSession.hasMutation({
|
|
7
|
-
causes: ['state.interaction.clear', 'runtime.interaction.
|
|
7
|
+
causes: ['state.interaction.clear', 'runtime.interaction.completeCoreDragTo']
|
|
8
8
|
})) {
|
|
9
9
|
return;
|
|
10
10
|
}
|
|
@@ -3,10 +3,11 @@ import type { MutationSession, ReadonlyMutationSession } from '../../mutation/ty
|
|
|
3
3
|
import type { BoardStateMutationPayloadByCause } from '../../state/board/mutation.js';
|
|
4
4
|
import type { ChangeStateMutationPayloadByCause } from '../../state/change/mutation.js';
|
|
5
5
|
import type { InteractionStateMutationPayloadByCause } from '../../state/interaction/mutation.js';
|
|
6
|
-
import type { DragSessionCoreOwnedSnapshot } from '../../state/interaction/types/internal.js';
|
|
6
|
+
import type { DragSessionCoreOwnedSnapshot, DragSessionExtensionOwnedSnapshot } from '../../state/interaction/types/internal.js';
|
|
7
7
|
import type { ViewStateMutationPayloadByCause } from '../../state/view/mutation.js';
|
|
8
8
|
type RuntimeOwnMutationPayloadByCause = {
|
|
9
|
-
'runtime.interaction.
|
|
9
|
+
'runtime.interaction.completeCoreDragTo': DragSessionCoreOwnedSnapshot;
|
|
10
|
+
'runtime.interaction.completeExtensionDragTo': DragSessionExtensionOwnedSnapshot;
|
|
10
11
|
'runtime.interaction.resolveDeferredUIMoveRequest': undefined;
|
|
11
12
|
'runtime.interaction.cancelDeferredUIMoveRequest': undefined;
|
|
12
13
|
};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { DefaultBuiltinChessboardExtensions } from '../extensions/types/wrapper.js';
|
|
2
|
-
import { Chessboard, ChessboardExtensionInput, ChessboardInitOptions } from './types.js';
|
|
2
|
+
import { type Chessboard, type ChessboardExtensionInput, type ChessboardInitOptions } from './types.js';
|
|
3
3
|
export declare function createBoard<TExtensions extends readonly ChessboardExtensionInput[] = DefaultBuiltinChessboardExtensions>(options: ChessboardInitOptions<TExtensions>): Chessboard<TExtensions>;
|
package/dist/wrapper/factory.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { builtInExtensionFactoryMap, DefaultBuiltinChessboardExtensions } from '../extensions/types/wrapper.js';
|
|
2
2
|
import { createRuntime } from '../runtime/factory/main.js';
|
|
3
|
+
function resolveBuiltInExtensionWithOptions(input) {
|
|
4
|
+
const factory = builtInExtensionFactoryMap[input.builtin];
|
|
5
|
+
return factory(input.options);
|
|
6
|
+
}
|
|
3
7
|
export function createBoard(options) {
|
|
4
8
|
// prepare init options for runtime
|
|
5
9
|
const extensionsInput = options.extensions ?? DefaultBuiltinChessboardExtensions;
|
|
@@ -8,6 +12,10 @@ export function createBoard(options) {
|
|
|
8
12
|
// built-in extension, convert to definition
|
|
9
13
|
return builtInExtensionFactoryMap[ext]();
|
|
10
14
|
}
|
|
15
|
+
if ('builtin' in ext) {
|
|
16
|
+
// built-in extension with options, convert to definition
|
|
17
|
+
return resolveBuiltInExtensionWithOptions(ext);
|
|
18
|
+
}
|
|
11
19
|
// assume it's already a definition
|
|
12
20
|
return ext;
|
|
13
21
|
});
|
package/dist/wrapper/types.d.ts
CHANGED
|
@@ -1,15 +1,25 @@
|
|
|
1
1
|
import type { AnyExtensionDefinition, ExtensionDefinitionId, ExtensionDefinitionPublicApi } from '../extensions/types/extension.js';
|
|
2
|
-
import { BuiltInExtensionDefinitionMap, BuiltInExtensionId, DefaultBuiltinChessboardExtensions } from '../extensions/types/wrapper.js';
|
|
3
|
-
import { Runtime } from '../runtime/types/main.js';
|
|
4
|
-
import { RuntimeStateInitOptions } from '../state/types.js';
|
|
2
|
+
import { type BuiltInExtensionDefinitionMap, type BuiltInExtensionId, type DefaultBuiltinChessboardExtensions, builtInExtensionFactoryMap } from '../extensions/types/wrapper.js';
|
|
3
|
+
import type { Runtime } from '../runtime/types/main.js';
|
|
4
|
+
import type { RuntimeStateInitOptions } from '../state/types.js';
|
|
5
5
|
/**
|
|
6
6
|
* What createBoard accepts in options.extensions
|
|
7
7
|
*/
|
|
8
|
-
export type
|
|
8
|
+
export type BuiltInExtensionFactoryInitOptions<TId extends BuiltInExtensionId> = Parameters<(typeof builtInExtensionFactoryMap)[TId]> extends [] ? never : NonNullable<Parameters<(typeof builtInExtensionFactoryMap)[TId]>[0]>;
|
|
9
|
+
type BuiltInExtensionIdsWithOptions = {
|
|
10
|
+
[TId in BuiltInExtensionId]: [BuiltInExtensionFactoryInitOptions<TId>] extends [never] ? never : TId;
|
|
11
|
+
}[BuiltInExtensionId];
|
|
12
|
+
export type BuiltInExtensionInitOptions = {
|
|
13
|
+
[TId in BuiltInExtensionIdsWithOptions]: {
|
|
14
|
+
builtin: TId;
|
|
15
|
+
options: BuiltInExtensionFactoryInitOptions<TId>;
|
|
16
|
+
};
|
|
17
|
+
}[BuiltInExtensionIdsWithOptions];
|
|
18
|
+
export type ChessboardExtensionInput = BuiltInExtensionId | BuiltInExtensionInitOptions | AnyExtensionDefinition;
|
|
9
19
|
/**
|
|
10
20
|
* Resolve one public input item into a concrete extension definition type
|
|
11
21
|
*/
|
|
12
|
-
export type ResolveChessboardExtensionInput<T> = T extends keyof BuiltInExtensionDefinitionMap ? BuiltInExtensionDefinitionMap[T] : T extends AnyExtensionDefinition ? T : never;
|
|
22
|
+
export type ResolveChessboardExtensionInput<T> = T extends keyof BuiltInExtensionDefinitionMap ? BuiltInExtensionDefinitionMap[T] : T extends BuiltInExtensionInitOptions ? T['builtin'] extends keyof BuiltInExtensionDefinitionMap ? BuiltInExtensionDefinitionMap[T['builtin']] : never : T extends AnyExtensionDefinition ? T : never;
|
|
13
23
|
/**
|
|
14
24
|
* Resolve an input tuple into a tuple of concrete extension definitions
|
|
15
25
|
*/
|
package/package.json
CHANGED