@alepot55/chessboardjs 2.2.1 → 2.2.2

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.
Files changed (80) hide show
  1. package/.eslintrc.json +227 -0
  2. package/README.md +125 -401
  3. package/assets/themes/alepot/theme.json +42 -0
  4. package/assets/themes/default/theme.json +42 -0
  5. package/chessboard.bundle.js +708 -58
  6. package/config/jest.config.js +15 -0
  7. package/config/rollup.config.js +36 -0
  8. package/dist/chessboard.cjs.js +10690 -0
  9. package/dist/chessboard.css +228 -0
  10. package/dist/chessboard.esm.js +10621 -0
  11. package/dist/chessboard.iife.js +10696 -0
  12. package/dist/chessboard.umd.js +10696 -0
  13. package/jest.config.js +2 -7
  14. package/package.json +18 -3
  15. package/rollup.config.js +2 -11
  16. package/{chessboard.move.js → src/components/Move.js} +3 -3
  17. package/src/components/Piece.js +288 -0
  18. package/{chessboard.square.js → src/components/Square.js} +60 -7
  19. package/src/constants/index.js +15 -0
  20. package/src/constants/positions.js +62 -0
  21. package/src/core/Chessboard.js +1939 -0
  22. package/src/core/ChessboardConfig.js +458 -0
  23. package/src/core/ChessboardFactory.js +385 -0
  24. package/src/core/index.js +141 -0
  25. package/src/errors/ChessboardError.js +133 -0
  26. package/src/errors/index.js +15 -0
  27. package/src/errors/messages.js +189 -0
  28. package/src/index.js +103 -0
  29. package/src/services/AnimationService.js +180 -0
  30. package/src/services/BoardService.js +156 -0
  31. package/src/services/CoordinateService.js +355 -0
  32. package/src/services/EventService.js +955 -0
  33. package/src/services/MoveService.js +629 -0
  34. package/src/services/PieceService.js +312 -0
  35. package/src/services/PositionService.js +237 -0
  36. package/src/services/ValidationService.js +673 -0
  37. package/src/services/index.js +14 -0
  38. package/src/styles/animations.css +46 -0
  39. package/{chessboard.css → src/styles/board.css} +8 -4
  40. package/src/styles/index.css +4 -0
  41. package/src/styles/pieces.css +70 -0
  42. package/src/utils/animations.js +37 -0
  43. package/{chess.js → src/utils/chess.js} +16 -16
  44. package/src/utils/coordinates.js +62 -0
  45. package/src/utils/cross-browser.js +150 -0
  46. package/src/utils/logger.js +422 -0
  47. package/src/utils/performance.js +311 -0
  48. package/src/utils/validation.js +458 -0
  49. package/tests/unit/chessboard-config-animations.test.js +106 -0
  50. package/tests/unit/chessboard-robust.test.js +163 -0
  51. package/tests/unit/chessboard.test.js +183 -0
  52. package/chessboard.config.js +0 -147
  53. package/chessboard.js +0 -979
  54. package/chessboard.piece.js +0 -115
  55. package/test/chessboard.test.js +0 -128
  56. /package/{alepot_theme → assets/themes/alepot}/bb.svg +0 -0
  57. /package/{alepot_theme → assets/themes/alepot}/bw.svg +0 -0
  58. /package/{alepot_theme → assets/themes/alepot}/kb.svg +0 -0
  59. /package/{alepot_theme → assets/themes/alepot}/kw.svg +0 -0
  60. /package/{alepot_theme → assets/themes/alepot}/nb.svg +0 -0
  61. /package/{alepot_theme → assets/themes/alepot}/nw.svg +0 -0
  62. /package/{alepot_theme → assets/themes/alepot}/pb.svg +0 -0
  63. /package/{alepot_theme → assets/themes/alepot}/pw.svg +0 -0
  64. /package/{alepot_theme → assets/themes/alepot}/qb.svg +0 -0
  65. /package/{alepot_theme → assets/themes/alepot}/qw.svg +0 -0
  66. /package/{alepot_theme → assets/themes/alepot}/rb.svg +0 -0
  67. /package/{alepot_theme → assets/themes/alepot}/rw.svg +0 -0
  68. /package/{default_pieces → assets/themes/default}/bb.svg +0 -0
  69. /package/{default_pieces → assets/themes/default}/bw.svg +0 -0
  70. /package/{default_pieces → assets/themes/default}/kb.svg +0 -0
  71. /package/{default_pieces → assets/themes/default}/kw.svg +0 -0
  72. /package/{default_pieces → assets/themes/default}/nb.svg +0 -0
  73. /package/{default_pieces → assets/themes/default}/nw.svg +0 -0
  74. /package/{default_pieces → assets/themes/default}/pb.svg +0 -0
  75. /package/{default_pieces → assets/themes/default}/pw.svg +0 -0
  76. /package/{default_pieces → assets/themes/default}/qb.svg +0 -0
  77. /package/{default_pieces → assets/themes/default}/qw.svg +0 -0
  78. /package/{default_pieces → assets/themes/default}/rb.svg +0 -0
  79. /package/{default_pieces → assets/themes/default}/rw.svg +0 -0
  80. /package/{.babelrc → config/.babelrc} +0 -0
