gigaboard 1.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 +21 -0
- package/README.md +27 -0
- package/dist/board-model-BvJOtwQ3.d.cts +675 -0
- package/dist/board-model-BvJOtwQ3.d.ts +675 -0
- package/dist/canvas.cjs +8 -0
- package/dist/canvas.cjs.map +1 -0
- package/dist/canvas.d.cts +14 -0
- package/dist/canvas.d.ts +14 -0
- package/dist/canvas.js +6 -0
- package/dist/canvas.js.map +1 -0
- package/dist/chunk-3HNIF4ZE.js +3 -0
- package/dist/chunk-3HNIF4ZE.js.map +1 -0
- package/dist/chunk-44YKPXXT.js +63 -0
- package/dist/chunk-44YKPXXT.js.map +1 -0
- package/dist/chunk-5WAOEWKS.js +16 -0
- package/dist/chunk-5WAOEWKS.js.map +1 -0
- package/dist/chunk-AYVQCHSG.cjs +10 -0
- package/dist/chunk-AYVQCHSG.cjs.map +1 -0
- package/dist/chunk-B26QLI2K.cjs +18 -0
- package/dist/chunk-B26QLI2K.cjs.map +1 -0
- package/dist/chunk-B2TBDDJN.cjs +10 -0
- package/dist/chunk-B2TBDDJN.cjs.map +1 -0
- package/dist/chunk-BFN5JI3T.js +8 -0
- package/dist/chunk-BFN5JI3T.js.map +1 -0
- package/dist/chunk-BWNBPN3P.cjs +10 -0
- package/dist/chunk-BWNBPN3P.cjs.map +1 -0
- package/dist/chunk-CXDGJMYL.js +105 -0
- package/dist/chunk-CXDGJMYL.js.map +1 -0
- package/dist/chunk-EOSX5UX3.js +8 -0
- package/dist/chunk-EOSX5UX3.js.map +1 -0
- package/dist/chunk-FNRS6YJI.cjs +67 -0
- package/dist/chunk-FNRS6YJI.cjs.map +1 -0
- package/dist/chunk-G6ZFOJZR.cjs +18 -0
- package/dist/chunk-G6ZFOJZR.cjs.map +1 -0
- package/dist/chunk-HSMILJKQ.cjs +18 -0
- package/dist/chunk-HSMILJKQ.cjs.map +1 -0
- package/dist/chunk-I4BQGFP5.cjs +113 -0
- package/dist/chunk-I4BQGFP5.cjs.map +1 -0
- package/dist/chunk-J6GGNP5S.js +1104 -0
- package/dist/chunk-J6GGNP5S.js.map +1 -0
- package/dist/chunk-JQSBAWIZ.cjs +4 -0
- package/dist/chunk-JQSBAWIZ.cjs.map +1 -0
- package/dist/chunk-KW56FEBY.js +8 -0
- package/dist/chunk-KW56FEBY.js.map +1 -0
- package/dist/chunk-N7ED2MZS.cjs +10 -0
- package/dist/chunk-N7ED2MZS.cjs.map +1 -0
- package/dist/chunk-NAA5O4BT.js +16 -0
- package/dist/chunk-NAA5O4BT.js.map +1 -0
- package/dist/chunk-OQLY5GJF.js +16 -0
- package/dist/chunk-OQLY5GJF.js.map +1 -0
- package/dist/chunk-P72B3YTG.js +16 -0
- package/dist/chunk-P72B3YTG.js.map +1 -0
- package/dist/chunk-U6WAD322.js +8 -0
- package/dist/chunk-U6WAD322.js.map +1 -0
- package/dist/chunk-UUTEFNFO.cjs +1148 -0
- package/dist/chunk-UUTEFNFO.cjs.map +1 -0
- package/dist/chunk-VYSVIIZA.cjs +18 -0
- package/dist/chunk-VYSVIIZA.cjs.map +1 -0
- package/dist/core.cjs +180 -0
- package/dist/core.cjs.map +1 -0
- package/dist/core.d.cts +164 -0
- package/dist/core.d.ts +164 -0
- package/dist/core.js +3 -0
- package/dist/core.js.map +1 -0
- package/dist/create-image-piece-set-BcmRKGql.d.cts +100 -0
- package/dist/create-image-piece-set-BcmRKGql.d.ts +100 -0
- package/dist/gigachess-3BDD--yT.d.cts +22 -0
- package/dist/gigachess-DolQlR82.d.ts +22 -0
- package/dist/index.cjs +2972 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +435 -0
- package/dist/index.d.ts +435 -0
- package/dist/index.js +2898 -0
- package/dist/index.js.map +1 -0
- package/dist/pieces/alpha.cjs +13 -0
- package/dist/pieces/alpha.cjs.map +1 -0
- package/dist/pieces/alpha.d.cts +17 -0
- package/dist/pieces/alpha.d.ts +17 -0
- package/dist/pieces/alpha.js +4 -0
- package/dist/pieces/alpha.js.map +1 -0
- package/dist/pieces/cburnett.cjs +13 -0
- package/dist/pieces/cburnett.cjs.map +1 -0
- package/dist/pieces/cburnett.d.cts +19 -0
- package/dist/pieces/cburnett.d.ts +19 -0
- package/dist/pieces/cburnett.js +4 -0
- package/dist/pieces/cburnett.js.map +1 -0
- package/dist/pieces/chesscom.cjs +14 -0
- package/dist/pieces/chesscom.cjs.map +1 -0
- package/dist/pieces/chesscom.d.cts +3 -0
- package/dist/pieces/chesscom.d.ts +3 -0
- package/dist/pieces/chesscom.js +5 -0
- package/dist/pieces/chesscom.js.map +1 -0
- package/dist/pieces/merida.cjs +13 -0
- package/dist/pieces/merida.cjs.map +1 -0
- package/dist/pieces/merida.d.cts +17 -0
- package/dist/pieces/merida.d.ts +17 -0
- package/dist/pieces/merida.js +4 -0
- package/dist/pieces/merida.js.map +1 -0
- package/dist/pieces/neo.cjs +13 -0
- package/dist/pieces/neo.cjs.map +1 -0
- package/dist/pieces/neo.d.cts +18 -0
- package/dist/pieces/neo.d.ts +18 -0
- package/dist/pieces/neo.js +4 -0
- package/dist/pieces/neo.js.map +1 -0
- package/dist/pieces.cjs +55 -0
- package/dist/pieces.cjs.map +1 -0
- package/dist/pieces.d.cts +21 -0
- package/dist/pieces.d.ts +21 -0
- package/dist/pieces.js +24 -0
- package/dist/pieces.js.map +1 -0
- package/dist/server.cjs +207 -0
- package/dist/server.cjs.map +1 -0
- package/dist/server.d.cts +60 -0
- package/dist/server.d.ts +60 -0
- package/dist/server.js +205 -0
- package/dist/server.js.map +1 -0
- package/dist/sounds/capture.mp3 +0 -0
- package/dist/sounds/castle.mp3 +0 -0
- package/dist/sounds/game-end.mp3 +0 -0
- package/dist/sounds/move-check.mp3 +0 -0
- package/dist/sounds/move-opponent.mp3 +0 -0
- package/dist/sounds/move-self.mp3 +0 -0
- package/dist/sounds/promote.mp3 +0 -0
- package/dist/themes/blue.cjs +12 -0
- package/dist/themes/blue.cjs.map +1 -0
- package/dist/themes/blue.d.cts +102 -0
- package/dist/themes/blue.d.ts +102 -0
- package/dist/themes/blue.js +3 -0
- package/dist/themes/blue.js.map +1 -0
- package/dist/themes/brown.cjs +12 -0
- package/dist/themes/brown.cjs.map +1 -0
- package/dist/themes/brown.d.cts +1 -0
- package/dist/themes/brown.d.ts +1 -0
- package/dist/themes/brown.js +3 -0
- package/dist/themes/brown.js.map +1 -0
- package/dist/themes/green.cjs +12 -0
- package/dist/themes/green.cjs.map +1 -0
- package/dist/themes/green.d.cts +1 -0
- package/dist/themes/green.d.ts +1 -0
- package/dist/themes/green.js +3 -0
- package/dist/themes/green.js.map +1 -0
- package/dist/themes/wood.cjs +12 -0
- package/dist/themes/wood.cjs.map +1 -0
- package/dist/themes/wood.d.cts +1 -0
- package/dist/themes/wood.d.ts +1 -0
- package/dist/themes/wood.js +3 -0
- package/dist/themes/wood.js.map +1 -0
- package/dist/themes.cjs +36 -0
- package/dist/themes.cjs.map +1 -0
- package/dist/themes.d.cts +1 -0
- package/dist/themes.d.ts +1 -0
- package/dist/themes.js +21 -0
- package/dist/themes.js.map +1 -0
- package/dist/types-Bg2xiUHE.d.cts +501 -0
- package/dist/types-D5eBJGzj.d.ts +501 -0
- package/package.json +210 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* gigaboard/canvas — opt-in full-canvas renderer.
|
|
3
|
+
*
|
|
4
|
+
* For stress use cases: very large boards (fairy chess), many simultaneous arrows,
|
|
5
|
+
* or low-end devices where per-square DOM nodes become a cost. Drops some DOM
|
|
6
|
+
* superpowers (ARIA grid, CSS theming of individual squares, `renderSquare` escape
|
|
7
|
+
* hatches). The default DOM renderer is recommended for almost all applications.
|
|
8
|
+
*
|
|
9
|
+
* @remarks
|
|
10
|
+
* Lands in M8 (post-1.0). This is a scaffolding placeholder.
|
|
11
|
+
*/
|
|
12
|
+
declare const CANVAS_RENDERER_VERSION = "0.0.0";
|
|
13
|
+
|
|
14
|
+
export { CANVAS_RENDERER_VERSION };
|
package/dist/canvas.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* gigaboard/canvas — opt-in full-canvas renderer.
|
|
3
|
+
*
|
|
4
|
+
* For stress use cases: very large boards (fairy chess), many simultaneous arrows,
|
|
5
|
+
* or low-end devices where per-square DOM nodes become a cost. Drops some DOM
|
|
6
|
+
* superpowers (ARIA grid, CSS theming of individual squares, `renderSquare` escape
|
|
7
|
+
* hatches). The default DOM renderer is recommended for almost all applications.
|
|
8
|
+
*
|
|
9
|
+
* @remarks
|
|
10
|
+
* Lands in M8 (post-1.0). This is a scaffolding placeholder.
|
|
11
|
+
*/
|
|
12
|
+
declare const CANVAS_RENDERER_VERSION = "0.0.0";
|
|
13
|
+
|
|
14
|
+
export { CANVAS_RENDERER_VERSION };
|
package/dist/canvas.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/renderers/canvas.ts"],"names":[],"mappings":";AAYO,IAAM,uBAAA,GAA0B","file":"canvas.js","sourcesContent":["/**\n * gigaboard/canvas — opt-in full-canvas renderer.\n *\n * For stress use cases: very large boards (fairy chess), many simultaneous arrows,\n * or low-end devices where per-square DOM nodes become a cost. Drops some DOM\n * superpowers (ARIA grid, CSS theming of individual squares, `renderSquare` escape\n * hatches). The default DOM renderer is recommended for almost all applications.\n *\n * @remarks\n * Lands in M8 (post-1.0). This is a scaffolding placeholder.\n */\n\nexport const CANVAS_RENDERER_VERSION = \"0.0.0\";\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-3HNIF4ZE.js"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
// src/pieces/create-image-piece-set.tsx
|
|
4
|
+
var BOARD_CELL_KEY = Object.freeze({
|
|
5
|
+
wP: 1,
|
|
6
|
+
wN: 2,
|
|
7
|
+
wB: 3,
|
|
8
|
+
wR: 4,
|
|
9
|
+
wQ: 5,
|
|
10
|
+
wK: 6,
|
|
11
|
+
bP: 7,
|
|
12
|
+
bN: 8,
|
|
13
|
+
bB: 9,
|
|
14
|
+
bR: 10,
|
|
15
|
+
bQ: 11,
|
|
16
|
+
bK: 12
|
|
17
|
+
});
|
|
18
|
+
function pieceLabel(cell) {
|
|
19
|
+
if (cell <= 0 || cell > 12) return "";
|
|
20
|
+
const color = cell > 6 ? "black" : "white";
|
|
21
|
+
const type = (cell - 1) % 6;
|
|
22
|
+
const name = ["pawn", "knight", "bishop", "rook", "queen", "king"][type];
|
|
23
|
+
return `${color} ${name}`;
|
|
24
|
+
}
|
|
25
|
+
var PIECE_IMG_STYLE = Object.freeze({
|
|
26
|
+
display: "block",
|
|
27
|
+
width: "100%",
|
|
28
|
+
height: "100%",
|
|
29
|
+
pointerEvents: "none",
|
|
30
|
+
userSelect: "none"
|
|
31
|
+
});
|
|
32
|
+
function createImagePieceSet(urls) {
|
|
33
|
+
const pool = new Array(13).fill(null);
|
|
34
|
+
for (let cell = 1; cell <= 12; cell++) {
|
|
35
|
+
const url = urls[cell];
|
|
36
|
+
if (url === void 0) continue;
|
|
37
|
+
pool[cell] = /* @__PURE__ */ jsx("img", { src: url, alt: pieceLabel(cell), draggable: false, style: PIECE_IMG_STYLE });
|
|
38
|
+
}
|
|
39
|
+
return function ImagePieceSet({ cell }) {
|
|
40
|
+
return pool[cell] ?? null;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function chesscomPieceUrls(style, size = 150) {
|
|
44
|
+
const base = `https://images.chesscomfiles.com/chess-themes/pieces/${style}/${size}`;
|
|
45
|
+
return Object.freeze({
|
|
46
|
+
1: `${base}/wp.png`,
|
|
47
|
+
2: `${base}/wn.png`,
|
|
48
|
+
3: `${base}/wb.png`,
|
|
49
|
+
4: `${base}/wr.png`,
|
|
50
|
+
5: `${base}/wq.png`,
|
|
51
|
+
6: `${base}/wk.png`,
|
|
52
|
+
7: `${base}/bp.png`,
|
|
53
|
+
8: `${base}/bn.png`,
|
|
54
|
+
9: `${base}/bb.png`,
|
|
55
|
+
10: `${base}/br.png`,
|
|
56
|
+
11: `${base}/bq.png`,
|
|
57
|
+
12: `${base}/bk.png`
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export { BOARD_CELL_KEY, chesscomPieceUrls, createImagePieceSet };
|
|
62
|
+
//# sourceMappingURL=chunk-44YKPXXT.js.map
|
|
63
|
+
//# sourceMappingURL=chunk-44YKPXXT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/pieces/create-image-piece-set.tsx"],"names":[],"mappings":"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","file":"chunk-44YKPXXT.js","sourcesContent":["/**\n * Shared piece-renderer factory.\n *\n * Every piece set shipped by `gigaboard/pieces` is a URL-based set — a\n * thin map from board-cell → image URL. This factory builds a memoised\n * {@link PieceRenderer} around such a map, so every set file is two lines\n * of configuration plus a URL table.\n *\n * ### Why images, not inline SVG?\n *\n * The React packages target <15 KB gzip. Shipping 12 detailed SVG paths\n * per set × 4 sets would blow that budget immediately. URL-based sets\n * push the bytes onto the browser's image cache, where the pieces are\n * decoded exactly once per session and shared across every board.\n *\n * ### Render cost\n *\n * One `<img>` per occupied square. The image is `pointer-events: none`\n * so it never intercepts drag/click; the piece layer on the board owns\n * hit testing. Each renderer is pure and does not allocate on the hot\n * path — the URL lookup is a constant-time array read.\n */\n\nimport type { ReactNode } from \"react\";\n\n/** Shape a consumer's `PieceRenderer` prop expects. */\nexport type PieceRenderer = (args: { readonly cell: number; readonly square: number }) => ReactNode;\n\n/**\n * 12-entry URL table, indexed by board cell `1..12`. Cell `0` is the\n * empty square and is never looked up. Use {@link BOARD_CELL_KEY} to\n * remember which index maps to which piece.\n */\nexport type PieceUrlTable = Readonly<{\n /** white pawn (cell 1) */ 1: string;\n /** white knight (cell 2) */ 2: string;\n /** white bishop (cell 3) */ 3: string;\n /** white rook (cell 4) */ 4: string;\n /** white queen (cell 5) */ 5: string;\n /** white king (cell 6) */ 6: string;\n /** black pawn (cell 7) */ 7: string;\n /** black knight (cell 8) */ 8: string;\n /** black bishop (cell 9) */ 9: string;\n /** black rook (cell 10) */ 10: string;\n /** black queen (cell 11) */ 11: string;\n /** black king (cell 12) */ 12: string;\n}>;\n\n/** Readable cell labels for the table — useful for callers building sets. */\nexport const BOARD_CELL_KEY = Object.freeze({\n wP: 1,\n wN: 2,\n wB: 3,\n wR: 4,\n wQ: 5,\n wK: 6,\n bP: 7,\n bN: 8,\n bB: 9,\n bR: 10,\n bQ: 11,\n bK: 12,\n} as const);\n\n/** Readable piece-name for `aria-label`, derived from a board cell. */\nfunction pieceLabel(cell: number): string {\n if (cell <= 0 || cell > 12) return \"\";\n const color = cell > 6 ? \"black\" : \"white\";\n const type = (cell - 1) % 6;\n const name = [\"pawn\", \"knight\", \"bishop\", \"rook\", \"queen\", \"king\"][type];\n return `${color} ${name}`;\n}\n\n/**\n * Shared style object for every `<img>` — frozen and re-used so React's\n * shallow-equality checks short-circuit and we don't allocate a fresh\n * object on every render.\n */\nconst PIECE_IMG_STYLE = Object.freeze({\n display: \"block\",\n width: \"100%\",\n height: \"100%\",\n pointerEvents: \"none\",\n userSelect: \"none\",\n} as const);\n\n/**\n * Build a {@link PieceRenderer} backed by a URL table. The returned\n * function is referentially stable AND allocates **zero** React elements\n * on the hot path: we pre-materialise one `<img>` element per piece\n * code at factory time and hand out the same element for every call with\n * the same cell.\n *\n * Why pre-materialise? The renderer is called inside `<PieceSlot/>` on\n * every move that touches its square. Returning a fresh React element\n * per call means React's reconciler has to shallow-diff the new element\n * against the last one to decide whether DOM changed. A pool of 12\n * frozen elements (one per piece code) bypasses that entirely — React\n * short-circuits on identity.\n */\nexport function createImagePieceSet(urls: PieceUrlTable): PieceRenderer {\n // Pre-materialise the 12 piece elements at factory time. `cell === 0`\n // (empty square) returns null; we don't allocate an element for it.\n const pool: Array<ReactNode | null> = new Array(13).fill(null);\n for (let cell = 1; cell <= 12; cell++) {\n const url = (urls as Record<number, string | undefined>)[cell];\n if (url === undefined) continue;\n pool[cell] = <img src={url} alt={pieceLabel(cell)} draggable={false} style={PIECE_IMG_STYLE} />;\n }\n return function ImagePieceSet({ cell }: { readonly cell: number }) {\n return pool[cell] ?? null;\n };\n}\n\n/**\n * Helper that builds a chess.com-style PNG CDN URL for a given piece style.\n *\n * chess.com serves piece artwork at:\n * `https://images.chesscomfiles.com/chess-themes/pieces/<style>/<size>/<colorPiece>.png`\n *\n * where `colorPiece` is one of `wp wn wb wr wq wk bp bn bb br bq bk`. The\n * `size` options are `150` (default), `300`, etc. We pin to 150 by default\n * because boards render at roughly that density on desktop, and larger\n * sizes inflate page weight without perceptible benefit.\n *\n * @param style chess.com piece-style slug. Known values include `neo`\n * (chess.com's default), `alpha`, `bases`, `cases`, `classic`,\n * `club`, `condal`, `graffiti`, `leipzig`, `marble`, `maya`,\n * `metal`, `modern`, `nature`, `neo_wood`, `newspaper`, `ocean`,\n * `sky`, `space`, `tournament`, `vintage`, `wood`.\n * @param size One of chess.com's supported pixel sizes (default 150).\n */\nexport function chesscomPieceUrls(style: string, size: 150 | 300 = 150): PieceUrlTable {\n const base = `https://images.chesscomfiles.com/chess-themes/pieces/${style}/${size}`;\n return Object.freeze({\n 1: `${base}/wp.png`,\n 2: `${base}/wn.png`,\n 3: `${base}/wb.png`,\n 4: `${base}/wr.png`,\n 5: `${base}/wq.png`,\n 6: `${base}/wk.png`,\n 7: `${base}/bp.png`,\n 8: `${base}/bn.png`,\n 9: `${base}/bb.png`,\n 10: `${base}/br.png`,\n 11: `${base}/bq.png`,\n 12: `${base}/bk.png`,\n });\n}\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// src/themes/brown.ts
|
|
2
|
+
var brown = Object.freeze({
|
|
3
|
+
"--gb-sq-light": "#f0d9b5",
|
|
4
|
+
"--gb-sq-dark": "#b58863",
|
|
5
|
+
"--gb-last-move": "rgba(155, 199, 0, 0.41)",
|
|
6
|
+
"--gb-selected": "rgba(20, 85, 30, 0.5)",
|
|
7
|
+
"--gb-legal-target": "rgba(0, 0, 0, 0.14)",
|
|
8
|
+
"--gb-legal-target-capture": "rgba(0, 0, 0, 0.3)",
|
|
9
|
+
"--gb-check": "radial-gradient(rgba(255, 0, 0, 0.55) 30%, rgba(255, 0, 0, 0) 80%)",
|
|
10
|
+
"--gb-coord-light": "#b58863",
|
|
11
|
+
"--gb-coord-dark": "#f0d9b5"
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
export { brown };
|
|
15
|
+
//# sourceMappingURL=chunk-5WAOEWKS.js.map
|
|
16
|
+
//# sourceMappingURL=chunk-5WAOEWKS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/themes/brown.ts"],"names":[],"mappings":";AAcO,IAAM,KAAA,GAAe,OAAO,MAAA,CAAO;AAAA,EACxC,eAAA,EAAiB,SAAA;AAAA,EACjB,cAAA,EAAgB,SAAA;AAAA,EAChB,gBAAA,EAAkB,yBAAA;AAAA,EAClB,eAAA,EAAiB,uBAAA;AAAA,EACjB,mBAAA,EAAqB,qBAAA;AAAA,EACrB,2BAAA,EAA6B,oBAAA;AAAA,EAC7B,YAAA,EAAc,oEAAA;AAAA,EACd,kBAAA,EAAoB,SAAA;AAAA,EACpB,iBAAA,EAAmB;AACrB,CAAC","file":"chunk-5WAOEWKS.js","sourcesContent":["/**\n * Brown theme — the classic lichess-inspired wood-tone board.\n *\n * CSS-variable-only. Import this theme and pass it as the `theme` prop on\n * `<Chessboard/>`:\n *\n * ```tsx\n * import { brown } from \"gigaboard/themes/brown\";\n * <Chessboard game={game} theme={brown} />\n * ```\n */\n\nimport type { Theme } from \"./index.js\";\n\nexport const brown: Theme = Object.freeze({\n \"--gb-sq-light\": \"#f0d9b5\",\n \"--gb-sq-dark\": \"#b58863\",\n \"--gb-last-move\": \"rgba(155, 199, 0, 0.41)\",\n \"--gb-selected\": \"rgba(20, 85, 30, 0.5)\",\n \"--gb-legal-target\": \"rgba(0, 0, 0, 0.14)\",\n \"--gb-legal-target-capture\": \"rgba(0, 0, 0, 0.3)\",\n \"--gb-check\": \"radial-gradient(rgba(255, 0, 0, 0.55) 30%, rgba(255, 0, 0, 0) 80%)\",\n \"--gb-coord-light\": \"#b58863\",\n \"--gb-coord-dark\": \"#f0d9b5\",\n});\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkFNRS6YJI_cjs = require('./chunk-FNRS6YJI.cjs');
|
|
4
|
+
|
|
5
|
+
// src/pieces/sets/neo.ts
|
|
6
|
+
var neo = chunkFNRS6YJI_cjs.createImagePieceSet(chunkFNRS6YJI_cjs.chesscomPieceUrls("neo"));
|
|
7
|
+
|
|
8
|
+
exports.neo = neo;
|
|
9
|
+
//# sourceMappingURL=chunk-AYVQCHSG.cjs.map
|
|
10
|
+
//# sourceMappingURL=chunk-AYVQCHSG.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/pieces/sets/neo.ts"],"names":["createImagePieceSet","chesscomPieceUrls"],"mappings":";;;;;AAeO,IAAM,GAAA,GAAMA,qCAAA,CAAoBC,mCAAA,CAAkB,KAAK,CAAC","file":"chunk-AYVQCHSG.cjs","sourcesContent":["/**\n * **Neo** — chess.com's default piece set.\n *\n * ```tsx\n * import { neo } from \"gigaboard/pieces/neo\";\n * <Chessboard game={game} pieces={neo} />\n * ```\n *\n * Sources its PNGs from chess.com's public piece CDN. Neo is the set\n * chess.com ships on every board by default, so this renderer delivers\n * the highest chess.com-visual-parity out of the box.\n */\n\nimport { chesscomPieceUrls, createImagePieceSet } from \"../create-image-piece-set.js\";\n\nexport const neo = createImagePieceSet(chesscomPieceUrls(\"neo\"));\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/themes/blue.ts
|
|
4
|
+
var blue = Object.freeze({
|
|
5
|
+
"--gb-sq-light": "#dee3e6",
|
|
6
|
+
"--gb-sq-dark": "#8ca2ad",
|
|
7
|
+
"--gb-last-move": "rgba(122, 178, 216, 0.5)",
|
|
8
|
+
"--gb-selected": "rgba(122, 178, 216, 0.65)",
|
|
9
|
+
"--gb-legal-target": "rgba(0, 0, 0, 0.14)",
|
|
10
|
+
"--gb-legal-target-capture": "rgba(0, 0, 0, 0.3)",
|
|
11
|
+
"--gb-check": "radial-gradient(rgba(255, 0, 0, 0.55) 30%, rgba(255, 0, 0, 0) 80%)",
|
|
12
|
+
"--gb-coord-light": "#8ca2ad",
|
|
13
|
+
"--gb-coord-dark": "#dee3e6"
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
exports.blue = blue;
|
|
17
|
+
//# sourceMappingURL=chunk-B26QLI2K.cjs.map
|
|
18
|
+
//# sourceMappingURL=chunk-B26QLI2K.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/themes/blue.ts"],"names":[],"mappings":";;;AAeO,IAAM,IAAA,GAAc,OAAO,MAAA,CAAO;AAAA,EACvC,eAAA,EAAiB,SAAA;AAAA,EACjB,cAAA,EAAgB,SAAA;AAAA,EAChB,gBAAA,EAAkB,0BAAA;AAAA,EAClB,eAAA,EAAiB,2BAAA;AAAA,EACjB,mBAAA,EAAqB,qBAAA;AAAA,EACrB,2BAAA,EAA6B,oBAAA;AAAA,EAC7B,YAAA,EAAc,oEAAA;AAAA,EACd,kBAAA,EAAoB,SAAA;AAAA,EACpB,iBAAA,EAAmB;AACrB,CAAC","file":"chunk-B26QLI2K.cjs","sourcesContent":["/**\n * Blue theme — chess.com's \"Blue\" board.\n *\n * Calm, high-contrast palette that reads well on bright monitors and\n * projector setups. Light square is near-white; dark square is a muted\n * steel blue.\n *\n * ```tsx\n * import { blue } from \"gigaboard/themes/blue\";\n * <Chessboard game={game} theme={blue} />\n * ```\n */\n\nimport type { Theme } from \"./index.js\";\n\nexport const blue: Theme = Object.freeze({\n \"--gb-sq-light\": \"#dee3e6\",\n \"--gb-sq-dark\": \"#8ca2ad\",\n \"--gb-last-move\": \"rgba(122, 178, 216, 0.5)\",\n \"--gb-selected\": \"rgba(122, 178, 216, 0.65)\",\n \"--gb-legal-target\": \"rgba(0, 0, 0, 0.14)\",\n \"--gb-legal-target-capture\": \"rgba(0, 0, 0, 0.3)\",\n \"--gb-check\": \"radial-gradient(rgba(255, 0, 0, 0.55) 30%, rgba(255, 0, 0, 0) 80%)\",\n \"--gb-coord-light\": \"#8ca2ad\",\n \"--gb-coord-dark\": \"#dee3e6\",\n});\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkFNRS6YJI_cjs = require('./chunk-FNRS6YJI.cjs');
|
|
4
|
+
|
|
5
|
+
// src/pieces/sets/alpha.ts
|
|
6
|
+
var alpha = chunkFNRS6YJI_cjs.createImagePieceSet(chunkFNRS6YJI_cjs.chesscomPieceUrls("alpha"));
|
|
7
|
+
|
|
8
|
+
exports.alpha = alpha;
|
|
9
|
+
//# sourceMappingURL=chunk-B2TBDDJN.cjs.map
|
|
10
|
+
//# sourceMappingURL=chunk-B2TBDDJN.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/pieces/sets/alpha.ts"],"names":["createImagePieceSet","chesscomPieceUrls"],"mappings":";;;;;AAcO,IAAM,KAAA,GAAQA,qCAAA,CAAoBC,mCAAA,CAAkB,OAAO,CAAC","file":"chunk-B2TBDDJN.cjs","sourcesContent":["/**\n * **Alpha** — chess.com's Alpha set.\n *\n * Thin, minimalist silhouettes; reads well at small sizes. Good fit for\n * mobile boards and puzzle thumbnails.\n *\n * ```tsx\n * import { alpha } from \"gigaboard/pieces/alpha\";\n * <Chessboard game={game} pieces={alpha} />\n * ```\n */\n\nimport { chesscomPieceUrls, createImagePieceSet } from \"../create-image-piece-set.js\";\n\nexport const alpha = createImagePieceSet(chesscomPieceUrls(\"alpha\"));\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { createImagePieceSet, chesscomPieceUrls } from './chunk-44YKPXXT.js';
|
|
2
|
+
|
|
3
|
+
// src/pieces/sets/alpha.ts
|
|
4
|
+
var alpha = createImagePieceSet(chesscomPieceUrls("alpha"));
|
|
5
|
+
|
|
6
|
+
export { alpha };
|
|
7
|
+
//# sourceMappingURL=chunk-BFN5JI3T.js.map
|
|
8
|
+
//# sourceMappingURL=chunk-BFN5JI3T.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/pieces/sets/alpha.ts"],"names":[],"mappings":";;;AAcO,IAAM,KAAA,GAAQ,mBAAA,CAAoB,iBAAA,CAAkB,OAAO,CAAC","file":"chunk-BFN5JI3T.js","sourcesContent":["/**\n * **Alpha** — chess.com's Alpha set.\n *\n * Thin, minimalist silhouettes; reads well at small sizes. Good fit for\n * mobile boards and puzzle thumbnails.\n *\n * ```tsx\n * import { alpha } from \"gigaboard/pieces/alpha\";\n * <Chessboard game={game} pieces={alpha} />\n * ```\n */\n\nimport { chesscomPieceUrls, createImagePieceSet } from \"../create-image-piece-set.js\";\n\nexport const alpha = createImagePieceSet(chesscomPieceUrls(\"alpha\"));\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkFNRS6YJI_cjs = require('./chunk-FNRS6YJI.cjs');
|
|
4
|
+
|
|
5
|
+
// src/pieces/sets/merida.ts
|
|
6
|
+
var merida = chunkFNRS6YJI_cjs.createImagePieceSet(chunkFNRS6YJI_cjs.chesscomPieceUrls("neo_wood"));
|
|
7
|
+
|
|
8
|
+
exports.merida = merida;
|
|
9
|
+
//# sourceMappingURL=chunk-BWNBPN3P.cjs.map
|
|
10
|
+
//# sourceMappingURL=chunk-BWNBPN3P.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/pieces/sets/merida.ts"],"names":["createImagePieceSet","chesscomPieceUrls"],"mappings":";;;;;AAcO,IAAM,MAAA,GAASA,qCAAA,CAAoBC,mCAAA,CAAkB,UAAU,CAAC","file":"chunk-BWNBPN3P.cjs","sourcesContent":["/**\n * **Merida** — chess.com's `neo_wood` set.\n *\n * Warm wood-tinted pieces with traditional proportions; visually closest\n * to the classic `merida` tournament set used in print publications.\n *\n * ```tsx\n * import { merida } from \"gigaboard/pieces/merida\";\n * <Chessboard game={game} pieces={merida} />\n * ```\n */\n\nimport { chesscomPieceUrls, createImagePieceSet } from \"../create-image-piece-set.js\";\n\nexport const merida = createImagePieceSet(chesscomPieceUrls(\"neo_wood\"));\n"]}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { green } from './chunk-OQLY5GJF.js';
|
|
2
|
+
import { neo } from './chunk-U6WAD322.js';
|
|
3
|
+
|
|
4
|
+
// src/default-theme.ts
|
|
5
|
+
var CSS_VARS = {
|
|
6
|
+
SQ_LIGHT: "--gb-sq-light",
|
|
7
|
+
SQ_DARK: "--gb-sq-dark",
|
|
8
|
+
LAST_MOVE: "--gb-last-move",
|
|
9
|
+
SELECTED: "--gb-selected",
|
|
10
|
+
LEGAL_TARGET: "--gb-legal-target",
|
|
11
|
+
LEGAL_TARGET_CAPTURE: "--gb-legal-target-capture",
|
|
12
|
+
CHECK: "--gb-check",
|
|
13
|
+
COORDINATE_LIGHT: "--gb-coord-light",
|
|
14
|
+
COORDINATE_DARK: "--gb-coord-dark",
|
|
15
|
+
/**
|
|
16
|
+
* Opacity of the piece left behind at the drag origin while the ghost
|
|
17
|
+
* is in flight. Default `0.35` (lichess parity). Themes may override
|
|
18
|
+
* to `0` for a chess.com-style "piece vanishes" effect.
|
|
19
|
+
*/
|
|
20
|
+
DRAG_GHOST_OPACITY: "--gb-drag-ghost-opacity"
|
|
21
|
+
};
|
|
22
|
+
var defaultTheme = Object.freeze({
|
|
23
|
+
...green,
|
|
24
|
+
[CSS_VARS.DRAG_GHOST_OPACITY]: "0.35"
|
|
25
|
+
});
|
|
26
|
+
var defaultArrowColors = Object.freeze({
|
|
27
|
+
default: "rgba(21, 120, 27, 0.8)",
|
|
28
|
+
shift: "rgba(153, 40, 40, 0.8)",
|
|
29
|
+
alt: "rgba(230, 160, 0, 0.8)",
|
|
30
|
+
ctrl: "rgba(0, 60, 130, 0.8)"
|
|
31
|
+
});
|
|
32
|
+
var DEFAULT_PREMOVE_TINT = "rgba(30, 98, 255, 0.4)";
|
|
33
|
+
var DEFAULT_ILLEGAL_FLASH_TINT = "rgba(220, 40, 40, 0.55)";
|
|
34
|
+
|
|
35
|
+
// src/fen.ts
|
|
36
|
+
function pieceCellFromFenChar(ch) {
|
|
37
|
+
switch (ch) {
|
|
38
|
+
case "P":
|
|
39
|
+
return 1;
|
|
40
|
+
case "N":
|
|
41
|
+
return 2;
|
|
42
|
+
case "B":
|
|
43
|
+
return 3;
|
|
44
|
+
case "R":
|
|
45
|
+
return 4;
|
|
46
|
+
case "Q":
|
|
47
|
+
return 5;
|
|
48
|
+
case "K":
|
|
49
|
+
return 6;
|
|
50
|
+
case "p":
|
|
51
|
+
return 7;
|
|
52
|
+
case "n":
|
|
53
|
+
return 8;
|
|
54
|
+
case "b":
|
|
55
|
+
return 9;
|
|
56
|
+
case "r":
|
|
57
|
+
return 10;
|
|
58
|
+
case "q":
|
|
59
|
+
return 11;
|
|
60
|
+
case "k":
|
|
61
|
+
return 12;
|
|
62
|
+
default:
|
|
63
|
+
return 0;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function parseFenPlacement(fen) {
|
|
67
|
+
const placement = fen.trim().split(/\s+/)[0];
|
|
68
|
+
if (placement === void 0) {
|
|
69
|
+
throw new Error("FEN is empty");
|
|
70
|
+
}
|
|
71
|
+
const ranks = placement.split("/");
|
|
72
|
+
if (ranks.length !== 8) {
|
|
73
|
+
throw new Error(`FEN must have 8 ranks, got ${ranks.length}`);
|
|
74
|
+
}
|
|
75
|
+
const board = new Uint8Array(64);
|
|
76
|
+
for (let r = 0; r < 8; r++) {
|
|
77
|
+
const rank = 7 - r;
|
|
78
|
+
const row = ranks[r];
|
|
79
|
+
if (row === void 0) throw new Error(`FEN rank ${rank + 1} missing`);
|
|
80
|
+
let file = 0;
|
|
81
|
+
for (const ch of row) {
|
|
82
|
+
if (file > 7) throw new Error(`FEN rank ${rank + 1} has too many files`);
|
|
83
|
+
const skip = Number.parseInt(ch, 10);
|
|
84
|
+
if (!Number.isNaN(skip)) {
|
|
85
|
+
file += skip;
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
const cell = pieceCellFromFenChar(ch);
|
|
89
|
+
if (cell === 0) throw new Error(`FEN contains unknown piece: ${ch}`);
|
|
90
|
+
board[rank * 8 + file] = cell;
|
|
91
|
+
file++;
|
|
92
|
+
}
|
|
93
|
+
if (file !== 8) {
|
|
94
|
+
throw new Error(`FEN rank ${rank + 1} ended at file ${file}, expected 8`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return board;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// src/pieces/default-pieces.tsx
|
|
101
|
+
var defaultPieces = neo;
|
|
102
|
+
|
|
103
|
+
export { CSS_VARS, DEFAULT_ILLEGAL_FLASH_TINT, DEFAULT_PREMOVE_TINT, defaultArrowColors, defaultPieces, defaultTheme, parseFenPlacement };
|
|
104
|
+
//# sourceMappingURL=chunk-CXDGJMYL.js.map
|
|
105
|
+
//# sourceMappingURL=chunk-CXDGJMYL.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/default-theme.ts","../src/fen.ts","../src/pieces/default-pieces.tsx"],"names":[],"mappings":"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","file":"chunk-CXDGJMYL.js","sourcesContent":["import { green } from \"./themes/green.js\";\nimport type { Theme } from \"./types.js\";\n\n/** Keys every Gigaboard board understands. */\nexport const CSS_VARS = {\n SQ_LIGHT: \"--gb-sq-light\",\n SQ_DARK: \"--gb-sq-dark\",\n LAST_MOVE: \"--gb-last-move\",\n SELECTED: \"--gb-selected\",\n LEGAL_TARGET: \"--gb-legal-target\",\n LEGAL_TARGET_CAPTURE: \"--gb-legal-target-capture\",\n CHECK: \"--gb-check\",\n COORDINATE_LIGHT: \"--gb-coord-light\",\n COORDINATE_DARK: \"--gb-coord-dark\",\n /**\n * Opacity of the piece left behind at the drag origin while the ghost\n * is in flight. Default `0.35` (lichess parity). Themes may override\n * to `0` for a chess.com-style \"piece vanishes\" effect.\n */\n DRAG_GHOST_OPACITY: \"--gb-drag-ghost-opacity\",\n} as const;\n\nexport const defaultTheme: Theme = Object.freeze({\n ...green,\n [CSS_VARS.DRAG_GHOST_OPACITY]: \"0.35\",\n});\n\n/**\n * Default arrow-channel colours. Close to lichess's palette so arrows feel\n * familiar to players migrating over.\n */\nexport const defaultArrowColors = Object.freeze({\n default: \"rgba(21, 120, 27, 0.8)\",\n shift: \"rgba(153, 40, 40, 0.8)\",\n alt: \"rgba(230, 160, 0, 0.8)\",\n ctrl: \"rgba(0, 60, 130, 0.8)\",\n});\n\n/** Distinct blue tint used to preview pending premoves. */\nexport const DEFAULT_PREMOVE_TINT = \"rgba(30, 98, 255, 0.4)\";\n\n/** Red tint used to announce rejected moves. */\nexport const DEFAULT_ILLEGAL_FLASH_TINT = \"rgba(220, 40, 40, 0.55)\";\n","/**\n * FEN placement parsing — the one slice of FEN that both the server\n * `<StaticChessboard/>` and the client fallback-render path need.\n *\n * The parser is intentionally narrow: it only consumes the first\n * whitespace-delimited field of a FEN (piece placement) and returns a\n * 64-byte `Uint8Array` using our {@link BoardCell} encoding. Side-to-move,\n * castling, en-passant and the move clocks are the engine's business and\n * don't affect how the board is drawn.\n *\n * Kept in its own module so that:\n *\n * 1. `server.tsx` can import it without pulling a `\"use client\"` module.\n * 2. The client `<Chessboard/>`'s fallback path (`fallbackFen`) can reuse\n * the exact same parser — one source of truth for FEN shape.\n *\n * Throws on malformed input so misconfiguration fails at render time\n * rather than silently producing a blank board.\n */\n\nimport type { BoardCell } from \"./core/index.js\";\n\n/** FEN piece letter → our 1..12 `BoardCell` code, or 0 for unknown. */\nfunction pieceCellFromFenChar(ch: string): BoardCell {\n switch (ch) {\n case \"P\":\n return 1 as BoardCell;\n case \"N\":\n return 2 as BoardCell;\n case \"B\":\n return 3 as BoardCell;\n case \"R\":\n return 4 as BoardCell;\n case \"Q\":\n return 5 as BoardCell;\n case \"K\":\n return 6 as BoardCell;\n case \"p\":\n return 7 as BoardCell;\n case \"n\":\n return 8 as BoardCell;\n case \"b\":\n return 9 as BoardCell;\n case \"r\":\n return 10 as BoardCell;\n case \"q\":\n return 11 as BoardCell;\n case \"k\":\n return 12 as BoardCell;\n default:\n return 0 as BoardCell;\n }\n}\n\n/**\n * Parse the piece-placement field of a FEN into a 64-byte `Uint8Array`\n * in LERF order (index 0 = a1, index 63 = h8).\n *\n * Only the first whitespace-delimited token is read; anything after it\n * is ignored. That means both a full FEN (`\"rnbq... w KQkq - 0 1\"`) and\n * a bare placement (`\"rnbq...\"`) are accepted.\n */\nexport function parseFenPlacement(fen: string): Uint8Array {\n const placement = fen.trim().split(/\\s+/)[0];\n if (placement === undefined) {\n throw new Error(\"FEN is empty\");\n }\n const ranks = placement.split(\"/\");\n if (ranks.length !== 8) {\n throw new Error(`FEN must have 8 ranks, got ${ranks.length}`);\n }\n const board = new Uint8Array(64);\n for (let r = 0; r < 8; r++) {\n // FEN lists ranks 8→1; our LERF layout has rank 7 at top, 0 at bottom.\n const rank = 7 - r;\n const row = ranks[r];\n if (row === undefined) throw new Error(`FEN rank ${rank + 1} missing`);\n let file = 0;\n for (const ch of row) {\n if (file > 7) throw new Error(`FEN rank ${rank + 1} has too many files`);\n const skip = Number.parseInt(ch, 10);\n if (!Number.isNaN(skip)) {\n file += skip;\n continue;\n }\n const cell = pieceCellFromFenChar(ch);\n if (cell === 0) throw new Error(`FEN contains unknown piece: ${ch}`);\n board[rank * 8 + file] = cell;\n file++;\n }\n if (file !== 8) {\n throw new Error(`FEN rank ${rank + 1} ended at file ${file}, expected 8`);\n }\n }\n return board;\n}\n\n/** Standard starting position FEN, re-exported for convenience. */\nexport const STARTING_FEN = \"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1\";\n","import type { PieceRenderer } from \"../types.js\";\nimport { neo } from \"./sets/neo.js\";\n\nexport const defaultPieces: PieceRenderer = neo;\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { createImagePieceSet, chesscomPieceUrls } from './chunk-44YKPXXT.js';
|
|
2
|
+
|
|
3
|
+
// src/pieces/sets/merida.ts
|
|
4
|
+
var merida = createImagePieceSet(chesscomPieceUrls("neo_wood"));
|
|
5
|
+
|
|
6
|
+
export { merida };
|
|
7
|
+
//# sourceMappingURL=chunk-EOSX5UX3.js.map
|
|
8
|
+
//# sourceMappingURL=chunk-EOSX5UX3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/pieces/sets/merida.ts"],"names":[],"mappings":";;;AAcO,IAAM,MAAA,GAAS,mBAAA,CAAoB,iBAAA,CAAkB,UAAU,CAAC","file":"chunk-EOSX5UX3.js","sourcesContent":["/**\n * **Merida** — chess.com's `neo_wood` set.\n *\n * Warm wood-tinted pieces with traditional proportions; visually closest\n * to the classic `merida` tournament set used in print publications.\n *\n * ```tsx\n * import { merida } from \"gigaboard/pieces/merida\";\n * <Chessboard game={game} pieces={merida} />\n * ```\n */\n\nimport { chesscomPieceUrls, createImagePieceSet } from \"../create-image-piece-set.js\";\n\nexport const merida = createImagePieceSet(chesscomPieceUrls(\"neo_wood\"));\n"]}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
|
|
5
|
+
// src/pieces/create-image-piece-set.tsx
|
|
6
|
+
var BOARD_CELL_KEY = Object.freeze({
|
|
7
|
+
wP: 1,
|
|
8
|
+
wN: 2,
|
|
9
|
+
wB: 3,
|
|
10
|
+
wR: 4,
|
|
11
|
+
wQ: 5,
|
|
12
|
+
wK: 6,
|
|
13
|
+
bP: 7,
|
|
14
|
+
bN: 8,
|
|
15
|
+
bB: 9,
|
|
16
|
+
bR: 10,
|
|
17
|
+
bQ: 11,
|
|
18
|
+
bK: 12
|
|
19
|
+
});
|
|
20
|
+
function pieceLabel(cell) {
|
|
21
|
+
if (cell <= 0 || cell > 12) return "";
|
|
22
|
+
const color = cell > 6 ? "black" : "white";
|
|
23
|
+
const type = (cell - 1) % 6;
|
|
24
|
+
const name = ["pawn", "knight", "bishop", "rook", "queen", "king"][type];
|
|
25
|
+
return `${color} ${name}`;
|
|
26
|
+
}
|
|
27
|
+
var PIECE_IMG_STYLE = Object.freeze({
|
|
28
|
+
display: "block",
|
|
29
|
+
width: "100%",
|
|
30
|
+
height: "100%",
|
|
31
|
+
pointerEvents: "none",
|
|
32
|
+
userSelect: "none"
|
|
33
|
+
});
|
|
34
|
+
function createImagePieceSet(urls) {
|
|
35
|
+
const pool = new Array(13).fill(null);
|
|
36
|
+
for (let cell = 1; cell <= 12; cell++) {
|
|
37
|
+
const url = urls[cell];
|
|
38
|
+
if (url === void 0) continue;
|
|
39
|
+
pool[cell] = /* @__PURE__ */ jsxRuntime.jsx("img", { src: url, alt: pieceLabel(cell), draggable: false, style: PIECE_IMG_STYLE });
|
|
40
|
+
}
|
|
41
|
+
return function ImagePieceSet({ cell }) {
|
|
42
|
+
return pool[cell] ?? null;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function chesscomPieceUrls(style, size = 150) {
|
|
46
|
+
const base = `https://images.chesscomfiles.com/chess-themes/pieces/${style}/${size}`;
|
|
47
|
+
return Object.freeze({
|
|
48
|
+
1: `${base}/wp.png`,
|
|
49
|
+
2: `${base}/wn.png`,
|
|
50
|
+
3: `${base}/wb.png`,
|
|
51
|
+
4: `${base}/wr.png`,
|
|
52
|
+
5: `${base}/wq.png`,
|
|
53
|
+
6: `${base}/wk.png`,
|
|
54
|
+
7: `${base}/bp.png`,
|
|
55
|
+
8: `${base}/bn.png`,
|
|
56
|
+
9: `${base}/bb.png`,
|
|
57
|
+
10: `${base}/br.png`,
|
|
58
|
+
11: `${base}/bq.png`,
|
|
59
|
+
12: `${base}/bk.png`
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
exports.BOARD_CELL_KEY = BOARD_CELL_KEY;
|
|
64
|
+
exports.chesscomPieceUrls = chesscomPieceUrls;
|
|
65
|
+
exports.createImagePieceSet = createImagePieceSet;
|
|
66
|
+
//# sourceMappingURL=chunk-FNRS6YJI.cjs.map
|
|
67
|
+
//# sourceMappingURL=chunk-FNRS6YJI.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/pieces/create-image-piece-set.tsx"],"names":["jsx"],"mappings":"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","file":"chunk-FNRS6YJI.cjs","sourcesContent":["/**\n * Shared piece-renderer factory.\n *\n * Every piece set shipped by `gigaboard/pieces` is a URL-based set — a\n * thin map from board-cell → image URL. This factory builds a memoised\n * {@link PieceRenderer} around such a map, so every set file is two lines\n * of configuration plus a URL table.\n *\n * ### Why images, not inline SVG?\n *\n * The React packages target <15 KB gzip. Shipping 12 detailed SVG paths\n * per set × 4 sets would blow that budget immediately. URL-based sets\n * push the bytes onto the browser's image cache, where the pieces are\n * decoded exactly once per session and shared across every board.\n *\n * ### Render cost\n *\n * One `<img>` per occupied square. The image is `pointer-events: none`\n * so it never intercepts drag/click; the piece layer on the board owns\n * hit testing. Each renderer is pure and does not allocate on the hot\n * path — the URL lookup is a constant-time array read.\n */\n\nimport type { ReactNode } from \"react\";\n\n/** Shape a consumer's `PieceRenderer` prop expects. */\nexport type PieceRenderer = (args: { readonly cell: number; readonly square: number }) => ReactNode;\n\n/**\n * 12-entry URL table, indexed by board cell `1..12`. Cell `0` is the\n * empty square and is never looked up. Use {@link BOARD_CELL_KEY} to\n * remember which index maps to which piece.\n */\nexport type PieceUrlTable = Readonly<{\n /** white pawn (cell 1) */ 1: string;\n /** white knight (cell 2) */ 2: string;\n /** white bishop (cell 3) */ 3: string;\n /** white rook (cell 4) */ 4: string;\n /** white queen (cell 5) */ 5: string;\n /** white king (cell 6) */ 6: string;\n /** black pawn (cell 7) */ 7: string;\n /** black knight (cell 8) */ 8: string;\n /** black bishop (cell 9) */ 9: string;\n /** black rook (cell 10) */ 10: string;\n /** black queen (cell 11) */ 11: string;\n /** black king (cell 12) */ 12: string;\n}>;\n\n/** Readable cell labels for the table — useful for callers building sets. */\nexport const BOARD_CELL_KEY = Object.freeze({\n wP: 1,\n wN: 2,\n wB: 3,\n wR: 4,\n wQ: 5,\n wK: 6,\n bP: 7,\n bN: 8,\n bB: 9,\n bR: 10,\n bQ: 11,\n bK: 12,\n} as const);\n\n/** Readable piece-name for `aria-label`, derived from a board cell. */\nfunction pieceLabel(cell: number): string {\n if (cell <= 0 || cell > 12) return \"\";\n const color = cell > 6 ? \"black\" : \"white\";\n const type = (cell - 1) % 6;\n const name = [\"pawn\", \"knight\", \"bishop\", \"rook\", \"queen\", \"king\"][type];\n return `${color} ${name}`;\n}\n\n/**\n * Shared style object for every `<img>` — frozen and re-used so React's\n * shallow-equality checks short-circuit and we don't allocate a fresh\n * object on every render.\n */\nconst PIECE_IMG_STYLE = Object.freeze({\n display: \"block\",\n width: \"100%\",\n height: \"100%\",\n pointerEvents: \"none\",\n userSelect: \"none\",\n} as const);\n\n/**\n * Build a {@link PieceRenderer} backed by a URL table. The returned\n * function is referentially stable AND allocates **zero** React elements\n * on the hot path: we pre-materialise one `<img>` element per piece\n * code at factory time and hand out the same element for every call with\n * the same cell.\n *\n * Why pre-materialise? The renderer is called inside `<PieceSlot/>` on\n * every move that touches its square. Returning a fresh React element\n * per call means React's reconciler has to shallow-diff the new element\n * against the last one to decide whether DOM changed. A pool of 12\n * frozen elements (one per piece code) bypasses that entirely — React\n * short-circuits on identity.\n */\nexport function createImagePieceSet(urls: PieceUrlTable): PieceRenderer {\n // Pre-materialise the 12 piece elements at factory time. `cell === 0`\n // (empty square) returns null; we don't allocate an element for it.\n const pool: Array<ReactNode | null> = new Array(13).fill(null);\n for (let cell = 1; cell <= 12; cell++) {\n const url = (urls as Record<number, string | undefined>)[cell];\n if (url === undefined) continue;\n pool[cell] = <img src={url} alt={pieceLabel(cell)} draggable={false} style={PIECE_IMG_STYLE} />;\n }\n return function ImagePieceSet({ cell }: { readonly cell: number }) {\n return pool[cell] ?? null;\n };\n}\n\n/**\n * Helper that builds a chess.com-style PNG CDN URL for a given piece style.\n *\n * chess.com serves piece artwork at:\n * `https://images.chesscomfiles.com/chess-themes/pieces/<style>/<size>/<colorPiece>.png`\n *\n * where `colorPiece` is one of `wp wn wb wr wq wk bp bn bb br bq bk`. The\n * `size` options are `150` (default), `300`, etc. We pin to 150 by default\n * because boards render at roughly that density on desktop, and larger\n * sizes inflate page weight without perceptible benefit.\n *\n * @param style chess.com piece-style slug. Known values include `neo`\n * (chess.com's default), `alpha`, `bases`, `cases`, `classic`,\n * `club`, `condal`, `graffiti`, `leipzig`, `marble`, `maya`,\n * `metal`, `modern`, `nature`, `neo_wood`, `newspaper`, `ocean`,\n * `sky`, `space`, `tournament`, `vintage`, `wood`.\n * @param size One of chess.com's supported pixel sizes (default 150).\n */\nexport function chesscomPieceUrls(style: string, size: 150 | 300 = 150): PieceUrlTable {\n const base = `https://images.chesscomfiles.com/chess-themes/pieces/${style}/${size}`;\n return Object.freeze({\n 1: `${base}/wp.png`,\n 2: `${base}/wn.png`,\n 3: `${base}/wb.png`,\n 4: `${base}/wr.png`,\n 5: `${base}/wq.png`,\n 6: `${base}/wk.png`,\n 7: `${base}/bp.png`,\n 8: `${base}/bn.png`,\n 9: `${base}/bb.png`,\n 10: `${base}/br.png`,\n 11: `${base}/bq.png`,\n 12: `${base}/bk.png`,\n });\n}\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/themes/green.ts
|
|
4
|
+
var green = Object.freeze({
|
|
5
|
+
"--gb-sq-light": "#eeeed2",
|
|
6
|
+
"--gb-sq-dark": "#769656",
|
|
7
|
+
"--gb-last-move": "rgba(255, 255, 51, 0.45)",
|
|
8
|
+
"--gb-selected": "rgba(255, 255, 51, 0.55)",
|
|
9
|
+
"--gb-legal-target": "rgba(0, 0, 0, 0.14)",
|
|
10
|
+
"--gb-legal-target-capture": "rgba(0, 0, 0, 0.3)",
|
|
11
|
+
"--gb-check": "radial-gradient(rgba(255, 0, 0, 0.55) 30%, rgba(255, 0, 0, 0) 80%)",
|
|
12
|
+
"--gb-coord-light": "#769656",
|
|
13
|
+
"--gb-coord-dark": "#eeeed2"
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
exports.green = green;
|
|
17
|
+
//# sourceMappingURL=chunk-G6ZFOJZR.cjs.map
|
|
18
|
+
//# sourceMappingURL=chunk-G6ZFOJZR.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/themes/green.ts"],"names":[],"mappings":";;;AAkBO,IAAM,KAAA,GAAe,OAAO,MAAA,CAAO;AAAA,EACxC,eAAA,EAAiB,SAAA;AAAA,EACjB,cAAA,EAAgB,SAAA;AAAA,EAChB,gBAAA,EAAkB,0BAAA;AAAA,EAClB,eAAA,EAAiB,0BAAA;AAAA,EACjB,mBAAA,EAAqB,qBAAA;AAAA,EACrB,2BAAA,EAA6B,oBAAA;AAAA,EAC7B,YAAA,EAAc,oEAAA;AAAA,EACd,kBAAA,EAAoB,SAAA;AAAA,EACpB,iBAAA,EAAmB;AACrB,CAAC","file":"chunk-G6ZFOJZR.cjs","sourcesContent":["/**\n * Green theme — chess.com's default green/cream board.\n *\n * CSS-variable-only. Import this theme and pass it as the `theme` prop on\n * `<Chessboard/>`:\n *\n * ```tsx\n * import { green } from \"gigaboard/themes/green\";\n * <Chessboard game={game} theme={green} />\n * ```\n *\n * Palette tuned to visually match chess.com's board at a glance — the light\n * square is a warm off-white and the dark square is the recognisable\n * olive-green used across their web and mobile clients.\n */\n\nimport type { Theme } from \"./index.js\";\n\nexport const green: Theme = Object.freeze({\n \"--gb-sq-light\": \"#eeeed2\",\n \"--gb-sq-dark\": \"#769656\",\n \"--gb-last-move\": \"rgba(255, 255, 51, 0.45)\",\n \"--gb-selected\": \"rgba(255, 255, 51, 0.55)\",\n \"--gb-legal-target\": \"rgba(0, 0, 0, 0.14)\",\n \"--gb-legal-target-capture\": \"rgba(0, 0, 0, 0.3)\",\n \"--gb-check\": \"radial-gradient(rgba(255, 0, 0, 0.55) 30%, rgba(255, 0, 0, 0) 80%)\",\n \"--gb-coord-light\": \"#769656\",\n \"--gb-coord-dark\": \"#eeeed2\",\n});\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/themes/brown.ts
|
|
4
|
+
var brown = Object.freeze({
|
|
5
|
+
"--gb-sq-light": "#f0d9b5",
|
|
6
|
+
"--gb-sq-dark": "#b58863",
|
|
7
|
+
"--gb-last-move": "rgba(155, 199, 0, 0.41)",
|
|
8
|
+
"--gb-selected": "rgba(20, 85, 30, 0.5)",
|
|
9
|
+
"--gb-legal-target": "rgba(0, 0, 0, 0.14)",
|
|
10
|
+
"--gb-legal-target-capture": "rgba(0, 0, 0, 0.3)",
|
|
11
|
+
"--gb-check": "radial-gradient(rgba(255, 0, 0, 0.55) 30%, rgba(255, 0, 0, 0) 80%)",
|
|
12
|
+
"--gb-coord-light": "#b58863",
|
|
13
|
+
"--gb-coord-dark": "#f0d9b5"
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
exports.brown = brown;
|
|
17
|
+
//# sourceMappingURL=chunk-HSMILJKQ.cjs.map
|
|
18
|
+
//# sourceMappingURL=chunk-HSMILJKQ.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/themes/brown.ts"],"names":[],"mappings":";;;AAcO,IAAM,KAAA,GAAe,OAAO,MAAA,CAAO;AAAA,EACxC,eAAA,EAAiB,SAAA;AAAA,EACjB,cAAA,EAAgB,SAAA;AAAA,EAChB,gBAAA,EAAkB,yBAAA;AAAA,EAClB,eAAA,EAAiB,uBAAA;AAAA,EACjB,mBAAA,EAAqB,qBAAA;AAAA,EACrB,2BAAA,EAA6B,oBAAA;AAAA,EAC7B,YAAA,EAAc,oEAAA;AAAA,EACd,kBAAA,EAAoB,SAAA;AAAA,EACpB,iBAAA,EAAmB;AACrB,CAAC","file":"chunk-HSMILJKQ.cjs","sourcesContent":["/**\n * Brown theme — the classic lichess-inspired wood-tone board.\n *\n * CSS-variable-only. Import this theme and pass it as the `theme` prop on\n * `<Chessboard/>`:\n *\n * ```tsx\n * import { brown } from \"gigaboard/themes/brown\";\n * <Chessboard game={game} theme={brown} />\n * ```\n */\n\nimport type { Theme } from \"./index.js\";\n\nexport const brown: Theme = Object.freeze({\n \"--gb-sq-light\": \"#f0d9b5\",\n \"--gb-sq-dark\": \"#b58863\",\n \"--gb-last-move\": \"rgba(155, 199, 0, 0.41)\",\n \"--gb-selected\": \"rgba(20, 85, 30, 0.5)\",\n \"--gb-legal-target\": \"rgba(0, 0, 0, 0.14)\",\n \"--gb-legal-target-capture\": \"rgba(0, 0, 0, 0.3)\",\n \"--gb-check\": \"radial-gradient(rgba(255, 0, 0, 0.55) 30%, rgba(255, 0, 0, 0) 80%)\",\n \"--gb-coord-light\": \"#b58863\",\n \"--gb-coord-dark\": \"#f0d9b5\",\n});\n"]}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkG6ZFOJZR_cjs = require('./chunk-G6ZFOJZR.cjs');
|
|
4
|
+
var chunkAYVQCHSG_cjs = require('./chunk-AYVQCHSG.cjs');
|
|
5
|
+
|
|
6
|
+
// src/default-theme.ts
|
|
7
|
+
var CSS_VARS = {
|
|
8
|
+
SQ_LIGHT: "--gb-sq-light",
|
|
9
|
+
SQ_DARK: "--gb-sq-dark",
|
|
10
|
+
LAST_MOVE: "--gb-last-move",
|
|
11
|
+
SELECTED: "--gb-selected",
|
|
12
|
+
LEGAL_TARGET: "--gb-legal-target",
|
|
13
|
+
LEGAL_TARGET_CAPTURE: "--gb-legal-target-capture",
|
|
14
|
+
CHECK: "--gb-check",
|
|
15
|
+
COORDINATE_LIGHT: "--gb-coord-light",
|
|
16
|
+
COORDINATE_DARK: "--gb-coord-dark",
|
|
17
|
+
/**
|
|
18
|
+
* Opacity of the piece left behind at the drag origin while the ghost
|
|
19
|
+
* is in flight. Default `0.35` (lichess parity). Themes may override
|
|
20
|
+
* to `0` for a chess.com-style "piece vanishes" effect.
|
|
21
|
+
*/
|
|
22
|
+
DRAG_GHOST_OPACITY: "--gb-drag-ghost-opacity"
|
|
23
|
+
};
|
|
24
|
+
var defaultTheme = Object.freeze({
|
|
25
|
+
...chunkG6ZFOJZR_cjs.green,
|
|
26
|
+
[CSS_VARS.DRAG_GHOST_OPACITY]: "0.35"
|
|
27
|
+
});
|
|
28
|
+
var defaultArrowColors = Object.freeze({
|
|
29
|
+
default: "rgba(21, 120, 27, 0.8)",
|
|
30
|
+
shift: "rgba(153, 40, 40, 0.8)",
|
|
31
|
+
alt: "rgba(230, 160, 0, 0.8)",
|
|
32
|
+
ctrl: "rgba(0, 60, 130, 0.8)"
|
|
33
|
+
});
|
|
34
|
+
var DEFAULT_PREMOVE_TINT = "rgba(30, 98, 255, 0.4)";
|
|
35
|
+
var DEFAULT_ILLEGAL_FLASH_TINT = "rgba(220, 40, 40, 0.55)";
|
|
36
|
+
|
|
37
|
+
// src/fen.ts
|
|
38
|
+
function pieceCellFromFenChar(ch) {
|
|
39
|
+
switch (ch) {
|
|
40
|
+
case "P":
|
|
41
|
+
return 1;
|
|
42
|
+
case "N":
|
|
43
|
+
return 2;
|
|
44
|
+
case "B":
|
|
45
|
+
return 3;
|
|
46
|
+
case "R":
|
|
47
|
+
return 4;
|
|
48
|
+
case "Q":
|
|
49
|
+
return 5;
|
|
50
|
+
case "K":
|
|
51
|
+
return 6;
|
|
52
|
+
case "p":
|
|
53
|
+
return 7;
|
|
54
|
+
case "n":
|
|
55
|
+
return 8;
|
|
56
|
+
case "b":
|
|
57
|
+
return 9;
|
|
58
|
+
case "r":
|
|
59
|
+
return 10;
|
|
60
|
+
case "q":
|
|
61
|
+
return 11;
|
|
62
|
+
case "k":
|
|
63
|
+
return 12;
|
|
64
|
+
default:
|
|
65
|
+
return 0;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function parseFenPlacement(fen) {
|
|
69
|
+
const placement = fen.trim().split(/\s+/)[0];
|
|
70
|
+
if (placement === void 0) {
|
|
71
|
+
throw new Error("FEN is empty");
|
|
72
|
+
}
|
|
73
|
+
const ranks = placement.split("/");
|
|
74
|
+
if (ranks.length !== 8) {
|
|
75
|
+
throw new Error(`FEN must have 8 ranks, got ${ranks.length}`);
|
|
76
|
+
}
|
|
77
|
+
const board = new Uint8Array(64);
|
|
78
|
+
for (let r = 0; r < 8; r++) {
|
|
79
|
+
const rank = 7 - r;
|
|
80
|
+
const row = ranks[r];
|
|
81
|
+
if (row === void 0) throw new Error(`FEN rank ${rank + 1} missing`);
|
|
82
|
+
let file = 0;
|
|
83
|
+
for (const ch of row) {
|
|
84
|
+
if (file > 7) throw new Error(`FEN rank ${rank + 1} has too many files`);
|
|
85
|
+
const skip = Number.parseInt(ch, 10);
|
|
86
|
+
if (!Number.isNaN(skip)) {
|
|
87
|
+
file += skip;
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
const cell = pieceCellFromFenChar(ch);
|
|
91
|
+
if (cell === 0) throw new Error(`FEN contains unknown piece: ${ch}`);
|
|
92
|
+
board[rank * 8 + file] = cell;
|
|
93
|
+
file++;
|
|
94
|
+
}
|
|
95
|
+
if (file !== 8) {
|
|
96
|
+
throw new Error(`FEN rank ${rank + 1} ended at file ${file}, expected 8`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return board;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// src/pieces/default-pieces.tsx
|
|
103
|
+
var defaultPieces = chunkAYVQCHSG_cjs.neo;
|
|
104
|
+
|
|
105
|
+
exports.CSS_VARS = CSS_VARS;
|
|
106
|
+
exports.DEFAULT_ILLEGAL_FLASH_TINT = DEFAULT_ILLEGAL_FLASH_TINT;
|
|
107
|
+
exports.DEFAULT_PREMOVE_TINT = DEFAULT_PREMOVE_TINT;
|
|
108
|
+
exports.defaultArrowColors = defaultArrowColors;
|
|
109
|
+
exports.defaultPieces = defaultPieces;
|
|
110
|
+
exports.defaultTheme = defaultTheme;
|
|
111
|
+
exports.parseFenPlacement = parseFenPlacement;
|
|
112
|
+
//# sourceMappingURL=chunk-I4BQGFP5.cjs.map
|
|
113
|
+
//# sourceMappingURL=chunk-I4BQGFP5.cjs.map
|