@weasel-js/routing 1.10.0 → 1.11.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,10 +1,10 @@
1
- import { createDepRegistry, createDispatcher, assembleEntries, liveScope, isDev, reportRouteConflicts, offhandKeyFor, makeToolOffhandAction, buildToolOffhandBindings, dlog, ScopeNode, isTool, DEV, publishLiveDispatch, LONG_PRESS_HAPTIC_MS, multiTouchGestureId, openPointerSession, pushOwner, evaluateEnabled, validateActionId, validateActionDefaultBinding, depNodeOf, DepNode, clientToCanvas, buildDepsFromRequires, isEditableTarget, focusedControlOwnsKey, itemsFromClipboardData, itemsFromDataTransfer, itemTypesFromDataTransfer } from './chunk-4DR6AJMN.js';
2
- import { createContext, useState, useContext, useEffect, useRef, useCallback, useMemo, useSyncExternalStore } from 'react';
3
- import { isApplePlatform, createPointerRecognizer, isInControlWithin, longPressEvents, stylusOf } from '@weasel-js/gestures';
4
- import { useLatest, useStableByContent, sameList } from '@weasel-js/react';
1
+ import { createDepRegistry, createDispatcher, assembleEntries, liveScope, reportRouteConflicts, offhandKeyFor, makeToolOffhandAction, buildToolOffhandBindings, dlog, ScopeNode, tuneAction, createMenuHost, pushOwner, evaluateEnabled, tunedParams, validateActionId, validateActionDefaultBinding, isTool, depNodeOf, DepNode, buildDepsFromRequires, clientToCanvas, DEV, publishLiveDispatch, LONG_PRESS_HAPTIC_MS, multiTouchGestureId, openPointerSession, addCarrySurface, gestureIdFor, isEditableTarget, focusedControlOwnsKey, itemsFromClipboardData, itemsFromDataTransfer, itemTypesFromDataTransfer, actionCursor } from './chunk-QBQQIFPI.js';
2
+ import { createContext, useState, useContext, useEffect, useMemo, useRef, useCallback, useSyncExternalStore } from 'react';
3
+ import { isApplePlatform, heldPointers, createPointerRecognizer, isInControlWithin, longPressEvents, stylusOf } from '@weasel-js/gestures';
4
+ import { isDev, useLatest, useKitSettings, useStableByContent, sameList } from '@weasel-js/react';
5
5
  import { jsx, Fragment } from 'react/jsx-runtime';
6
6
  import { createCursorSink, resolveCursorTier } from '@weasel-js/cursor';
7
- import { createEmitter } from '@weasel-js/registry';
7
+ import { deepEqual, createEmitter } from '@weasel-js/registry';
8
8
  import { activeModeOf } from '@weasel-js/modes';
9
9
 
10
10
  var ToolNode = class extends ScopeNode {
@@ -111,6 +111,277 @@ function useDepSource(name, source) {
111
111
  return registry.register(name, () => sourceRef.current());
112
112
  }, [name, registry, sourceRef]);
113
113
  }