@@ -0,0 +1,46 @@
1
+ /* Animation styles */
2
+ @keyframes fadeIn {
3
+ from { opacity: 0; }
4
+ to { opacity: 1; }
5
+ }
6
+
7
+ @keyframes fadeOut {
8
+ from { opacity: 1; }
9
+ to { opacity: 0; }
10
+ }
11
+
12
+ @keyframes slideIn {
13
+ from { transform: translateY(-10px); opacity: 0; }
14
+ to { transform: translateY(0); opacity: 1; }
15
+ }
16
+
17
+ @keyframes bounce {
18
+ 0%, 20%, 53%, 80%, 100% {
19
+ transform: translate3d(0, 0, 0);
20
+ }
21
+ 40%, 43% {
22
+ transform: translate3d(0, -5px, 0);
23
+ }
24
+ 70% {
25
+ transform: translate3d(0, -3px, 0);
26
+ }
27
+ 90% {
28
+ transform: translate3d(0, -1px, 0);
29
+ }
30
+ }
31
+
32
+ .fade-in {
33
+ animation: fadeIn var(--fade-time, 150ms) var(--fade-animation, ease);
34
+ }
35
+
36
+ .fade-out {
37
+ animation: fadeOut var(--fade-time, 150ms) var(--fade-animation, ease);
38
+ }
39
+
40
+ .slide-in {
41
+ animation: slideIn var(--fade-time, 150ms) var(--fade-animation, ease);
42
+ }
43
+
44
+ .bounce {
45
+ animation: bounce 1s ease;
46
+ }
@@ -1,6 +1,7 @@
1
1
  :root {
2
2
  --dimBoard: 600px;
3
3
  --pieceRatio: 0.9;
4
+ --square-size: calc(var(--dimBoard) / 8);
4
5
 
5
6
  --blackSquare: #b58863;
6
7
  --whiteSquare: #f0d9b5;
@@ -19,11 +20,14 @@
19
20
  grid-template: repeat(8, 1fr) / repeat(8, 1fr);
20
21
  width: var(--dimBoard);
21
22
  height: var(--dimBoard);
23
+ /* Enable hardware acceleration for better performance */
24
+ transform: translateZ(0);
25
+ will-change: auto;
22
26
  }
23
27
 
