@mirasen/chessboard 1.1.4 → 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,11 @@
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
+
3
9
  ## 1.1.4
4
10
 
5
11
  ### Patch Changes
package/README.md CHANGED
@@ -275,6 +275,12 @@ board = createBoard({
275
275
  });
276
276
  ```
277
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
+
278
284
  ## Architecture
279
285
 
280
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.4",
4
+ "version": "1.1.5",
5
5
  "license": "MIT",
6
6
  "author": {
7
7
  "name": "Mirasen",