@neta-art/cohub 11.3.3 → 11.3.4
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/README.md
CHANGED
|
@@ -218,6 +218,12 @@ editor.addItem("acme.order", { at: editor.viewCenter(), props: { orderId: "o-1",
|
|
|
218
218
|
// React: const selection = useSyncExternalStore((fn) => editor.subscribe("selection", fn), () => editor.selection);
|
|
219
219
|
```
|
|
220
220
|
|
|
221
|
+
For draggable DOM item views, use `createBoardPointerGestures(element, { move, end })`
|
|
222
|
+
from `board/stage`: call `start(event)` for accepted pointer downs and `cancel()`
|
|
223
|
+
on unmount. It follows active pointers outside the element, preserves mouse gestures
|
|
224
|
+
when capture is lost, and cancels on window blur or page hide. Forward events through
|
|
225
|
+
`context.toPointerEvent` to the editor; keep hover handling separate from active gestures.
|
|
226
|
+
|
|
221
227
|
Items of a type the client does not know still render as a placeholder, move
|
|
222
228
|
and keep every field, so documents written by newer clients are never
|
|
223
229
|
rewritten by older ones. For a canvas look instead of DOM, pass renderers to
|
|
@@ -2,8 +2,9 @@ import { DEFAULT_LRU_BUDGET, LruBudget, LruEntry, selectLruEvictions } from "./l
|
|
|
2
2
|
import { BoardImageTexturePool, boardImageTexturePool, createBoardImageTexturePool, loadBoardImageTexture, unloadBoardImageTexture } from "./texture-pool.js";
|
|
3
3
|
import { BoardAssetManager, BoardAssetManagerOptions, BoardModelPreviewRequest, BoardModelPreviews, boardAssetKey, createBoardAssetManager } from "./assets.js";
|
|
4
4
|
import { toBoardPointerEvent } from "./pointer.js";
|
|
5
|
+
import { createBoardPointerGestures } from "./pointer-gestures.js";
|
|
5
6
|
import { BoardLiveStroke, BoardScene, BoardSceneNode, SceneSyncInput, createBoardScene } from "./scene.js";
|
|
6
7
|
import { BoardItemView, BoardItemViewContext, BoardItemViewInstance, BoardItemViewLayer, createBoardItemViewLayer } from "./views.js";
|
|
7
8
|
import { BoardStage, BoardStageOptions, BoardStagePointerPhase, BoardStageTheme, mountBoardStage } from "./stage.js";
|
|
8
9
|
import { BoardOverlayInput, drawBoardOverlay, expandFrame } from "./overlay.js";
|
|
9
|
-
export { BoardAssetManager, BoardAssetManagerOptions, BoardImageTexturePool, BoardItemView, BoardItemViewContext, BoardItemViewInstance, BoardItemViewLayer, BoardLiveStroke, BoardModelPreviewRequest, BoardModelPreviews, BoardOverlayInput, BoardScene, BoardSceneNode, BoardStage, BoardStageOptions, BoardStagePointerPhase, BoardStageTheme, DEFAULT_LRU_BUDGET, LruBudget, LruEntry, SceneSyncInput, boardAssetKey, boardImageTexturePool, createBoardAssetManager, createBoardImageTexturePool, createBoardItemViewLayer, createBoardScene, drawBoardOverlay, expandFrame, loadBoardImageTexture, mountBoardStage, selectLruEvictions, toBoardPointerEvent, unloadBoardImageTexture };
|
|
10
|
+
export { BoardAssetManager, BoardAssetManagerOptions, BoardImageTexturePool, BoardItemView, BoardItemViewContext, BoardItemViewInstance, BoardItemViewLayer, BoardLiveStroke, BoardModelPreviewRequest, BoardModelPreviews, BoardOverlayInput, BoardScene, BoardSceneNode, BoardStage, BoardStageOptions, BoardStagePointerPhase, BoardStageTheme, DEFAULT_LRU_BUDGET, LruBudget, LruEntry, SceneSyncInput, boardAssetKey, boardImageTexturePool, createBoardAssetManager, createBoardImageTexturePool, createBoardItemViewLayer, createBoardPointerGestures, createBoardScene, drawBoardOverlay, expandFrame, loadBoardImageTexture, mountBoardStage, selectLruEvictions, toBoardPointerEvent, unloadBoardImageTexture };
|
|
@@ -2,8 +2,9 @@ import { DEFAULT_LRU_BUDGET, selectLruEvictions } from "./lru.js";
|
|
|
2
2
|
import { boardImageTexturePool, createBoardImageTexturePool, loadBoardImageTexture, unloadBoardImageTexture } from "./texture-pool.js";
|
|
3
3
|
import { boardAssetKey, createBoardAssetManager } from "./assets.js";
|
|
4
4
|
import { toBoardPointerEvent } from "./pointer.js";
|
|
5
|
+
import { createBoardPointerGestures } from "./pointer-gestures.js";
|
|
5
6
|
import { createBoardScene } from "./scene.js";
|
|
6
7
|
import { drawBoardOverlay, expandFrame } from "./overlay.js";
|
|
7
8
|
import { createBoardItemViewLayer } from "./views.js";
|
|
8
9
|
import { mountBoardStage } from "./stage.js";
|
|
9
|
-
export { DEFAULT_LRU_BUDGET, boardAssetKey, boardImageTexturePool, createBoardAssetManager, createBoardImageTexturePool, createBoardItemViewLayer, createBoardScene, drawBoardOverlay, expandFrame, loadBoardImageTexture, mountBoardStage, selectLruEvictions, toBoardPointerEvent, unloadBoardImageTexture };
|
|
10
|
+
export { DEFAULT_LRU_BUDGET, boardAssetKey, boardImageTexturePool, createBoardAssetManager, createBoardImageTexturePool, createBoardItemViewLayer, createBoardPointerGestures, createBoardScene, drawBoardOverlay, expandFrame, loadBoardImageTexture, mountBoardStage, selectLruEvictions, toBoardPointerEvent, unloadBoardImageTexture };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region src/board/stage/pointer-gestures.d.ts
|
|
2
|
+
type BoardPointerGestureHandlers = {
|
|
3
|
+
move(event: PointerEvent): void;
|
|
4
|
+
end(event: PointerEvent): void;
|
|
5
|
+
};
|
|
6
|
+
declare function createBoardPointerGestures(host: HTMLElement, handlers: BoardPointerGestureHandlers): {
|
|
7
|
+
has: (pointerId: number) => boolean;
|
|
8
|
+
start(event: PointerEvent): void;
|
|
9
|
+
cancel: () => void;
|
|
10
|
+
};
|
|
11
|
+
//#endregion
|
|
12
|
+
export { createBoardPointerGestures };
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
//#region src/board/stage/pointer-gestures.ts
|
|
2
|
+
function createBoardPointerGestures(host, handlers) {
|
|
3
|
+
const document = host.ownerDocument;
|
|
4
|
+
const window = document.defaultView;
|
|
5
|
+
const pointers = /* @__PURE__ */ new Map();
|
|
6
|
+
function listen(active) {
|
|
7
|
+
const method = active ? "addEventListener" : "removeEventListener";
|
|
8
|
+
document[method]("pointermove", move, true);
|
|
9
|
+
document[method]("pointerup", end, true);
|
|
10
|
+
document[method]("pointercancel", end, true);
|
|
11
|
+
host[method]("lostpointercapture", lost);
|
|
12
|
+
window?.[method]("blur", cancel);
|
|
13
|
+
document[method]("visibilitychange", visibility);
|
|
14
|
+
}
|
|
15
|
+
function move(event) {
|
|
16
|
+
const previous = pointers.get(event.pointerId);
|
|
17
|
+
if (!previous) return;
|
|
18
|
+
if (event.pointerType === "mouse" && event.buttons === 0 && window) {
|
|
19
|
+
end(new window.PointerEvent("pointerup", {
|
|
20
|
+
pointerId: event.pointerId,
|
|
21
|
+
pointerType: event.pointerType,
|
|
22
|
+
clientX: previous.clientX,
|
|
23
|
+
clientY: previous.clientY,
|
|
24
|
+
button: 0,
|
|
25
|
+
buttons: 0,
|
|
26
|
+
shiftKey: event.shiftKey,
|
|
27
|
+
altKey: event.altKey,
|
|
28
|
+
ctrlKey: event.ctrlKey,
|
|
29
|
+
metaKey: event.metaKey
|
|
30
|
+
}));
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
pointers.set(event.pointerId, event);
|
|
34
|
+
handlers.move(event);
|
|
35
|
+
}
|
|
36
|
+
function end(event) {
|
|
37
|
+
if (!pointers.delete(event.pointerId)) return;
|
|
38
|
+
if (pointers.size === 0) listen(false);
|
|
39
|
+
if (host.hasPointerCapture(event.pointerId)) host.releasePointerCapture(event.pointerId);
|
|
40
|
+
handlers.end(event);
|
|
41
|
+
}
|
|
42
|
+
function lost(event) {
|
|
43
|
+
if (event.target === host && event.pointerType !== "mouse") end(event);
|
|
44
|
+
}
|
|
45
|
+
function cancel() {
|
|
46
|
+
if (!window) return;
|
|
47
|
+
for (const event of [...pointers.values()]) end(new window.PointerEvent("pointercancel", event));
|
|
48
|
+
}
|
|
49
|
+
function visibility() {
|
|
50
|
+
if (document.hidden) cancel();
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
has: (pointerId) => pointers.has(pointerId),
|
|
54
|
+
start(event) {
|
|
55
|
+
host.setPointerCapture(event.pointerId);
|
|
56
|
+
if (pointers.size === 0) listen(true);
|
|
57
|
+
pointers.set(event.pointerId, event);
|
|
58
|
+
},
|
|
59
|
+
cancel
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
//#endregion
|
|
63
|
+
export { createBoardPointerGestures };
|
|
@@ -18,6 +18,7 @@ import { defaultBoardRenderStyle } from "../render/style.js";
|
|
|
18
18
|
import { createBoardPlayer } from "../player/index.js";
|
|
19
19
|
import { createBoardScriptObservers } from "../model/script-observers.js";
|
|
20
20
|
import { toBoardPointerEvent } from "./pointer.js";
|
|
21
|
+
import { createBoardPointerGestures } from "./pointer-gestures.js";
|
|
21
22
|
import { createBoardScene } from "./scene.js";
|
|
22
23
|
import { scheduleBoardMaintenance } from "./maintenance.js";
|
|
23
24
|
import { createBoardScriptPointerRouter } from "./script-pointer.js";
|
|
@@ -679,10 +680,7 @@ function mountBoardStage(host, options) {
|
|
|
679
680
|
x: event.clientX,
|
|
680
681
|
y: event.clientY
|
|
681
682
|
}, event.type !== "pointerup");
|
|
682
|
-
if (type === "down" && recipient) {
|
|
683
|
-
host.setPointerCapture(event.pointerId);
|
|
684
|
-
host.focus({ preventScroll: true });
|
|
685
|
-
}
|
|
683
|
+
if (type === "down" && recipient) host.focus({ preventScroll: true });
|
|
686
684
|
if (recipient && type !== "leave") sendScriptEvent(recipient, input.cancelled ? "pointercancel" : `pointer${type}`, event, input);
|
|
687
685
|
if (click) sendScriptEvent(click, "click", event, input);
|
|
688
686
|
return consumed || recipient !== null;
|
|
@@ -701,24 +699,33 @@ function mountBoardStage(host, options) {
|
|
|
701
699
|
scripts?.event(scriptHover.owner, input);
|
|
702
700
|
event.stopPropagation();
|
|
703
701
|
}
|
|
702
|
+
const pointers = createBoardPointerGestures(host, {
|
|
703
|
+
move: routePointerMove,
|
|
704
|
+
end: handlePointerUp
|
|
705
|
+
});
|
|
704
706
|
function handlePointerDown(event) {
|
|
705
|
-
if (inViews(event)) return;
|
|
707
|
+
if (!active || inViews(event)) return;
|
|
706
708
|
editor.takeCameraControl();
|
|
707
709
|
const input = toInput(event);
|
|
708
|
-
if (scriptPointer("down", event, input))
|
|
710
|
+
if (scriptPointer("down", event, input)) {
|
|
711
|
+
pointers.start(event);
|
|
712
|
+
return;
|
|
713
|
+
}
|
|
709
714
|
if (options.onPointer?.("down", event, input) === false) return;
|
|
710
|
-
|
|
715
|
+
pointers.start(event);
|
|
711
716
|
editor.pointerDown(input);
|
|
712
717
|
}
|
|
713
718
|
function handlePointerMove(event) {
|
|
714
|
-
if (inViews(event)) return;
|
|
719
|
+
if (!active || pointers.has(event.pointerId) || inViews(event)) return;
|
|
720
|
+
routePointerMove(event);
|
|
721
|
+
}
|
|
722
|
+
function routePointerMove(event) {
|
|
715
723
|
const input = toInput(event);
|
|
716
724
|
if (scriptPointer("move", event, input)) return;
|
|
717
725
|
if (options.onPointer?.("move", event, input) === false) return;
|
|
718
726
|
editor.pointerMove(input);
|
|
719
727
|
}
|
|
720
728
|
function handlePointerUp(event) {
|
|
721
|
-
if (inViews(event)) return;
|
|
722
729
|
const input = toInput(event);
|
|
723
730
|
if (scriptPointer("up", event, input)) return;
|
|
724
731
|
if (options.onPointer?.("up", event, input) === false) return;
|
|
@@ -758,9 +765,6 @@ function mountBoardStage(host, options) {
|
|
|
758
765
|
["keyup", handleScriptKey],
|
|
759
766
|
["pointerdown", handlePointerDown],
|
|
760
767
|
["pointermove", handlePointerMove],
|
|
761
|
-
["pointerup", handlePointerUp],
|
|
762
|
-
["pointercancel", handlePointerUp],
|
|
763
|
-
["lostpointercapture", handlePointerUp],
|
|
764
768
|
["pointerleave", handlePointerLeave],
|
|
765
769
|
[
|
|
766
770
|
"wheel",
|
|
@@ -874,6 +878,7 @@ function mountBoardStage(host, options) {
|
|
|
874
878
|
if (active === next) return;
|
|
875
879
|
active = next;
|
|
876
880
|
if (!active) {
|
|
881
|
+
pointers.cancel();
|
|
877
882
|
stopMarch();
|
|
878
883
|
cancelScriptPointers();
|
|
879
884
|
cancelAnimationFrame(renderFrame);
|
|
@@ -902,6 +907,7 @@ function mountBoardStage(host, options) {
|
|
|
902
907
|
toWorld: (clientX, clientY) => screenToWorld(clientX, clientY, rectOf(), renderCamera()),
|
|
903
908
|
destroy() {
|
|
904
909
|
disposed = true;
|
|
910
|
+
pointers.cancel();
|
|
905
911
|
stopMarch();
|
|
906
912
|
scriptPointers.clear();
|
|
907
913
|
stopTransforms?.();
|