@weasel-js/routing 1.5.1 → 1.6.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/dist/react.js CHANGED
@@ -1,4 +1,4 @@
1
- import { createDispatcher, buildDepsFromRequires, validateActionId, validateActionDefaultBinding, scopeBindings, liveScope, offhandKeyFor, makeToolOffhandAction, buildToolOffhandBindings, isDev, reportRouteConflicts, dlog, isEditableTarget, clientToCanvasRect, openPointerSession, pointerGestureId, itemsFromDataTransfer, itemsFromClipboardData } from './chunk-ZZICE4J7.js';
1
+ import { createDispatcher, buildDepsFromRequires, validateActionId, validateActionDefaultBinding, scopeBindings, liveScope, offhandKeyFor, makeToolOffhandAction, buildToolOffhandBindings, isDev, reportRouteConflicts, dlog, isEditableTarget, clientToCanvasRect, openPointerSession, pointerGestureId, itemsFromDataTransfer, itemsFromClipboardData } from './chunk-D2TZLDP5.js';
2
2
  import { createContext, useState, useCallback, useMemo, useContext, useRef, useEffect } from 'react';
3
3
  import { jsx, Fragment } from 'react/jsx-runtime';
4
4
  import { resolveCursorTier } from '@weasel-js/cursor';
@@ -137,6 +137,7 @@ function useGestureDispatcher(opts) {
137
137
  const { canvasRef, actions, toolsById, enabled = true, keyboard = true, affordanceAt, classifyTarget, dispatcher: dispatcherOpt, clientToWorld, requestRedraw, paintedCursor, getRuleCtx, onDoubleClick, views, channels } = opts;
138
138
  const pointerChannel = channels?.pointer !== false;
139
139
  const wheelChannel = channels?.wheel !== false;
140
+ const pinchChannel = channels?.pinch !== false;
140
141
  const contextMenuChannel = channels?.contextMenu !== false;
141
142
  const ingestChannel = channels?.ingest !== false;
142
143
  const onDoubleClickRef = useRef(onDoubleClick);
@@ -261,6 +262,14 @@ function useGestureDispatcher(opts) {
261
262
  );
262
263
  return { centroid: toCanvasLocal(centroid), spread };
263
264
  };
265
+ let pinchLive = false;
266
+ let pinchScale = 1;
267
+ let pinchRotation = 0;
268
+ const endPinch = () => {
269
+ pinchLive = false;
270
+ pinchScale = 1;
271
+ pinchRotation = 0;
272
+ };
264
273
  let multiTouchStart = null;
265
274
  const TAP_THRESHOLD_PX = 8;
266
275
  const DRAG_THRESHOLD_PX = 4;
