@mirasen/chessboard 1.4.0 → 1.5.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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @mirasen/chessboard
2
2
 
3
+ ## 1.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 5c12439: Extend the check extension's `square` input to accept a color (`ColorInput`) in addition to a `SquareString`. When a color is provided, the highlight is placed on that color's king square.
8
+
3
9
  ## 1.4.0
4
10
 
5
11
  ### Minor Changes
@@ -1,9 +1,10 @@
1
1
  import assert from '@ktarmyshov/assert';
2
2
  import { toMerged } from 'es-toolkit';
3
- import { isSquareString } from '../../../state/board/check.js';
4
- import { denormalizeSquare } from '../../../state/board/denormalize.js';
5
- import { normalizeSquare } from '../../../state/board/normalize.js';
6
3
  import { createSvgElement, updateSvgElementAttributes } from '../../../render/svg/helpers.js';
4
+ import { isColorInput, isSquareString } from '../../../state/board/check.js';
5
+ import { normalizeColor, normalizeSquare } from '../../../state/board/normalize.js';
6
+ import { toPieceCode } from '../../../state/board/piece.js';
7
+ import { SQUARE_COUNT } from '../../../state/board/types/internal.js';
7
8
  import { isUpdateContextRenderable } from '../../types/context/update.js';
8
9
  import { extensionCreateInternalBase, extensionDestroyBase, extensionMountBase, extensionUnmountBase } from '../common/helpers.js';
9
10
  import { markHighlightDirtyAndRequestRender } from './invalidation.js';
