@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 +12 -0
- package/README.md +10 -0
- package/assets/watermark/mirasen.svg +10 -0
- package/dist/extensions/first-party/watermark/factory.d.ts +2 -0
- package/dist/extensions/first-party/watermark/factory.js +82 -0
- package/dist/extensions/first-party/watermark/types.d.ts +13 -0
- package/dist/extensions/first-party/watermark/types.js +2 -0
- package/dist/extensions/types/wrapper.d.ts +3 -1
- package/dist/extensions/types/wrapper.js +4 -0
- package/package.json +1 -1
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,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
|
+
}
|
|
@@ -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