@@ -301,8 +310,10 @@ function useGestureDispatcher(opts) {
301
310
  if (result === "unhandled") {
302
311
  dispatch({
303
312
  kind: "contextmenu",
304
- worldX: down.worldX,
305
- worldY: down.worldY,
313
+ x: down.worldX,
314
+ y: down.worldY,
315
+ clientX: down.clientX,
316
+ clientY: down.clientY,
306
317
  ...shared
307
318
  });
308
319
  }
@@ -357,6 +368,7 @@ function useGestureDispatcher(opts) {
357
368
  heldKeys.delete(e.key);
358
369
  };
359
370
  const onWindowBlur = () => {
371
+ endPinch();
360
372
  for (const p of [...held.values()]) p.session.cancel();
361
373
  for (const key of heldKeys) {
362
374
  const ev = {
@@ -373,6 +385,11 @@ function useGestureDispatcher(opts) {
373
385
  heldKeys.clear();
374
386
  };
375
387
  const onWheel = (e) => {
388
+ if (pinchLive && e.ctrlKey) {
389
+ e.preventDefault();
390
+ e.stopPropagation();
391
+ return;
392
+ }
376
393
  routeAt(null, e.clientX, e.clientY);
377
394
  const rect = canvas?.getBoundingClientRect();
378
395
  const [localX, localY] = rect ? clientToCanvasRect(rect, e.clientX, e.clientY) : [e.clientX, e.clientY];
@@ -399,6 +416,57 @@ function useGestureDispatcher(opts) {
399
416
  e.stopPropagation();
400
417
  }
401
418
  };
419
+ const pinchEventOf = (e, scale, rotation) => {
420
+ const g = e;
421
+ const rect = canvas?.getBoundingClientRect();
422
+ const cx = typeof g.clientX === "number" ? g.clientX : rect ? rect.left + rect.width / 2 : 0;
423
+ const cy = typeof g.clientY === "number" ? g.clientY : rect ? rect.top + rect.height / 2 : 0;
424
+ routeAt(null, cx, cy);
425
+ const [localX, localY] = rect ? clientToCanvasRect(rect, cx, cy) : [cx, cy];
426
+ const hitPoint = toWorld(cx, cy);
427
+ const affordance = target().affordanceAt?.(hitPoint) ?? void 0;
428
+ const body = target().classifyTarget?.(hitPoint);
429
+ return {
430
+ kind: "pinch",
431
+ altKey: g.altKey === true,
432
+ ctrlKey: g.ctrlKey === true,
433
+ metaKey: g.metaKey === true,
434
+ shiftKey: g.shiftKey === true,
435
+ scale,
436
+ rotation,
437
+ clientX: localX,
438
+ clientY: localY,
439
+ ...affordance !== void 0 ? { affordance } : {},
440
+ ...body?.body !== void 0 ? { bodyTarget: body.body } : {},
441
+ ...body?.kind !== void 0 ? { bodyKind: body.kind } : {}
442
+ };
443
+ };
444
+ const onGestureStart = (e) => {
445
+ endPinch();
446
+ const probe = pinchEventOf(e, 1, 0);
447
+ if (dispatcherNow().resolveOnly(probe, ctxNow()) === null) return;
448
+ pinchLive = true;
449
+ e.preventDefault();
450
+ };
451
+ const onGestureChange = (e) => {
452
+ const g = e;
453
+ const scale = typeof g.scale === "number" && g.scale > 0 ? g.scale : pinchScale;
454
+ const rotation = typeof g.rotation === "number" ? g.rotation : pinchRotation;
455
+ const step = scale / pinchScale;
456
+ const turn = rotation - pinchRotation;
457
+ pinchScale = scale;
458
+ pinchRotation = rotation;
459
+ if (dispatch(pinchEventOf(e, step, turn)) === "handled") {
460
+ pinchLive = true;
461
+ e.preventDefault();
462
+ } else if (pinchLive) {
463
+ e.preventDefault();
464
+ }
465
+ };
466
+ const onGestureEnd = (e) => {
467
+ if (pinchLive) e.preventDefault();
468
+ endPinch();
469
+ };
402
470
  const onPointerDown = (e) => {
403
471
  if ((e.button ?? 0) !== 0) return;
404
472
  if (!canvas) return;
@@ -607,7 +675,7 @@ function useGestureDispatcher(opts) {
607
675
  ctx
608
676
  )?.action.cursor;
609
677
  const cursor = dragCursor ?? dispatcherNow().resolveOnly(
610
- { kind: "click", worldX: w.x, worldY: w.y, pressX: w.x, pressY: w.y, ...where },
678
+ { kind: "click", x: w.x, y: w.y, pressX: w.x, pressY: w.y, ...where },
611
679
  ctx
612
680
  )?.action.cursor;
613
681
  applyHoverCursor(cursor ?? null);
@@ -696,8 +764,10 @@ function useGestureDispatcher(opts) {
696
764
  ctrlKey: e.ctrlKey,
697
765
  metaKey: e.metaKey,
698
766
  shiftKey: e.shiftKey,
699
- worldX: wClick.x,
700
- worldY: wClick.y,
767
+ x: wClick.x,
768
+ y: wClick.y,
769
+ clientX: e.clientX,
770
+ clientY: e.clientY,
701
771
  pressX: down.worldX,
702
772
  pressY: down.worldY,
703
773
  ...down.affordance !== void 0 ? { affordance: down.affordance } : {},
@@ -717,8 +787,10 @@ function useGestureDispatcher(opts) {
717
787
  ctrlKey: e.ctrlKey,
718
788
  metaKey: e.metaKey,
719
789
  shiftKey: e.shiftKey,
720
- worldX: wClick.x,
721
- worldY: wClick.y,
790
+ x: wClick.x,
791
+ y: wClick.y,
792
+ clientX: e.clientX,
793
+ clientY: e.clientY,
722
794
  ...down.affordance !== void 0 ? { affordance: down.affordance } : {},
723
795
  ...down.bodyTarget !== void 0 ? { bodyTarget: down.bodyTarget } : {},
724
796
  ...down.bodyKind !== void 0 ? { bodyKind: down.bodyKind } : {}
@@ -775,8 +847,10 @@ function useGestureDispatcher(opts) {
775
847
  ctrlKey: e.ctrlKey,
776
848
  metaKey: e.metaKey,
777
849
  shiftKey: e.shiftKey,
778
- worldX: w.x,
779
- worldY: w.y,
850
+ x: w.x,
851
+ y: w.y,
852
+ clientX: e.clientX,
853
+ clientY: e.clientY,
780
854
  ...affordance !== void 0 ? { affordance } : {},
781
855
  ...menuBody?.body !== void 0 ? { bodyTarget: menuBody.body } : {},
782
856
  ...menuBody?.kind !== void 0 ? { bodyKind: menuBody.kind } : {}
@@ -850,6 +924,11 @@ function useGestureDispatcher(opts) {
850
924
  canvas?.addEventListener("pointermove", onHoverMove);
851
925
  }
852
926
  if (wheelChannel) canvas?.addEventListener("wheel", onWheel, { passive: false });
927
+ if (pinchChannel) {
928
+ canvas?.addEventListener("gesturestart", onGestureStart);
929
+ canvas?.addEventListener("gesturechange", onGestureChange);
930
+ canvas?.addEventListener("gestureend", onGestureEnd);
931
+ }
853
932
  if (contextMenuChannel) canvas?.addEventListener("contextmenu", onContextMenu);
854
933
  if (ingestChannel) {
855
934
  canvas?.addEventListener("dragenter", onDragOver);
@@ -868,6 +947,9 @@ function useGestureDispatcher(opts) {
868
947
  window.removeEventListener("keyup", scheduleHoverCursorRefresh);
869
948
  canvas?.removeEventListener("pointerleave", onHoverPointerLeave);
870
949
  canvas?.removeEventListener("wheel", onWheel);
950
+ canvas?.removeEventListener("gesturestart", onGestureStart);
951
+ canvas?.removeEventListener("gesturechange", onGestureChange);
952
+ canvas?.removeEventListener("gestureend", onGestureEnd);
871
953
  canvas?.removeEventListener("pointerdown", onPointerDown);
872
954
  canvas?.removeEventListener("pointermove", onHoverMove);
873
955
  canvas?.removeEventListener("contextmenu", onContextMenu);
@@ -884,7 +966,7 @@ function useGestureDispatcher(opts) {
884
966
  held.clear();
885
967
  for (const d of allDispatchers()) d.cancelAll("cancel");
886
968
  };
887
- }, [enabled, keyboard, canvasRef, pointerChannel, wheelChannel, contextMenuChannel, ingestChannel]);
969
+ }, [enabled, keyboard, canvasRef, pointerChannel, wheelChannel, pinchChannel, contextMenuChannel, ingestChannel]);
888
970
  }
889
971
  var ActionsContext = createContext(null);
890
972
  function useMuted(base) {
@@ -1109,6 +1191,39 @@ function useAction(action) {
1109
1191
  return reg.register(action);
1110
1192
  }, [reg, action]);
1111
1193
  }
1194
+ function useOngoingAction(actionId) {
1195
+ const reg = useActionsRegistry();
1196
+ const regRef = useRef(reg);
1197
+ regRef.current = reg;
1198
+ const idRef = useRef(actionId);
1199
+ idRef.current = actionId;
1200
+ const ctrlRef = useRef(null);
1201
+ const edit = useMemo(() => {
1202
+ const end = (reason) => {
1203
+ const ctrl = ctrlRef.current;
1204
+ ctrlRef.current = null;
1205
+ ctrl?.end(reason);
1206
+ };
1207
+ return {
1208
+ input(params) {
1209
+ if (ctrlRef.current) ctrlRef.current.update(params);
1210
+ else ctrlRef.current = regRef.current?.begin(idRef.current, params) ?? null;
1211
+ },
1212
+ commit(params) {
1213
+ if (params !== void 0) {
1214
+ if (ctrlRef.current) ctrlRef.current.update(params);
1215
+ else ctrlRef.current = regRef.current?.begin(idRef.current, params) ?? null;
1216
+ }
1217
+ end("commit");
1218
+ },
1219
+ cancel() {
1220
+ end("cancel");
1221
+ }
1222
+ };
1223
+ }, []);
1224
+ useEffect(() => () => edit.commit(), [edit, actionId]);
1225
+ return edit;
1226
+ }
1112
1227
  function useContributions(opts) {
1113
1228
  const ctx = useActiveToolContext();
1114
1229
  const actionsRegistry = useActionsRegistry();
@@ -1305,6 +1420,6 @@ function useTools(opts) {
1305
1420
  );
1306
1421
  }
1307
1422
 
1308
- export { ActionsProvider, ActionsScope, ActiveToolContextProvider, ActiveToolContextProviderIfRoot, DepRegistryProvider, useAction, useActionsRegistry, useActiveToolContext, useContributions, useDepRegistry, useDepSource, useGestureDispatcher, useOptionalActiveToolContext, useOptionalDepRegistry, useTools };
1423
+ export { ActionsProvider, ActionsScope, ActiveToolContextProvider, ActiveToolContextProviderIfRoot, DepRegistryProvider, useAction, useActionsRegistry, useActiveToolContext, useContributions, useDepRegistry, useDepSource, useGestureDispatcher, useOngoingAction, useOptionalActiveToolContext, useOptionalDepRegistry, useTools };
1309
1424
  //# sourceMappingURL=react.js.map
1310
1425
  //# sourceMappingURL=react.js.map