114
+ var MenuHostContext = createContext(null);
115
+ function useMenuHost() {
116
+ return useContext(MenuHostContext);
117
+ }
118
+ function useMenus(defs, owner = null) {
119
+ const host = useMenuHost();
120
+ useEffect(() => {
121
+ if (!host) return;
122
+ const releases = defs.map((d) => host.define(d, owner));
123
+ return () => {
124
+ for (const r of releases) r();
125
+ };
126
+ }, [host, defs, owner]);
127
+ }
128
+ var ActionsContext = createContext(null);
129
+ function depsFor(a, r) {
130
+ if (!r) return {};
131
+ if (a.requires) return buildDepsFromRequires(a, r);
132
+ return {
133
+ selection: r.get("selection"),
134
+ scene: r.get("scene"),
135
+ history: r.get("history"),
136
+ view: r.get("view"),
137
+ activeTool: r.get("activeTool"),
138
+ booleansAdapter: r.get("booleansAdapter")
139
+ };
140
+ }
141
+ var ActionsNode = class extends ScopeNode {
142
+ constructor(parent, descends, contextDeps) {
143
+ super(parent, descends);
144
+ this.contextDeps = contextDeps;
145
+ NODES.set(this.registry, this);
146
+ }
147
+ contextDeps;
148
+ actions = /* @__PURE__ */ new Map();
149
+ muted = /* @__PURE__ */ new Map();
150
+ tunings = /* @__PURE__ */ new Map();
151
+ dispatchers = [];
152
+ cache = null;
153
+ host = null;
154
+ /** Called on `activate`, so a scope's dep and tool nodes move with it. */
155
+ onActivate = [];
156
+ resolve(id) {
157
+ for (const n of this.chain()) {
158
+ if (n.muted.has(id)) return void 0;
159
+ const a = n.actions.get(id)?.at(-1);
160
+ if (a) return this.tuned(a);
161
+ }
162
+ return void 0;
163
+ }
164
+ /** Every tuning for `id` from the root down to here, root first. */
165
+ tuningsOf(id) {
166
+ const tunings = [];
167
+ for (const n of this.chain()) {
168
+ const stack = n.tunings.get(id);
169
+ if (stack) tunings.unshift(...stack);
170
+ }
171
+ return tunings;
172
+ }
173
+ /** `a` under every tuning for its id from the root down to here. */
174
+ tuned(a) {
175
+ const tunings = this.tuningsOf(a.id);
176
+ return tunings.length ? tuneAction(a, tunings) : a;
177
+ }
178
+ snapshot() {
179
+ const leaf = this.start();
180
+ const cached = this.cache;
181
+ if (cached && cached.version === this.tree.version && cached.leaf === leaf) return cached.list;
182
+ const ids = /* @__PURE__ */ new Set();
183
+ for (const n of leaf.chain()) for (const id of n.actions.keys()) ids.add(id);
184
+ const out = [];
185
+ for (const id of ids) {
186
+ const a = leaf.resolve(id);
187
+ if (a) out.push(a);
188
+ }
189
+ const list = Object.freeze(out);
190
+ this.cache = { version: this.tree.version, leaf, list };
191
+ return list;
192
+ }
193
+ deps() {
194
+ for (const n of this.chain()) {
195
+ const r = n.contextDeps();
196
+ if (r) return r;
197
+ }
198
+ return null;
199
+ }
200
+ /** The actions registered at this node itself, live, unmuted and tuned —
201
+ * none from the scopes below it. */
202
+ ownActions() {
203
+ const out = [];
204
+ for (const [id, stack] of this.actions) {
205
+ if (stack.length > 0 && !this.muted.has(id)) out.push(this.tuned(stack.at(-1)));
206
+ }
207
+ return out;
208
+ }
209
+ /** The deps `a` is invoked with from here: the active scope's, which is
210
+ * what `trigger` and `begin` run it with. */
211
+ depsOf(a) {
212
+ return depsFor(a, this.start().deps());
213
+ }
214
+ /** The menu host of this node's tree, made by its root on first ask. Rows
215
+ * resolve and run against the active scope, as chrome's `trigger` does. */
216
+ menuHost() {
217
+ const root = [...this.chain()].at(-1);
218
+ return root.host ??= createMenuHost({
219
+ actions: () => root.registry.list(),
220
+ depsFor: (a) => root.depsOf(a),
221
+ trigger: (id, params) => root.registry.trigger(id, params),
222
+ activeTool: () => root.start().deps()?.get("activeTool")?.active ?? null
223
+ });
224
+ }
225
+ dispatcher() {
226
+ for (const n of this.chain()) {
227
+ const d = n.dispatchers.at(-1);
228
+ if (d) return d;
229
+ }
230
+ return null;
231
+ }
232
+ activate() {
233
+ keyHolder = this;
234
+ super.activate();
235
+ for (const f of this.onActivate) f();
236
+ }
237
+ registry = {
238
+ register: (action) => {
239
+ validateActionId(action.id);
240
+ validateActionDefaultBinding(action);
241
+ const stack = this.actions.get(action.id);
242
+ if (stack) stack.push(action);
243
+ else this.actions.set(action.id, [action]);
244
+ this.changed();
245
+ let released = false;
246
+ return () => {
247
+ if (released) return;
248
+ released = true;
249
+ const cur = this.actions.get(action.id);
250
+ if (!cur) return;
251
+ const i = cur.lastIndexOf(action);
252
+ if (i === -1) return;
253
+ cur.splice(i, 1);
254
+ if (cur.length === 0) {
255
+ queueMicrotask(() => {
256
+ if (cur.length === 0 && this.actions.get(action.id) === cur) this.actions.delete(action.id);
257
+ });
258
+ }
259
+ this.changed();
260
+ };
261
+ },
262
+ unregister: (id) => {
263
+ if (this.actions.delete(id)) this.changed();
264
+ },
265
+ mute: (id) => {
266
+ this.muted.set(id, (this.muted.get(id) ?? 0) + 1);
267
+ this.changed();
268
+ let released = false;
269
+ return () => {
270
+ if (released) return;
271
+ released = true;
272
+ const held = this.muted.get(id);
273
+ if (held === void 0) return;
274
+ if (held > 1) this.muted.set(id, held - 1);
275
+ else this.muted.delete(id);
276
+ this.changed();
277
+ };
278
+ },
279
+ tune: (id, tuning) => {
280
+ let stack = this.tunings.get(id);
281
+ if (!stack) this.tunings.set(id, stack = []);
282
+ const release = pushOwner(stack, tuning);
283
+ this.changed();
284
+ let released = false;
285
+ return () => {
286
+ if (released) return;
287
+ released = true;
288
+ release();
289
+ if (stack.length === 0) this.tunings.delete(id);
290
+ this.changed();
291
+ };
292
+ },
293
+ paramsOf: (id, given) => tunedParams(this.tuningsOf(id), given),
294
+ list: () => this.snapshot(),
295
+ trigger: (id, params) => {
296
+ const leaf = this.start();
297
+ const a = leaf.resolve(id);
298
+ if (!a?.invoker || a.invoker.timing !== "immediate") return false;
299
+ const deps = leaf.depsOf(a);
300
+ if (!evaluateEnabled(a, deps, pointOf(params)).enabled) return false;
301
+ try {
302
+ a.invoker.run(deps, params);
303
+ } catch (err) {
304
+ console.error(`weasel ActionsRegistry: action "${id}" threw`, err);
305
+ }
306
+ return true;
307
+ },
308
+ preview: (id, params) => {
309
+ const leaf = this.start();
310
+ const a = leaf.resolve(id);
311
+ if (!a?.preview) return NO_PREVIEW;
312
+ const deps = leaf.depsOf(a);
313
+ if (!evaluateEnabled(a, deps, pointOf(params)).enabled) return NO_PREVIEW;
314
+ let stop;
315
+ try {
316
+ stop = a.preview(deps, params);
317
+ } catch (err) {
318
+ console.error(`weasel ActionsRegistry: preview of "${id}" threw`, err);
319
+ return NO_PREVIEW;
320
+ }
321
+ if (typeof stop !== "function") return NO_PREVIEW;
322
+ let down = false;
323
+ return () => {
324
+ if (down) return;
325
+ down = true;
326
+ try {
327
+ stop();
328
+ } catch (err) {
329
+ console.error(`weasel ActionsRegistry: preview of "${id}" threw as it ended`, err);
330
+ }
331
+ };
332
+ },
333
+ subscribe: (listener) => this.tree.listeners.subscribe(listener),
334
+ setDispatcher: (d) => pushOwner(this.dispatchers, d),
335
+ begin: (id, params) => {
336
+ const leaf = this.start();
337
+ const a = leaf.resolve(id);
338
+ const disp = leaf.dispatcher();
339
+ if (!a || !disp) return null;
340
+ return disp.beginUiOngoing(id, leaf.depsOf(a), params);
341
+ },
342
+ activate: () => this.activate(),
343
+ isActive: () => this.isActive(),
344
+ holdsKeys: () => keyHolder === this,
345
+ dropKeys: () => {
346
+ if (keyHolder === this) keyHolder = null;
347
+ }
348
+ };
349
+ };
350
+ var NO_PREVIEW = () => {
351
+ };
352
+ function pointOf(params) {
353
+ const { worldX: x, worldY: y } = params ?? {};
354
+ return typeof x === "number" && typeof y === "number" ? { x, y } : void 0;
355
+ }
356
+ var keyHolder = null;
357
+ var NODES = /* @__PURE__ */ new WeakMap();
358
+ function actionsNodeOf(registry) {
359
+ return registry ? NODES.get(registry) ?? null : null;
360
+ }
361
+ function ActionsProvider({ children }) {
362
+ const depReg = useOptionalDepRegistry();
363
+ const depRegRef = useLatest(depReg);
364
+ const node = useMemo(() => new ActionsNode(null, true, () => depRegRef.current), [depRegRef]);
365
+ return /* @__PURE__ */ jsx(ActionsContext.Provider, { value: node.registry, children: /* @__PURE__ */ jsx(MenuHostContext.Provider, { value: node.menuHost(), children }) });
366
+ }
367
+ var IS_DEV = isDev();
368
+ function useActionsRegistry() {
369
+ return useContext(ActionsContext);
370
+ }
371
+ function useAction(action) {
372
+ const reg = useActionsRegistry();
373
+ useEffect(() => {
374
+ if (!reg) {
375
+ if (IS_DEV) {
376
+ console.warn(
377
+ `useAction("${action.id}"): no <ActionsProvider> is in scope, so the action was not registered and its bindings will never fire.`
378
+ );
379
+ }
380
+ return;
381
+ }
382
+ return reg.register(action);
383
+ }, [reg, action]);
384
+ }
114
385
  function useToolLifecycle(opts) {
115
386
  const { active, hotkeyStack } = opts;
116
387
  const liveRef = useRef(/* @__PURE__ */ new Set());
@@ -133,7 +404,7 @@ function useToolLifecycle(opts) {
133
404
  const next = new Set(active === null ? hotkeyStack : [active, ...hotkeyStack]);
134
405
  liveRef.current = next;
135
406
  for (const id of prev) if (!next.has(id)) fire(id, "onDeactivate");
136
- if (prevActiveRef.current !== active) onSwitchRef.current?.();
407
+ if (prevActiveRef.current !== null && prevActiveRef.current !== active) onSwitchRef.current?.();
137
408
  prevActiveRef.current = active;
138
409
  for (const id of next) if (!prev.has(id)) fire(id, "onActivate");
139
410
  });
