@mirasen/chessboard 1.1.3 → 1.1.5

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,17 @@
1
1
  # @mirasen/chessboard
2
2
 
3
+ ## 1.1.5
4
+
5
+ ### Patch Changes
6
+
7
+ - 1256271: Add a subtle default Mirasen board watermark.
8
+
9
+ ## 1.1.4
10
+
11
+ ### Patch Changes
12
+
13
+ - 86d630d: Link to the React chessboard package from the README.
14
+
3
15
  ## 1.1.3
4
16
 
5
17
  ### Patch Changes
package/README.md CHANGED
@@ -14,6 +14,10 @@ A framework-agnostic TypeScript chessboard platform with real chess interaction
14
14
  - [Try the promotion flow](https://mirasen.io/chessboard/examples/promotion.html)
15
15
  - [Try the minimal example](https://mirasen.io/chessboard/examples/minimal.html)
16
16
 
17
+ ## Using React?
18
+
19
+ Use [`@mirasen/react-chessboard`](https://github.com/mirasen-io/react-chessboard) for a React component with the same built-in interaction, promotion, animation, and chess.js integration.
20
+
17
21
  ## Why this exists
18
22
 
19
23
  Most chessboards fall into one of two buckets:
@@ -271,6 +275,12 @@ board = createBoard({
271
275
  });
272
276
  ```
273
277
 
278
+ ### Default visual identity
279
+
280
+ The default first-party extension baseline includes a subtle Mirasen board watermark.
281
+
282
+ If you want full control over the visual baseline, use an explicit extension list and omit the `watermark` extension.
283
+
274
284
  ## Architecture
275
285
 
276
286
  `@mirasen/chessboard` is built around explicit boundaries:
@@ -0,0 +1,10 @@
1
+ <svg width="512" height="512" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path
3
+ d="M41.91 158.82V41.18H62.5L100.74 108.82L138.97 41.18H159.56V158.82H138.97V76.47L105.15 161.76H96.32L62.5 76.47V158.82H41.91Z"
4
+ fill="#707a8a"
5
+ />
6
+
7
+ <circle cx="62.5" cy="41.18" r="12" fill="#9F8B4A" />
8
+ <circle cx="100.74" cy="108.82" r="12" fill="#9F8B4A" />
9
+ <circle cx="138.97" cy="41.18" r="12" fill="#9F8B4A" />
10
+ </svg>
@@ -0,0 +1,2 @@
1
+ import { WatermarkDefinition } from './types.js';
2
+ export declare function createWatermark(): WatermarkDefinition;
@@ -0,0 +1,82 @@
1
+ import assert from '@ktarmyshov/assert';
2
+ import { createSvgElement, updateElementAttributes } from '../../../render/svg/helpers.js';
3
+ import { isUpdateContextRenderable } from '../../types/context/update.js';
4
+ import { extensionCreateInternalBase, extensionDestroyBase, extensionMountBase, extensionUnmountBase } from '../common/helpers.js';
5
+ import { EXTENSION_ID, EXTENSION_SLOTS } from './types.js';
6
+ export function createWatermark() {
7
+ return {
8
+ id: EXTENSION_ID,
9
+ slots: EXTENSION_SLOTS,
10
+ createInstance() {
11
+ return createWatermarkInstance();
12
+ }
13
+ };
14
+ }
15
+ function createWatermarkInternal() {
16
+ return {
17
+ ...extensionCreateInternalBase(),
18
+ svgWatermark: null
19
+ };
20
+ }
21
+ function extensionClean(state) {
22
+ state.svgWatermark = null;
23
+ }
24
+ const watermarkUrl = new URL('../../../../assets/watermark/mirasen.svg', import.meta.url).toString();
25
+ const squareRatio = 0.8; // watermark size relative to square size
26
+ const opacity = '0.3';
27
+ function createWatermarkInstance() {
28
+ const internalState = createWatermarkInternal();
29
+ return {
30
+ id: EXTENSION_ID,
31
+ mount(env) {
32
+ extensionMountBase(internalState, env.slotRoots);
33
+ },
34
+ onUpdate(context) {
35
+ const needsRender = context.mutation.hasMutation({
36
+ causes: ['layout.refreshGeometry']
37
+ }) && isUpdateContextRenderable(context);
38
+ if (!needsRender) {
39
+ return;
40
+ }
41
+ context.invalidation.markDirty(1 /* DirtyLayer.Watermark */);
42
+ },
43
+ render(context) {
44
+ assert(context.invalidation.dirtyLayers !== 0, 'Render should only be called when there are dirty layers');
45
+ const watermarkSquare = context.currentFrame.state.view.orientation === 0 /* ColorCode.White */ ? 7 : 56;
46
+ const geometry = context.currentFrame.layout.geometry;
47
+ const r = geometry.getSquareRect(watermarkSquare);
48
+ const centerX = r.x + r.width / 2;
49
+ const centerY = r.y + r.height / 2;
50
+ const size = Math.min(r.width, r.height) * squareRatio;
51
+ const x = centerX - size / 2;
52
+ const y = centerY - size / 2;
53
+ const watermarkAttributes = {
54
+ opacity: opacity,
55
+ x: x.toString(),
56
+ y: y.toString(),
57
+ width: size.toString(),
58
+ height: size.toString(),
59
+ href: watermarkUrl,
60
+ 'pointer-events': 'none'
61
+ };
62
+ if (internalState.svgWatermark === null) {
63
+ assert(internalState.slotRoots, 'Slot roots should be available when render is called');
64
+ internalState.svgWatermark = createSvgElement(internalState.slotRoots.board, 'image', {
65
+ 'data-chessboard-id': 'watermark',
66
+ ...watermarkAttributes
67
+ });
68
+ }
69
+ else {
70
+ updateElementAttributes(internalState.svgWatermark, watermarkAttributes);
71
+ }
72
+ },
73
+ unmount() {
74
+ extensionUnmountBase(internalState);
75
+ extensionClean(internalState);
76
+ },
77
+ destroy() {
78
+ extensionDestroyBase(internalState);
79
+ extensionClean(internalState);
80
+ }
81
+ };
82
+ }
@@ -0,0 +1,13 @@
1
+ import { ExtensionDefinition, ExtensionInstance } from '../../types/extension.js';
2
+ import { ExtensionInternalBase } from '../common/types.js';
3
+ export declare const EXTENSION_SLOTS: readonly ["board"];
4
+ export type ExtensionSlotsType = typeof EXTENSION_SLOTS;
5
+ export declare const EXTENSION_ID: "watermark";
6
+ export type WatermarkDefinition = ExtensionDefinition<typeof EXTENSION_ID, typeof EXTENSION_SLOTS, never>;
7
+ export type WatermarkInstance = ExtensionInstance<typeof EXTENSION_ID, typeof EXTENSION_SLOTS, never>;
8
+ export interface WatermarkInstanceInternal extends ExtensionInternalBase<ExtensionSlotsType> {
9
+ svgWatermark: SVGImageElement | null;
10
+ }
11
+ export declare const enum DirtyLayer {
12
+ Watermark = 1
13
+ }
@@ -0,0 +1,2 @@
1
+ export const EXTENSION_SLOTS = ['board'];
2
+ export const EXTENSION_ID = 'watermark';
@@ -6,8 +6,10 @@ import { createLegalMoves } from '../first-party/legal-moves/factory.js';
6
6
  import { createMainRenderer } from '../first-party/main-renderer/factory.js';
7
7
  import { createPromotion } from '../first-party/promotion/factory.js';
8
8
  import { createSelectedSquare } from '../first-party/selected-square/factory.js';
9
+ import { createWatermark } from '../first-party/watermark/factory.js';
9
10
  export declare const builtInExtensionFactoryMap: {
10
11
  renderer: typeof createMainRenderer;
12
+ watermark: typeof createWatermark;
11
13
  selectedSquare: typeof createSelectedSquare;
12
14
  lastMove: typeof createLastMove;
13
15
  activeTarget: typeof createActiveTarget;
@@ -20,5 +22,5 @@ export type BuiltInExtensionId = keyof typeof builtInExtensionFactoryMap;
20
22
  export type BuiltInExtensionDefinitionMap = {
21
23
  [Id in BuiltInExtensionId]: ReturnType<(typeof builtInExtensionFactoryMap)[Id]>;
22
24
  };
23
- export declare const DefaultBuiltinChessboardExtensions: readonly ["renderer", "selectedSquare", "lastMove", "activeTarget", "legalMoves", "events", "autoPromote", "promotion"];
25
+ export declare const DefaultBuiltinChessboardExtensions: readonly ["renderer", "watermark", "selectedSquare", "lastMove", "activeTarget", "legalMoves", "events", "autoPromote", "promotion"];
24
26
  export type DefaultBuiltinChessboardExtensions = typeof DefaultBuiltinChessboardExtensions;
@@ -14,8 +14,11 @@ import { createPromotion } from '../first-party/promotion/factory.js';
14
14
  import { EXTENSION_ID as EXTENSION_ID_PROMOTION } from '../first-party/promotion/types/main.js';
15
15
  import { createSelectedSquare } from '../first-party/selected-square/factory.js';
16
16
  import { EXTENSION_ID as EXTENSION_ID_SELECTED_SQUARE } from '../first-party/selected-square/types.js';
17
+ import { createWatermark } from '../first-party/watermark/factory.js';
18
+ import { EXTENSION_ID as EXTENSION_ID_WATERMARK } from '../first-party/watermark/types.js';
17
19
  export const builtInExtensionFactoryMap = {
18
20
  [EXTENSION_ID_RENDERER]: createMainRenderer,
21
+ [EXTENSION_ID_WATERMARK]: createWatermark,
19
22
  [EXTENSION_ID_SELECTED_SQUARE]: createSelectedSquare,
20
23
  [EXTENSION_ID_LAST_MOVE]: createLastMove,
21
24
  [EXTENSION_ID_ACTIVE_TARGET]: createActiveTarget,
@@ -26,6 +29,7 @@ export const builtInExtensionFactoryMap = {
26
29
  };
27
30
  export const DefaultBuiltinChessboardExtensions = [
28
31
  EXTENSION_ID_RENDERER,
32
+ EXTENSION_ID_WATERMARK,
29
33
  EXTENSION_ID_SELECTED_SQUARE,
30
34
  EXTENSION_ID_LAST_MOVE,
31
35
  EXTENSION_ID_ACTIVE_TARGET,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mirasen/chessboard",
3
3
  "description": "Framework-agnostic TypeScript chessboard platform with real chess interaction built in.",
4
- "version": "1.1.3",
4
+ "version": "1.1.5",
5
5
  "license": "MIT",
6
6
  "author": {
7
7
  "name": "Mirasen",