@mirasen/chessboard 0.1.1 → 1.0.0-rc.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 +10 -0
- package/README.md +224 -47
- package/dist/animation/planner.d.ts +11 -6
- package/dist/animation/planner.js +164 -45
- package/dist/animation/render/fade.d.ts +2 -2
- package/dist/animation/render/fade.js +3 -3
- package/dist/animation/render/move.d.ts +3 -3
- package/dist/animation/render/move.js +5 -5
- package/dist/animation/render/plan.d.ts +3 -3
- package/dist/animation/render/static.d.ts +2 -2
- package/dist/animation/render/static.js +3 -3
- package/dist/animation/types.d.ts +14 -15
- package/dist/animation/types.js +1 -6
- package/dist/extensions/factory/main.js +23 -2
- package/dist/extensions/factory/runtime.d.ts +2 -1
- package/dist/extensions/factory/runtime.js +48 -4
- package/dist/extensions/first-party/active-target/factory.js +5 -5
- package/dist/extensions/first-party/auto-promote/factory.d.ts +2 -0
- package/dist/extensions/first-party/auto-promote/factory.js +51 -0
- package/dist/extensions/first-party/auto-promote/types.d.ts +14 -0
- package/dist/extensions/first-party/auto-promote/types.js +2 -0
- package/dist/extensions/first-party/board-events/factory.js +1 -16
- package/dist/extensions/first-party/board-events/types.d.ts +1 -2
- package/dist/extensions/first-party/last-move/factory.js +6 -6
- package/dist/extensions/first-party/legal-moves/factory.js +1 -1
- package/dist/extensions/first-party/main-renderer/animation/render.js +1 -2
- package/dist/extensions/first-party/main-renderer/animation/update.js +9 -23
- package/dist/extensions/first-party/main-renderer/board/render.js +3 -3
- package/dist/extensions/first-party/main-renderer/board/update.js +5 -3
- package/dist/extensions/first-party/main-renderer/coordinates/render.js +4 -4
- package/dist/extensions/first-party/main-renderer/drag/render.js +1 -1
- package/dist/extensions/first-party/main-renderer/normalize.d.ts +2 -3
- package/dist/extensions/first-party/main-renderer/normalize.js +1 -1
- package/dist/extensions/first-party/main-renderer/pieces/render.js +5 -5
- package/dist/extensions/first-party/main-renderer/pieces/suppress.js +7 -2
- package/dist/extensions/first-party/main-renderer/types/extension.d.ts +1 -1
- package/dist/extensions/first-party/main-renderer/types/extension.js +1 -1
- package/dist/extensions/first-party/promotion/factory.d.ts +3 -0
- package/dist/extensions/first-party/promotion/factory.js +219 -0
- package/dist/extensions/first-party/promotion/normalize.d.ts +3 -0
- package/dist/extensions/first-party/promotion/normalize.js +37 -0
- package/dist/extensions/first-party/promotion/types/input.d.ts +10 -0
- package/dist/extensions/first-party/promotion/types/internal.d.ts +12 -0
- package/dist/extensions/first-party/promotion/types/internal.js +22 -0
- package/dist/extensions/first-party/promotion/types/main.d.ts +24 -0
- package/dist/extensions/first-party/promotion/types/main.js +2 -0
- package/dist/extensions/first-party/selected-square/factory.js +3 -3
- package/dist/extensions/index.d.ts +1 -1
- package/dist/extensions/types/basic/events.d.ts +8 -31
- package/dist/extensions/types/basic/events.js +9 -5
- package/dist/extensions/types/basic/interaction.d.ts +21 -0
- package/dist/extensions/types/basic/transient-visuals.d.ts +2 -1
- package/dist/extensions/types/context/events.d.ts +5 -0
- package/dist/extensions/types/context/events.js +1 -0
- package/dist/extensions/types/context/ui-move.d.ts +3 -15
- package/dist/extensions/types/extension.d.ts +10 -8
- package/dist/extensions/types/main.d.ts +11 -6
- package/dist/extensions/types/surface/commands.d.ts +9 -0
- package/dist/extensions/types/surface/events.d.ts +2 -3
- package/dist/extensions/types/wrapper.d.ts +23 -22
- package/dist/extensions/types/wrapper.js +34 -6
- package/dist/extensions/update.d.ts +2 -2
- package/dist/extensions/update.js +1 -1
- package/dist/layout/factory.js +3 -3
- package/dist/layout/geometry/factory.d.ts +2 -11
- package/dist/layout/geometry/factory.js +16 -17
- package/dist/layout/geometry/helpers.d.ts +5 -0
- package/dist/layout/geometry/helpers.js +33 -0
- package/dist/layout/geometry/types.d.ts +13 -12
- package/dist/layout/helpers.d.ts +3 -4
- package/dist/layout/helpers.js +5 -5
- package/dist/layout/reducers.js +9 -8
- package/dist/layout/types.d.ts +5 -5
- package/dist/render/mount.js +2 -2
- package/dist/render/rendering/state.js +7 -7
- package/dist/runtime/factory/events.d.ts +3 -0
- package/dist/runtime/factory/events.js +18 -0
- package/dist/runtime/factory/helpers.js +12 -12
- package/dist/runtime/factory/input.js +17 -10
- package/dist/runtime/factory/main.js +44 -4
- package/dist/runtime/input/adapter/event.d.ts +3 -0
- package/dist/runtime/input/adapter/event.js +19 -0
- package/dist/runtime/input/adapter/factory.js +19 -38
- package/dist/runtime/input/adapter/helpers.d.ts +3 -5
- package/dist/runtime/input/adapter/helpers.js +60 -12
- package/dist/runtime/input/adapter/pointer.d.ts +6 -10
- package/dist/runtime/input/adapter/pointer.js +37 -70
- package/dist/runtime/input/adapter/types.d.ts +6 -3
- package/dist/runtime/input/adapter/types.js +6 -1
- package/dist/runtime/input/controller/factory.js +12 -11
- package/dist/runtime/input/controller/pointer.d.ts +5 -6
- package/dist/runtime/input/controller/pointer.js +36 -35
- package/dist/runtime/input/controller/transient-visuals.d.ts +2 -2
- package/dist/runtime/input/controller/transient-visuals.js +12 -5
- package/dist/runtime/input/controller/types.d.ts +5 -4
- package/dist/runtime/lifecycle.js +6 -6
- package/dist/runtime/mutation/interaction.js +1 -5
- package/dist/runtime/mutation/types.d.ts +10 -8
- package/dist/runtime/types/main.d.ts +2 -0
- package/dist/state/change/{factory.d.ts → factory/main.d.ts} +1 -1
- package/dist/state/change/{factory.js → factory/main.js} +8 -5
- package/dist/state/change/factory/ui-move.d.ts +4 -0
- package/dist/{runtime → state/change}/factory/ui-move.js +9 -9
- package/dist/state/change/helpers.d.ts +4 -2
- package/dist/state/change/helpers.js +11 -1
- package/dist/state/change/mutation.d.ts +1 -1
- package/dist/state/change/reducers.d.ts +3 -3
- package/dist/state/change/reducers.js +4 -4
- package/dist/state/change/types/main.d.ts +18 -0
- package/dist/state/change/types/main.js +1 -0
- package/dist/state/change/types/ui-move.d.ts +25 -0
- package/dist/state/change/types/ui-move.js +1 -0
- package/dist/state/factory.js +1 -1
- package/dist/state/interaction/factory.js +4 -2
- package/dist/state/interaction/helpers.d.ts +2 -0
- package/dist/state/interaction/helpers.js +3 -0
- package/dist/state/interaction/types/internal.d.ts +9 -1
- package/dist/state/types.d.ts +1 -1
- package/dist/wrapper/factory.js +2 -26
- package/package.json +9 -5
- package/dist/runtime/factory/ui-move.d.ts +0 -4
- package/dist/runtime/types/ui-move.d.ts +0 -9
- package/dist/state/change/types.d.ts +0 -17
- /package/dist/{runtime/types/ui-move.js → extensions/first-party/promotion/types/input.js} +0 -0
- /package/dist/{state/change/types.js → extensions/types/basic/interaction.js} +0 -0
|
@@ -10,6 +10,7 @@ import { createInteractionController } from '../input/controller/factory.js';
|
|
|
10
10
|
import { runtimeDestroy, runtimeMount, runtimeUnmount } from '../lifecycle.js';
|
|
11
11
|
import { createRuntimeMutationPipeline } from '../mutation/factory.js';
|
|
12
12
|
import { runtimeRunMutationPipeline } from '../mutation/run.js';
|
|
13
|
+
import { createExtensionRuntimeSurfaceEvents } from './events.js';
|
|
13
14
|
import { createRuntimeInteractionSurface } from './input.js';
|
|
14
15
|
function createRuntimeInternal(options) {
|
|
15
16
|
const extensionSystem = createExtensionSystem(options);
|
|
@@ -30,7 +31,7 @@ function createRuntimeInternal(options) {
|
|
|
30
31
|
})
|
|
31
32
|
};
|
|
32
33
|
}
|
|
33
|
-
function
|
|
34
|
+
function createExtensionRuntimeSurfaceCommandsInternalSurface(getInternalState) {
|
|
34
35
|
return {
|
|
35
36
|
setPosition(input) {
|
|
36
37
|
const state = getInternalState();
|
|
@@ -103,6 +104,13 @@ function createExtensionRuntimeSurfaceCommands(getInternalState) {
|
|
|
103
104
|
runtimeRunMutationPipeline(state);
|
|
104
105
|
return changed;
|
|
105
106
|
},
|
|
107
|
+
startDrag(session) {
|
|
108
|
+
const state = getInternalState();
|
|
109
|
+
const mutationSession = state.mutation.getSession();
|
|
110
|
+
const changed = state.state.interaction.setDragSession(session, mutationSession);
|
|
111
|
+
runtimeRunMutationPipeline(state);
|
|
112
|
+
return changed;
|
|
113
|
+
},
|
|
106
114
|
clearActiveInteraction() {
|
|
107
115
|
const state = getInternalState();
|
|
108
116
|
const mutationSession = state.mutation.getSession();
|
|
@@ -117,6 +125,36 @@ function createExtensionRuntimeSurfaceCommands(getInternalState) {
|
|
|
117
125
|
runtimeRunMutationPipeline(state);
|
|
118
126
|
return changed;
|
|
119
127
|
},
|
|
128
|
+
resolveDeferredUIMoveRequest(details) {
|
|
129
|
+
const state = getInternalState();
|
|
130
|
+
const deferredRequest = state.state.change.deferredUIMoveRequest;
|
|
131
|
+
assert(deferredRequest, 'No deferred UI move request to resolve');
|
|
132
|
+
const { sourceSquare, destination } = deferredRequest;
|
|
133
|
+
const moveRequest = {
|
|
134
|
+
from: sourceSquare,
|
|
135
|
+
to: destination.to,
|
|
136
|
+
...(destination.capturedSquare !== undefined && {
|
|
137
|
+
capturedSquare: destination.capturedSquare
|
|
138
|
+
}),
|
|
139
|
+
...(destination.secondary !== undefined && { secondary: destination.secondary }),
|
|
140
|
+
promotedTo: details.promotedTo
|
|
141
|
+
};
|
|
142
|
+
const mutationSession = state.mutation.getSession();
|
|
143
|
+
const move = state.state.board.move(moveRequest, mutationSession);
|
|
144
|
+
state.state.change.setDeferredUIMoveRequest(null, mutationSession);
|
|
145
|
+
mutationSession.addMutation('runtime.interaction.resolveDeferredUIMoveRequest', true);
|
|
146
|
+
runtimeRunMutationPipeline(state);
|
|
147
|
+
return move;
|
|
148
|
+
},
|
|
149
|
+
cancelDeferredUIMoveRequest() {
|
|
150
|
+
const state = getInternalState();
|
|
151
|
+
assert(state.state.change.deferredUIMoveRequest, 'No deferred UI move request to cancel');
|
|
152
|
+
const mutationSession = state.mutation.getSession();
|
|
153
|
+
const changed = state.state.change.setDeferredUIMoveRequest(null, mutationSession);
|
|
154
|
+
mutationSession.addMutation('runtime.interaction.cancelDeferredUIMoveRequest', changed);
|
|
155
|
+
runtimeRunMutationPipeline(state);
|
|
156
|
+
return changed;
|
|
157
|
+
},
|
|
120
158
|
getSnapshot() {
|
|
121
159
|
const state = getInternalState();
|
|
122
160
|
return {
|
|
@@ -139,11 +177,13 @@ export function createRuntime(options) {
|
|
|
139
177
|
return internalState;
|
|
140
178
|
}
|
|
141
179
|
// Create RuntimeExtensionSurface to pass to the extension system for initialization of extension instances
|
|
142
|
-
const
|
|
180
|
+
const extensionSurfaceCommands = createExtensionRuntimeSurfaceCommandsInternalSurface(getInternalState);
|
|
181
|
+
const extensionSurfaceEvents = createExtensionRuntimeSurfaceEvents(getInternalState);
|
|
143
182
|
// Now construct the internal state
|
|
144
183
|
const optionsInternal = {
|
|
145
184
|
...options,
|
|
146
|
-
extensionRuntimeSurfaceCommands:
|
|
185
|
+
extensionRuntimeSurfaceCommands: extensionSurfaceCommands,
|
|
186
|
+
extensionRuntimeSurfaceEvents: extensionSurfaceEvents,
|
|
147
187
|
getInternalState
|
|
148
188
|
};
|
|
149
189
|
internalState = createRuntimeInternal(optionsInternal);
|
|
@@ -174,7 +214,7 @@ export function createRuntime(options) {
|
|
|
174
214
|
internalStatus = 'destroyed';
|
|
175
215
|
internalState = null;
|
|
176
216
|
},
|
|
177
|
-
...
|
|
217
|
+
...extensionSurfaceCommands,
|
|
178
218
|
getExtensionsPublicRecord() {
|
|
179
219
|
return getInternalState().extensionSystem.getPublicRecord();
|
|
180
220
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ALL_SCENE_POINTER_EVENT_TYPES } from '../../../extensions/types/basic/events.js';
|
|
2
|
+
import { pointerEventDestroy, pointerEventHandler } from './pointer.js';
|
|
3
|
+
export function eventHandler(state, e) {
|
|
4
|
+
let context = null;
|
|
5
|
+
if (ALL_SCENE_POINTER_EVENT_TYPES.has(e.type)) {
|
|
6
|
+
context = pointerEventHandler(state, e);
|
|
7
|
+
}
|
|
8
|
+
if (!context) {
|
|
9
|
+
context = {
|
|
10
|
+
rawEvent: e,
|
|
11
|
+
sceneEvent: null
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
// Pass to controller for extension handling
|
|
15
|
+
state.controller.onEvent(context);
|
|
16
|
+
}
|
|
17
|
+
export function eventDestroy(state) {
|
|
18
|
+
pointerEventDestroy(state);
|
|
19
|
+
}
|
|
@@ -1,55 +1,36 @@
|
|
|
1
|
-
import
|
|
1
|
+
import assert from '@ktarmyshov/assert';
|
|
2
|
+
import { eventDestroy, eventHandler } from './event.js';
|
|
3
|
+
import { NEED_EVENT_TYPES } from './types.js';
|
|
2
4
|
function createInputAdapterInternal(options) {
|
|
3
5
|
return {
|
|
4
6
|
container: options.container,
|
|
5
|
-
|
|
7
|
+
getRenderGeometry: options.getRenderGeometry,
|
|
6
8
|
controller: options.controller,
|
|
7
9
|
activePointerId: null
|
|
8
10
|
};
|
|
9
11
|
}
|
|
10
12
|
export function createInputAdapter(options) {
|
|
11
13
|
const internalState = createInputAdapterInternal(options);
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
return;
|
|
15
|
-
onPointerDown(internalState, e);
|
|
16
|
-
};
|
|
17
|
-
const onPointerMoveHandler = (e) => {
|
|
18
|
-
if (!isPointerRelevantEvent(e))
|
|
19
|
-
return;
|
|
20
|
-
onPointerMove(internalState, e);
|
|
21
|
-
};
|
|
22
|
-
const onPointerUpHandler = (e) => {
|
|
23
|
-
if (!isPointerRelevantEvent(e))
|
|
24
|
-
return;
|
|
25
|
-
onPointerUp(internalState, e);
|
|
26
|
-
};
|
|
27
|
-
const onPointerCancelHandler = (e) => {
|
|
28
|
-
if (!isPointerRelevantEvent(e))
|
|
29
|
-
return;
|
|
30
|
-
onPointerCancel(internalState, e);
|
|
31
|
-
};
|
|
32
|
-
const onPointerLeaveHandler = (e) => {
|
|
33
|
-
if (!isPointerRelevantEvent(e))
|
|
34
|
-
return;
|
|
35
|
-
onPointerLeave(internalState, e);
|
|
14
|
+
const onEventHander = (e) => {
|
|
15
|
+
eventHandler(internalState, e);
|
|
36
16
|
};
|
|
37
17
|
const inputAdapter = {
|
|
18
|
+
subscribeEvent(type) {
|
|
19
|
+
internalState.container.addEventListener(type, onEventHander);
|
|
20
|
+
},
|
|
21
|
+
unsubscribeEvent(type) {
|
|
22
|
+
assert(NEED_EVENT_TYPES.has(type), `Unsubscribe for event type ${type} is not supported. This is required event type for the board to function properly.`);
|
|
23
|
+
internalState.container.removeEventListener(type, onEventHander);
|
|
24
|
+
},
|
|
38
25
|
destroy() {
|
|
39
|
-
|
|
40
|
-
|
|
26
|
+
for (const type of NEED_EVENT_TYPES) {
|
|
27
|
+
internalState.container.removeEventListener(type, onEventHander);
|
|
41
28
|
}
|
|
42
|
-
internalState
|
|
43
|
-
internalState.container.removeEventListener('pointermove', onPointerMoveHandler);
|
|
44
|
-
internalState.container.removeEventListener('pointerup', onPointerUpHandler);
|
|
45
|
-
internalState.container.removeEventListener('pointercancel', onPointerCancelHandler);
|
|
46
|
-
internalState.container.removeEventListener('pointerleave', onPointerLeaveHandler);
|
|
29
|
+
eventDestroy(internalState);
|
|
47
30
|
}
|
|
48
31
|
};
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
internalState.container.addEventListener('pointercancel', onPointerCancelHandler);
|
|
53
|
-
internalState.container.addEventListener('pointerleave', onPointerLeaveHandler);
|
|
32
|
+
for (const type of NEED_EVENT_TYPES) {
|
|
33
|
+
internalState.container.addEventListener(type, onEventHander);
|
|
34
|
+
}
|
|
54
35
|
return inputAdapter;
|
|
55
36
|
}
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
export declare function mapBoardPointToSquare(x: number, y: number, geometry: RenderGeometry): Square | null;
|
|
5
|
-
export declare function clampBoardPoint(point: ScenePoint, geometry: RenderGeometry): ScenePoint;
|
|
1
|
+
import { ScenePointerEvent } from '../../../extensions/types/basic/events.js';
|
|
2
|
+
import { InputAdapterInternal } from './types.js';
|
|
3
|
+
export declare function makeScenePointerEvent(state: InputAdapterInternal, e: PointerEvent): ScenePointerEvent;
|
|
@@ -1,12 +1,67 @@
|
|
|
1
|
-
export function
|
|
1
|
+
export function makeScenePointerEvent(state, e) {
|
|
2
|
+
const containerRect = state.container.getBoundingClientRect();
|
|
3
|
+
const sceneRect = makeSceneRectFromDOMRect(containerRect);
|
|
4
|
+
const point = toScenePoint(e, containerRect);
|
|
5
|
+
const clampedPoint = clampToSceneRect(point, sceneRect);
|
|
6
|
+
let clampedToBoardPoint = null;
|
|
7
|
+
let targetSquare = null;
|
|
8
|
+
const geometry = state.getRenderGeometry();
|
|
9
|
+
if (geometry) {
|
|
10
|
+
const sceneBoardRect = geometry.boardRect;
|
|
11
|
+
clampedToBoardPoint = clampToSceneRect(point, sceneBoardRect);
|
|
12
|
+
targetSquare = mapScenePointToSquare(point, geometry);
|
|
13
|
+
}
|
|
14
|
+
return {
|
|
15
|
+
// DOM part
|
|
16
|
+
type: e.type,
|
|
17
|
+
// scene part
|
|
18
|
+
point,
|
|
19
|
+
clampedPoint,
|
|
20
|
+
boardClampedPoint: clampedToBoardPoint,
|
|
21
|
+
// board part
|
|
22
|
+
targetSquare
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function toScenePoint(e, inRect) {
|
|
26
|
+
return {
|
|
27
|
+
x: e.clientX - inRect.x,
|
|
28
|
+
y: e.clientY - inRect.y
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function makeSceneRectFromDOMRect(domRect) {
|
|
32
|
+
return {
|
|
33
|
+
x: 0,
|
|
34
|
+
y: 0,
|
|
35
|
+
width: domRect.width,
|
|
36
|
+
height: domRect.height
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function clampToSceneRect(point, boundRect) {
|
|
40
|
+
// X cannot go below boundRect.x, cannot go above boundRect.x + boundRect.width
|
|
41
|
+
// Y cannot go below boundRect.y, cannot go above boundRect.y + boundRect.height
|
|
42
|
+
return {
|
|
43
|
+
x: Math.max(boundRect.x, Math.min(point.x, boundRect.x + boundRect.width)),
|
|
44
|
+
y: Math.max(boundRect.y, Math.min(point.y, boundRect.y + boundRect.height))
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function mapScenePointToSquare(point, geometry) {
|
|
48
|
+
const { x, y } = point;
|
|
2
49
|
if (!Number.isFinite(x) || !Number.isFinite(y))
|
|
3
50
|
return null;
|
|
4
|
-
const
|
|
5
|
-
|
|
51
|
+
const orientation = geometry.orientation;
|
|
52
|
+
const boardRect = geometry.boardRect;
|
|
53
|
+
const boardSize = boardRect.width;
|
|
54
|
+
const squareSize = geometry.squareSize;
|
|
55
|
+
if (x < boardRect.x ||
|
|
56
|
+
x >= boardRect.x + boardSize ||
|
|
57
|
+
y < boardRect.y ||
|
|
58
|
+
y >= boardRect.y + boardSize)
|
|
6
59
|
return null;
|
|
7
60
|
// Grid cell indices, each in [0, 7].
|
|
8
|
-
const xIndex = Math.floor(x / squareSize);
|
|
9
|
-
const yIndex = Math.floor(y / squareSize);
|
|
61
|
+
const xIndex = Math.floor((x - boardRect.x) / squareSize);
|
|
62
|
+
const yIndex = Math.floor((y - boardRect.y) / squareSize);
|
|
63
|
+
if (xIndex < 0 || xIndex > 7 || yIndex < 0 || yIndex > 7)
|
|
64
|
+
return null;
|
|
10
65
|
// Invert the orientation mapping used by geometry.squareRect:
|
|
11
66
|
// white: xIndex = file, yIndex = 7 - rank → file = xIndex, rank = 7 - yIndex
|
|
12
67
|
// black: xIndex = 7 - file, yIndex = rank → file = 7 - xIndex, rank = yIndex
|
|
@@ -14,10 +69,3 @@ export function mapBoardPointToSquare(x, y, geometry) {
|
|
|
14
69
|
const rank = orientation === 0 /* ColorCode.White */ ? 7 - yIndex : yIndex;
|
|
15
70
|
return (rank * 8 + file);
|
|
16
71
|
}
|
|
17
|
-
export function clampBoardPoint(point, geometry) {
|
|
18
|
-
const { boardSize } = geometry;
|
|
19
|
-
return {
|
|
20
|
-
x: Math.min(Math.max(point.x, 0), boardSize),
|
|
21
|
-
y: Math.min(Math.max(point.y, 0), boardSize)
|
|
22
|
-
};
|
|
23
|
-
}
|
|
@@ -1,13 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ExtensionOnEventContext } from '../../../extensions/types/context/events.js';
|
|
2
2
|
import { InputAdapterInternal } from './types.js';
|
|
3
|
-
export
|
|
4
|
-
type: ScenePointerEventType;
|
|
5
|
-
};
|
|
6
|
-
export declare function isPointerRelevantEvent(e: PointerEvent): e is PointerRelevantEvent;
|
|
3
|
+
export declare function pointerEventHandler(state: InputAdapterInternal, e: PointerEvent): ExtensionOnEventContext;
|
|
7
4
|
/** Release capture for the currently tracked pointer and clear tracking state. */
|
|
8
5
|
export declare function releaseCapture(state: InputAdapterInternal): void;
|
|
9
|
-
export declare function
|
|
10
|
-
export declare function
|
|
11
|
-
export declare function
|
|
12
|
-
export declare function
|
|
13
|
-
export declare function onPointerLeave(state: InputAdapterInternal, e: PointerRelevantEvent): void;
|
|
6
|
+
export declare function adapterOnPointerDown(state: InputAdapterInternal, e: PointerEvent): void;
|
|
7
|
+
export declare function adapterOnPointerUp(state: InputAdapterInternal, e: PointerEvent): void;
|
|
8
|
+
export declare function adapterOnPointerCancel(state: InputAdapterInternal, e: PointerEvent): void;
|
|
9
|
+
export declare function pointerEventDestroy(state: InputAdapterInternal): void;
|
|
@@ -1,9 +1,30 @@
|
|
|
1
1
|
import assert from '@ktarmyshov/assert';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
import { ALL_SCENE_POINTER_EVENT_TYPES } from '../../../extensions/types/basic/events.js';
|
|
3
|
+
import { makeScenePointerEvent } from './helpers.js';
|
|
4
|
+
export function pointerEventHandler(state, e) {
|
|
5
|
+
assert(ALL_SCENE_POINTER_EVENT_TYPES.has(e.type), `Unexpected pointer event type: ${e.type}`);
|
|
6
|
+
// First convert to scene event for controller
|
|
7
|
+
const sceneEvent = makeScenePointerEvent(state, e);
|
|
8
|
+
// Then handle pointer event within the adapter logic (e.g. tracking active pointer, capturing, etc.)
|
|
9
|
+
pointerEventAdapterHandler(state, e);
|
|
10
|
+
// Then create context and pass to controller for extension handling
|
|
11
|
+
return {
|
|
12
|
+
rawEvent: e,
|
|
13
|
+
sceneEvent
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function pointerEventAdapterHandler(state, e) {
|
|
17
|
+
switch (e.type) {
|
|
18
|
+
case 'pointerdown':
|
|
19
|
+
adapterOnPointerDown(state, e);
|
|
20
|
+
break;
|
|
21
|
+
case 'pointerup':
|
|
22
|
+
adapterOnPointerUp(state, e);
|
|
23
|
+
break;
|
|
24
|
+
case 'pointercancel':
|
|
25
|
+
adapterOnPointerCancel(state, e);
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
7
28
|
}
|
|
8
29
|
/** Release capture for the currently tracked pointer and clear tracking state. */
|
|
9
30
|
export function releaseCapture(state) {
|
|
@@ -14,84 +35,30 @@ export function releaseCapture(state) {
|
|
|
14
35
|
}
|
|
15
36
|
state.activePointerId = null;
|
|
16
37
|
}
|
|
17
|
-
function
|
|
18
|
-
|
|
19
|
-
if (!geometry)
|
|
20
|
-
return { target: null, rawPoint: null, clampedPoint: null };
|
|
21
|
-
const rect = state.container.getBoundingClientRect();
|
|
22
|
-
const x = e.clientX - rect.left;
|
|
23
|
-
const y = e.clientY - rect.top;
|
|
24
|
-
const target = mapBoardPointToSquare(x, y, geometry);
|
|
25
|
-
const point = { x, y };
|
|
26
|
-
return { target, rawPoint: point, clampedPoint: clampBoardPoint(point, geometry) };
|
|
27
|
-
}
|
|
28
|
-
function makeBoardPointerEvent(e, pointerTarget) {
|
|
29
|
-
assert(e.defaultPrevented === false, 'Expected event to be unhandled before making BoardPointerEvent');
|
|
30
|
-
let defaultPrevented = false;
|
|
31
|
-
return {
|
|
32
|
-
type: e.type,
|
|
33
|
-
// DOM part
|
|
34
|
-
pointerId: e.pointerId,
|
|
35
|
-
isPrimary: e.isPrimary,
|
|
36
|
-
button: e.button,
|
|
37
|
-
buttons: e.buttons,
|
|
38
|
-
ctrlKey: e.ctrlKey,
|
|
39
|
-
altKey: e.altKey,
|
|
40
|
-
shiftKey: e.shiftKey,
|
|
41
|
-
metaKey: e.metaKey,
|
|
42
|
-
// Board part
|
|
43
|
-
rawPoint: pointerTarget.rawPoint,
|
|
44
|
-
clampedPoint: pointerTarget.clampedPoint,
|
|
45
|
-
target: pointerTarget.target,
|
|
46
|
-
// Mechanics
|
|
47
|
-
get defaultPrevented() {
|
|
48
|
-
return defaultPrevented;
|
|
49
|
-
},
|
|
50
|
-
preventDefault() {
|
|
51
|
-
defaultPrevented = true;
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
export function onPointerDown(state, e) {
|
|
38
|
+
export function adapterOnPointerDown(state, e) {
|
|
39
|
+
assert(e.type === 'pointerdown', `Expected pointerdown event, got ${e.type}`);
|
|
56
40
|
if (!e.isPrimary)
|
|
57
41
|
return; // ignore non-primary pointers
|
|
58
42
|
if (state.activePointerId !== null)
|
|
59
43
|
return; // already tracking
|
|
60
44
|
state.activePointerId = e.pointerId;
|
|
61
45
|
state.container.setPointerCapture(e.pointerId);
|
|
62
|
-
const pointerTarget = resolvePointerTarget(state, e);
|
|
63
|
-
const boardEvent = makeBoardPointerEvent(e, pointerTarget);
|
|
64
|
-
e.preventDefault(); // prevent native text selection during drag
|
|
65
|
-
state.controller.onEvent(boardEvent);
|
|
66
46
|
}
|
|
67
|
-
export function
|
|
47
|
+
export function adapterOnPointerUp(state, e) {
|
|
48
|
+
assert(e.type === 'pointerup', `Expected pointerup event, got ${e.type}`);
|
|
68
49
|
if (e.pointerId !== state.activePointerId)
|
|
69
50
|
return;
|
|
70
|
-
const pointerTarget = resolvePointerTarget(state, e);
|
|
71
|
-
const boardEvent = makeBoardPointerEvent(e, pointerTarget);
|
|
72
|
-
e.preventDefault(); // prevent native text selection during drag
|
|
73
|
-
state.controller.onEvent(boardEvent);
|
|
74
|
-
}
|
|
75
|
-
export function onPointerUp(state, e) {
|
|
76
|
-
if (e.pointerId !== state.activePointerId)
|
|
77
|
-
return;
|
|
78
|
-
const pointerTarget = resolvePointerTarget(state, e); // resolve before releasing capture
|
|
79
51
|
releaseCapture(state);
|
|
80
|
-
const boardEvent = makeBoardPointerEvent(e, pointerTarget);
|
|
81
|
-
state.controller.onEvent(boardEvent);
|
|
82
52
|
}
|
|
83
|
-
export function
|
|
53
|
+
export function adapterOnPointerCancel(state, e) {
|
|
54
|
+
assert(e.type === 'pointercancel', `Expected pointercancel event, got ${e.type}`);
|
|
84
55
|
if (e.pointerId !== state.activePointerId)
|
|
85
56
|
return;
|
|
86
|
-
const pointerTarget = resolvePointerTarget(state, e); // resolve before releasing capture
|
|
87
57
|
releaseCapture(state);
|
|
88
|
-
const boardEvent = makeBoardPointerEvent(e, pointerTarget);
|
|
89
|
-
state.controller.onEvent(boardEvent);
|
|
90
58
|
}
|
|
91
|
-
export function
|
|
92
|
-
if (
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
state.controller.onEvent(boardEvent);
|
|
59
|
+
export function pointerEventDestroy(state) {
|
|
60
|
+
if (state.activePointerId !== null) {
|
|
61
|
+
releaseCapture(state);
|
|
62
|
+
}
|
|
63
|
+
state.activePointerId = null;
|
|
97
64
|
}
|
|
@@ -1,16 +1,19 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SceneRenderGeometry } from '../../../layout/geometry/types.js';
|
|
2
2
|
import { InteractionController } from '../controller/types.js';
|
|
3
3
|
export interface InputAdapterInitOptions {
|
|
4
4
|
container: HTMLElement;
|
|
5
|
-
|
|
5
|
+
getRenderGeometry: () => SceneRenderGeometry | null;
|
|
6
6
|
controller: InteractionController;
|
|
7
7
|
}
|
|
8
8
|
export interface InputAdapterInternal {
|
|
9
9
|
readonly container: HTMLElement;
|
|
10
|
-
readonly
|
|
10
|
+
readonly getRenderGeometry: () => SceneRenderGeometry | null;
|
|
11
11
|
readonly controller: InteractionController;
|
|
12
12
|
activePointerId: number | null;
|
|
13
13
|
}
|
|
14
14
|
export interface InputAdapter {
|
|
15
|
+
subscribeEvent<K extends keyof HTMLElementEventMap>(type: K): void;
|
|
16
|
+
unsubscribeEvent<K extends keyof HTMLElementEventMap>(type: K): void;
|
|
15
17
|
destroy(): void;
|
|
16
18
|
}
|
|
19
|
+
export declare const NEED_EVENT_TYPES: Set<string>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { handlePointerCancel, handlePointerDown,
|
|
1
|
+
import { handlePointerCancel, handlePointerDown, handlePointerMove, handlePointerUp } from './pointer.js';
|
|
2
2
|
import { transmitTransientInput } from './transient-visuals.js';
|
|
3
3
|
function createInteractionControllerInternal(options) {
|
|
4
4
|
return {
|
|
@@ -8,25 +8,26 @@ function createInteractionControllerInternal(options) {
|
|
|
8
8
|
export function createInteractionController(options) {
|
|
9
9
|
const internalState = createInteractionControllerInternal(options);
|
|
10
10
|
return {
|
|
11
|
-
onEvent(
|
|
12
|
-
|
|
11
|
+
onEvent(context) {
|
|
12
|
+
internalState.surface.onEvent(context);
|
|
13
|
+
if (context.rawEvent.defaultPrevented) {
|
|
14
|
+
return; // The event has been handled by the surface (extensions)
|
|
15
|
+
}
|
|
16
|
+
switch (context.rawEvent.type) {
|
|
13
17
|
case 'pointerdown':
|
|
14
|
-
handlePointerDown(internalState,
|
|
18
|
+
handlePointerDown(internalState, context);
|
|
15
19
|
break;
|
|
16
20
|
case 'pointermove':
|
|
17
|
-
handlePointerMove(internalState,
|
|
21
|
+
handlePointerMove(internalState, context);
|
|
18
22
|
break;
|
|
19
23
|
case 'pointerup':
|
|
20
|
-
handlePointerUp(internalState,
|
|
24
|
+
handlePointerUp(internalState, context);
|
|
21
25
|
break;
|
|
22
26
|
case 'pointercancel':
|
|
23
|
-
handlePointerCancel(internalState,
|
|
24
|
-
break;
|
|
25
|
-
case 'pointerleave':
|
|
26
|
-
handlePointerLeave(internalState, event);
|
|
27
|
+
handlePointerCancel(internalState, context);
|
|
27
28
|
break;
|
|
28
29
|
}
|
|
29
|
-
transmitTransientInput(internalState,
|
|
30
|
+
transmitTransientInput(internalState, context);
|
|
30
31
|
}
|
|
31
32
|
};
|
|
32
33
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ExtensionOnEventContext } from '../../../extensions/types/context/events.js';
|
|
2
2
|
import { InteractionControllerInternal } from './types.js';
|
|
3
|
-
export declare function handlePointerDown(state: InteractionControllerInternal,
|
|
4
|
-
export declare function handlePointerMove(state: InteractionControllerInternal,
|
|
5
|
-
export declare function handlePointerUp(state: InteractionControllerInternal,
|
|
6
|
-
export declare function handlePointerCancel(state: InteractionControllerInternal,
|
|
7
|
-
export declare function handlePointerLeave(state: InteractionControllerInternal, event: ScenePointerEvent): void;
|
|
3
|
+
export declare function handlePointerDown(state: InteractionControllerInternal, context: ExtensionOnEventContext): void;
|
|
4
|
+
export declare function handlePointerMove(state: InteractionControllerInternal, context: ExtensionOnEventContext): void;
|
|
5
|
+
export declare function handlePointerUp(state: InteractionControllerInternal, context: ExtensionOnEventContext): void;
|
|
6
|
+
export declare function handlePointerCancel(state: InteractionControllerInternal, context: ExtensionOnEventContext): void;
|