@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 +6 -0
- package/README.md +6 -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
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,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