@lichess-org/chessground 9.2.3
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/LICENSE +674 -0
- package/README.md +110 -0
- package/assets/chessground.base.css +224 -0
- package/assets/chessground.brown.css +62 -0
- package/assets/chessground.cburnett.css +37 -0
- package/dist/anim.d.ts +17 -0
- package/dist/anim.js +99 -0
- package/dist/anim.js.map +1 -0
- package/dist/api.d.ts +28 -0
- package/dist/api.js +98 -0
- package/dist/api.js.map +1 -0
- package/dist/autoPieces.d.ts +3 -0
- package/dist/autoPieces.js +38 -0
- package/dist/autoPieces.js.map +1 -0
- package/dist/board.d.ts +25 -0
- package/dist/board.js +331 -0
- package/dist/board.js.map +1 -0
- package/dist/chessground.d.ts +7 -0
- package/dist/chessground.js +63 -0
- package/dist/chessground.js.map +1 -0
- package/dist/chessground.min.js +1 -0
- package/dist/config.d.ts +87 -0
- package/dist/config.js +64 -0
- package/dist/config.js.map +1 -0
- package/dist/drag.d.ts +20 -0
- package/dist/drag.js +208 -0
- package/dist/drag.js.map +1 -0
- package/dist/draw.d.ts +65 -0
- package/dist/draw.js +90 -0
- package/dist/draw.js.map +1 -0
- package/dist/drop.d.ts +5 -0
- package/dist/drop.js +31 -0
- package/dist/drop.js.map +1 -0
- package/dist/events.d.ts +4 -0
- package/dist/events.js +72 -0
- package/dist/events.js.map +1 -0
- package/dist/explosion.d.ts +3 -0
- package/dist/explosion.js +18 -0
- package/dist/explosion.js.map +1 -0
- package/dist/fen.d.ts +4 -0
- package/dist/fen.js +79 -0
- package/dist/fen.js.map +1 -0
- package/dist/premove.d.ts +6 -0
- package/dist/premove.js +57 -0
- package/dist/premove.js.map +1 -0
- package/dist/render.d.ts +4 -0
- package/dist/render.js +235 -0
- package/dist/render.js.map +1 -0
- package/dist/state.d.ts +100 -0
- package/dist/state.js +92 -0
- package/dist/state.js.map +1 -0
- package/dist/svg.d.ts +8 -0
- package/dist/svg.js +348 -0
- package/dist/svg.js.map +1 -0
- package/dist/sync.d.ts +8 -0
- package/dist/sync.js +27 -0
- package/dist/sync.js.map +1 -0
- package/dist/types.d.ts +94 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/util.d.ts +20 -0
- package/dist/util.js +89 -0
- package/dist/util.js.map +1 -0
- package/dist/wrap.d.ts +3 -0
- package/dist/wrap.js +90 -0
- package/dist/wrap.js.map +1 -0
- package/package.json +58 -0
- package/src/anim.ts +139 -0
- package/src/api.ts +187 -0
- package/src/autoPieces.ts +47 -0
- package/src/board.ts +371 -0
- package/src/chessground.ts +67 -0
- package/src/config.ts +165 -0
- package/src/drag.ts +223 -0
- package/src/draw.ts +154 -0
- package/src/drop.ts +36 -0
- package/src/events.ts +86 -0
- package/src/explosion.ts +19 -0
- package/src/fen.ts +78 -0
- package/src/premove.ts +76 -0
- package/src/render.ts +262 -0
- package/src/state.ts +199 -0
- package/src/svg.ts +441 -0
- package/src/sync.ts +36 -0
- package/src/types.ts +110 -0
- package/src/util.ts +105 -0
- package/src/wrap.ts +111 -0
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
export type Color = (typeof colors)[number];
|
|
2
|
+
export type Role = (typeof roles)[number];
|
|
3
|
+
export type File = (typeof files)[number];
|
|
4
|
+
export type Rank = (typeof ranks)[number];
|
|
5
|
+
export type Key = 'a0' | `${File}${Rank}`;
|
|
6
|
+
export type FEN = string;
|
|
7
|
+
export type Pos = [number, number];
|
|
8
|
+
export interface Piece {
|
|
9
|
+
role: Role;
|
|
10
|
+
color: Color;
|
|
11
|
+
promoted?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface Drop {
|
|
14
|
+
role: Role;
|
|
15
|
+
key: Key;
|
|
16
|
+
}
|
|
17
|
+
export type Pieces = Map<Key, Piece>;
|
|
18
|
+
export type PiecesDiff = Map<Key, Piece | undefined>;
|
|
19
|
+
export type KeyPair = [Key, Key];
|
|
20
|
+
export type NumberPair = [number, number];
|
|
21
|
+
export type NumberQuad = [number, number, number, number];
|
|
22
|
+
export interface Rect {
|
|
23
|
+
left: number;
|
|
24
|
+
top: number;
|
|
25
|
+
width: number;
|
|
26
|
+
height: number;
|
|
27
|
+
}
|
|
28
|
+
export type Dests = Map<Key, Key[]>;
|
|
29
|
+
export interface Elements {
|
|
30
|
+
board: HTMLElement;
|
|
31
|
+
wrap: HTMLElement;
|
|
32
|
+
container: HTMLElement;
|
|
33
|
+
ghost?: HTMLElement;
|
|
34
|
+
svg?: SVGElement;
|
|
35
|
+
customSvg?: SVGElement;
|
|
36
|
+
autoPieces?: HTMLElement;
|
|
37
|
+
}
|
|
38
|
+
export interface Dom {
|
|
39
|
+
elements: Elements;
|
|
40
|
+
bounds: Memo<DOMRectReadOnly>;
|
|
41
|
+
redraw: () => void;
|
|
42
|
+
redrawNow: (skipSvg?: boolean) => void;
|
|
43
|
+
unbind?: Unbind;
|
|
44
|
+
destroyed?: boolean;
|
|
45
|
+
}
|
|
46
|
+
export interface Exploding {
|
|
47
|
+
stage: number;
|
|
48
|
+
keys: readonly Key[];
|
|
49
|
+
}
|
|
50
|
+
export interface MoveMetadata {
|
|
51
|
+
premove: boolean;
|
|
52
|
+
ctrlKey?: boolean;
|
|
53
|
+
holdTime?: number;
|
|
54
|
+
captured?: Piece;
|
|
55
|
+
predrop?: boolean;
|
|
56
|
+
}
|
|
57
|
+
export interface SetPremoveMetadata {
|
|
58
|
+
ctrlKey?: boolean;
|
|
59
|
+
}
|
|
60
|
+
export type MouchEvent = Event & Partial<MouseEvent & TouchEvent>;
|
|
61
|
+
export interface KeyedNode extends HTMLElement {
|
|
62
|
+
cgKey: Key;
|
|
63
|
+
}
|
|
64
|
+
export interface PieceNode extends KeyedNode {
|
|
65
|
+
tagName: 'PIECE';
|
|
66
|
+
cgPiece: string;
|
|
67
|
+
cgAnimating?: boolean;
|
|
68
|
+
cgFading?: boolean;
|
|
69
|
+
cgDragging?: boolean;
|
|
70
|
+
cgScale?: number;
|
|
71
|
+
}
|
|
72
|
+
export interface SquareNode extends KeyedNode {
|
|
73
|
+
tagName: 'SQUARE';
|
|
74
|
+
}
|
|
75
|
+
export interface Memo<A> {
|
|
76
|
+
(): A;
|
|
77
|
+
clear: () => void;
|
|
78
|
+
}
|
|
79
|
+
export interface Timer {
|
|
80
|
+
start: () => void;
|
|
81
|
+
cancel: () => void;
|
|
82
|
+
stop: () => number;
|
|
83
|
+
}
|
|
84
|
+
export type Redraw = () => void;
|
|
85
|
+
export type Unbind = () => void;
|
|
86
|
+
export type Milliseconds = number;
|
|
87
|
+
export type KHz = number;
|
|
88
|
+
export declare const colors: readonly ["white", "black"];
|
|
89
|
+
export declare const roles: readonly ["pawn", "knight", "bishop", "rook", "queen", "king"];
|
|
90
|
+
export declare const files: readonly ["a", "b", "c", "d", "e", "f", "g", "h"];
|
|
91
|
+
export declare const ranks: readonly ["1", "2", "3", "4", "5", "6", "7", "8"];
|
|
92
|
+
export type RanksPosition = 'left' | 'right';
|
|
93
|
+
export type BrushColor = 'green' | 'red' | 'blue' | 'yellow';
|
|
94
|
+
export type SquareClasses = Map<Key, string>;
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export const colors = ['white', 'black'];
|
|
2
|
+
export const roles = ['pawn', 'knight', 'bishop', 'rook', 'queen', 'king'];
|
|
3
|
+
export const files = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'];
|
|
4
|
+
export const ranks = ['1', '2', '3', '4', '5', '6', '7', '8'];
|
|
5
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAoGA,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,OAAO,EAAE,OAAO,CAAU,CAAC;AAClD,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAU,CAAC;AACpF,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAU,CAAC;AACvE,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAU,CAAC"}
|
package/dist/util.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as cg from './types.js';
|
|
2
|
+
export declare const invRanks: readonly cg.Rank[];
|
|
3
|
+
export declare const allKeys: readonly cg.Key[];
|
|
4
|
+
export declare const pos2key: (pos: cg.Pos) => cg.Key;
|
|
5
|
+
export declare const key2pos: (k: cg.Key) => cg.Pos;
|
|
6
|
+
export declare const uciToMove: (uci: string | undefined) => cg.Key[] | undefined;
|
|
7
|
+
export declare const allPos: readonly cg.Pos[];
|
|
8
|
+
export declare function memo<A>(f: () => A): cg.Memo<A>;
|
|
9
|
+
export declare const timer: () => cg.Timer;
|
|
10
|
+
export declare const opposite: (c: cg.Color) => cg.Color;
|
|
11
|
+
export declare const distanceSq: (pos1: cg.Pos, pos2: cg.Pos) => number;
|
|
12
|
+
export declare const samePiece: (p1: cg.Piece, p2: cg.Piece) => boolean;
|
|
13
|
+
export declare const posToTranslate: (bounds: DOMRectReadOnly) => ((pos: cg.Pos, asWhite: boolean) => cg.NumberPair);
|
|
14
|
+
export declare const translate: (el: HTMLElement, pos: cg.NumberPair) => void;
|
|
15
|
+
export declare const translateAndScale: (el: HTMLElement, pos: cg.NumberPair, scale?: number) => void;
|
|
16
|
+
export declare const setVisible: (el: HTMLElement, v: boolean) => void;
|
|
17
|
+
export declare const eventPosition: (e: cg.MouchEvent) => cg.NumberPair | undefined;
|
|
18
|
+
export declare const isRightButton: (e: cg.MouchEvent) => boolean;
|
|
19
|
+
export declare const createEl: (tagName: string, className?: string) => HTMLElement;
|
|
20
|
+
export declare function computeSquareCenter(key: cg.Key, asWhite: boolean, bounds: DOMRectReadOnly): cg.NumberPair;
|
package/dist/util.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import * as cg from './types.js';
|
|
2
|
+
export const invRanks = [...cg.ranks].reverse();
|
|
3
|
+
export const allKeys = Array.prototype.concat(...cg.files.map(c => cg.ranks.map(r => c + r)));
|
|
4
|
+
export const pos2key = (pos) => allKeys[8 * pos[0] + pos[1]];
|
|
5
|
+
export const key2pos = (k) => [k.charCodeAt(0) - 97, k.charCodeAt(1) - 49];
|
|
6
|
+
export const uciToMove = (uci) => {
|
|
7
|
+
if (!uci)
|
|
8
|
+
return undefined;
|
|
9
|
+
if (uci[1] === '@')
|
|
10
|
+
return [uci.slice(2, 4)];
|
|
11
|
+
return [uci.slice(0, 2), uci.slice(2, 4)];
|
|
12
|
+
};
|
|
13
|
+
export const allPos = allKeys.map(key2pos);
|
|
14
|
+
export function memo(f) {
|
|
15
|
+
let v;
|
|
16
|
+
const ret = () => {
|
|
17
|
+
if (v === undefined)
|
|
18
|
+
v = f();
|
|
19
|
+
return v;
|
|
20
|
+
};
|
|
21
|
+
ret.clear = () => {
|
|
22
|
+
v = undefined;
|
|
23
|
+
};
|
|
24
|
+
return ret;
|
|
25
|
+
}
|
|
26
|
+
export const timer = () => {
|
|
27
|
+
let startAt;
|
|
28
|
+
return {
|
|
29
|
+
start() {
|
|
30
|
+
startAt = performance.now();
|
|
31
|
+
},
|
|
32
|
+
cancel() {
|
|
33
|
+
startAt = undefined;
|
|
34
|
+
},
|
|
35
|
+
stop() {
|
|
36
|
+
if (!startAt)
|
|
37
|
+
return 0;
|
|
38
|
+
const time = performance.now() - startAt;
|
|
39
|
+
startAt = undefined;
|
|
40
|
+
return time;
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
export const opposite = (c) => (c === 'white' ? 'black' : 'white');
|
|
45
|
+
export const distanceSq = (pos1, pos2) => {
|
|
46
|
+
const dx = pos1[0] - pos2[0], dy = pos1[1] - pos2[1];
|
|
47
|
+
return dx * dx + dy * dy;
|
|
48
|
+
};
|
|
49
|
+
export const samePiece = (p1, p2) => p1.role === p2.role && p1.color === p2.color;
|
|
50
|
+
export const posToTranslate = (bounds) => (pos, asWhite) => [
|
|
51
|
+
((asWhite ? pos[0] : 7 - pos[0]) * bounds.width) / 8,
|
|
52
|
+
((asWhite ? 7 - pos[1] : pos[1]) * bounds.height) / 8,
|
|
53
|
+
];
|
|
54
|
+
export const translate = (el, pos) => {
|
|
55
|
+
el.style.transform = `translate(${pos[0]}px,${pos[1]}px)`;
|
|
56
|
+
};
|
|
57
|
+
export const translateAndScale = (el, pos, scale = 1) => {
|
|
58
|
+
el.style.transform = `translate(${pos[0]}px,${pos[1]}px) scale(${scale})`;
|
|
59
|
+
};
|
|
60
|
+
export const setVisible = (el, v) => {
|
|
61
|
+
el.style.visibility = v ? 'visible' : 'hidden';
|
|
62
|
+
};
|
|
63
|
+
export const eventPosition = (e) => {
|
|
64
|
+
var _a;
|
|
65
|
+
if (e.clientX || e.clientX === 0)
|
|
66
|
+
return [e.clientX, e.clientY];
|
|
67
|
+
if ((_a = e.targetTouches) === null || _a === void 0 ? void 0 : _a[0])
|
|
68
|
+
return [e.targetTouches[0].clientX, e.targetTouches[0].clientY];
|
|
69
|
+
return; // touchend has no position!
|
|
70
|
+
};
|
|
71
|
+
export const isRightButton = (e) => e.button === 2;
|
|
72
|
+
export const createEl = (tagName, className) => {
|
|
73
|
+
const el = document.createElement(tagName);
|
|
74
|
+
if (className)
|
|
75
|
+
el.className = className;
|
|
76
|
+
return el;
|
|
77
|
+
};
|
|
78
|
+
export function computeSquareCenter(key, asWhite, bounds) {
|
|
79
|
+
const pos = key2pos(key);
|
|
80
|
+
if (!asWhite) {
|
|
81
|
+
pos[0] = 7 - pos[0];
|
|
82
|
+
pos[1] = 7 - pos[1];
|
|
83
|
+
}
|
|
84
|
+
return [
|
|
85
|
+
bounds.left + (bounds.width * pos[0]) / 8 + bounds.width / 16,
|
|
86
|
+
bounds.top + (bounds.height * (7 - pos[1])) / 8 + bounds.height / 16,
|
|
87
|
+
];
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=util.js.map
|
package/dist/util.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"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"}
|
package/dist/wrap.d.ts
ADDED
package/dist/wrap.js
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { setVisible, createEl } from './util.js';
|
|
2
|
+
import { colors, files, ranks } from './types.js';
|
|
3
|
+
import { createElement as createSVG, setAttributes, createDefs } from './svg.js';
|
|
4
|
+
export function renderWrap(element, s) {
|
|
5
|
+
// .cg-wrap (element passed to Chessground)
|
|
6
|
+
// cg-container
|
|
7
|
+
// cg-board
|
|
8
|
+
// svg.cg-shapes
|
|
9
|
+
// defs
|
|
10
|
+
// g
|
|
11
|
+
// svg.cg-custom-svgs
|
|
12
|
+
// g
|
|
13
|
+
// cg-auto-pieces
|
|
14
|
+
// coords.ranks
|
|
15
|
+
// coords.files
|
|
16
|
+
// piece.ghost
|
|
17
|
+
element.innerHTML = '';
|
|
18
|
+
// ensure the cg-wrap class is set
|
|
19
|
+
// so bounds calculation can use the CSS width/height values
|
|
20
|
+
// add that class yourself to the element before calling chessground
|
|
21
|
+
// for a slight performance improvement! (avoids recomputing style)
|
|
22
|
+
element.classList.add('cg-wrap');
|
|
23
|
+
for (const c of colors)
|
|
24
|
+
element.classList.toggle('orientation-' + c, s.orientation === c);
|
|
25
|
+
element.classList.toggle('manipulable', !s.viewOnly);
|
|
26
|
+
const container = createEl('cg-container');
|
|
27
|
+
element.appendChild(container);
|
|
28
|
+
const board = createEl('cg-board');
|
|
29
|
+
container.appendChild(board);
|
|
30
|
+
let svg;
|
|
31
|
+
let customSvg;
|
|
32
|
+
let autoPieces;
|
|
33
|
+
if (s.drawable.visible) {
|
|
34
|
+
svg = setAttributes(createSVG('svg'), {
|
|
35
|
+
class: 'cg-shapes',
|
|
36
|
+
viewBox: '-4 -4 8 8',
|
|
37
|
+
preserveAspectRatio: 'xMidYMid slice',
|
|
38
|
+
});
|
|
39
|
+
svg.appendChild(createDefs());
|
|
40
|
+
svg.appendChild(createSVG('g'));
|
|
41
|
+
customSvg = setAttributes(createSVG('svg'), {
|
|
42
|
+
class: 'cg-custom-svgs',
|
|
43
|
+
viewBox: '-3.5 -3.5 8 8',
|
|
44
|
+
preserveAspectRatio: 'xMidYMid slice',
|
|
45
|
+
});
|
|
46
|
+
customSvg.appendChild(createSVG('g'));
|
|
47
|
+
autoPieces = createEl('cg-auto-pieces');
|
|
48
|
+
container.appendChild(svg);
|
|
49
|
+
container.appendChild(customSvg);
|
|
50
|
+
container.appendChild(autoPieces);
|
|
51
|
+
}
|
|
52
|
+
if (s.coordinates) {
|
|
53
|
+
const orientClass = s.orientation === 'black' ? ' black' : '';
|
|
54
|
+
const ranksPositionClass = s.ranksPosition === 'left' ? ' left' : '';
|
|
55
|
+
if (s.coordinatesOnSquares) {
|
|
56
|
+
const rankN = s.orientation === 'white' ? i => i + 1 : i => 8 - i;
|
|
57
|
+
files.forEach((f, i) => container.appendChild(renderCoords(ranks.map(r => f + r), 'squares rank' + rankN(i) + orientClass + ranksPositionClass)));
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
container.appendChild(renderCoords(ranks, 'ranks' + orientClass + ranksPositionClass));
|
|
61
|
+
container.appendChild(renderCoords(files, 'files' + orientClass));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
let ghost;
|
|
65
|
+
if (s.draggable.enabled && s.draggable.showGhost) {
|
|
66
|
+
ghost = createEl('piece', 'ghost');
|
|
67
|
+
setVisible(ghost, false);
|
|
68
|
+
container.appendChild(ghost);
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
board,
|
|
72
|
+
container,
|
|
73
|
+
wrap: element,
|
|
74
|
+
ghost,
|
|
75
|
+
svg,
|
|
76
|
+
customSvg,
|
|
77
|
+
autoPieces,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
function renderCoords(elems, className) {
|
|
81
|
+
const el = createEl('coords', className);
|
|
82
|
+
let f;
|
|
83
|
+
for (const elem of elems) {
|
|
84
|
+
f = createEl('coord');
|
|
85
|
+
f.textContent = elem;
|
|
86
|
+
el.appendChild(f);
|
|
87
|
+
}
|
|
88
|
+
return el;
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=wrap.js.map
|
package/dist/wrap.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wrap.js","sourceRoot":"","sources":["../src/wrap.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lichess-org/chessground",
|
|
3
|
+
"version": "9.2.3",
|
|
4
|
+
"description": "lichess.org chess ui",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/chessground.js",
|
|
7
|
+
"types": "chessground.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": "./dist/chessground.js",
|
|
10
|
+
"./assets/*": "./assets/*",
|
|
11
|
+
"./*": "./dist/*.js"
|
|
12
|
+
},
|
|
13
|
+
"typesVersions": {
|
|
14
|
+
"*": {
|
|
15
|
+
"*": [
|
|
16
|
+
"dist/*"
|
|
17
|
+
]
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@typescript-eslint/eslint-plugin": "^7.7.0",
|
|
22
|
+
"@typescript-eslint/parser": "^7.7.0",
|
|
23
|
+
"esbuild": "^0.25.0",
|
|
24
|
+
"eslint": "^8.57.0",
|
|
25
|
+
"prettier": "^3.2.5",
|
|
26
|
+
"typescript": "^5.6.3"
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"/dist/*.js",
|
|
30
|
+
"/dist/*.d.ts",
|
|
31
|
+
"/dist/*.js.map",
|
|
32
|
+
"/assets/*.css",
|
|
33
|
+
"/src/*.ts"
|
|
34
|
+
],
|
|
35
|
+
"repository": "https://github.com/lichess-org/chessground",
|
|
36
|
+
"keywords": [
|
|
37
|
+
"chess",
|
|
38
|
+
"lichess",
|
|
39
|
+
"lichess.org",
|
|
40
|
+
"chessboard",
|
|
41
|
+
"ui",
|
|
42
|
+
"typescript"
|
|
43
|
+
],
|
|
44
|
+
"author": "Lichess Team <contact@lichess.org>",
|
|
45
|
+
"license": "GPL-3.0-or-later",
|
|
46
|
+
"bugs": {
|
|
47
|
+
"url": "https://github.com/lichess-org/chessground/issues"
|
|
48
|
+
},
|
|
49
|
+
"funding": "https://lichess.org/patron",
|
|
50
|
+
"scripts": {
|
|
51
|
+
"compile": "tsc --sourceMap --declaration",
|
|
52
|
+
"lint": "eslint src/*.ts",
|
|
53
|
+
"format": "prettier --write .",
|
|
54
|
+
"check-format": "prettier --check .",
|
|
55
|
+
"bundle": "esbuild src/chessground.ts --bundle --format=esm --outfile=dist/chessground.min.js --minify",
|
|
56
|
+
"dist": "$npm_execpath run compile && $npm_execpath run bundle"
|
|
57
|
+
}
|
|
58
|
+
}
|
package/src/anim.ts
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { State } from './state.js';
|
|
2
|
+
import * as util from './util.js';
|
|
3
|
+
import * as cg from './types.js';
|
|
4
|
+
|
|
5
|
+
export type Mutation<A> = (state: State) => A;
|
|
6
|
+
|
|
7
|
+
// 0,1 animation goal
|
|
8
|
+
// 2,3 animation current status
|
|
9
|
+
export type AnimVector = cg.NumberQuad;
|
|
10
|
+
|
|
11
|
+
export type AnimVectors = Map<cg.Key, AnimVector>;
|
|
12
|
+
|
|
13
|
+
export type AnimFadings = Map<cg.Key, cg.Piece>;
|
|
14
|
+
|
|
15
|
+
export interface AnimPlan {
|
|
16
|
+
anims: AnimVectors;
|
|
17
|
+
fadings: AnimFadings;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface AnimCurrent {
|
|
21
|
+
start: DOMHighResTimeStamp;
|
|
22
|
+
frequency: cg.KHz;
|
|
23
|
+
plan: AnimPlan;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const anim = <A>(mutation: Mutation<A>, state: State): A =>
|
|
27
|
+
state.animation.enabled ? animate(mutation, state) : render(mutation, state);
|
|
28
|
+
|
|
29
|
+
export function render<A>(mutation: Mutation<A>, state: State): A {
|
|
30
|
+
const result = mutation(state);
|
|
31
|
+
state.dom.redraw();
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
interface AnimPiece {
|
|
36
|
+
key: cg.Key;
|
|
37
|
+
pos: cg.Pos;
|
|
38
|
+
piece: cg.Piece;
|
|
39
|
+
}
|
|
40
|
+
type AnimPieces = Map<cg.Key, AnimPiece>;
|
|
41
|
+
|
|
42
|
+
const makePiece = (key: cg.Key, piece: cg.Piece): AnimPiece => ({
|
|
43
|
+
key: key,
|
|
44
|
+
pos: util.key2pos(key),
|
|
45
|
+
piece: piece,
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const closer = (piece: AnimPiece, pieces: AnimPiece[]): AnimPiece | undefined =>
|
|
49
|
+
pieces.sort((p1, p2) => util.distanceSq(piece.pos, p1.pos) - util.distanceSq(piece.pos, p2.pos))[0];
|
|
50
|
+
|
|
51
|
+
function computePlan(prevPieces: cg.Pieces, current: State): AnimPlan {
|
|
52
|
+
const anims: AnimVectors = new Map(),
|
|
53
|
+
animedOrigs: cg.Key[] = [],
|
|
54
|
+
fadings: AnimFadings = new Map(),
|
|
55
|
+
missings: AnimPiece[] = [],
|
|
56
|
+
news: AnimPiece[] = [],
|
|
57
|
+
prePieces: AnimPieces = new Map();
|
|
58
|
+
let curP: cg.Piece | undefined, preP: AnimPiece | undefined, vector: cg.NumberPair;
|
|
59
|
+
for (const [k, p] of prevPieces) {
|
|
60
|
+
prePieces.set(k, makePiece(k, p));
|
|
61
|
+
}
|
|
62
|
+
for (const key of util.allKeys) {
|
|
63
|
+
curP = current.pieces.get(key);
|
|
64
|
+
preP = prePieces.get(key);
|
|
65
|
+
if (curP) {
|
|
66
|
+
if (preP) {
|
|
67
|
+
if (!util.samePiece(curP, preP.piece)) {
|
|
68
|
+
missings.push(preP);
|
|
69
|
+
news.push(makePiece(key, curP));
|
|
70
|
+
}
|
|
71
|
+
} else news.push(makePiece(key, curP));
|
|
72
|
+
} else if (preP) missings.push(preP);
|
|
73
|
+
}
|
|
74
|
+
for (const newP of news) {
|
|
75
|
+
preP = closer(
|
|
76
|
+
newP,
|
|
77
|
+
missings.filter(p => util.samePiece(newP.piece, p.piece)),
|
|
78
|
+
);
|
|
79
|
+
if (preP) {
|
|
80
|
+
vector = [preP.pos[0] - newP.pos[0], preP.pos[1] - newP.pos[1]];
|
|
81
|
+
anims.set(newP.key, vector.concat(vector) as AnimVector);
|
|
82
|
+
animedOrigs.push(preP.key);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
for (const p of missings) {
|
|
86
|
+
if (!animedOrigs.includes(p.key)) fadings.set(p.key, p.piece);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
anims: anims,
|
|
91
|
+
fadings: fadings,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function step(state: State, now: DOMHighResTimeStamp): void {
|
|
96
|
+
const cur = state.animation.current;
|
|
97
|
+
if (cur === undefined) {
|
|
98
|
+
// animation was canceled :(
|
|
99
|
+
if (!state.dom.destroyed) state.dom.redrawNow();
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
const rest = 1 - (now - cur.start) * cur.frequency;
|
|
103
|
+
if (rest <= 0) {
|
|
104
|
+
state.animation.current = undefined;
|
|
105
|
+
state.dom.redrawNow();
|
|
106
|
+
} else {
|
|
107
|
+
const ease = easing(rest);
|
|
108
|
+
for (const cfg of cur.plan.anims.values()) {
|
|
109
|
+
cfg[2] = cfg[0] * ease;
|
|
110
|
+
cfg[3] = cfg[1] * ease;
|
|
111
|
+
}
|
|
112
|
+
state.dom.redrawNow(true); // optimisation: don't render SVG changes during animations
|
|
113
|
+
requestAnimationFrame((now = performance.now()) => step(state, now));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function animate<A>(mutation: Mutation<A>, state: State): A {
|
|
118
|
+
// clone state before mutating it
|
|
119
|
+
const prevPieces: cg.Pieces = new Map(state.pieces);
|
|
120
|
+
|
|
121
|
+
const result = mutation(state);
|
|
122
|
+
const plan = computePlan(prevPieces, state);
|
|
123
|
+
if (plan.anims.size || plan.fadings.size) {
|
|
124
|
+
const alreadyRunning = state.animation.current && state.animation.current.start;
|
|
125
|
+
state.animation.current = {
|
|
126
|
+
start: performance.now(),
|
|
127
|
+
frequency: 1 / state.animation.duration,
|
|
128
|
+
plan: plan,
|
|
129
|
+
};
|
|
130
|
+
if (!alreadyRunning) step(state, performance.now());
|
|
131
|
+
} else {
|
|
132
|
+
// don't animate, just render right away
|
|
133
|
+
state.dom.redraw();
|
|
134
|
+
}
|
|
135
|
+
return result;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// https://gist.github.com/gre/1650294
|
|
139
|
+
const easing = (t: number): number => (t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1);
|