@@ -22,6 +23,7 @@ function createCheckInternal(options, config) {
22
23
  return {
23
24
  ...extensionCreateInternalBase(options),
24
25
  square: null,
26
+ inputSquare: null,
25
27
  svgRect: null,
26
28
  svgGradient: null,
27
29
  runtimeSurface: options.runtimeSurface,
@@ -35,10 +37,23 @@ function extensionClean(state) {
35
37
  function createCheckInstancePublic(state) {
36
38
  return {
37
39
  get square() {
38
- return state.square === null ? null : denormalizeSquare(state.square);
40
+ return state.inputSquare;
39
41
  },
40
42
  set square(value) {
41
- const next = value === null ? null : normalizeSquare(assertSquareString(value));
43
+ let next;
44
+ if (value === null) {
45
+ next = null;
46
+ }
47
+ else if (isSquareString(value)) {
48
+ next = normalizeSquare(value);
49
+ }
50
+ else if (isColorInput(value)) {
51
+ next = findKing(state, value);
52
+ }
53
+ else {
54
+ throw new TypeError(`Invalid check square: ${String(value)}`);
55
+ }
56
+ state.inputSquare = value;
42
57
  if (next === state.square) {
43
58
  return; // no-op: same square (or both null)
44
59
  }
@@ -47,11 +62,18 @@ function createCheckInstancePublic(state) {
47
62
  }
48
63
  };
49
64
  }
50
- function assertSquareString(value) {
51
- if (!isSquareString(value)) {
52
- throw new TypeError(`Invalid check square: ${String(value)}`);
65
+ function findKing(state, color) {
66
+ const snapshot = state.runtimeSurface.commands.getSnapshot();
67
+ const pieces = snapshot.state.board.pieces;
68
+ const colorCode = normalizeColor(color);
69
+ const kingPieceCode = toPieceCode(6 /* RoleCode.King */, colorCode);
70
+ for (let sq = 0; sq < SQUARE_COUNT; sq++) {
71
+ const piece = pieces[sq];
72
+ if (piece === kingPieceCode) {
73
+ return sq;
74
+ }
53
75
  }
54
- return value;
76
+ throw new Error("King of color '" + color + "' not found");
55
77
  }
56
78
  function removeHighlight(state) {
57
79
  if (state.svgRect !== null) {
@@ -1,9 +1,9 @@
1
1
  import { PartialDeep } from 'type-fest';
2
+ import type { ColorInput, SquareString } from '../../../state/board/types/input.js';
2
3
  import type { Square } from '../../../state/board/types/internal.js';
3
4
  import { ExtensionDefinition, ExtensionInstance } from '../../types/extension.js';
4
- import { ExtensionInternalBase, OpaqueColor } from '../common/types.js';
5
5
  import type { ExtensionRuntimeSurface } from '../../types/surface/main.js';
6
- import type { SquareString } from '../../../state/board/types/input.js';
6
+ import { ExtensionInternalBase, OpaqueColor } from '../common/types.js';
7
7
  export declare const EXTENSION_SLOTS: readonly ["defs", "underPieces"];
8
8
  export type ExtensionSlotsType = typeof EXTENSION_SLOTS;
9
9
  export declare const EXTENSION_ID: "check";
@@ -24,12 +24,13 @@ export declare const GRADIENT_STOPS: readonly [{
24
24
  }];
25
25
  export type CheckInitConfig = PartialDeep<CheckConfig>;
26
26
  export type CheckPublic = {
27
- square: SquareString | null;
27
+ square: SquareString | ColorInput | null;
28
28
  };
29
29
  export type CheckDefinition = ExtensionDefinition<typeof EXTENSION_ID, typeof EXTENSION_SLOTS, CheckPublic>;
30
30
  export type CheckInstance = ExtensionInstance<typeof EXTENSION_ID, typeof EXTENSION_SLOTS, CheckPublic>;
31
31
  export interface CheckInstanceInternal extends ExtensionInternalBase<ExtensionSlotsType> {
32
32
  square: Square | null;
33
+ inputSquare: SquareString | ColorInput | null;
33
34
  svgRect: SVGRectElement | null;
34
35
  svgGradient: SVGRadialGradientElement | null;
35
36
  readonly runtimeSurface: ExtensionRuntimeSurface;
@@ -1,4 +1,4 @@
1
- import { Color, ColorShort, MoveRequestInput, Piece, PiecePositionInput, PiecePositionRecord, PiecePositionRecordShort, PiecePositionRecordString, PieceShort, PieceString, Role, RoleShort, SquareString } from './types/input.js';
1
+ import { Color, ColorInput, ColorShort, MoveRequestInput, Piece, PiecePositionInput, PiecePositionRecord, PiecePositionRecordShort, PiecePositionRecordString, PieceShort, PieceString, Role, RoleShort, SquareString } from './types/input.js';
2
2
  import { EmptyPieceCode, MoveRequest, NonEmptyPieceCode, PieceCode, PiecePositionSnapshot, PositionSnapshot, RolePromotionCode, Square, SquareFile, SquareRank } from './types/internal.js';
3
3
  import type { BoardStateSnapshot } from './types/main.js';
4
4
  export declare function isWhitePieceCode(code: NonEmptyPieceCode): boolean;
@@ -17,6 +17,7 @@ export declare function isPieceString(value: unknown): value is PieceString;
17
17
  export declare function isSquareString(value: unknown): value is SquareString;
18
18
  export declare function isPositionMapString(pos: PiecePositionInput): pos is PiecePositionRecordString;
19
19
  export declare function isColorShort(value: unknown): value is ColorShort;
20
+ export declare function isColorInput(value: unknown): value is ColorInput;
20
21
  export declare function isRoleShort(value: unknown): value is RoleShort;
21
22
  export declare function isPieceShort(value: unknown): value is PieceShort;
22
23
  export declare function isPositionMapShort(pos: PiecePositionInput): pos is PiecePositionRecordShort;
@@ -74,6 +74,9 @@ export function isPositionMapString(pos) {
74
74
  export function isColorShort(value) {
75
75
  return value === 'w' || value === 'b';
76
76
  }
77
+ export function isColorInput(value) {
78
+ return isColor(value) || isColorShort(value);
79
+ }
77
80
  export function isRoleShort(value) {
78
81
  return (value === 'K' ||
79
82
  value === 'Q' ||
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mirasen/chessboard",
3
3
  "description": "Production-grade framework-agnostic TypeScript chessboard platform with real chess interaction built in.",
4
- "version": "1.4.0",
4
+ "version": "1.5.0",
5
5
  "license": "MIT",
6
6
  "author": {
7
7
  "name": "Mirasen"