cm-chessboard 8.9.0 → 8.10.0

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/README.md CHANGED
@@ -20,8 +20,9 @@ functionality](https://shaack.com/projekte/cm-chessboard/examples/extensions/arr
20
20
 
21
21
  The core of cm-chessboard is small, fast and reduced to the essentials. You can easily extend its functionality with extensions.
22
22
 
23
- - [Markers Extension](https://shaack.com/projekte/cm-chessboard/examples/extensions/markers-extension.html) create markers on specific squares
24
- - [Arrows Extension](https://shaack.com/projekte/cm-chessboard/examples/extensions/arrows-extension.html) ⇨ renders arrows on the chessboard
23
+ - [RightClickAnnotator](https://shaack.com/projekte/cm-chessboard/examples/extensions/right-click-annotator.html) ⇨ Uses [Markers Extension](https://shaack.com/projekte/cm-chessboard/examples/extensions/markers-extension.html) and [Arrows Extension](https://shaack.com/projekte/cm-chessboard/examples/extensions/arrows-extension.html) and adds the handling mouse events to draw them on the board.
24
+ - [Markers Extension](https://shaack.com/projekte/cm-chessboard/examples/extensions/markers-extension.html) ⇨ create markers on specific squares
25
+ - [Arrows Extension](https://shaack.com/projekte/cm-chessboard/examples/extensions/arrows-extension.html) ⇨ renders arrows on the chessboard
25
26
  - [Accessibility Extension](https://shaack.com/projekte/cm-chessboard/examples/extensions/accessibility-extension.html) ⇨ makes the chessboard more accessible
26
27
  - [PromotionDialog Extension](https://shaack.com/projekte/cm-chessboard/examples/extensions/promotion-dialog-extension.html) ⇨ shows a dialog to select the piece to promote to
27
28
 
@@ -1,47 +1,91 @@
1
1
  .cm-chessboard .markers {
2
- pointer-events: none; }
3
- .cm-chessboard .markers .marker.marker-frame {
4
- stroke: #000000;
5
- stroke-width: 1.8px;
6
- opacity: 0.5; }
7
- .cm-chessboard .markers .marker.marker-frame-primary {
8
- stroke: #0009bd;
9
- stroke-width: 1.8px;
10
- opacity: 0.4; }
11
- .cm-chessboard .markers .marker.marker-frame-danger {
12
- stroke: #aa0000;
13
- stroke-width: 1.8px;
14
- opacity: 0.4; }
15
- .cm-chessboard .markers .marker.marker-circle {
16
- stroke: #000000;
17
- stroke-width: 3px;
18
- opacity: 0.3; }
19
- .cm-chessboard .markers .marker.marker-circle-primary {
20
- stroke: #0009bd;
21
- stroke-width: 3px;
22
- opacity: 0.4; }
23
- .cm-chessboard .markers .marker.marker-circle-danger {
24
- stroke: #aa0000;
25
- stroke-width: 3px;
26
- opacity: 0.4; }
27
- .cm-chessboard .markers .marker.marker-square {
28
- fill: black;
29
- opacity: 0.11; }
30
- .cm-chessboard .markers .marker.marker-dot {
31
- fill: black;
32
- opacity: 0.2; }
33
- .cm-chessboard .markers .marker.marker-bevel {
34
- fill: black;
35
- opacity: 0.2; }
2
+ pointer-events: none;
3
+ }
4
+ .cm-chessboard .markers .marker.marker-frame {
5
+ stroke: black;
6
+ stroke-width: 1.8px;
7
+ opacity: 0.5;
8
+ }
9
+ .cm-chessboard .markers .marker.marker-frame-primary, .cm-chessboard .markers .marker.marker-frame-info {
10
+ stroke: blue;
11
+ stroke-width: 1.8px;
12
+ opacity: 0.4;
13
+ }
14
+ .cm-chessboard .markers .marker.marker-frame-danger {
15
+ stroke: red;
16
+ stroke-width: 1.8px;
17
+ opacity: 0.4;
18
+ }
19
+ .cm-chessboard .markers .marker.marker-frame-warning {
20
+ stroke: orange;
21
+ stroke-width: 1.8px;
22
+ opacity: 0.4;
23
+ }
24
+ .cm-chessboard .markers .marker.marker-circle {
25
+ stroke: black;
26
+ stroke-width: 3px;
27
+ opacity: 0.3;
28
+ }
29
+ .cm-chessboard .markers .marker.marker-circle-primary {
30
+ stroke: blue;
31
+ stroke-width: 3px;
32
+ opacity: 0.4;
33
+ }
34
+ .cm-chessboard .markers .marker.marker-circle-info {
35
+ stroke: blue;
36
+ stroke-width: 3px;
37
+ opacity: 0.4;
38
+ }
39
+ .cm-chessboard .markers .marker.marker-circle-info-filled {
40
+ stroke: blue;
41
+ fill: blue;
42
+ stroke-width: 3px;
43
+ opacity: 0.4;
44
+ }
45
+ .cm-chessboard .markers .marker.marker-circle-danger {
46
+ stroke: red;
47
+ stroke-width: 3px;
48
+ opacity: 0.4;
49
+ }
50
+ .cm-chessboard .markers .marker.marker-circle-danger-filled {
51
+ stroke: red;
52
+ fill: red;
53
+ stroke-width: 3px;
54
+ opacity: 0.4;
55
+ }
56
+ .cm-chessboard .markers .marker.marker-circle-warning {
57
+ stroke: orange;
58
+ stroke-width: 3px;
59
+ opacity: 0.4;
60
+ }
61
+ .cm-chessboard .markers .marker.marker-circle-warning-filled {
62
+ stroke: orange;
63
+ fill: orange;
64
+ stroke-width: 3px;
65
+ opacity: 0.4;
66
+ }
67
+ .cm-chessboard .markers .marker.marker-circle-success {
68
+ stroke: green;
69
+ stroke-width: 3px;
70
+ opacity: 0.4;
71
+ }
72
+ .cm-chessboard .markers .marker.marker-circle-success-filled {
73
+ stroke: green;
74
+ fill: green;
75
+ stroke-width: 3px;
76
+ opacity: 0.4;
77
+ }
78
+ .cm-chessboard .markers .marker.marker-square {
79
+ fill: black;
80
+ opacity: 0.11;
81
+ }
82
+ .cm-chessboard .markers .marker.marker-dot {
83
+ fill: black;
84
+ opacity: 0.2;
85
+ }
86
+ .cm-chessboard .markers .marker.marker-bevel {
87
+ fill: black;
88
+ opacity: 0.2;
89
+ }
36
90
 
37
- /* custom colors for RightClickAnnotator */
38
- .cm-chessboard .markers .marker.marker-circle-green {
39
- stroke: #2e7d32; /* green */
40
- stroke-width: 3px;
41
- opacity: 0.4; }
42
- .cm-chessboard .markers .marker.marker-circle-orange {
43
- stroke: #ff9800; /* orange */
44
- stroke-width: 3px;
45
- opacity: 0.4; }
46
-
47
- /*# sourceMappingURL=markers.css.map */
91
+ /*# sourceMappingURL=markers.css.map */
@@ -1,9 +1 @@
1
- {
2
- "version": 3,
3
- "file": "markers.css",
4
- "sources": [
5
- "markers.scss"
6
- ],
7
- "names": [],
8
- "mappings": "AAIA,AACE,cADY,CACZ,QAAQ,CAAC;EACP,cAAc,EAAE,IAAI,GAuDrB;EAzDH,AAKM,cALQ,CACZ,QAAQ,CAGN,OAAO,AACJ,aAAa,CAAC;IACb,MAAM,EAVC,OAAO;IAWd,YAAY,EAAE,KAAK;IACnB,OAAO,EAAE,GAAG,GACb;EATP,AAWM,cAXQ,CACZ,QAAQ,CAGN,OAAO,AAOJ,qBAAqB,CAAC;IACrB,MAAM,EAfS,OAAO;IAgBtB,YAAY,EAAE,KAAK;IACnB,OAAO,EAAE,GAAG,GACb;EAfP,AAiBM,cAjBQ,CACZ,QAAQ,CAGN,OAAO,AAaJ,oBAAoB,CAAC;IACpB,MAAM,EApBQ,OAAO;IAqBrB,YAAY,EAAE,KAAK;IACnB,OAAO,EAAE,GAAG,GACb;EArBP,AAuBM,cAvBQ,CACZ,QAAQ,CAGN,OAAO,AAmBJ,cAAc,CAAC;IACd,MAAM,EA5BC,OAAO;IA6Bd,YAAY,EAAE,GAAG;IACjB,OAAO,EAAE,GAAG,GACb;EA3BP,AA6BM,cA7BQ,CACZ,QAAQ,CAGN,OAAO,AAyBJ,sBAAsB,CAAC;IACtB,MAAM,EAjCS,OAAO;IAkCtB,YAAY,EAAE,GAAG;IACjB,OAAO,EAAE,GAAG,GACb;EAjCP,AAmCM,cAnCQ,CACZ,QAAQ,CAGN,OAAO,AA+BJ,qBAAqB,CAAC;IACrB,MAAM,EAtCQ,OAAO;IAuCrB,YAAY,EAAE,GAAG;IACjB,OAAO,EAAE,GAAG,GACb;EAvCP,AAyCM,cAzCQ,CACZ,QAAQ,CAGN,OAAO,AAqCJ,cAAc,CAAC;IACd,IAAI,EAAE,KAAK;IACX,OAAO,EAAE,IAAI,GACd;EA5CP,AA8CM,cA9CQ,CACZ,QAAQ,CAGN,OAAO,AA0CJ,WAAW,CAAC;IACX,IAAI,EAAE,KAAK;IACX,OAAO,EAAE,GAAG,GACb;EAjDP,AAmDM,cAnDQ,CACZ,QAAQ,CAGN,OAAO,AA+CJ,aAAa,CAAC;IACb,IAAI,EAAE,KAAK;IACX,OAAO,EAAE,GAAG,GACb"
9
- }
1
+ {"version":3,"sourceRoot":"","sources":["markers.scss"],"names":[],"mappings":"AAOE;EACE;;AAGE;EACE,QAZO;EAaP;EACA;;AAGF;EACE,QAjBY;EAkBZ;EACA;;AAGF;EACE,QAtBc;EAuBd;EACA;;AAGF;EACE,QA3Be;EA4Bf;EACA;;AAGF;EACE,QApCO;EAqCP;EACA;;AAGF;EACE,QAzCY;EA0CZ;EACA;;AAGF;EACE,QA/CY;EAgDZ;EACA;;AAGF;EACE,QArDY;EAsDZ,MAtDY;EAuDZ;EACA;;AAGF;EACE,QA3Dc;EA4Dd;EACA;;AAGF;EACE,QAjEc;EAkEd,MAlEc;EAmEd;EACA;;AAGF;EACE,QAvEe;EAwEf;EACA;;AAGF;EACE,QA7Ee;EA8Ef,MA9Ee;EA+Ef;EACA;;AAGF;EACE,QAnFe;EAoFf;EACA;;AAGF;EACE,QAzFe;EA0Ff,MA1Fe;EA2Ff;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA","file":"markers.css"}
@@ -1,6 +1,8 @@
1
- $marker-color: #000000;
2
- $marker-color-primary: #0009bd;
3
- $marker-color-danger: #aa0000;
1
+ $marker-color: black;
2
+ $marker-color-info: blue;
3
+ $marker-color-danger: red;
4
+ $marker-color-warning: orange;
5
+ $marker-color-success: green;
4
6
 
5
7
  .cm-chessboard {
6
8
  .markers {
@@ -13,8 +15,8 @@ $marker-color-danger: #aa0000;
13
15
  opacity: 0.5;
14
16
  }
15
17
 
16
- &.marker-frame-primary {
17
- stroke: $marker-color-primary;
18
+ &.marker-frame-primary, &.marker-frame-info {
19
+ stroke: $marker-color-info;
18
20
  stroke-width: 1.8px;
19
21
  opacity: 0.4;
20
22
  }
@@ -25,6 +27,12 @@ $marker-color-danger: #aa0000;
25
27
  opacity: 0.4;
26
28
  }
27
29
 
30
+ &.marker-frame-warning {
31
+ stroke: $marker-color-warning;
32
+ stroke-width: 1.8px;
33
+ opacity: 0.4;
34
+ }
35
+
28
36
  &.marker-circle {
29
37
  stroke: $marker-color;
30
38
  stroke-width: 3px;
@@ -32,7 +40,20 @@ $marker-color-danger: #aa0000;
32
40
  }
33
41
 
34
42
  &.marker-circle-primary {
35
- stroke: $marker-color-primary;
43
+ stroke: $marker-color-info;
44
+ stroke-width: 3px;
45
+ opacity: 0.4;
46
+ }
47
+
48
+ &.marker-circle-info {
49
+ stroke: $marker-color-info;
50
+ stroke-width: 3px;
51
+ opacity: 0.4;
52
+ }
53
+
54
+ &.marker-circle-info-filled {
55
+ stroke: $marker-color-info;
56
+ fill: $marker-color-info;
36
57
  stroke-width: 3px;
37
58
  opacity: 0.4;
38
59
  }
@@ -43,6 +64,39 @@ $marker-color-danger: #aa0000;
43
64
  opacity: 0.4;
44
65
  }
45
66
 
67
+ &.marker-circle-danger-filled {
68
+ stroke: $marker-color-danger;
69
+ fill: $marker-color-danger;
70
+ stroke-width: 3px;
71
+ opacity: 0.4;
72
+ }
73
+
74
+ &.marker-circle-warning {
75
+ stroke: $marker-color-warning;
76
+ stroke-width: 3px;
77
+ opacity: 0.4;
78
+ }
79
+
80
+ &.marker-circle-warning-filled {
81
+ stroke: $marker-color-warning;
82
+ fill: $marker-color-warning;
83
+ stroke-width: 3px;
84
+ opacity: 0.4;
85
+ }
86
+
87
+ &.marker-circle-success {
88
+ stroke: $marker-color-success;
89
+ stroke-width: 3px;
90
+ opacity: 0.4;
91
+ }
92
+
93
+ &.marker-circle-success-filled {
94
+ stroke: $marker-color-success;
95
+ fill: $marker-color-success;
96
+ stroke-width: 3px;
97
+ opacity: 0.4;
98
+ }
99
+
46
100
  &.marker-square {
47
101
  fill: black;
48
102
  opacity: 0.11;
@@ -18,6 +18,9 @@ Author: shaack (https://shaack.com)
18
18
  <g id="markerCircle" fill="#000000" fill-opacity="0">
19
19
  <circle cx="20" cy="20" r="18"/>
20
20
  </g>
21
+ <g id="markerCircleFilled">
22
+ <circle cx="20" cy="20" r="18"/>
23
+ </g>
21
24
  <g id="markerDot">
22
25
  <circle cx="20" cy="20" r="7"/>
23
26
  </g>
@@ -59,7 +59,7 @@
59
59
  return true
60
60
  })
61
61
  // define your own marker
62
- const myOwnMarker = {class: "marker-circle-danger", slice: "markerCircle"}
62
+ const myOwnMarker = {class: "marker-circle-danger-filled", slice: "markerCircleFilled"}
63
63
  board2.context.addEventListener("contextmenu", (event) => {
64
64
  event.preventDefault()
65
65
  })
@@ -12,8 +12,13 @@
12
12
  <body>
13
13
  <h1><a href="../..">cm-chessboard</a></h1>
14
14
  <h2>Example: RightClickAnnotator extension</h2>
15
- <p>Right-click to toggle green markers. Right-click + drag to draw green arrows. Use Alt for blue, Shift for red, Shift+Alt for orange.</p>
15
+ <ul>
16
+ <li>Right-click to toggle green markers</li>
17
+ <li>Right-click + drag to draw green arrows</li>
18
+ <li>Use Alt for blue, Shift for red, Shift+Alt for orange</li>
19
+ </ul>
16
20
  <div class="board" id="board"></div>
21
+ <button id="removeAllButton">Remove all annotations</button>
17
22
  <script type="module">
18
23
  import {Chessboard} from "../../src/Chessboard.js"
19
24
  import {FEN} from "../../src/model/Position.js"
@@ -24,6 +29,11 @@
24
29
  assetsUrl: "../../assets/",
25
30
  extensions: [{class: RightClickAnnotator}]
26
31
  })
32
+
33
+ document.getElementById("removeAllButton").addEventListener("click", (event) => {
34
+ board.removeArrows()
35
+ board.removeMarkers()
36
+ })
27
37
  </script>
28
38
  </body>
29
39
  </html>
@@ -7,6 +7,7 @@
7
7
  <link rel="stylesheet" href="styles/examples.css"/>
8
8
  <link rel="stylesheet" href="../assets/chessboard.css"/>
9
9
  <link rel="stylesheet" href="../assets/extensions/markers/markers.css"/>
10
+ <link rel="stylesheet" href="../assets/extensions/arrows/arrows.css"/>
10
11
  <link rel="stylesheet" href="../assets/extensions/promotion-dialog/promotion-dialog.css"/>
11
12
  </head>
12
13
  <body>
@@ -22,6 +23,7 @@
22
23
  import {PROMOTION_DIALOG_RESULT_TYPE, PromotionDialog} from "../src/extensions/promotion-dialog/PromotionDialog.js"
23
24
  import {Accessibility} from "../src/extensions/accessibility/Accessibility.js"
24
25
  import {Chess} from "https://cdn.jsdelivr.net/npm/chess.mjs@1/src/chess.mjs/Chess.js"
26
+ import {RightClickAnnotator} from "../src/extensions/right-click-annotator/RightClickAnnotator.js";
25
27
 
26
28
  const chess = new Chess()
27
29
 
@@ -101,6 +103,7 @@
101
103
  orientation: COLOR.white,
102
104
  extensions: [
103
105
  {class: Markers, props: {autoMarkers: MARKER_TYPE.square}},
106
+ {class: RightClickAnnotator},
104
107
  {class: PromotionDialog},
105
108
  {class: Accessibility, props: {visuallyHidden: true}}
106
109
  ]
package/index.html CHANGED
@@ -9,31 +9,42 @@
9
9
  </head>
10
10
  <body>
11
11
  <h1>cm-chessboard</h1>
12
- <p><i>A JavaScript chessboard which is lightweight, ES6 module based, responsive, SVG rendered and without dependencies.</i></p>
13
- <p>cm-chessboard is the chessboard of <a href="https://www.chessmail.de">chessmail</a> and is used every day by thousands of players.
14
- It works, it is cool and it is easy to use. 👍</p>
15
- <p><a href="https://github.com/shaack/cm-chessboard">Repository and documentation on GitHub</a></p>
12
+ <p>A JavaScript chessboard which is</p>
13
+ <ul>
14
+ <li>lightweight and ES6 module based</li>
15
+ <li>responsive and SVG rendered</li>
16
+ <li><b>without dependencies</b> 🥳</li>
17
+ <li>tested and it works</li>
18
+ </ul>
19
+
20
+ <p>cm-chessboard is the chessboard of <b><a href="https://www.chessmail.de">chessmail.de</a></b> and is used every day by <b>thousands of players</b>.</p>
21
+
22
+ <p class="text-info">cm-chessboard is easy to use: <a href="https://github.com/shaack/cm-chessboard">Repository and documentation on GitHub</a></p>
16
23
  <div>
17
24
  <h2>Examples</h2>
18
25
  <ul>
26
+ <li><a href="examples/extensions/right-click-annotator.html">Draw Arrows and Markers with right-click</a> 🆕🔥</li>
19
27
  <li><a href="examples/simple-boards.html">Simple chessboards, view only</a></li>
20
28
  <li><a href="examples/responsive-board.html">Responsive chessboard</a></li>
21
29
  <li><a href="examples/enable-input.html">Input enabled without validation</a></li>
22
30
  <li><a href="examples/validate-moves.html">Input enabled, with move validation and promotion dialog</a> 🔥</li>
23
31
  <li><a href="examples/pieces-animation.html">Set different positions, with animation</a></li>
24
- <li><a href="examples/extensions/markers-extension.html">Context input, mark squares and detect clicks on fields</a></li>
25
32
  <li><a href="examples/different-styles.html">Different styles and piece sets</a> 🎨</li>
26
- <li><a href="examples/pointer-events.html">Pointer events on squares</a> 🆕</li>
27
33
  <li><a href="examples/destroy-many-boards.html">Stress test, 5000 boards created and destroyed</a> 🤓 👍</li>
28
34
  </ul>
29
- <h3>Examples using the cm-chessboard extensions</h3>
35
+ <h3>Examples for the shipped cm-chessboard extensions</h3>
30
36
  <ul>
31
- <li><a href="examples/extensions/markers-extension.html">Markers extension</a></li>
32
- <li><a href="examples/extensions/arrows-extension.html">Arrows extension</a></li>
33
- <li><a href="examples/extensions/html-layer-extension.html">HTML Layer extension</a></li>
34
- <li><a href="examples/extensions/promotion-dialog-extension.html">PromotionDialog extension</a></li>
35
- <li><a href="examples/extensions/accessibility-extension.html">Accessibility extension</a></li>
36
- <li><a href="examples/extensions/right-click-annotator.html">RightClickAnnotator extension</a></li>
37
+ <li>
38
+ Draw arrows and markers on the board with
39
+ <a href="examples/extensions/right-click-annotator.html">RightClickAnnotator extension</a> 🆕🔥
40
+ <ul>
41
+ <li><a href="examples/extensions/markers-extension.html">Markers extension</a></li>
42
+ <li><a href="examples/extensions/arrows-extension.html">Arrows extension</a></li>
43
+ </ul>
44
+ </li>
45
+ <li>Draw HTML over the board with <a href="examples/extensions/html-layer-extension.html">HTML Layer extension</a></li>
46
+ <li>Allow displaying a promotion dialog with <a href="examples/extensions/promotion-dialog-extension.html">PromotionDialog extension</a></li>
47
+ <li>Make the board accessible with screen-reader support with <a href="examples/extensions/accessibility-extension.html">Accessibility extension</a></li>
37
48
  </ul>
38
49
  </div>
39
50
  <h2>Chessboard</h2>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cm-chessboard",
3
- "version": "8.9.0",
3
+ "version": "8.10.0",
4
4
  "description": "A JavaScript chessboard which is lightweight, ES6 module based, responsive, SVG rendered and without dependencies.",
5
5
  "keywords": [
6
6
  "chess",
@@ -5,6 +5,7 @@
5
5
  */
6
6
 
7
7
  import {Extension, EXTENSION_POINT} from "../../model/Extension.js"
8
+ import {Svg} from "../../lib/Svg.js"
8
9
  import {Utils} from "../../lib/Utils.js"
9
10
 
10
11
  export const ARROW_TYPE = {
@@ -15,6 +15,7 @@ export const MARKER_TYPE = {
15
15
  circle: {class: "marker-circle", slice: "markerCircle"},
16
16
  circlePrimary: {class: "marker-circle-primary", slice: "markerCircle"},
17
17
  circleDanger: {class: "marker-circle-danger", slice: "markerCircle"},
18
+ circleDangerFilled: {class: "marker-circle-danger-filled", slice: "markerCircleFilled"},
18
19
  square: {class: "marker-square", slice: "markerSquare"},
19
20
  dot: {class: "marker-dot", slice: "markerDot", position: 'above'},
20
21
  bevel: {class: "marker-bevel", slice: "markerBevel"}
@@ -10,17 +10,26 @@
10
10
  */
11
11
  import {Extension, EXTENSION_POINT} from "../../model/Extension.js"
12
12
  import {Arrows} from "../arrows/Arrows.js"
13
- import {Markers, MARKER_TYPE} from "../markers/Markers.js"
13
+ import {Markers} from "../markers/Markers.js"
14
14
  import {Svg} from "../../lib/Svg.js"
15
15
 
16
16
  export const ARROW_TYPE = {
17
- warning: { class: "arrow-warning", slice: "arrowDefault", headSize: 7}
17
+ success: { class: "arrow-success"},
18
+ warning: { class: "arrow-warning"},
19
+ info: { class: "arrow-info"},
20
+ danger: { class: "arrow-danger"}
18
21
  }
19
- export const MARKER_TYPE = {
20
22
 
23
+ export const MARKER_TYPE = {
24
+ success: {class: "marker-circle-success", slice: "markerCircle"},
25
+ warning: {class: "marker-circle-warning", slice: "markerCircle"},
26
+ info: {class: "marker-circle-info", slice: "markerCircle"},
27
+ danger: {class: "marker-circle-danger", slice: "markerCircle"},
21
28
  }
22
29
 
23
30
  export class RightClickAnnotator extends Extension {
31
+
32
+ /** @constructor */
24
33
  constructor(chessboard, props = {}) {
25
34
  super(chessboard)
26
35
  this.props = props || {}
@@ -39,7 +48,6 @@ export class RightClickAnnotator extends Extension {
39
48
  this.onMouseUp = this.onMouseUp.bind(this)
40
49
 
41
50
  this.dragStart = undefined // {square, modifiers}
42
- this.previewGroup = undefined
43
51
  this.previewActiveTo = undefined // cache last to-square for preview
44
52
 
45
53
  this.chessboard.context.addEventListener("contextmenu", this.onContextMenu)
@@ -48,11 +56,6 @@ export class RightClickAnnotator extends Extension {
48
56
  this.chessboard.context.addEventListener("mouseup", this.onMouseUp)
49
57
  this.chessboard.context.addEventListener("mouseleave", this.onMouseUp)
50
58
 
51
- // ensure preview group exists after redraws
52
- this.registerExtensionPoint(EXTENSION_POINT.afterRedrawBoard, () => {
53
- this.ensurePreviewGroup()
54
- })
55
-
56
59
  this.registerExtensionPoint(EXTENSION_POINT.destroy, () => {
57
60
  this.chessboard.context.removeEventListener("contextmenu", this.onContextMenu)
58
61
  this.chessboard.context.removeEventListener("mousedown", this.onMouseDown)
@@ -60,12 +63,35 @@ export class RightClickAnnotator extends Extension {
60
63
  this.chessboard.context.removeEventListener("mouseup", this.onMouseUp)
61
64
  this.chessboard.context.removeEventListener("mouseleave", this.onMouseUp)
62
65
  })
63
- // create preview group now
64
- this.ensurePreviewGroup()
66
+
67
+ // register public API
68
+ this.chessboard.getAnnotations = this.getAnnotations.bind(this.chessboard)
69
+ this.chessboard.setAnnotations = this.setAnnotations.bind(this.chessboard)
70
+ }
71
+
72
+ getAnnotations() {
73
+ return {
74
+ arrows: this.chessboard.getArrows(),
75
+ markers: this.chessboard.getMarkers()
76
+ }
77
+ }
78
+
79
+ setAnnotations(annotations) {
80
+ this.chessboard.removeArrows()
81
+ this.chessboard.removeMarkers()
82
+ if (annotations.arrows) {
83
+ for (const arrow of annotations.arrows) {
84
+ this.chessboard.addArrow(arrow.type, arrow.from, arrow.to)
85
+ }
86
+ }
87
+ if (annotations.markers) {
88
+ for (const marker of annotations.markers) {
89
+ this.chessboard.addMarker(marker.type, marker.square)
90
+ }
91
+ }
65
92
  }
66
93
 
67
94
  onContextMenu(event) {
68
- // prevent default context menu on chessboard
69
95
  event.preventDefault()
70
96
  }
71
97
 
@@ -89,9 +115,9 @@ export class RightClickAnnotator extends Extension {
89
115
 
90
116
  onMouseUp(event) {
91
117
  // clear preview regardless of button, but only act on right-button release
118
+ this.removePreviewArrow()
92
119
  const start = this.dragStart
93
120
  this.dragStart = undefined
94
- this.clearPreview()
95
121
  if (!start || event.button !== 2) {
96
122
  return
97
123
  }
@@ -130,27 +156,6 @@ export class RightClickAnnotator extends Extension {
130
156
  return el ? el.getAttribute("data-square") : undefined
131
157
  }
132
158
 
133
- ensurePreviewGroup() {
134
- // create or reset preview group used for transient arrow drawing
135
- if (!this.chessboard?.view?.markersTopLayer) {
136
- return
137
- }
138
- if (this.previewGroup && this.previewGroup.parentNode) {
139
- // keep and clear existing
140
- this.clearPreview()
141
- return
142
- }
143
- this.previewGroup = Svg.addElement(this.chessboard.view.markersTopLayer, "g", {class: "right-click-annotator-preview"})
144
- }
145
-
146
- clearPreview() {
147
- if (!this.previewGroup) return
148
- while (this.previewGroup.firstChild) {
149
- this.previewGroup.removeChild(this.previewGroup.firstChild)
150
- }
151
- this.previewActiveTo = undefined
152
- }
153
-
154
159
  onMouseMove(event) {
155
160
  if (!this.dragStart) {
156
161
  return
@@ -159,7 +164,6 @@ export class RightClickAnnotator extends Extension {
159
164
  // We rely mainly on our dragStart flag and clear on mouseup/mouseleave
160
165
  const toSquare = this.findSquareFromEvent(event)
161
166
  if (!toSquare || toSquare === this.dragStart.square) {
162
- this.clearPreview()
163
167
  return
164
168
  }
165
169
  if (this.previewActiveTo === toSquare) {
@@ -172,80 +176,38 @@ export class RightClickAnnotator extends Extension {
172
176
  }
173
177
 
174
178
  drawPreviewArrow(from, to, type) {
175
- this.ensurePreviewGroup()
176
- this.clearPreview()
177
- const view = this.chessboard.view
178
- const arrowsGroup = Svg.addElement(this.previewGroup, "g", {class: "arrow " + type.class})
179
- const ptFrom = view.squareToPoint(from)
180
- const ptTo = view.squareToPoint(to)
181
- const defs = Svg.addElement(arrowsGroup, "defs")
182
- const id = "arrow-preview-" + from + to
183
- const marker = Svg.addElement(defs, "marker", {
184
- id: id,
185
- markerWidth: type.headSize,
186
- markerHeight: type.headSize,
187
- refX: 20,
188
- refY: 20,
189
- viewBox: "0 0 40 40",
190
- orient: "auto",
191
- class: "arrow-head",
192
- })
193
- const spriteUrl = this.chessboard.props.assetsCache ? "" : this.chessboard.getExtension(Arrows)?.getSpriteUrl?.() || this.chessboard.props.assetsUrl + "extensions/arrows/arrows.svg"
194
- Svg.addElement(marker, "use", {href: `${spriteUrl}#${type.slice}`})
195
- // Compute centers of start and end squares
196
- const cx1 = ptFrom.x + view.squareWidth / 2
197
- const cy1 = ptFrom.y + view.squareHeight / 2
198
- const cx2 = ptTo.x + view.squareWidth / 2
199
- const cy2 = ptTo.y + view.squareHeight / 2
200
-
201
- // Offset the line so it starts/ends at the edge of an invisible circle inside each square
202
- const dx = cx2 - cx1
203
- const dy = cy2 - cy1
204
- const len = Math.hypot(dx, dy) || 1
205
- const ux = dx / len
206
- const uy = dy / len
207
- // get offsets from Arrows extension props to match final arrow rendering
208
- const arrowsExt = this.chessboard.getExtension(Arrows)
209
- const offsetFrom = arrowsExt?.props?.offsetFrom ?? 0.72
210
- const offsetTo = arrowsExt?.props?.offsetTo ?? 0.72
211
- const halfMin = Math.min(view.squareWidth, view.squareHeight) / 2
212
- const clamp01 = (v) => Math.max(0, Math.min(1, v))
213
- const rFrom = halfMin * clamp01(offsetFrom)
214
- const rTo = halfMin * clamp01(offsetTo)
215
- const x1 = cx1 + ux * rFrom
216
- const y1 = cy1 + uy * rFrom
217
- const x2 = cx2 - ux * rTo
218
- const y2 = cy2 - uy * rTo
219
-
220
- const width = ((view.scalingX + view.scalingY) / 2) * 8
221
- let lineFill = Svg.addElement(arrowsGroup, "line")
222
- lineFill.setAttribute('x1', x1.toString())
223
- lineFill.setAttribute('x2', x2.toString())
224
- lineFill.setAttribute('y1', y1.toString())
225
- lineFill.setAttribute('y2', y2.toString())
226
- lineFill.setAttribute('class', 'arrow-line')
227
- lineFill.setAttribute("marker-end", "url(#" + id + ")")
228
- lineFill.setAttribute('stroke-width', width + "px")
179
+ if(!this.previewArrowType) {
180
+ this.previewArrowType = {...type}
181
+ }
182
+ this.chessboard.removeArrows(this.previewArrowType)
183
+ this.chessboard.addArrow(this.previewArrowType, from, to)
184
+ }
185
+
186
+ removePreviewArrow() {
187
+ if(this.previewArrowType) {
188
+ this.chessboard.removeArrows(this.previewArrowType)
189
+ this.previewArrowType = undefined
190
+ }
229
191
  }
230
192
 
231
193
  modifiersToColorKey(modifiers) {
232
- if (modifiers.shift && modifiers.alt) return "orange"
233
- if (modifiers.shift) return "red"
234
- if (modifiers.alt) return "blue"
235
- return "orange"
194
+ if (modifiers.shift && modifiers.alt) return "warning"
195
+ if (modifiers.shift) return "danger"
196
+ if (modifiers.alt) return "info"
197
+ return "success"
236
198
  }
237
199
 
238
200
  typesForColorKey(colorKey) {
239
201
  switch (colorKey) {
240
- case "blue":
241
- return {arrowType: ARROW_TYPE.default, circleType: MARKER_TYPE.circlePrimary}
242
- case "red":
243
- return {arrowType: ARROW_TYPE.danger, circleType: MARKER_TYPE.circleDanger}
244
- case "orange":
245
- return {arrowType: ARROW_ORANGE, circleType: CIRCLE_ORANGE}
246
- case "green":
202
+ case "info":
203
+ return {arrowType: ARROW_TYPE.info, circleType: MARKER_TYPE.info}
204
+ case "danger":
205
+ return {arrowType: ARROW_TYPE.danger, circleType: MARKER_TYPE.danger}
206
+ case "warning":
207
+ return {arrowType: ARROW_TYPE.warning, circleType: MARKER_TYPE.warning}
208
+ case "success":
247
209
  default:
248
- return {arrowType: ARROW_GREEN, circleType: CIRCLE_GREEN}
210
+ return {arrowType: ARROW_TYPE.success, circleType: MARKER_TYPE.success}
249
211
  }
250
212
  }
251
213
  }