@@ -184,6 +455,8 @@ function createDispatchCore(src) {
184
455
  return fn ? fn(cx, cy) : { x: cx, y: cy };
185
456
  },
186
457
  toCanvasLocal: (cx, cy) => {
458
+ const own = src.clientToLocal();
459
+ if (own) return own(cx, cy);
187
460
  if (!canvas) return { x: cx, y: cy };
188
461
  const [x, y] = clientToCanvas(canvas, cx, cy);
189
462
  return { x, y };
@@ -232,6 +505,56 @@ function dispatcherWatch(onChange) {
232
505
  };
233
506
  }
234
507
 
508
+ // src/interactions/dispatcher/channels/carry.ts
509
+ function carryInput(core) {
510
+ const { canvas } = core;
511
+ if (!canvas) return () => {
512
+ };
513
+ const pinned = /* @__PURE__ */ new Map();
514
+ return addCarrySurface({
515
+ element: canvas,
516
+ receive(stage, payload, at, pointerId) {
517
+ if (core.disposed()) return "unhandled";
518
+ const event = () => {
519
+ const w = core.toWorld(at.clientX, at.clientY);
520
+ return {
521
+ kind: "carry",
522
+ stage,
523
+ pointerId,
524
+ type: payload.type,
525
+ value: payload.value,
526
+ x: w.x,
527
+ y: w.y,
528
+ clientX: at.clientX,
529
+ clientY: at.clientY,
530
+ altKey: at.altKey,
531
+ ctrlKey: at.ctrlKey,
532
+ metaKey: at.metaKey,
533
+ shiftKey: at.shiftKey
534
+ };
535
+ };
536
+ const routedNow = core.routedView();
537
+ try {
538
+ if (stage === "enter") {
539
+ core.routeAt(null, at.clientX, at.clientY);
540
+ pinned.set(pointerId, core.routedView());
541
+ return core.dispatch(event());
542
+ }
543
+ if (pinned.has(pointerId)) core.setRoutedView(pinned.get(pointerId));
544
+ if (stage !== "move") pinned.delete(pointerId);
545
+ const ev = event();
546
+ if (stage === "drop" && !core.dispatcherNow().inFlight().has(gestureIdFor(ev))) {
547
+ core.routeAt(null, at.clientX, at.clientY);
548
+ return core.dispatch(event());
549
+ }
550
+ return core.dispatch(ev);
551
+ } finally {
552
+ core.setRoutedView(routedNow);
553
+ }
554
+ }
555
+ });
556
+ }
557
+
235
558
  // src/interactions/dispatcher/underPointer.ts
236
559
  function underPointer(view, mods, w) {
237
560
  const affordance = view.affordanceAt?.(w) ?? void 0;
@@ -243,9 +566,13 @@ function underPointer(view, mods, w) {
243
566
  shiftKey: mods.shiftKey,
244
567
  ...affordance !== void 0 ? { affordance } : {},
245
568
  ...body?.body !== void 0 ? { bodyTarget: body.body } : {},
246
- ...body?.kind !== void 0 ? { bodyKind: body.kind } : {}
569
+ ...body?.kind !== void 0 ? { bodyKind: body.kind } : {},
570
+ ...body?.doubleClick !== void 0 ? { doubleClickBody: doubleClickBodyOf(body.doubleClick) } : {}
247
571
  };
248
572
  }
573
+ function doubleClickBodyOf(named) {
574
+ return { bodyTarget: named.body, ...named.kind !== void 0 ? { bodyKind: named.kind } : {} };
575
+ }
249
576
 
250
577
  // src/interactions/dispatcher/channels/contextMenu.ts