24
28
  .square {
25
- width: calc(var(--dimBoard) / 8);
26
- height: calc(var(--dimBoard) / 8);
29
+ width: var(--square-size);
30
+ height: var(--square-size);
27
31
  display: flex;
28
32
  justify-content: center;
29
33
  align-items: center;
@@ -32,8 +36,8 @@
32
36
  .piece {
33
37
  position: absolute;
34
38
  z-index: 10;
35
- width: calc(calc(var(--dimBoard) / 8) * var(--pieceRatio));
36
- height: calc(calc(var(--dimBoard) / 8) * var(--pieceRatio));
39
+ width: calc(var(--square-size) * var(--pieceRatio));
40
+ height: calc(var(--square-size) * var(--pieceRatio));
37
41
 
38
42
  /* No selection */
39
43
  -webkit-user-select: none;
@@ -0,0 +1,4 @@
1
+ /* Main stylesheet for Chessboard.js */
2
+ @import './board.css';
3
+ @import './pieces.css';
4
+ @import './animations.css';
@@ -0,0 +1,70 @@
1
+ /* Piece-specific styles */
2
+ .piece {
3
+ position: absolute;
4
+ cursor: pointer;
5
+ /* Solo transizioni specifiche, non "all" */
6
+ transition: opacity var(--fade-time, 150ms) var(--fade-animation, ease);
7
+ z-index: 10;
8
+ /* Hint al browser per ottimizzazioni */
9
+ will-change: auto;
10
+ }
11
+
12
+ .piece.dragging {
13
+ z-index: 100;
14
+ /* Disabilita completamente le transizioni durante il drag */
15
+ transition: none !important;
16
+ /* Hint per ottimizzazione durante drag */
17
+ will-change: left, top, transform;
18
+ /* Mantiene le dimensioni originali del pezzo durante il drag */
19
+ width: calc(var(--square-size) * var(--pieceRatio)) !important;
20
+ height: calc(var(--square-size) * var(--pieceRatio)) !important;
21
+ /* Assicura che il pezzo mantenga le proporzioni corrette */
22
+ box-sizing: border-box;
23
+ }
24
+
25
+ .piece.fading {
26
+ opacity: 0;
27
+ transition: opacity var(--fade-time, 150ms) var(--fade-animation, ease);
28
+ }
29
+
30
+ .piece.moving {
31
+ /* Solo transizione per transform, non position */
32
+ transition: transform var(--move-time, 200ms) var(--move-animation, ease);
33
+ }
34
+
35
+ /* Piece replacement during promotion - no transitions to avoid flickering */
36
+ .piece.replacing {
37
+ transition: none !important;
38
+ opacity: 1;
39
+ transform: none;
40
+ }
41
+
42
+ /* Piece transformation during promotion - smooth scaling animation */
43
+ .piece.transforming {
44
+ transition: none !important;
45
+ transform-origin: center center;
46
+ will-change: transform, opacity;
47
+ z-index: 50;
48
+ }
49
+
50
+ /* Subtle bounce effect after transformation */
51
+ .piece.transform-complete {
52
+ animation: transformBounce 0.4s ease-out;
53
+ }
54
+
55
+ @keyframes transformBounce {
56
+ 0% { transform: scale(1); }
57
+ 50% { transform: scale(1.1); }
58
+ 100% { transform: scale(1); }
59
+ }
60
+
61
+ /* Piece sizing */
62
+ .piece img {
63
+ width: 100%;
64
+ height: 100%;
65
+ object-fit: contain;
66
+ /* Previene conflitti di drag dell'immagine */
67
+ pointer-events: none;
68
+ /* Migliore rendering */
69
+ image-rendering: crisp-edges;
70
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Animation utilities for Chessboard.js
3
+ */
4
+
5
+ /**
6
+ * Get the CSS transition duration in milliseconds
7
+ * @param {string|number} time - Time value ('fast', 'slow', or number in ms)
8
+ * @returns {number} Duration in milliseconds
9
+ */
10
+ export function parseTime(time) {
11
+ if (typeof time === 'number') return time;
12
+
13
+ switch (time) {
14
+ case 'fast': return 150;
15
+ case 'slow': return 500;
16
+ default: return 200;
17
+ }
18
+ }
19
+
20
+ /**
21
+ * Get the CSS transition function
22
+ * @param {string} animation - Animation type ('ease', 'linear', etc.)
23
+ * @returns {string} CSS transition function
24
+ */
25
+ export function parseAnimation(animation) {
26
+ const validAnimations = ['ease', 'ease-in', 'ease-out', 'ease-in-out', 'linear'];
27
+ return validAnimations.includes(animation) ? animation : 'ease';
28
+ }
29
+
30
+ /**
31
+ * Create a promise that resolves after animation completion
32
+ * @param {number} duration - Duration in milliseconds
33
+ * @returns {Promise} Promise that resolves after the duration
34
+ */
35
+ export function animationPromise(duration) {
36
+ return new Promise(resolve => setTimeout(resolve, duration));
37
+ }
@@ -914,8 +914,8 @@ export class Chess {
914
914
  return true;
915
915
  }
916
916
  else if (
917
- // k vs. kn .... or .... k vs. kb
918
- numPieces === 3 &&
917
+ // k vs. kn .... or .... k vs. kb
918
+ numPieces === 3 &&
919
919
  (pieces[BISHOP] === 1 || pieces[KNIGHT] === 1)) {
920
920
  return true;
921
921
  }
@@ -1548,14 +1548,14 @@ export class Chess {
1548
1548
  function toHex(s) {
1549
1549
  return Array.from(s)
1550
1550
  .map(function (c) {
1551
- /*
1552
- * encodeURI doesn't transform most ASCII characters, so we handle
1553
- * these ourselves
1554
- */
1555
- return c.charCodeAt(0) < 128
1556
- ? c.charCodeAt(0).toString(16)
1557
- : encodeURIComponent(c).replace(/%/g, '').toLowerCase();
1558
- })
1551
+ /*
1552
+ * encodeURI doesn't transform most ASCII characters, so we handle
1553
+ * these ourselves
1554
+ */
1555
+ return c.charCodeAt(0) < 128
1556
+ ? c.charCodeAt(0).toString(16)
1557
+ : encodeURIComponent(c).replace(/%/g, '').toLowerCase();
1558
+ })
1559
1559
  .join('');
1560
1560
  }
1561
1561
  function fromHex(s) {
@@ -1576,12 +1576,12 @@ export class Chess {
1576
1576
  let ms = pgn
1577
1577
  .replace(headerString, '')
1578
1578
  .replace(
1579
- // encode comments so they don't get deleted below
1580
- new RegExp(`({[^}]*})+?|;([^${mask(newlineChar)}]*)`, 'g'), function (_match, bracket, semicolon) {
1581
- return bracket !== undefined
1582
- ? encodeComment(bracket)
1583
- : ' ' + encodeComment(`{${semicolon.slice(1)}}`);
1584
- })
1579
+ // encode comments so they don't get deleted below
1580
+ new RegExp(`({[^}]*})+?|;([^${mask(newlineChar)}]*)`, 'g'), function (_match, bracket, semicolon) {
1581
+ return bracket !== undefined
1582
+ ? encodeComment(bracket)
1583
+ : ' ' + encodeComment(`{${semicolon.slice(1)}}`);
1584
+ })
1585
1585
  .replace(new RegExp(mask(newlineChar), 'g'), ' ');
1586
1586
  // delete recursive annotation variations
1587
1587
  const ravRegex = /(\([^()]+\))+?/g;
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Coordinate utilities for Chessboard.js
3
+ */
4
+
5
+ /**
6
+ * Convert algebraic notation to array coordinates
7
+ * @param {string} square - Square in algebraic notation (e.g., 'a1', 'h8')
8
+ * @returns {Object} Object with row and col properties
9
+ */
10
+ export function algebraicToCoords(square) {
11
+ const file = square.charCodeAt(0) - 97; // 'a' = 0, 'b' = 1, etc.
12
+ const rank = parseInt(square[1]) - 1; // '1' = 0, '2' = 1, etc.
13
+
14
+ return { row: 7 - rank, col: file };
15
+ }
16
+
17
+ /**
18
+ * Convert array coordinates to algebraic notation
19
+ * @param {number} row - Row index (0-7)
20
+ * @param {number} col - Column index (0-7)
21
+ * @returns {string} Square in algebraic notation
22
+ */
23
+ export function coordsToAlgebraic(row, col) {
24
+ const file = String.fromCharCode(97 + col); // 0 = 'a', 1 = 'b', etc.
25
+ const rank = (8 - row).toString(); // 0 = '8', 1 = '7', etc.
26
+
27
+ return file + rank;
28
+ }
29
+
30
+ /**
31
+ * Get the color of a square
32
+ * @param {string} square - Square in algebraic notation
33
+ * @returns {string} 'light' or 'dark'
34
+ */
35
+ export function getSquareColor(square) {
36
+ const { row, col } = algebraicToCoords(square);
37
+ return (row + col) % 2 === 0 ? 'dark' : 'light';
38
+ }
39
+
40
+ /**
41
+ * Check if coordinates are valid
42
+ * @param {number} row - Row index
43
+ * @param {number} col - Column index
44
+ * @returns {boolean} True if coordinates are valid
45
+ */
46
+ export function isValidCoords(row, col) {
47
+ return row >= 0 && row <= 7 && col >= 0 && col <= 7;
48
+ }
49
+
50
+ /**
51
+ * Check if algebraic notation is valid
52
+ * @param {string} square - Square in algebraic notation
53
+ * @returns {boolean} True if square notation is valid
54
+ */
55
+ export function isValidSquare(square) {
56
+ if (typeof square !== 'string' || square.length !== 2) return false;
57
+
58
+ const file = square[0];
59
+ const rank = square[1];
60
+
61
+ return file >= 'a' && file <= 'h' && rank >= '1' && rank <= '8';
62
+ }
@@ -0,0 +1,150 @@
1
+ /**
2
+ * Cross-browser utilities for consistent drag & drop behavior
3
+ */
4
+
5
+ /**
6
+ * Detect browser type and version
7
+ * @returns {Object} Browser information
8
+ */
9
+ export function getBrowserInfo() {
10
+ const ua = navigator.userAgent;
11
+ const isChrome = ua.includes('Chrome') && !ua.includes('Edg');
12
+ const isFirefox = ua.includes('Firefox');
13
+ const isSafari = ua.includes('Safari') && !ua.includes('Chrome');
14
+ const isEdge = ua.includes('Edg');
15
+
16
+ return {
17
+ isChrome,
18
+ isFirefox,
19
+ isSafari,
20
+ isEdge,
21
+ devicePixelRatio: window.devicePixelRatio || 1,
22
+ userAgent: ua
23
+ };
24
+ }
25
+
26
+ /**
27
+ * Get accurate mouse coordinates accounting for browser differences
28
+ * @param {MouseEvent} event - Mouse event
29
+ * @returns {Object} Normalized coordinates
30
+ */
31
+ export function getNormalizedCoordinates(event) {
32
+ const browserInfo = getBrowserInfo();
33
+
34
+ // Base coordinates
35
+ let x = event.clientX;
36
+ let y = event.clientY;
37
+
38
+ // Add scroll offset for absolute positioning
39
+ x += window.scrollX || window.pageXOffset || 0;
40
+ y += window.scrollY || window.pageYOffset || 0;
41
+
42
+ // Chrome-specific adjustments if needed
43
+ if (browserInfo.isChrome) {
44
+ // Chrome sometimes has sub-pixel rendering differences
45
+ x = Math.round(x);
46
+ y = Math.round(y);
47
+ }
48
+
49
+ return { x, y };
50
+ }
51
+
52
+ /**
53
+ * Set element position using the most compatible method
54
+ * @param {HTMLElement} element - Element to position
55
+ * @param {number} x - X coordinate
56
+ * @param {number} y - Y coordinate
57
+ */
58
+ export function setElementPosition(element, x, y) {
59
+ // Ensure pixel-perfect positioning
60
+ element.style.left = `${Math.round(x)}px`;
61
+ element.style.top = `${Math.round(y)}px`;
62
+ }
63
+
64
+ /**
65
+ * Calculate offset from center for drag positioning
66
+ * @param {HTMLElement} element - Element being dragged
67
+ * @param {number} mouseX - Mouse X coordinate
68
+ * @param {number} mouseY - Mouse Y coordinate
69
+ * @returns {Object} Position coordinates
70
+ */
71
+ export function calculateDragPosition(element, mouseX, mouseY) {
72
+ const rect = element.getBoundingClientRect();
73
+ const halfWidth = rect.width / 2;
74
+ const halfHeight = rect.height / 2;
75
+
76
+ return {
77
+ x: mouseX - halfWidth,
78
+ y: mouseY - halfHeight
79
+ };
80
+ }
81
+
82
+ /**
83
+ * Enhanced mouse coordinate tracking for cross-browser compatibility
84
+ */
85
+ export class MouseTracker {
86
+ constructor() {
87
+ this.lastKnownPosition = { x: 0, y: 0 };
88
+ this.browserInfo = getBrowserInfo();
89
+ }
90
+
91
+ /**
92
+ * Update position from mouse event
93
+ * @param {MouseEvent} event - Mouse event
94
+ * @returns {Object} Normalized position
95
+ */
96
+ updatePosition(event) {
97
+ const coords = getNormalizedCoordinates(event);
98
+ this.lastKnownPosition = coords;
99
+ return coords;
100
+ }
101
+
102
+ /**
103
+ * Get element position for dragging
104
+ * @param {HTMLElement} element - Element to position
105
+ * @param {MouseEvent} event - Mouse event
106
+ * @returns {Object} Position for the element
107
+ */
108
+ getDragPosition(element, event) {
109
+ const mousePos = this.updatePosition(event);
110
+ return calculateDragPosition(element, mousePos.x, mousePos.y);
111
+ }
112
+ }
113
+
114
+ /**
115
+ * Browser-specific drag optimizations
116
+ */
117
+ export const DragOptimizations = {
118
+ /**
119
+ * Apply browser-specific optimizations to an element
120
+ * @param {HTMLElement} element - Element to optimize
121
+ */
122
+ enableForDrag(element) {
123
+ const browserInfo = getBrowserInfo();
124
+
125
+ // Base optimizations for all browsers
126
+ element.style.willChange = 'left, top';
127
+ element.style.pointerEvents = 'none'; // Prevent conflicts
128
+
129
+ // Chrome-specific optimizations
130
+ if (browserInfo.isChrome) {
131
+ element.style.transform = 'translateZ(0)'; // Force hardware acceleration
132
+ }
133
+
134
+ // Firefox-specific optimizations
135
+ if (browserInfo.isFirefox) {
136
+ element.style.backfaceVisibility = 'hidden';
137
+ }
138
+ },
139
+
140
+ /**
141
+ * Clean up optimizations after drag
142
+ * @param {HTMLElement} element - Element to clean up
143
+ */
144
+ cleanupAfterDrag(element) {
145
+ element.style.willChange = 'auto';
146
+ element.style.pointerEvents = '';
147
+ element.style.transform = '';
148
+ element.style.backfaceVisibility = '';
149
+ }
150
+ };