@neta-art/cohub 11.3.2 → 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)) return;
710
+ if (scriptPointer("down", event, input)) {
711
+ pointers.start(event);
712
+ return;
713
+ }
709
714
  if (options.onPointer?.("down", event, input) === false) return;
710
- host.setPointerCapture(event.pointerId);
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?.();
@@ -4986,7 +4986,7 @@ interface SystemOneRequest<Q extends Questions = Questions> {
4986
4986
  model?: string;
4987
4987
  }
4988
4988
  //#endregion
4989
- //#region ../../node_modules/.pnpm/@neta-art+generation@0.1.38/node_modules/@neta-art/generation/dist/builtins-BYR-8YTe.d.ts
4989
+ //#region ../../node_modules/.pnpm/@neta-art+generation@0.1.39/node_modules/@neta-art/generation/dist/builtins-BYR-8YTe.d.ts
4990
4990
  //#region src/types.d.ts
4991
4991
  declare const MODEL_SCHEMA: "neta.generation.model.v1";
4992
4992
  declare const GENERATION_MODEL_CATEGORIES: readonly ["image", "video", "audio", "3d", "decision"];
@@ -1109,7 +1109,10 @@ type UploadChatAttachmentInput = {
1109
1109
  onProgress?: (progress: PublicAssetUploadProgress) => void;
1110
1110
  signal?: AbortSignal;
1111
1111
  };
1112
- /** A local generation input (image, video, or audio); same shape as a chat attachment. */
1112
+ /**
1113
+ * A local generation input: an image, video or audio file, or a GLB, glTF, OBJ, FBX or STL model whose `filename`
1114
+ * ends with the format's extension. Same shape as a chat attachment.
1115
+ */
1113
1116
  type UploadGenerationInputInput = UploadChatAttachmentInput;
1114
1117
  /** @deprecated Prefer UploadChatAttachmentInput — images are a special case of chat attachments. */
1115
1118
  type UploadChatImageAttachmentInput = UploadChatAttachmentInput & {
@@ -1125,7 +1128,7 @@ declare class PublicAssetsApi {
1125
1128
  /** Durable public upload for any chat attachment (image or file). No space required. */
1126
1129
  uploadAppSource(input: UploadAppSourceInput): Promise<PublicAssetUploadBase>;
1127
1130
  uploadChatAttachment(input: UploadChatAttachmentInput): Promise<PublicAssetUploadBase>;
1128
- /** Durable, unlisted URL for a local generation input (image, video, or audio). */
1131
+ /** Durable, unlisted URL for a local generation input (image, video, audio, or 3D model named with its extension). */
1129
1132
  uploadGenerationInput(input: UploadGenerationInputInput): Promise<PublicAssetUploadBase>;
1130
1133
  /** Preprocessed chat image (webp/jpeg). Same durable path as uploadChatAttachment. */
1131
1134
  uploadChatImageAttachment(input: UploadChatImageAttachmentInput): Promise<PublicAssetUploadBase>;
@@ -945,7 +945,7 @@ var PublicAssetsApi = class {
945
945
  signal: input.signal
946
946
  });
947
947
  }
948
- /** Durable, unlisted URL for a local generation input (image, video, or audio). */
948
+ /** Durable, unlisted URL for a local generation input (image, video, audio, or 3D model named with its extension). */
949
949
  uploadGenerationInput(input) {
950
950
  return this.upload({
951
951
  ...input,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neta-art/cohub",
3
- "version": "11.3.2",
3
+ "version": "11.3.4",
4
4
  "description": "Cohub SDK for spaces, sessions, boards, and realtime agent collaboration.",
5
5
  "license": "Apache-2.0",
6
6
  "private": false,