251
578
  function contextMenuInput(core, takeNativeHold) {
@@ -253,6 +580,7 @@ function contextMenuInput(core, takeNativeHold) {
253
580
  const onContextMenu = (e) => {
254
581
  e.preventDefault();
255
582
  if (takeNativeHold()) return;
583
+ core.activate();
256
584
  routeAt(null, e.clientX, e.clientY);
257
585
  const w = toWorld(e.clientX, e.clientY);
258
586
  const ev = {
@@ -268,6 +596,11 @@ function contextMenuInput(core, takeNativeHold) {
268
596
  };
269
597
  return onContextMenu;
270
598
  }
599
+ var whereOf = ({ affordance, bodyTarget, bodyKind }) => ({
600
+ ...affordance !== void 0 ? { affordance } : {},
601
+ ...bodyTarget !== void 0 ? { bodyTarget } : {},
602
+ ...bodyKind !== void 0 ? { bodyKind } : {}
603
+ });
271
604
  var hoverOf = (e) => ({
272
605
  clientX: e.clientX,
273
606
  clientY: e.clientY,
@@ -304,7 +637,8 @@ function hoverCursorInput(core, paintedCursor, pointersHeld, cursorSink = () =>
304
637
  const press = { kind: "pointerdown", x: w.x, y: w.y, clientX: h.clientX, clientY: h.clientY, ...where };
305
638
  if (DEV) publishLiveDispatch(() => d.explain(press, ctx));
306
639
  const click = { kind: "click", x: w.x, y: w.y, pressX: w.x, pressY: w.y, ...where };
307
- const cursor = d.resolveOnly(press, ctx)?.action.cursor ?? dispatcherNow().resolveOnly(click, ctx)?.action.cursor;
640
+ const cursorOf = (r) => r ? actionCursor(r.action, r.params) : void 0;
641
+ const cursor = cursorOf(d.resolveOnly(press, ctx)) ?? cursorOf(dispatcherNow().resolveOnly(click, ctx));
308
642
  override.apply(cursor ?? null);
309
643
  };
310
644
  const refresh = () => {
@@ -319,15 +653,17 @@ function hoverCursorInput(core, paintedCursor, pointersHeld, cursorSink = () =>
319
653
  if (!core.disposed()) refresh();
320
654
  }, 0);
321
655
  };
656
+ const hoverAt = (at) => {
657
+ const w = toWorld(at.clientX, at.clientY);
658
+ const where = underPointer(target(), at, w);
659
+ const from = facts ? { from: whereOf(facts.where) } : {};
660
+ facts = { at, where };
661
+ dispatch({ kind: "hover", x: w.x, y: w.y, clientX: at.clientX, clientY: at.clientY, ...where, ...from });
662
+ };
322
663
  return {
323
664
  moved(e) {
324
665
  last = hoverOf(e);
325
- if (pointersHeld() === 0) {
326
- const w = toWorld(e.clientX, e.clientY);
327
- const where = underPointer(target(), last, w);
328
- facts = { at: last, where };
329
- dispatch({ kind: "hover", x: w.x, y: w.y, clientX: e.clientX, clientY: e.clientY, ...where });
330
- }
666
+ if (pointersHeld() === 0) hoverAt(last);
331
667
  refresh();
332
668
  },
333
669
  released(e) {
@@ -335,6 +671,12 @@ function hoverCursorInput(core, paintedCursor, pointersHeld, cursorSink = () =>
335
671
  refreshSoon();
336
672
  },
337
673
  onLeave() {
674
+ if (facts) {
675
+ const { at, where } = facts;
676
+ const w = toWorld(at.clientX, at.clientY);
677
+ dispatch({ kind: "hover", off: true, x: w.x, y: w.y, clientX: at.clientX, clientY: at.clientY, ...where, from: whereOf(where) });
678
+ }
679
+ facts = null;
338
680
  last = null;
339
681
  if (DEV) publishLiveDispatch(null);
340
682
  paintedCursor()?.clearPointer();
@@ -342,7 +684,10 @@ function hoverCursorInput(core, paintedCursor, pointersHeld, cursorSink = () =>
342
684
  },
343
685
  onKey(e) {
344
686
  if (!last) return;
687
+ const prev = last;
345
688
  last = { ...last, altKey: e.altKey, ctrlKey: e.ctrlKey, metaKey: e.metaKey, shiftKey: e.shiftKey };
689
+ const changed = prev.altKey !== last.altKey || prev.ctrlKey !== last.ctrlKey || prev.metaKey !== last.metaKey || prev.shiftKey !== last.shiftKey;
690
+ if (changed && pointersHeld() === 0) hoverAt(last);
346
691
  refreshSoon();
347
692
  },
348
693
  clear: override.clear
@@ -439,13 +784,14 @@ function typedWithAltGraph(e) {
439
784
  const base = /^(?:Key|Digit)(.)$/.exec(e.code)?.[1];
440
785
  return base === void 0 || base.toLowerCase() !== e.key.toLowerCase();
441
786
  }
787
+ var inMenu = (t) => t instanceof Element && t.closest('[role="menu"]') !== null;
442
788
  function keyboardInput(core) {
443
789
  const { dispatch, dispatcherNow } = core;
444
790
  const heldKeys = /* @__PURE__ */ new Map();
445
791
  const codeOf = (e) => e.code ? { code: e.code } : {};
446
792
  const physicalKey = (e) => e.code || e.key.toLowerCase();
447
793
  const onKeyDown = (e) => {
448
- if (e.defaultPrevented || isEditableTarget(e.target) || focusedControlOwnsKey(e)) return;
794
+ if (e.defaultPrevented || isEditableTarget(e.target) || inMenu(e.target) || focusedControlOwnsKey(e)) return;
449
795
  if (!core.holdsKeys()) return;
450
796
  if (e.repeat && heldKeys.has(physicalKey(e))) {
451
797
  e.preventDefault();
@@ -608,7 +954,11 @@ function pointerInput(core, opts) {
608
954
  clock: hold.clock,
609
955
  toWorld,
610
956
  toSurface: (p) => core.toCanvasLocal(p.x, p.y),
611
- longPressMs: () => opts.longPress()?.duration,
957
+ longPressMs: () => opts.longPress()?.duration ?? opts.kitSettings().get("gestures.longPressMs"),
958
+ doubleClickMs: () => opts.kitSettings().get("gestures.doubleClickMs"),
959
+ doubleClickPx: () => opts.kitSettings().get("gestures.doubleClickPx"),
960
+ tapPx: () => opts.kitSettings().get("gestures.tapPx"),
961
+ dragPx: () => opts.kitSettings().get("gestures.dragPx"),
612
962
  clicks: opts.clicks,
613
963
  observer: {
614
964
  click: (world) => {
@@ -678,7 +1028,6 @@ function pointerInput(core, opts) {
678
1028
  hold.routeToPress();
679
1029
  return recognizer.takeHold();
680
1030
  },
681
- heldCount: () => recognizer.heldCount(),
682
1031
  cancelHeld() {
683
1032
  for (const session of [...sessions.values()]) session.cancel();
684
1033
  },
@@ -754,6 +1103,12 @@ function webkitPinchInput(core) {
754
1103
  }
755
1104
 
756
1105
  // src/interactions/dispatcher/channels/wheel.ts
1106
+ var LINE_PX = 16;
1107
+ function pixelsPer(e, canvas) {
1108
+ if (e.deltaMode === 1) return LINE_PX;
1109
+ if (e.deltaMode === 2) return canvas?.clientHeight || LINE_PX * 20;
1110
+ return 1;
1111
+ }
757
1112
  function wheelInput(core, pinchLive) {
758
1113
  const { routeAt, toWorld, target, dispatch } = core;
759
1114
  const onWheel = (e) => {
@@ -766,10 +1121,11 @@ function wheelInput(core, pinchLive) {
766
1121
  routeAt(null, e.clientX, e.clientY);
767
1122
  const local = core.toCanvasLocal(e.clientX, e.clientY);
768
1123
  const hitPoint = toWorld(e.clientX, e.clientY);
1124
+ const toPx = pixelsPer(e, core.canvas);
769
1125
  const ev = {
770
1126
  kind: "wheel",
771
- deltaX: e.deltaX,
772
- deltaY: e.deltaY,
1127
+ deltaX: e.deltaX * toPx,
1128
+ deltaY: e.deltaY * toPx,
773
1129
  clientX: local.x,
774
1130
  clientY: local.y,
775
1131
  ...underPointer(target(), e, hitPoint)
@@ -783,14 +1139,101 @@ function wheelInput(core, pinchLive) {
783
1139
  return onWheel;
784
1140
  }
785
1141
 
1142
+ // src/interactions/dispatcher/attachInput.ts
1143
+ function attachInput(canvas, src, channels) {
1144
+ let disposed = false;
1145
+ const redraw = dispatcherWatch(src.requestRedraw);
1146
+ redraw.sync(src.dispatchers());
1147
+ const core = createDispatchCore({
1148
+ canvas,
1149
+ root: src.root,
1150
+ views: src.views,
1151
+ clientToLocal: src.clientToLocal,
1152
+ context: src.context,
1153
+ actions: src.actions,
1154
+ uses: () => {
1155
+ redraw.sync(src.dispatchers());
1156
+ },
1157
+ disposed: () => disposed
1158
+ });
1159
+ const keys = keyboardInput(core);
1160
+ const pinch = webkitPinchInput(core);
1161
+ const ingest = ingestInput(core);
1162
+ const held = canvas ? heldPointers(canvas) : null;
1163
+ const hover = hoverCursorInput(core, src.paintedCursor, () => held?.count() ?? 0, src.cursorSink);
1164
+ const pointer = pointerInput(core, {
1165
+ longPress: src.longPress,
1166
+ kitSettings: src.kitSettings,
1167
+ onClick: src.onClick,
1168
+ onDoubleClick: src.onDoubleClick,
1169
+ clicks: src.clicks,
1170
+ hover
1171
+ });
1172
+ const onWindowBlur = () => {
1173
+ pinch.end();
1174
+ pointer.cancelHeld();
1175
+ keys.releaseAll();
1176
+ };
1177
+ const listeners = listenerSet();
1178
+ const keyCapture = channels.keyboard === "first";
1179
+ if (channels.keyboard) {
1180
+ listeners.on(window, "keydown", keys.onKeyDown, keyCapture);
1181
+ listeners.on(window, "keyup", keys.onKeyUp, keyCapture);
1182
+ }
1183
+ listeners.on(window, "blur", onWindowBlur);
1184
+ listeners.on(canvas, "pointerdown", () => {
1185
+ src.actions().activate();
1186
+ });
1187
+ if (channels.pointer) {
1188
+ listeners.on(window, "keydown", hover.onKey);
1189
+ listeners.on(window, "keyup", hover.onKey);
1190
+ listeners.on(canvas, "pointerleave", hover.onLeave);
1191
+ listeners.on(canvas, "pointerdown", pointer.onPointerDown);
1192
+ listeners.on(canvas, "pointermove", pointer.onHoverMove);
1193
+ listeners.on(canvas, "dblclick", pointer.onNativeDoubleClick);
1194
+ }
1195
+ if (channels.wheel) {
1196
+ listeners.on(canvas, "wheel", wheelInput(core, pinch.live), { passive: false, capture: true });
1197
+ }
1198
+ if (channels.pinch) {
1199
+ listeners.on(canvas, "gesturestart", pinch.onGestureStart);
1200
+ listeners.on(canvas, "gesturechange", pinch.onGestureChange);
1201
+ listeners.on(canvas, "gestureend", pinch.onGestureEnd);
1202
+ }
1203
+ if (channels.contextMenu) {
1204
+ listeners.on(canvas, "contextmenu", contextMenuInput(core, pointer.takeNativeHold));
1205
+ }
1206
+ if (channels.ingest) {
1207
+ listeners.on(canvas, "dragenter", ingest.onDragOver);
1208
+ listeners.on(canvas, "dragover", ingest.onDragOver);
1209
+ listeners.on(canvas, "dragleave", ingest.onDragLeave);
1210
+ listeners.on(canvas, "drop", ingest.onDrop);
1211
+ listeners.on(window, "paste", ingest.onPaste);
1212
+ }
1213
+ const offCarry = channels.carry ? carryInput(core) : null;
1214
+ return () => {
1215
+ listeners.removeAll();
1216
+ offCarry?.();
1217
+ canvas?.classList.remove(DROPOVER_CLASS);
1218
+ src.actions().dropKeys();
1219
+ hover.clear();
1220
+ disposed = true;
1221
+ pointer.dispose();
1222
+ held?.release();
1223
+ redraw.stop();
1224
+ for (const d of src.dispatchers()) d.cancelAll("cancel");
1225
+ };
1226
+ }
1227
+
786
1228
  // src/interactions/dispatcher/useGestureDispatcher.tsx
787
1229
  function useGestureDispatcher(opts) {
788
- const { canvasRef, actions, entriesById, enabled = true, keyboard = true, affordanceAt, classifyTarget, dispatcher: dispatcherOpt, clientToWorld, requestRedraw, paintedCursor, cursorSink, getRuleCtx, onClick, onDoubleClick, views, channels, longPress, claimKeys = false } = opts;
1230
+ const { canvasRef, actions, entriesById, enabled = true, keyboard = true, affordanceAt, classifyTarget, dispatcher: dispatcherOpt, clientToWorld, clientToLocal, requestRedraw, paintedCursor, cursorSink, getRuleCtx, onClick, onDoubleClick, views, channels, longPress, claimKeys = false, hears = "scope" } = opts;
789
1231
  const pointerChannel = channels?.pointer !== false;
790
1232
  const wheelChannel = channels?.wheel !== false;
791
1233
  const pinchChannel = channels?.pinch !== false;
792
1234
  const contextMenuChannel = channels?.contextMenu !== false;
793
1235
  const ingestChannel = channels?.ingest !== false;
1236
+ const carryChannel = channels?.carry !== false;
794
1237
  const onClickRef = useLatest(onClick);
795
1238
  const onDoubleClickRef = useLatest(onDoubleClick);
796
1239
  const activeTool = useActiveToolContext();
@@ -801,8 +1244,12 @@ function useGestureDispatcher(opts) {
801
1244
  dispatcherRef.current = dispatcherOpt ?? createDispatcher();
802
1245
  }
803
1246
  const registryRef = useLatest(actions);
1247
+ const heard = useMemo(() => {
1248
+ const node = hears === "own" ? actionsNodeOf(actions) : null;
1249
+ return node ? { list: () => node.ownActions() } : actions;
1250
+ }, [actions, hears]);
804
1251
  const ctxRef = useLatest({
805
- actions,
1252
+ actions: heard,
806
1253
  depRegistry,
807
1254
  activeToolId: activeTool.active,
808
1255
  hotkeyStack: activeTool.hotkeyStack,
@@ -818,6 +1265,7 @@ function useGestureDispatcher(opts) {
818
1265
  getRuleCtx
819
1266
  });
820
1267
  const viewsRef = useLatest(views);
1268
+ const clientToLocalRef = useLatest(clientToLocal);
821
1269
  const allDispatchers = useCallback(() => [
822
1270
  rootTargetRef.current.dispatcher,
823
1271
  ...(viewsRef.current?.targets() ?? []).map((t) => t.dispatcher)
@@ -825,6 +1273,7 @@ function useGestureDispatcher(opts) {
825
1273
  const requestRedrawRef = useLatest(requestRedraw);
826
1274
  const cursorRef = useLatest({ painted: paintedCursor, sink: cursorSink });
827
1275
  const longPressRef = useLatest(longPress);
1276
+ const kitSettingsRef = useLatest(useKitSettings());
828
1277
  const clicksRef = useRef({ last: null });
829
1278
  useToolLifecycle({
830
1279
  entriesById,
@@ -840,85 +1289,32 @@ function useGestureDispatcher(opts) {
840
1289
  }, [enabled, claimKeys, registryRef]);
841
1290
  useEffect(() => {
842
1291
  if (!enabled) return;
843
- let disposed = false;
844
- const canvas = canvasRef.current;
845
- const redraw = dispatcherWatch(() => {
846
- requestRedrawRef.current?.();
847
- });
848
- redraw.sync(allDispatchers());
849
- const core = createDispatchCore({
850
- canvas,
1292
+ return attachInput(canvasRef.current, {
851
1293
  root: () => rootTargetRef.current,
852
1294
  views: () => viewsRef.current,
1295
+ clientToLocal: () => clientToLocalRef.current,
853
1296
  context: () => ctxRef.current,
854
1297
  actions: () => registryRef.current,
855
- uses: () => {
856
- redraw.sync(allDispatchers());
1298
+ dispatchers: allDispatchers,
1299
+ requestRedraw: () => {
1300
+ requestRedrawRef.current?.();
857
1301
  },
858
- disposed: () => disposed
859
- });
860
- const keys = keyboardInput(core);
861
- const pinch = webkitPinchInput(core);
862
- const ingest = ingestInput(core);
863
- const hover = hoverCursorInput(core, () => cursorRef.current.painted?.(), () => pointer.heldCount(), () => cursorRef.current.sink?.());
864
- const pointer = pointerInput(core, {
1302
+ paintedCursor: () => cursorRef.current.painted?.(),
1303
+ cursorSink: () => cursorRef.current.sink?.(),
865
1304
  longPress: () => longPressRef.current,
1305
+ kitSettings: () => kitSettingsRef.current,
866
1306
  onClick: () => onClickRef.current,
867
1307
  onDoubleClick: () => onDoubleClickRef.current,
868
- clicks: clicksRef.current,
869
- hover
1308
+ clicks: clicksRef.current
1309
+ }, {
1310
+ keyboard,
1311
+ pointer: pointerChannel,
1312
+ wheel: wheelChannel,
1313
+ pinch: pinchChannel,
1314
+ contextMenu: contextMenuChannel,
1315
+ ingest: ingestChannel,
1316
+ carry: carryChannel
870
1317
  });
871
- const onWindowBlur = () => {
872
- pinch.end();
873
- pointer.cancelHeld();
874
- keys.releaseAll();
875
- };
876
- const listeners = listenerSet();
877
- const keyCapture = keyboard === "first";
878
- if (keyboard) {
879
- listeners.on(window, "keydown", keys.onKeyDown, keyCapture);
880
- listeners.on(window, "keyup", keys.onKeyUp, keyCapture);
881
- }
882
- listeners.on(window, "blur", onWindowBlur);
883
- listeners.on(canvas, "pointerdown", () => {
884
- registryRef.current.activate();
885
- });
886
- if (pointerChannel) {
887
- listeners.on(window, "keydown", hover.onKey);
888
- listeners.on(window, "keyup", hover.onKey);
889
- listeners.on(canvas, "pointerleave", hover.onLeave);
890
- listeners.on(canvas, "pointerdown", pointer.onPointerDown);
891
- listeners.on(canvas, "pointermove", pointer.onHoverMove);
892
- listeners.on(canvas, "dblclick", pointer.onNativeDoubleClick);
893
- }
894
- if (wheelChannel) {
895
- listeners.on(canvas, "wheel", wheelInput(core, pinch.live), { passive: false, capture: true });
896
- }
897
- if (pinchChannel) {
898
- listeners.on(canvas, "gesturestart", pinch.onGestureStart);
899
- listeners.on(canvas, "gesturechange", pinch.onGestureChange);
900
- listeners.on(canvas, "gestureend", pinch.onGestureEnd);
901
- }
902
- if (contextMenuChannel) {
903
- listeners.on(canvas, "contextmenu", contextMenuInput(core, pointer.takeNativeHold));
904
- }
905
- if (ingestChannel) {
906
- listeners.on(canvas, "dragenter", ingest.onDragOver);
907
- listeners.on(canvas, "dragover", ingest.onDragOver);
908
- listeners.on(canvas, "dragleave", ingest.onDragLeave);
909
- listeners.on(canvas, "drop", ingest.onDrop);
910
- listeners.on(window, "paste", ingest.onPaste);
911
- }
912
- return () => {
913
- listeners.removeAll();
914
- canvas?.classList.remove(DROPOVER_CLASS);
915
- registryRef.current.dropKeys();
916
- hover.clear();
917
- disposed = true;
918
- pointer.dispose();
919
- redraw.stop();
920
- for (const d of allDispatchers()) d.cancelAll("cancel");
921
- };
922
1318
  }, [
923
1319
  enabled,
924
1320
  keyboard,
@@ -928,8 +1324,11 @@ function useGestureDispatcher(opts) {
928
1324
  pinchChannel,
929
1325
  contextMenuChannel,
930
1326
  ingestChannel,
1327
+ carryChannel,
931
1328
  allDispatchers,
1329
+ clientToLocalRef,
932
1330
  ctxRef,
1331
+ kitSettingsRef,
933
1332
  longPressRef,
934
1333
  onClickRef,
935
1334
  onDoubleClickRef,
@@ -940,182 +1339,36 @@ function useGestureDispatcher(opts) {
940
1339
  viewsRef
941
1340
  ]);
942
1341
  }
943
- var ActionsContext = createContext(null);
944
- function depsFor(a, r) {
945
- if (!r) return {};
946
- if (a.requires) return buildDepsFromRequires(a, r);
947
- return {
948
- selection: r.get("selection"),
949
- scene: r.get("scene"),
950
- history: r.get("history"),
951
- view: r.get("view"),
952
- activeTool: r.get("activeTool"),
953
- booleansAdapter: r.get("booleansAdapter")
954
- };
955
- }
956
- var ActionsNode = class extends ScopeNode {
957
- constructor(parent, descends, contextDeps) {
958
- super(parent, descends);
959
- this.contextDeps = contextDeps;
960
- NODES.set(this.registry, this);
961
- }
962
- contextDeps;
963
- actions = /* @__PURE__ */ new Map();
964
- muted = /* @__PURE__ */ new Map();
965
- dispatchers = [];
966
- cache = null;
967
- /** Called on `activate`, so a scope's dep and tool nodes move with it. */
968
- onActivate = [];
969
- resolve(id) {
970
- for (const n of this.chain()) {
971
- if (n.muted.has(id)) return void 0;
972
- const a = n.actions.get(id)?.at(-1);
973
- if (a) return a;
974
- }
975
- return void 0;
976
- }
977
- snapshot() {
978
- const leaf = this.start();
979
- const cached = this.cache;
980
- if (cached && cached.version === this.tree.version && cached.leaf === leaf) return cached.list;
981
- const ids = /* @__PURE__ */ new Set();
982
- for (const n of leaf.chain()) for (const id of n.actions.keys()) ids.add(id);
983
- const out = [];
984
- for (const id of ids) {
985
- const a = leaf.resolve(id);
986
- if (a) out.push(a);
987
- }
988
- const list = Object.freeze(out);
989
- this.cache = { version: this.tree.version, leaf, list };
990
- return list;
991
- }
992
- deps() {
993
- for (const n of this.chain()) {
994
- const r = n.contextDeps();
995
- if (r) return r;
996
- }
997
- return null;
998
- }
999
- dispatcher() {
1000
- for (const n of this.chain()) {
1001
- const d = n.dispatchers.at(-1);
1002
- if (d) return d;
1003
- }
1004
- return null;
1005
- }
1006
- activate() {
1007
- keyHolder = this;
1008
- super.activate();
1009
- for (const f of this.onActivate) f();
1010
- }
1011
- registry = {
1012
- register: (action) => {
1013
- validateActionId(action.id);
1014
- validateActionDefaultBinding(action);
1015
- const stack = this.actions.get(action.id);
1016
- if (stack) stack.push(action);
1017
- else this.actions.set(action.id, [action]);
1018
- this.changed();
1019
- let released = false;
1020
- return () => {
1021
- if (released) return;
1022
- released = true;
1023
- const cur = this.actions.get(action.id);
1024
- if (!cur) return;
1025
- const i = cur.lastIndexOf(action);
1026
- if (i === -1) return;
1027
- cur.splice(i, 1);
1028
- if (cur.length === 0) {
1029
- queueMicrotask(() => {
1030
- if (cur.length === 0 && this.actions.get(action.id) === cur) this.actions.delete(action.id);
1031
- });
1032
- }
1033
- this.changed();
1034
- };
1035
- },
1036
- unregister: (id) => {
1037
- if (this.actions.delete(id)) this.changed();
1038
- },
1039
- mute: (id) => {
1040
- this.muted.set(id, (this.muted.get(id) ?? 0) + 1);
1041
- this.changed();
1042
- let released = false;
1043
- return () => {
1044
- if (released) return;
1045
- released = true;
1046
- const held = this.muted.get(id);
1047
- if (held === void 0) return;
1048
- if (held > 1) this.muted.set(id, held - 1);
1049
- else this.muted.delete(id);
1050
- this.changed();
1051
- };
1052
- },
1053
- list: () => this.snapshot(),
1054
- trigger: (id, params) => {
1055
- const leaf = this.start();
1056
- const a = leaf.resolve(id);
1057
- if (!a?.invoker || a.invoker.timing !== "immediate") return false;
1058
- const deps = depsFor(a, leaf.deps());
1059
- if (!evaluateEnabled(a, deps).enabled) return false;
1060
- try {
1061
- a.invoker.run(deps, params);
1062
- } catch (err) {
1063
- console.error(`weasel ActionsRegistry: action "${id}" threw`, err);
1064
- }
1065
- return true;
1066
- },
1067
- subscribe: (listener) => this.tree.listeners.subscribe(listener),
1068
- setDispatcher: (d) => pushOwner(this.dispatchers, d),
1069
- begin: (id, params) => {
1070
- const leaf = this.start();
1071
- const a = leaf.resolve(id);
1072
- const disp = leaf.dispatcher();
1073
- if (!a || !disp) return null;
1074
- return disp.beginUiOngoing(id, depsFor(a, leaf.deps()), params);
1075
- },
1076
- activate: () => this.activate(),
1077
- isActive: () => this.isActive(),
1078
- holdsKeys: () => keyHolder === this,
1079
- dropKeys: () => {
1080
- if (keyHolder === this) keyHolder = null;
1081
- }
1082
- };
1083
- };
1084
- var keyHolder = null;
1085
- var NODES = /* @__PURE__ */ new WeakMap();
1086
- function actionsNodeOf(registry) {
1087
- return registry ? NODES.get(registry) ?? null : null;
1088
- }
1089
- function ActionsProvider({ children }) {
1090
- const depReg = useOptionalDepRegistry();
1091
- const depRegRef = useLatest(depReg);
1092
- const node = useMemo(() => new ActionsNode(null, true, () => depRegRef.current), [depRegRef]);
1093
- return /* @__PURE__ */ jsx(ActionsContext.Provider, { value: node.registry, children });
1094
- }
1095
- var IS_DEV = (() => {
1096
- try {
1097
- return Boolean(import.meta.env?.DEV);
1098
- } catch {
1099
- return false;
1100
- }
1101
- })();
1102
- function useActionsRegistry() {
1103
- return useContext(ActionsContext);
1342
+ function useCommand(id, label, run, options) {
1343
+ const latest = useLatest({ run, options });
1344
+ const keys = useStableByContent(options?.keys, deepEqual);
1345
+ const tags = useStableByContent(options?.tags, deepEqual);
1346
+ const variants = useStableByContent(options?.variants, deepEqual);
1347
+ const hasEnabled = options?.enabled !== void 0;
1348
+ const hasActive = options?.active !== void 0;
1349
+ const icon = options?.icon;
1350
+ const action = useMemo(() => {
1351
+ const read = () => latest.current.options;
1352
+ const a = {
1353
+ id,
1354
+ label,
1355
+ invoker: { timing: "immediate", run: (_deps, params) => latest.current.run(params) }
1356
+ };
1357
+ if (keys !== void 0) a.defaultBinding = bindingOf(keys);
1358
+ if (tags !== void 0) a.tags = tags;
1359
+ if (variants !== void 0) a.variants = variants;
1360
+ if (hasEnabled) a.enabled = () => read()?.enabled?.() ?? true;
1361
+ if (hasActive) a.active = () => read()?.active?.() ?? false;
1362
+ if (icon !== void 0) a.icon = icon;
1363
+ return a;
1364
+ }, [id, label, icon, keys, tags, variants, hasEnabled, hasActive, latest]);
1365
+ useAction(action);
1104
1366
  }
1105
- function useAction(action) {
1106
- const reg = useActionsRegistry();
1107
- useEffect(() => {
1108
- if (!reg) {
1109
- if (IS_DEV) {
1110
- console.warn(
1111
- `useAction("${action.id}"): no <ActionsProvider> is in scope, so the action was not registered and its bindings will never fire.`
1112
- );
1113
- }
1114
- return;
1115
- }
1116
- return reg.register(action);
1117
- }, [reg, action]);
1367
+ function bindingOf(keys) {
1368
+ if (isList(keys)) return [...keys];
1369
+ return "spec" in keys ? [keys] : keys;
1118
1370
  }
1371
+ var isList = (keys) => Array.isArray(keys);
1119
1372
  function useNodes(descends, ownsTool, parent) {
1120
1373
  const parentActions = useActionsRegistry();
1121
1374
  const parentDeps = useOptionalDepRegistry();
@@ -1139,7 +1392,8 @@ function useNodes(descends, ownsTool, parent) {
1139
1392
  return nodes;
1140
1393
  }
1141
1394
  function Provide({ nodes, children }) {
1142
- return /* @__PURE__ */ jsx(DepRegistryContext.Provider, { value: nodes.deps.registry, children: /* @__PURE__ */ jsx(ActionsContext.Provider, { value: nodes.actions.registry, children: /* @__PURE__ */ jsx(ActiveToolNodeContext.Provider, { value: nodes.tools, children }) }) });
1395
+ const menuHost = useContext(MenuHostContext) ?? nodes.actions.menuHost();
1396
+ return /* @__PURE__ */ jsx(DepRegistryContext.Provider, { value: nodes.deps.registry, children: /* @__PURE__ */ jsx(ActionsContext.Provider, { value: nodes.actions.registry, children: /* @__PURE__ */ jsx(ActiveToolNodeContext.Provider, { value: nodes.tools, children: /* @__PURE__ */ jsx(MenuHostContext.Provider, { value: menuHost, children }) }) }) });
1143
1397
  }
1144
1398
  function InputScope({ yoke, children }) {
1145
1399
  const nodes = useNodes(false, yoke === void 0, yoke);
@@ -1177,7 +1431,20 @@ function useOngoingAction(actionId) {
1177
1431
  }
1178
1432
  };
1179
1433
  }, [regRef, idRef]);
1180
- useEffect(() => () => edit.commit(), [edit, actionId]);
1434
+ const leaving = useRef(null);
1435
+ useEffect(() => {
1436
+ const left = leaving.current;
1437
+ leaving.current = null;
1438
+ if (left !== null && left !== actionId) edit.commit();
1439
+ return () => {
1440
+ leaving.current = actionId;
1441
+ queueMicrotask(() => {
1442
+ if (leaving.current !== actionId) return;
1443
+ leaving.current = null;
1444
+ edit.commit();
1445
+ });
1446
+ };
1447
+ }, [edit, actionId]);
1181
1448
  return edit;
1182
1449
  }
1183
1450
  function samePos(a, b) {
@@ -1459,6 +1726,6 @@ function useTools(opts) {
1459
1726
  );
1460
1727
  }
1461
1728
 
1462
- export { ActionsProvider, ActiveToolContextProvider, ActiveToolContextProviderIfRoot, DepRegistryProvider, InputScope, PointerContextProvider, SelectionContextProvider, SelectionContextProviderIfRoot, Yoke, createPointerStore, useAction, useActionsRegistry, useActiveToolContext, useContributions, useDepRegistry, useDepSource, useGestureDispatcher, useOffhandAction, useOngoingAction, useOptionalActiveToolContext, useOptionalDepRegistry, usePointerContext, usePointerPosition, usePublishSelection, useSelectionContext, useTools, useYoke };
1729
+ export { ActionsProvider, ActiveToolContextProvider, ActiveToolContextProviderIfRoot, DepRegistryProvider, InputScope, PointerContextProvider, SelectionContextProvider, SelectionContextProviderIfRoot, Yoke, createPointerStore, useAction, useActionsRegistry, useActiveToolContext, useCommand, useContributions, useDepRegistry, useDepSource, useGestureDispatcher, useMenuHost, useMenus, useOffhandAction, useOngoingAction, useOptionalActiveToolContext, useOptionalDepRegistry, usePointerContext, usePointerPosition, usePublishSelection, useSelectionContext, useTools, useYoke };
1463
1730
  //# sourceMappingURL=react.js.map
1464
1731
  //# sourceMappingURL=react.js.map