@mirasen/chessboard 0.1.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 +7 -0
- package/LICENSE +21 -0
- package/README.md +96 -0
- package/assets/pieces/chessnut/ATTRIBUTION.md +13 -0
- package/assets/pieces/chessnut/LICENSE.txt +202 -0
- package/assets/pieces/chessnut/bB.svg +58 -0
- package/assets/pieces/chessnut/bK.svg +51 -0
- package/assets/pieces/chessnut/bN.svg +19 -0
- package/assets/pieces/chessnut/bP.svg +17 -0
- package/assets/pieces/chessnut/bQ.svg +97 -0
- package/assets/pieces/chessnut/bR.svg +34 -0
- package/assets/pieces/chessnut/wB.svg +61 -0
- package/assets/pieces/chessnut/wK.svg +71 -0
- package/assets/pieces/chessnut/wN.svg +19 -0
- package/assets/pieces/chessnut/wP.svg +17 -0
- package/assets/pieces/chessnut/wQ.svg +40 -0
- package/assets/pieces/chessnut/wR.svg +38 -0
- package/dist/animation/planner.d.ts +6 -0
- package/dist/animation/planner.js +128 -0
- package/dist/animation/render/fade.d.ts +7 -0
- package/dist/animation/render/fade.js +24 -0
- package/dist/animation/render/move.d.ts +7 -0
- package/dist/animation/render/move.js +28 -0
- package/dist/animation/render/plan.d.ts +14 -0
- package/dist/animation/render/plan.js +69 -0
- package/dist/animation/render/static.d.ts +7 -0
- package/dist/animation/render/static.js +21 -0
- package/dist/animation/render/types.d.ts +21 -0
- package/dist/animation/render/types.js +1 -0
- package/dist/animation/types.d.ts +46 -0
- package/dist/animation/types.js +6 -0
- package/dist/extensions/animation/factory.d.ts +3 -0
- package/dist/extensions/animation/factory.js +88 -0
- package/dist/extensions/animation/types.d.ts +11 -0
- package/dist/extensions/animation/types.js +1 -0
- package/dist/extensions/factory/main.d.ts +2 -0
- package/dist/extensions/factory/main.js +101 -0
- package/dist/extensions/factory/runtime.d.ts +5 -0
- package/dist/extensions/factory/runtime.js +43 -0
- package/dist/extensions/first-party/active-target/factory.d.ts +2 -0
- package/dist/extensions/first-party/active-target/factory.js +109 -0
- package/dist/extensions/first-party/active-target/types.d.ts +25 -0
- package/dist/extensions/first-party/active-target/types.js +15 -0
- package/dist/extensions/first-party/board-events/factory.d.ts +2 -0
- package/dist/extensions/first-party/board-events/factory.js +65 -0
- package/dist/extensions/first-party/board-events/types.d.ts +27 -0
- package/dist/extensions/first-party/board-events/types.js +2 -0
- package/dist/extensions/first-party/common/helpers.d.ts +8 -0
- package/dist/extensions/first-party/common/helpers.js +33 -0
- package/dist/extensions/first-party/common/types.d.ts +10 -0
- package/dist/extensions/first-party/common/types.js +1 -0
- package/dist/extensions/first-party/last-move/factory.d.ts +2 -0
- package/dist/extensions/first-party/last-move/factory.js +106 -0
- package/dist/extensions/first-party/last-move/types.d.ts +19 -0
- package/dist/extensions/first-party/last-move/types.js +6 -0
- package/dist/extensions/first-party/legal-moves/factory.d.ts +2 -0
- package/dist/extensions/first-party/legal-moves/factory.js +101 -0
- package/dist/extensions/first-party/legal-moves/types.d.ts +29 -0
- package/dist/extensions/first-party/legal-moves/types.js +19 -0
- package/dist/extensions/first-party/main-renderer/animation/factory.d.ts +4 -0
- package/dist/extensions/first-party/main-renderer/animation/factory.js +35 -0
- package/dist/extensions/first-party/main-renderer/animation/render.d.ts +7 -0
- package/dist/extensions/first-party/main-renderer/animation/render.js +46 -0
- package/dist/extensions/first-party/main-renderer/animation/types.d.ts +24 -0
- package/dist/extensions/first-party/main-renderer/animation/types.js +1 -0
- package/dist/extensions/first-party/main-renderer/animation/update.d.ts +3 -0
- package/dist/extensions/first-party/main-renderer/animation/update.js +40 -0
- package/dist/extensions/first-party/main-renderer/board/factory.d.ts +3 -0
- package/dist/extensions/first-party/main-renderer/board/factory.js +16 -0
- package/dist/extensions/first-party/main-renderer/board/render.d.ts +3 -0
- package/dist/extensions/first-party/main-renderer/board/render.js +24 -0
- package/dist/extensions/first-party/main-renderer/board/types.d.ts +10 -0
- package/dist/extensions/first-party/main-renderer/board/types.js +1 -0
- package/dist/extensions/first-party/main-renderer/board/update.d.ts +3 -0
- package/dist/extensions/first-party/main-renderer/board/update.js +27 -0
- package/dist/extensions/first-party/main-renderer/coordinates/factory.d.ts +3 -0
- package/dist/extensions/first-party/main-renderer/coordinates/factory.js +9 -0
- package/dist/extensions/first-party/main-renderer/coordinates/render.d.ts +3 -0
- package/dist/extensions/first-party/main-renderer/coordinates/render.js +60 -0
- package/dist/extensions/first-party/main-renderer/coordinates/types.d.ts +8 -0
- package/dist/extensions/first-party/main-renderer/coordinates/types.js +1 -0
- package/dist/extensions/first-party/main-renderer/drag/factory.d.ts +4 -0
- package/dist/extensions/first-party/main-renderer/drag/factory.js +23 -0
- package/dist/extensions/first-party/main-renderer/drag/render.d.ts +3 -0
- package/dist/extensions/first-party/main-renderer/drag/render.js +27 -0
- package/dist/extensions/first-party/main-renderer/drag/types.d.ts +16 -0
- package/dist/extensions/first-party/main-renderer/drag/types.js +1 -0
- package/dist/extensions/first-party/main-renderer/drag/update.d.ts +3 -0
- package/dist/extensions/first-party/main-renderer/drag/update.js +23 -0
- package/dist/extensions/first-party/main-renderer/factory.d.ts +2 -0
- package/dist/extensions/first-party/main-renderer/factory.js +95 -0
- package/dist/extensions/first-party/main-renderer/normalize.d.ts +4 -0
- package/dist/extensions/first-party/main-renderer/normalize.js +27 -0
- package/dist/extensions/first-party/main-renderer/pieces/factory.d.ts +3 -0
- package/dist/extensions/first-party/main-renderer/pieces/factory.js +27 -0
- package/dist/extensions/first-party/main-renderer/pieces/render.d.ts +3 -0
- package/dist/extensions/first-party/main-renderer/pieces/render.js +45 -0
- package/dist/extensions/first-party/main-renderer/pieces/suppress.d.ts +5 -0
- package/dist/extensions/first-party/main-renderer/pieces/suppress.js +9 -0
- package/dist/extensions/first-party/main-renderer/pieces/types.d.ts +20 -0
- package/dist/extensions/first-party/main-renderer/pieces/types.js +1 -0
- package/dist/extensions/first-party/main-renderer/pieces/update.d.ts +6 -0
- package/dist/extensions/first-party/main-renderer/pieces/update.js +31 -0
- package/dist/extensions/first-party/main-renderer/types/extension.d.ts +15 -0
- package/dist/extensions/first-party/main-renderer/types/extension.js +10 -0
- package/dist/extensions/first-party/main-renderer/types/input.d.ts +4 -0
- package/dist/extensions/first-party/main-renderer/types/input.js +1 -0
- package/dist/extensions/first-party/main-renderer/types/instance.d.ts +16 -0
- package/dist/extensions/first-party/main-renderer/types/instance.js +1 -0
- package/dist/extensions/first-party/main-renderer/types/internal.d.ts +17 -0
- package/dist/extensions/first-party/main-renderer/types/internal.js +30 -0
- package/dist/extensions/first-party/main-renderer/types/template.d.ts +5 -0
- package/dist/extensions/first-party/main-renderer/types/template.js +1 -0
- package/dist/extensions/first-party/selected-square/factory.d.ts +2 -0
- package/dist/extensions/first-party/selected-square/factory.js +88 -0
- package/dist/extensions/first-party/selected-square/types.d.ts +18 -0
- package/dist/extensions/first-party/selected-square/types.js +6 -0
- package/dist/extensions/index.d.ts +8 -0
- package/dist/extensions/index.js +6 -0
- package/dist/extensions/invalidation/factory.d.ts +2 -0
- package/dist/extensions/invalidation/factory.js +22 -0
- package/dist/extensions/invalidation/types.d.ts +11 -0
- package/dist/extensions/invalidation/types.js +1 -0
- package/dist/extensions/types/basic/animation.d.ts +28 -0
- package/dist/extensions/types/basic/animation.js +6 -0
- package/dist/extensions/types/basic/events.d.ts +34 -0
- package/dist/extensions/types/basic/events.js +7 -0
- package/dist/extensions/types/basic/mount.d.ts +7 -0
- package/dist/extensions/types/basic/mount.js +14 -0
- package/dist/extensions/types/basic/render.d.ts +9 -0
- package/dist/extensions/types/basic/render.js +1 -0
- package/dist/extensions/types/basic/transient-visuals.d.ts +10 -0
- package/dist/extensions/types/basic/transient-visuals.js +1 -0
- package/dist/extensions/types/basic/update.d.ts +16 -0
- package/dist/extensions/types/basic/update.js +11 -0
- package/dist/extensions/types/context/animation.d.ts +31 -0
- package/dist/extensions/types/context/animation.js +9 -0
- package/dist/extensions/types/context/render.d.ts +6 -0
- package/dist/extensions/types/context/render.js +1 -0
- package/dist/extensions/types/context/transient-visuals.d.ts +7 -0
- package/dist/extensions/types/context/transient-visuals.js +1 -0
- package/dist/extensions/types/context/ui-move.d.ts +16 -0
- package/dist/extensions/types/context/ui-move.js +1 -0
- package/dist/extensions/types/context/update.d.ts +25 -0
- package/dist/extensions/types/context/update.js +10 -0
- package/dist/extensions/types/extension.d.ts +40 -0
- package/dist/extensions/types/extension.js +1 -0
- package/dist/extensions/types/main.d.ts +44 -0
- package/dist/extensions/types/main.js +1 -0
- package/dist/extensions/types/surface/commands.d.ts +26 -0
- package/dist/extensions/types/surface/commands.js +1 -0
- package/dist/extensions/types/surface/events.d.ts +5 -0
- package/dist/extensions/types/surface/events.js +1 -0
- package/dist/extensions/types/surface/main.d.ts +10 -0
- package/dist/extensions/types/surface/main.js +1 -0
- package/dist/extensions/types/surface/transient-visuals.d.ts +4 -0
- package/dist/extensions/types/surface/transient-visuals.js +1 -0
- package/dist/extensions/types/wrapper.d.ts +26 -0
- package/dist/extensions/types/wrapper.js +11 -0
- package/dist/extensions/update.d.ts +4 -0
- package/dist/extensions/update.js +29 -0
- package/dist/helpers/util.d.ts +1 -0
- package/dist/helpers/util.js +9 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +1 -0
- package/dist/layout/factory.d.ts +2 -0
- package/dist/layout/factory.js +33 -0
- package/dist/layout/geometry/factory.d.ts +12 -0
- package/dist/layout/geometry/factory.js +33 -0
- package/dist/layout/geometry/types.d.ts +20 -0
- package/dist/layout/geometry/types.js +1 -0
- package/dist/layout/helpers.d.ts +4 -0
- package/dist/layout/helpers.js +6 -0
- package/dist/layout/mutation.d.ts +6 -0
- package/dist/layout/mutation.js +1 -0
- package/dist/layout/reducers.d.ts +2 -0
- package/dist/layout/reducers.js +30 -0
- package/dist/layout/types.d.ts +23 -0
- package/dist/layout/types.js +1 -0
- package/dist/mutation/pipeline.d.ts +2 -0
- package/dist/mutation/pipeline.js +36 -0
- package/dist/mutation/session.d.ts +3 -0
- package/dist/mutation/session.js +66 -0
- package/dist/mutation/types.d.ts +26 -0
- package/dist/mutation/types.js +1 -0
- package/dist/render/factory.d.ts +2 -0
- package/dist/render/factory.js +117 -0
- package/dist/render/mount.d.ts +3 -0
- package/dist/render/mount.js +28 -0
- package/dist/render/rendering/animation.d.ts +13 -0
- package/dist/render/rendering/animation.js +92 -0
- package/dist/render/rendering/helpers.d.ts +3 -0
- package/dist/render/rendering/helpers.js +10 -0
- package/dist/render/rendering/state.d.ts +4 -0
- package/dist/render/rendering/state.js +48 -0
- package/dist/render/rendering/visuals.d.ts +3 -0
- package/dist/render/rendering/visuals.js +21 -0
- package/dist/render/scheduler/scheduler.d.ts +2 -0
- package/dist/render/scheduler/scheduler.js +53 -0
- package/dist/render/scheduler/types.d.ts +12 -0
- package/dist/render/scheduler/types.js +1 -0
- package/dist/render/svg/factory.d.ts +4 -0
- package/dist/render/svg/factory.js +38 -0
- package/dist/render/svg/helpers.d.ts +18 -0
- package/dist/render/svg/helpers.js +34 -0
- package/dist/render/types.d.ts +42 -0
- package/dist/render/types.js +1 -0
- package/dist/runtime/factory/helpers.d.ts +6 -0
- package/dist/runtime/factory/helpers.js +42 -0
- package/dist/runtime/factory/input.d.ts +3 -0
- package/dist/runtime/factory/input.js +98 -0
- package/dist/runtime/factory/main.d.ts +2 -0
- package/dist/runtime/factory/main.js +182 -0
- package/dist/runtime/factory/ui-move.d.ts +4 -0
- package/dist/runtime/factory/ui-move.js +84 -0
- package/dist/runtime/input/adapter/factory.d.ts +2 -0
- package/dist/runtime/input/adapter/factory.js +55 -0
- package/dist/runtime/input/adapter/helpers.d.ts +5 -0
- package/dist/runtime/input/adapter/helpers.js +23 -0
- package/dist/runtime/input/adapter/pointer.d.ts +13 -0
- package/dist/runtime/input/adapter/pointer.js +97 -0
- package/dist/runtime/input/adapter/types.d.ts +16 -0
- package/dist/runtime/input/adapter/types.js +1 -0
- package/dist/runtime/input/controller/factory.d.ts +2 -0
- package/dist/runtime/input/controller/factory.js +32 -0
- package/dist/runtime/input/controller/helpers.d.ts +3 -0
- package/dist/runtime/input/controller/helpers.js +12 -0
- package/dist/runtime/input/controller/pointer.d.ts +7 -0
- package/dist/runtime/input/controller/pointer.js +104 -0
- package/dist/runtime/input/controller/transient-visuals.d.ts +3 -0
- package/dist/runtime/input/controller/transient-visuals.js +12 -0
- package/dist/runtime/input/controller/types.d.ts +25 -0
- package/dist/runtime/input/controller/types.js +1 -0
- package/dist/runtime/layout.d.ts +2 -0
- package/dist/runtime/layout.js +10 -0
- package/dist/runtime/lifecycle.d.ts +12 -0
- package/dist/runtime/lifecycle.js +49 -0
- package/dist/runtime/mutation/extension-update.d.ts +2 -0
- package/dist/runtime/mutation/extension-update.js +26 -0
- package/dist/runtime/mutation/factory.d.ts +2 -0
- package/dist/runtime/mutation/factory.js +47 -0
- package/dist/runtime/mutation/interaction.d.ts +2 -0
- package/dist/runtime/mutation/interaction.js +34 -0
- package/dist/runtime/mutation/invalidation.d.ts +0 -0
- package/dist/runtime/mutation/invalidation.js +2 -0
- package/dist/runtime/mutation/last-move.d.ts +3 -0
- package/dist/runtime/mutation/last-move.js +19 -0
- package/dist/runtime/mutation/layout.d.ts +2 -0
- package/dist/runtime/mutation/layout.js +8 -0
- package/dist/runtime/mutation/pipeline.d.ts +22 -0
- package/dist/runtime/mutation/pipeline.js +1 -0
- package/dist/runtime/mutation/request-render.d.ts +2 -0
- package/dist/runtime/mutation/request-render.js +29 -0
- package/dist/runtime/mutation/run.d.ts +2 -0
- package/dist/runtime/mutation/run.js +3 -0
- package/dist/runtime/mutation/types.d.ts +14 -0
- package/dist/runtime/mutation/types.js +1 -0
- package/dist/runtime/types/main.d.ts +36 -0
- package/dist/runtime/types/main.js +1 -0
- package/dist/runtime/types/ui-move.d.ts +9 -0
- package/dist/runtime/types/ui-move.js +1 -0
- package/dist/state/board/check.d.ts +27 -0
- package/dist/state/board/check.js +148 -0
- package/dist/state/board/coords.d.ts +4 -0
- package/dist/state/board/coords.js +9 -0
- package/dist/state/board/denormalize.d.ts +11 -0
- package/dist/state/board/denormalize.js +77 -0
- package/dist/state/board/factory.d.ts +3 -0
- package/dist/state/board/factory.js +46 -0
- package/dist/state/board/mutation.d.ts +9 -0
- package/dist/state/board/mutation.js +1 -0
- package/dist/state/board/normalize.d.ts +8 -0
- package/dist/state/board/normalize.js +76 -0
- package/dist/state/board/piece.d.ts +3 -0
- package/dist/state/board/piece.js +11 -0
- package/dist/state/board/position.d.ts +4 -0
- package/dist/state/board/position.js +94 -0
- package/dist/state/board/reducers.d.ts +8 -0
- package/dist/state/board/reducers.js +80 -0
- package/dist/state/board/types/input.d.ts +35 -0
- package/dist/state/board/types/input.js +1 -0
- package/dist/state/board/types/internal.d.ts +54 -0
- package/dist/state/board/types/internal.js +17 -0
- package/dist/state/board/types/main.d.ts +18 -0
- package/dist/state/board/types/main.js +1 -0
- package/dist/state/board/types/output.d.ts +5 -0
- package/dist/state/board/types/output.js +1 -0
- package/dist/state/board/types/template.d.ts +23 -0
- package/dist/state/board/types/template.js +1 -0
- package/dist/state/change/factory.d.ts +2 -0
- package/dist/state/change/factory.js +28 -0
- package/dist/state/change/helpers.d.ts +8 -0
- package/dist/state/change/helpers.js +86 -0
- package/dist/state/change/mutation.d.ts +6 -0
- package/dist/state/change/mutation.js +1 -0
- package/dist/state/change/reducers.d.ts +5 -0
- package/dist/state/change/reducers.js +16 -0
- package/dist/state/change/types.d.ts +17 -0
- package/dist/state/change/types.js +1 -0
- package/dist/state/factory.d.ts +2 -0
- package/dist/state/factory.js +24 -0
- package/dist/state/interaction/factory.d.ts +2 -0
- package/dist/state/interaction/factory.js +83 -0
- package/dist/state/interaction/helpers.d.ts +4 -0
- package/dist/state/interaction/helpers.js +16 -0
- package/dist/state/interaction/movability.d.ts +5 -0
- package/dist/state/interaction/movability.js +87 -0
- package/dist/state/interaction/mutation.d.ts +11 -0
- package/dist/state/interaction/mutation.js +1 -0
- package/dist/state/interaction/normalize.d.ts +5 -0
- package/dist/state/interaction/normalize.js +50 -0
- package/dist/state/interaction/reducers.d.ts +11 -0
- package/dist/state/interaction/reducers.js +81 -0
- package/dist/state/interaction/types/input.d.ts +18 -0
- package/dist/state/interaction/types/input.js +1 -0
- package/dist/state/interaction/types/internal.d.ts +35 -0
- package/dist/state/interaction/types/internal.js +1 -0
- package/dist/state/interaction/types/main.d.ts +33 -0
- package/dist/state/interaction/types/main.js +1 -0
- package/dist/state/types.d.ts +30 -0
- package/dist/state/types.js +1 -0
- package/dist/state/view/factory.d.ts +2 -0
- package/dist/state/view/factory.js +24 -0
- package/dist/state/view/mutation.d.ts +5 -0
- package/dist/state/view/mutation.js +1 -0
- package/dist/state/view/reducers.d.ts +3 -0
- package/dist/state/view/reducers.js +6 -0
- package/dist/state/view/types/internal.d.ts +6 -0
- package/dist/state/view/types/internal.js +1 -0
- package/dist/state/view/types/main.d.ts +12 -0
- package/dist/state/view/types/main.js +1 -0
- package/dist/wrapper/factory.d.ts +3 -0
- package/dist/wrapper/factory.js +61 -0
- package/dist/wrapper/types.d.ts +56 -0
- package/dist/wrapper/types.js +1 -0
- package/package.json +98 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { updateElementAttributes } from '../svg/helpers';
|
|
2
|
+
import { validateIsMounted } from './helpers';
|
|
3
|
+
export function checkNeedsRender(state) {
|
|
4
|
+
for (const extensionRec of state.extensions.values()) {
|
|
5
|
+
if (extensionRec.extension.invalidation.dirtyLayers !== 0) {
|
|
6
|
+
return true;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
export function performRenderPass(state, request) {
|
|
12
|
+
validateIsMounted(state);
|
|
13
|
+
if (!request) {
|
|
14
|
+
throw new Error('render() called without a valid render request');
|
|
15
|
+
}
|
|
16
|
+
if (!request.layout.geometry) {
|
|
17
|
+
throw new Error('render() called without a valid layout geometry');
|
|
18
|
+
}
|
|
19
|
+
const currentSize = request.layout.geometry.boardSize;
|
|
20
|
+
const prevSize = state.currentFrame?.layout.geometry?.boardSize;
|
|
21
|
+
if (currentSize !== prevSize) {
|
|
22
|
+
const size = String(currentSize);
|
|
23
|
+
updateElementAttributes(state.svgRoots.svgRoot, {
|
|
24
|
+
width: size,
|
|
25
|
+
height: size,
|
|
26
|
+
viewBox: `0 0 ${size} ${size}`
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
// Check if we have any invalidation states
|
|
30
|
+
if (!checkNeedsRender(state)) {
|
|
31
|
+
// Save the last rendered common base context
|
|
32
|
+
state.currentFrame = request;
|
|
33
|
+
return; // no-op
|
|
34
|
+
}
|
|
35
|
+
// Now run over the extensions that have invalidation layers marked and call their render method
|
|
36
|
+
for (const extensionRec of state.extensions.values()) {
|
|
37
|
+
if (extensionRec.extension.invalidation.dirtyLayers !== 0) {
|
|
38
|
+
const context = {
|
|
39
|
+
currentFrame: request,
|
|
40
|
+
invalidation: extensionRec.extension.invalidation
|
|
41
|
+
};
|
|
42
|
+
extensionRec.extension.instance.render?.(context);
|
|
43
|
+
extensionRec.extension.invalidation.clear();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// Save the last rendered common base context
|
|
47
|
+
state.currentFrame = request;
|
|
48
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { validateIsMounted } from './helpers';
|
|
2
|
+
export function performRenderTransientVisualsPass(state, request) {
|
|
3
|
+
validateIsMounted(state);
|
|
4
|
+
const currentFrame = state.currentFrame;
|
|
5
|
+
if (!currentFrame) {
|
|
6
|
+
throw new Error('renderTransientVisuals() called but no previous render state found. render() must be called before renderTransientVisuals().');
|
|
7
|
+
}
|
|
8
|
+
// Loop over the subscribers and call renderTransientVisuals on each)
|
|
9
|
+
const context = {
|
|
10
|
+
currentFrame,
|
|
11
|
+
transientInput: request
|
|
12
|
+
};
|
|
13
|
+
for (const extensionId of state.transientVisualsSubscribers) {
|
|
14
|
+
const extensionRec = state.extensions.get(extensionId);
|
|
15
|
+
if (!extensionRec) {
|
|
16
|
+
throw new Error(`Extension with id ${extensionId} is subscribed to transient visuals but not found in render system extensions.`);
|
|
17
|
+
}
|
|
18
|
+
const extension = extensionRec.extension.instance;
|
|
19
|
+
extension.renderTransientVisuals?.(context);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export function createScheduler(opts) {
|
|
2
|
+
const { render } = opts;
|
|
3
|
+
let scheduled = false;
|
|
4
|
+
let runId = 0;
|
|
5
|
+
let rafHandle = null;
|
|
6
|
+
const flushCore = () => {
|
|
7
|
+
if (!scheduled && rafHandle == null) {
|
|
8
|
+
// Maybe was cancelled after the rAF callback was scheduled but before it fired.
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
// Reset scheduled flags first to allow schedule() during render to queue the next frame.
|
|
12
|
+
scheduled = false;
|
|
13
|
+
if (rafHandle != null) {
|
|
14
|
+
rafHandle = null;
|
|
15
|
+
}
|
|
16
|
+
render();
|
|
17
|
+
};
|
|
18
|
+
return {
|
|
19
|
+
schedule() {
|
|
20
|
+
const raf = globalThis.requestAnimationFrame;
|
|
21
|
+
if (scheduled || rafHandle != null)
|
|
22
|
+
return;
|
|
23
|
+
scheduled = true;
|
|
24
|
+
const id = ++runId;
|
|
25
|
+
rafHandle = raf(() => {
|
|
26
|
+
if (id !== runId)
|
|
27
|
+
return; // ignore stale callbacks invalidated by flushNow()
|
|
28
|
+
flushCore();
|
|
29
|
+
});
|
|
30
|
+
},
|
|
31
|
+
flushNow() {
|
|
32
|
+
// Invalidate any pending rAF render immediately.
|
|
33
|
+
if (scheduled) {
|
|
34
|
+
runId++;
|
|
35
|
+
scheduled = false;
|
|
36
|
+
}
|
|
37
|
+
if (rafHandle != null) {
|
|
38
|
+
const caf = globalThis.cancelAnimationFrame;
|
|
39
|
+
caf(rafHandle);
|
|
40
|
+
rafHandle = null;
|
|
41
|
+
}
|
|
42
|
+
flushCore();
|
|
43
|
+
},
|
|
44
|
+
cancel() {
|
|
45
|
+
scheduled = false;
|
|
46
|
+
if (rafHandle != null) {
|
|
47
|
+
const caf = globalThis.cancelAnimationFrame;
|
|
48
|
+
caf(rafHandle);
|
|
49
|
+
}
|
|
50
|
+
rafHandle = null;
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type RenderCallback = () => void;
|
|
2
|
+
export interface SchedulerOptions {
|
|
3
|
+
render: RenderCallback;
|
|
4
|
+
}
|
|
5
|
+
export interface Scheduler {
|
|
6
|
+
/** Request a render; multiple calls before the next frame coalesce into one. */
|
|
7
|
+
schedule(): void;
|
|
8
|
+
/** Flush immediately (synchronous), useful for deterministic tests or SSR. */
|
|
9
|
+
flushNow(): void;
|
|
10
|
+
/** Cancel any pending frame. */
|
|
11
|
+
cancel(): void;
|
|
12
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { ExtensionAllocatedSlotsInternal, ExtensionSlotName } from '../../extensions/types/basic/mount';
|
|
2
|
+
import { RenderSystemInitOptionsInternal, SvgRoots } from '../types';
|
|
3
|
+
export declare function createSvgRoots(options: RenderSystemInitOptionsInternal): SvgRoots;
|
|
4
|
+
export declare function allocateExtensionSlotRoots(svgRoots: SvgRoots, extensionId: string, slots: readonly ExtensionSlotName[]): ExtensionAllocatedSlotsInternal;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { createSvgElement } from './helpers';
|
|
2
|
+
export function createSvgRoots(options) {
|
|
3
|
+
const { doc } = options;
|
|
4
|
+
const svgRoot = createSvgElement(doc, 'svg', { 'data-chessboard-id': 'svg-root' });
|
|
5
|
+
const result = {
|
|
6
|
+
svgRoot,
|
|
7
|
+
defs: createSvgElement(doc, 'defs', { 'data-chessboard-id': 'defs-root' }),
|
|
8
|
+
board: createSvgElement(doc, 'g', { 'data-chessboard-id': 'board-root' }),
|
|
9
|
+
coordinates: createSvgElement(doc, 'g', { 'data-chessboard-id': 'coordinates-root' }),
|
|
10
|
+
underPieces: createSvgElement(doc, 'g', { 'data-chessboard-id': 'under-pieces-root' }),
|
|
11
|
+
pieces: createSvgElement(doc, 'g', { 'data-chessboard-id': 'pieces-root' }),
|
|
12
|
+
overPieces: createSvgElement(doc, 'g', { 'data-chessboard-id': 'over-pieces-root' }),
|
|
13
|
+
animation: createSvgElement(doc, 'g', { 'data-chessboard-id': 'animation-root' }),
|
|
14
|
+
underDrag: createSvgElement(doc, 'g', { 'data-chessboard-id': 'under-drag-root' }),
|
|
15
|
+
drag: createSvgElement(doc, 'g', { 'data-chessboard-id': 'drag-root' }),
|
|
16
|
+
overDrag: createSvgElement(doc, 'g', { 'data-chessboard-id': 'over-drag-root' })
|
|
17
|
+
};
|
|
18
|
+
// Attach layers in the correct order
|
|
19
|
+
svgRoot.appendChild(result.defs);
|
|
20
|
+
svgRoot.appendChild(result.board);
|
|
21
|
+
svgRoot.appendChild(result.coordinates);
|
|
22
|
+
svgRoot.appendChild(result.underPieces);
|
|
23
|
+
svgRoot.appendChild(result.pieces);
|
|
24
|
+
svgRoot.appendChild(result.overPieces);
|
|
25
|
+
svgRoot.appendChild(result.animation);
|
|
26
|
+
svgRoot.appendChild(result.underDrag);
|
|
27
|
+
svgRoot.appendChild(result.drag);
|
|
28
|
+
svgRoot.appendChild(result.overDrag);
|
|
29
|
+
return result;
|
|
30
|
+
}
|
|
31
|
+
export function allocateExtensionSlotRoots(svgRoots, extensionId, slots) {
|
|
32
|
+
const result = {};
|
|
33
|
+
for (const slot of slots) {
|
|
34
|
+
const id = `extension-slot-root-${slot}-${extensionId}`;
|
|
35
|
+
result[slot] = createSvgElement(svgRoots[slot], 'g', { 'data-chessboard-id': id });
|
|
36
|
+
}
|
|
37
|
+
return result;
|
|
38
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Square } from '../../state/board/types/internal';
|
|
2
|
+
export declare const SVG_NS = "http://www.w3.org/2000/svg";
|
|
3
|
+
/**
|
|
4
|
+
* Helper to compute light/dark square parity.
|
|
5
|
+
* Returns true for light squares, false for dark.
|
|
6
|
+
* Convention: a1 is dark in many sets; here we follow theming from state (renderer decides).
|
|
7
|
+
* If you need the classic pattern where a1 is dark, use: (file + rank) % 2 === 1
|
|
8
|
+
*/
|
|
9
|
+
export declare function isLightSquare(sq: Square): boolean;
|
|
10
|
+
export type SvgElementNames = keyof SVGElementTagNameMap;
|
|
11
|
+
export type SvgElementAttributes = Record<string, string>;
|
|
12
|
+
export type SvgElementOtherAttributes = SvgElementAttributes;
|
|
13
|
+
export type SvgElementWithIdAttributes = SvgElementAttributes & {
|
|
14
|
+
'data-chessboard-id': string;
|
|
15
|
+
};
|
|
16
|
+
export declare function createSvgElement<K extends SvgElementNames>(parentOrDoc: Element | Document, name: K, attrs: SvgElementWithIdAttributes): SVGElementTagNameMap[K];
|
|
17
|
+
export declare function updateElementAttributes(element: Element, attrs: SvgElementOtherAttributes): void;
|
|
18
|
+
export declare function clearElementChildren(element: Element): void;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { fileOf, rankOf } from '../../state/board/coords';
|
|
2
|
+
export const SVG_NS = 'http://www.w3.org/2000/svg';
|
|
3
|
+
/**
|
|
4
|
+
* Helper to compute light/dark square parity.
|
|
5
|
+
* Returns true for light squares, false for dark.
|
|
6
|
+
* Convention: a1 is dark in many sets; here we follow theming from state (renderer decides).
|
|
7
|
+
* If you need the classic pattern where a1 is dark, use: (file + rank) % 2 === 1
|
|
8
|
+
*/
|
|
9
|
+
export function isLightSquare(sq) {
|
|
10
|
+
const f = fileOf(sq);
|
|
11
|
+
const r = rankOf(sq);
|
|
12
|
+
return ((f + r) & 1) === 1;
|
|
13
|
+
}
|
|
14
|
+
export function createSvgElement(parentOrDoc, name, attrs) {
|
|
15
|
+
const doc = parentOrDoc instanceof Document ? parentOrDoc : parentOrDoc.ownerDocument;
|
|
16
|
+
const el = doc.createElementNS(SVG_NS, name);
|
|
17
|
+
for (const [key, value] of Object.entries(attrs)) {
|
|
18
|
+
el.setAttribute(key, value);
|
|
19
|
+
}
|
|
20
|
+
if (parentOrDoc instanceof Element) {
|
|
21
|
+
parentOrDoc.appendChild(el);
|
|
22
|
+
}
|
|
23
|
+
return el;
|
|
24
|
+
}
|
|
25
|
+
export function updateElementAttributes(element, attrs) {
|
|
26
|
+
for (const [key, value] of Object.entries(attrs)) {
|
|
27
|
+
element.setAttribute(key, value);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export function clearElementChildren(element) {
|
|
31
|
+
while (element.firstChild) {
|
|
32
|
+
element.removeChild(element.firstChild);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { ALL_EXTENSION_SLOTS, ExtensionAllocatedSlotsInternal, ExtensionSlotSvgRoots } from '../extensions/types/basic/mount';
|
|
2
|
+
import { RenderFrameSnapshot } from '../extensions/types/basic/render';
|
|
3
|
+
import { TransientInput } from '../extensions/types/basic/transient-visuals';
|
|
4
|
+
import { ExtensionSystemExtensionRecord, ExtensionSystemSharedDataForRenderSystem } from '../extensions/types/main';
|
|
5
|
+
import { Scheduler } from './scheduler/types';
|
|
6
|
+
export interface SvgRoots extends ExtensionSlotSvgRoots<typeof ALL_EXTENSION_SLOTS> {
|
|
7
|
+
readonly svgRoot: SVGSVGElement;
|
|
8
|
+
readonly defs: SVGDefsElement;
|
|
9
|
+
}
|
|
10
|
+
export interface RenderExtensionRecordRender {
|
|
11
|
+
readonly slots: ExtensionAllocatedSlotsInternal;
|
|
12
|
+
}
|
|
13
|
+
export interface RenderExtensionRecord {
|
|
14
|
+
readonly id: string;
|
|
15
|
+
readonly extension: ExtensionSystemExtensionRecord;
|
|
16
|
+
readonly render: RenderExtensionRecordRender;
|
|
17
|
+
}
|
|
18
|
+
export interface RenderSystemInternal {
|
|
19
|
+
container: HTMLElement | null;
|
|
20
|
+
currentFrame: RenderFrameSnapshot | null;
|
|
21
|
+
readonly scheduler: Scheduler;
|
|
22
|
+
readonly svgRoots: SvgRoots;
|
|
23
|
+
readonly extensions: Map<string, RenderExtensionRecord>;
|
|
24
|
+
readonly transientVisualsSubscribers: ReadonlySet<string>;
|
|
25
|
+
}
|
|
26
|
+
export interface RenderSystemInitOptions {
|
|
27
|
+
doc: Document;
|
|
28
|
+
sharedDataFromExtensionSystem: ExtensionSystemSharedDataForRenderSystem;
|
|
29
|
+
}
|
|
30
|
+
export interface RenderSystemInitOptionsInternal extends RenderSystemInitOptions {
|
|
31
|
+
performRender: () => void;
|
|
32
|
+
}
|
|
33
|
+
export interface RenderSystem {
|
|
34
|
+
readonly extensions: ReadonlyMap<string, RenderExtensionRecord>;
|
|
35
|
+
requestRender(request?: RenderFrameSnapshot): void;
|
|
36
|
+
requestRenderAnimation(): void;
|
|
37
|
+
requestRenderVisuals(request: TransientInput): void;
|
|
38
|
+
mount(element: HTMLElement): void;
|
|
39
|
+
unmount(): void;
|
|
40
|
+
readonly isMounted: boolean;
|
|
41
|
+
readonly container: HTMLElement | null;
|
|
42
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Square } from '../../state/board/types/internal';
|
|
2
|
+
import { RuntimeInternal } from '../types/main';
|
|
3
|
+
/**
|
|
4
|
+
* Helper functions for common flow for dropTo and releaseTo interactions
|
|
5
|
+
*/
|
|
6
|
+
export declare function uiMoveCompleteTo(state: RuntimeInternal, target: Square): void;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import assert from '@ktarmyshov/assert';
|
|
2
|
+
import { isEmptyPieceCode } from '../../state/board/check';
|
|
3
|
+
import { canMoveTo } from '../input/controller/helpers';
|
|
4
|
+
import { createUIMoveRequestContext } from './ui-move';
|
|
5
|
+
function assertResolvedAfterAutoResolve(state) {
|
|
6
|
+
if (state.status !== 'resolved') {
|
|
7
|
+
throw new Error('UI move request must be resolved after autoresolve');
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Helper functions for common flow for dropTo and releaseTo interactions
|
|
12
|
+
*/
|
|
13
|
+
export function uiMoveCompleteTo(state, target) {
|
|
14
|
+
const mutationSession = state.mutation.getSession();
|
|
15
|
+
const interaction = state.state.interaction;
|
|
16
|
+
const dragSession = interaction.dragSession;
|
|
17
|
+
assert(dragSession !== null, 'dropTo/releaseTo requires an active drag session');
|
|
18
|
+
assert(dragSession.targetSquare === target, 'dropTo/releaseTo target must match drag session current target');
|
|
19
|
+
assert(interaction.selected !== null, 'dropTo/releaseTo requires a selected piece');
|
|
20
|
+
assert(!isEmptyPieceCode(interaction.selected.pieceCode), 'Selected piece must be valid');
|
|
21
|
+
assert(dragSession.sourceSquare === interaction.selected.square, 'drag session source must match selected square');
|
|
22
|
+
assert(canMoveTo(interaction.getSnapshot(), target), 'dropTo/releaseTo target must be a valid move destination');
|
|
23
|
+
// canMoveTo already confirmed we can move, but if 'FREE' movability it can be that there are no activeDestinations for the target square, so we need to handle that case as well
|
|
24
|
+
const destination = interaction.activeDestinations.get(target) ?? { to: target };
|
|
25
|
+
const moveRequestContext = createUIMoveRequestContext(dragSession.sourceSquare, destination);
|
|
26
|
+
state.extensionSystem.onUIMoveRequest(moveRequestContext);
|
|
27
|
+
if (moveRequestContext.status === 'deferred') {
|
|
28
|
+
state.state.change.setDeferredUIMoveRequestContext(moveRequestContext, mutationSession);
|
|
29
|
+
}
|
|
30
|
+
else if (moveRequestContext.status === 'unresolved') {
|
|
31
|
+
// Try to auto-resolve if possible (e.g. if there are no promotion choices to be made)
|
|
32
|
+
moveRequestContext.autoresolve();
|
|
33
|
+
assertResolvedAfterAutoResolve(moveRequestContext);
|
|
34
|
+
}
|
|
35
|
+
if (moveRequestContext.status === 'resolved') {
|
|
36
|
+
const moveRequest = moveRequestContext.resolvedMoveRequest;
|
|
37
|
+
if (moveRequest !== null) {
|
|
38
|
+
state.state.board.move(moveRequest, mutationSession);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
interaction.clear(mutationSession);
|
|
42
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import assert from '@ktarmyshov/assert';
|
|
2
|
+
import { isEmptyPieceCode } from '../../state/board/check';
|
|
3
|
+
import { runtimeRunMutationPipeline } from '../mutation/run';
|
|
4
|
+
import { uiMoveCompleteTo } from './helpers';
|
|
5
|
+
export function createRuntimeInteractionSurface(state) {
|
|
6
|
+
return {
|
|
7
|
+
getInteractionStateSnapshot() {
|
|
8
|
+
const internalState = state();
|
|
9
|
+
return internalState.state.interaction.getSnapshot();
|
|
10
|
+
},
|
|
11
|
+
getPieceCodeAt(square) {
|
|
12
|
+
const internalState = state();
|
|
13
|
+
return internalState.state.board.getPieceCodeAt(square);
|
|
14
|
+
},
|
|
15
|
+
startLiftedDrag(source, target) {
|
|
16
|
+
const internalState = state();
|
|
17
|
+
const interactionMutationSession = internalState.mutation.getSession();
|
|
18
|
+
const interaction = internalState.state.interaction;
|
|
19
|
+
const pieceCode = internalState.state.board.getPieceCodeAt(source);
|
|
20
|
+
assert(!isEmptyPieceCode(pieceCode), 'Cannot start a lifted-piece-drag session from an empty square');
|
|
21
|
+
const interactionSource = {
|
|
22
|
+
square: source,
|
|
23
|
+
pieceCode
|
|
24
|
+
};
|
|
25
|
+
interaction.setSelected(interactionSource, interactionMutationSession);
|
|
26
|
+
const dragSession = {
|
|
27
|
+
type: 'lifted-piece-drag',
|
|
28
|
+
sourceSquare: interactionSource.square,
|
|
29
|
+
sourcePieceCode: interactionSource.pieceCode,
|
|
30
|
+
targetSquare: target
|
|
31
|
+
};
|
|
32
|
+
interaction.setDragSession(dragSession, interactionMutationSession);
|
|
33
|
+
runtimeRunMutationPipeline(internalState);
|
|
34
|
+
},
|
|
35
|
+
transientInput(input) {
|
|
36
|
+
const internalState = state();
|
|
37
|
+
internalState.renderSystem.requestRenderVisuals(input);
|
|
38
|
+
},
|
|
39
|
+
dropTo(target) {
|
|
40
|
+
const internalState = state();
|
|
41
|
+
const mutationSession = internalState.mutation.getSession();
|
|
42
|
+
const interaction = internalState.state.interaction;
|
|
43
|
+
const dragSession = interaction.dragSession;
|
|
44
|
+
assert(dragSession !== null, 'dropTo requires an active drag session');
|
|
45
|
+
assert(dragSession.type === 'lifted-piece-drag', 'dropTo requires a lifted-piece-drag session');
|
|
46
|
+
uiMoveCompleteTo(internalState, target);
|
|
47
|
+
mutationSession.addMutation('runtime.interaction.dropTo', true);
|
|
48
|
+
runtimeRunMutationPipeline(internalState);
|
|
49
|
+
},
|
|
50
|
+
releaseTo(target) {
|
|
51
|
+
const internalState = state();
|
|
52
|
+
const mutationSession = internalState.mutation.getSession();
|
|
53
|
+
const interaction = internalState.state.interaction;
|
|
54
|
+
const dragSession = interaction.dragSession;
|
|
55
|
+
assert(dragSession !== null, 'releaseTo requires an active drag session');
|
|
56
|
+
assert(dragSession.type === 'release-targeting', 'releaseTo requires a release-targeting session');
|
|
57
|
+
uiMoveCompleteTo(internalState, target);
|
|
58
|
+
mutationSession.addMutation('runtime.interaction.releaseTo', true);
|
|
59
|
+
runtimeRunMutationPipeline(internalState);
|
|
60
|
+
},
|
|
61
|
+
startReleaseTargetingDrag(source, target) {
|
|
62
|
+
const internalState = state();
|
|
63
|
+
const mutationSession = internalState.mutation.getSession();
|
|
64
|
+
const interaction = internalState.state.interaction;
|
|
65
|
+
assert(interaction.selected !== null, 'startReleaseTargetingDrag requires a selected piece');
|
|
66
|
+
assert(interaction.selected.square === source, 'startReleaseTargetingDrag source must match selected square');
|
|
67
|
+
const dragSession = {
|
|
68
|
+
type: 'release-targeting',
|
|
69
|
+
sourceSquare: source,
|
|
70
|
+
sourcePieceCode: interaction.selected.pieceCode,
|
|
71
|
+
targetSquare: target
|
|
72
|
+
};
|
|
73
|
+
interaction.setDragSession(dragSession, mutationSession);
|
|
74
|
+
runtimeRunMutationPipeline(internalState);
|
|
75
|
+
},
|
|
76
|
+
cancelActiveInteraction() {
|
|
77
|
+
const internalState = state();
|
|
78
|
+
const mutationSession = internalState.mutation.getSession();
|
|
79
|
+
internalState.state.interaction.clearActive(mutationSession);
|
|
80
|
+
runtimeRunMutationPipeline(internalState);
|
|
81
|
+
},
|
|
82
|
+
cancelInteraction() {
|
|
83
|
+
const internalState = state();
|
|
84
|
+
const mutationSession = internalState.mutation.getSession();
|
|
85
|
+
internalState.state.interaction.clear(mutationSession);
|
|
86
|
+
runtimeRunMutationPipeline(internalState);
|
|
87
|
+
},
|
|
88
|
+
updateDragSessionCurrentTarget(target) {
|
|
89
|
+
const internalState = state();
|
|
90
|
+
const interactionMutationSession = internalState.mutation.getSession();
|
|
91
|
+
const interaction = internalState.state.interaction;
|
|
92
|
+
const currentDragSession = interaction.dragSession;
|
|
93
|
+
assert(currentDragSession !== null, 'No active drag session to update');
|
|
94
|
+
internalState.state.interaction.updateDragSessionCurrentTarget(target, interactionMutationSession);
|
|
95
|
+
runtimeRunMutationPipeline(internalState);
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import assert from '@ktarmyshov/assert';
|
|
2
|
+
import { createExtensionSystem } from '../../extensions/factory/main';
|
|
3
|
+
import { assertFrameRenderable } from '../../extensions/types/basic/update';
|
|
4
|
+
import { createLayout } from '../../layout/factory';
|
|
5
|
+
import { createRenderSystem } from '../../render/factory';
|
|
6
|
+
import { isNonEmptyPieceCode } from '../../state/board/check';
|
|
7
|
+
import { normalizeSquare } from '../../state/board/normalize';
|
|
8
|
+
import { createRuntimeState } from '../../state/factory';
|
|
9
|
+
import { createInteractionController } from '../input/controller/factory';
|
|
10
|
+
import { runtimeDestroy, runtimeMount, runtimeUnmount } from '../lifecycle';
|
|
11
|
+
import { createRuntimeMutationPipeline } from '../mutation/factory';
|
|
12
|
+
import { runtimeRunMutationPipeline } from '../mutation/run';
|
|
13
|
+
import { createRuntimeInteractionSurface } from './input';
|
|
14
|
+
function createRuntimeInternal(options) {
|
|
15
|
+
const extensionSystem = createExtensionSystem(options);
|
|
16
|
+
const render = createRenderSystem({
|
|
17
|
+
doc: options.doc,
|
|
18
|
+
sharedDataFromExtensionSystem: extensionSystem.getSharedDataForRenderSystem()
|
|
19
|
+
});
|
|
20
|
+
return {
|
|
21
|
+
state: createRuntimeState(options.state ?? {}),
|
|
22
|
+
layout: createLayout(),
|
|
23
|
+
mutation: createRuntimeMutationPipeline(),
|
|
24
|
+
renderSystem: render,
|
|
25
|
+
extensionSystem: extensionSystem,
|
|
26
|
+
resizeObserver: null,
|
|
27
|
+
inputAdapter: null,
|
|
28
|
+
interactionController: createInteractionController({
|
|
29
|
+
surface: createRuntimeInteractionSurface(options.getInternalState)
|
|
30
|
+
})
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function createExtensionRuntimeSurfaceCommands(getInternalState) {
|
|
34
|
+
return {
|
|
35
|
+
setPosition(input) {
|
|
36
|
+
const state = getInternalState();
|
|
37
|
+
const mutationSession = state.mutation.getSession();
|
|
38
|
+
const changed = state.state.board.setPosition(input, mutationSession);
|
|
39
|
+
runtimeRunMutationPipeline(state);
|
|
40
|
+
return changed;
|
|
41
|
+
},
|
|
42
|
+
setPiecePosition(input) {
|
|
43
|
+
const state = getInternalState();
|
|
44
|
+
const mutationSession = state.mutation.getSession();
|
|
45
|
+
const changed = state.state.board.setPiecePosition(input, mutationSession);
|
|
46
|
+
runtimeRunMutationPipeline(state);
|
|
47
|
+
return changed;
|
|
48
|
+
},
|
|
49
|
+
setTurn(turn) {
|
|
50
|
+
const state = getInternalState();
|
|
51
|
+
const mutationSession = state.mutation.getSession();
|
|
52
|
+
const changed = state.state.board.setTurn(turn, mutationSession);
|
|
53
|
+
runtimeRunMutationPipeline(state);
|
|
54
|
+
return changed;
|
|
55
|
+
},
|
|
56
|
+
move(request) {
|
|
57
|
+
const state = getInternalState();
|
|
58
|
+
const mutationSession = state.mutation.getSession();
|
|
59
|
+
const move = state.state.board.move(request, mutationSession);
|
|
60
|
+
runtimeRunMutationPipeline(state);
|
|
61
|
+
return move;
|
|
62
|
+
},
|
|
63
|
+
requestRender(request) {
|
|
64
|
+
const state = getInternalState();
|
|
65
|
+
if (request.state) {
|
|
66
|
+
const renderRequest = {
|
|
67
|
+
isMounted: state.renderSystem.isMounted,
|
|
68
|
+
state: state.state.getSnapshot(),
|
|
69
|
+
layout: state.layout.getSnapshot()
|
|
70
|
+
};
|
|
71
|
+
assertFrameRenderable(renderRequest);
|
|
72
|
+
state.renderSystem.requestRender(renderRequest);
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
setOrientation(orientation) {
|
|
76
|
+
const state = getInternalState();
|
|
77
|
+
const mutationSession = state.mutation.getSession();
|
|
78
|
+
const changed = state.state.view.setOrientation(orientation, mutationSession);
|
|
79
|
+
runtimeRunMutationPipeline(state);
|
|
80
|
+
return changed;
|
|
81
|
+
},
|
|
82
|
+
setMovability(movability) {
|
|
83
|
+
const state = getInternalState();
|
|
84
|
+
const mutationSession = state.mutation.getSession();
|
|
85
|
+
const changed = state.state.interaction.setMovability(movability, mutationSession);
|
|
86
|
+
runtimeRunMutationPipeline(state);
|
|
87
|
+
return changed;
|
|
88
|
+
},
|
|
89
|
+
select(square) {
|
|
90
|
+
const state = getInternalState();
|
|
91
|
+
const mutationSession = state.mutation.getSession();
|
|
92
|
+
let interactionStateSelected = null;
|
|
93
|
+
if (square !== null) {
|
|
94
|
+
const normalizedSquare = normalizeSquare(square);
|
|
95
|
+
const piece = state.state.board.getPieceCodeAt(normalizedSquare);
|
|
96
|
+
assert(isNonEmptyPieceCode(piece), 'Selected square is expected to have a piece');
|
|
97
|
+
interactionStateSelected = {
|
|
98
|
+
square: normalizedSquare,
|
|
99
|
+
pieceCode: piece
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
const changed = state.state.interaction.setSelected(interactionStateSelected, mutationSession);
|
|
103
|
+
runtimeRunMutationPipeline(state);
|
|
104
|
+
return changed;
|
|
105
|
+
},
|
|
106
|
+
clearActiveInteraction() {
|
|
107
|
+
const state = getInternalState();
|
|
108
|
+
const mutationSession = state.mutation.getSession();
|
|
109
|
+
const changed = state.state.interaction.clearActive(mutationSession);
|
|
110
|
+
runtimeRunMutationPipeline(state);
|
|
111
|
+
return changed;
|
|
112
|
+
},
|
|
113
|
+
clearInteraction() {
|
|
114
|
+
const state = getInternalState();
|
|
115
|
+
const mutationSession = state.mutation.getSession();
|
|
116
|
+
const changed = state.state.interaction.clear(mutationSession);
|
|
117
|
+
runtimeRunMutationPipeline(state);
|
|
118
|
+
return changed;
|
|
119
|
+
},
|
|
120
|
+
getSnapshot() {
|
|
121
|
+
const state = getInternalState();
|
|
122
|
+
return {
|
|
123
|
+
state: state.state.getSnapshot(),
|
|
124
|
+
layout: state.layout.getSnapshot()
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
export function createRuntime(options) {
|
|
130
|
+
let internalState = null;
|
|
131
|
+
let internalStatus = 'constructing';
|
|
132
|
+
function getInternalState() {
|
|
133
|
+
if (internalStatus === 'constructing' || internalStatus === 'destroyed') {
|
|
134
|
+
throw new Error(`Cannot access internal state when runtime is ${internalStatus}`);
|
|
135
|
+
}
|
|
136
|
+
if (!internalState) {
|
|
137
|
+
throw new Error('Internal state is not initialized');
|
|
138
|
+
}
|
|
139
|
+
return internalState;
|
|
140
|
+
}
|
|
141
|
+
// Create RuntimeExtensionSurface to pass to the extension system for initialization of extension instances
|
|
142
|
+
const extensionSurface = createExtensionRuntimeSurfaceCommands(getInternalState);
|
|
143
|
+
// Now construct the internal state
|
|
144
|
+
const optionsInternal = {
|
|
145
|
+
...options,
|
|
146
|
+
extensionRuntimeSurfaceCommands: extensionSurface,
|
|
147
|
+
getInternalState
|
|
148
|
+
};
|
|
149
|
+
internalState = createRuntimeInternal(optionsInternal);
|
|
150
|
+
// Initial creation, so we mark board position as mutated to trigger mutation pipeline
|
|
151
|
+
internalState.mutation.addMutation('state.board.setPosition', true);
|
|
152
|
+
// We will have two different interfaces here
|
|
153
|
+
// One is returned, one is for controller - with different methods
|
|
154
|
+
// At the moment our assumption that controller will use Runtime but not opposite direction
|
|
155
|
+
// So we can construct these two objects separately so they would not be huge!
|
|
156
|
+
// TODO: const inputControllerSurface = createRuntimeInputControllerSurface(internalState);
|
|
157
|
+
// Initial run to process initial mutations and set up previousContext for the next runs
|
|
158
|
+
internalStatus = 'unmounted';
|
|
159
|
+
internalState.mutation.run(internalState);
|
|
160
|
+
return {
|
|
161
|
+
get status() {
|
|
162
|
+
return internalStatus;
|
|
163
|
+
},
|
|
164
|
+
mount(container) {
|
|
165
|
+
runtimeMount(getInternalState(), container);
|
|
166
|
+
internalStatus = 'mounted';
|
|
167
|
+
},
|
|
168
|
+
unmount() {
|
|
169
|
+
runtimeUnmount(getInternalState());
|
|
170
|
+
internalStatus = 'unmounted';
|
|
171
|
+
},
|
|
172
|
+
destroy() {
|
|
173
|
+
runtimeDestroy(getInternalState());
|
|
174
|
+
internalStatus = 'destroyed';
|
|
175
|
+
internalState = null;
|
|
176
|
+
},
|
|
177
|
+
...extensionSurface,
|
|
178
|
+
getExtensionsPublicRecord() {
|
|
179
|
+
return getInternalState().extensionSystem.getPublicRecord();
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { ExtensionUIMoveRequestContext } from '../../extensions/types/context/ui-move';
|
|
2
|
+
import { Square } from '../../state/board/types/internal';
|
|
3
|
+
import { MoveDestinationSnapshot } from '../../state/interaction/types/internal';
|
|
4
|
+
export declare function createUIMoveRequestContext(sourceSquare: Square, destination: MoveDestinationSnapshot): ExtensionUIMoveRequestContext;
|