@weasel-js/routing 1.11.0 → 1.12.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.
@@ -1,10 +1,10 @@
1
1
  import { isDev } from '@weasel-js/react';
2
2
  import { createEmitter } from '@weasel-js/registry';
3
- import { RESERVED_ID_PREFIXES, RESERVED_ID_NAMES, isApplePlatform, routeGestureForSpecKind, getGestureDescriptor, formatRoute, parseTargetSpec, matchSpec, canonicalModifiers, UNKNOWN_MIME, specificity, VALID_MOD_NAMES, stylusOf } from '@weasel-js/gestures';
3
+ import { RESERVED_ID_PREFIXES, RESERVED_ID_NAMES, isApplePlatform, bindingSpec, routeGestureForSpecKind, getGestureDescriptor, formatRoute, parseTargetSpec, matchSpec, canonicalModifiers, UNKNOWN_MIME, specificity, formatShortcut, VALID_MOD_NAMES, stylusOf } from '@weasel-js/gestures';
4
4
  export { GESTURE_DESCRIPTORS, LONG_PRESS_MS, RESERVED_ID_NAMES, RESERVED_ID_PREFIXES, ROUTE_FIELD_DEFINITIONS, ROUTE_TERMS, activatesFocusedControl, canonicalModifiers, collapseShiftPairs, describeRoute, describeRouteParts, focusedControlOwnsKey, formatPhaseAtom, formatRoute, getGestureDescriptor, isEditableTarget, isKnownGestureName, matchKey, matchModifiers, matchPhase, matchSpec, matchTarget, parseRoute, routeGestureForSpecKind, specKindForRouteGesture, specificity } from '@weasel-js/gestures';
5
5
  import { activeModeOf, NORMAL, DEFAULT_MODES, capabilitiesAllowed } from '@weasel-js/modes';
6
6
  import { resolveCursor } from '@weasel-js/cursor';
7
- import { prefIsShown, prefIsEnabled, isPrefLeaf, prefAliasTarget, prefLeafAt, prefAliasedLeaf, prefNumberAt, resolvePrefUnit, prefDisplayBounds, prefUnitAccepts } from '@weasel-js/prefs';
7
+ import { prefIsShown, prefIsEnabled, isPrefLeaf, prefAliasTarget, prefLeafAt, prefAliasedLeaf, prefNumberAt, resolvePrefUnit, prefDisplayBounds, prefUnitAccepts, prefValueAtPath } from '@weasel-js/prefs';
8
8
  import { endlessAllows } from '@weasel-js/quantity';
9
9
 
10
10
  // src/interactions/actions/actionItems.ts
@@ -34,6 +34,21 @@ function actionItemTitle(item) {
34
34
  return `${item.action.label}: ${item.label}`;
35
35
  }
36
36
 
37
+ // src/interactions/actions/actionSettings.ts
38
+ var EMPTY = { values: {} };
39
+ function readActionSettings(action, deps) {
40
+ const settings = action.settings;
41
+ if (!settings) return null;
42
+ try {
43
+ return settings.read(deps ?? {});
44
+ } catch {
45
+ return EMPTY;
46
+ }
47
+ }
48
+ function actionSettingsParams(settings, path, value) {
49
+ return settings.params ? settings.params(path, value) : { [path]: value };
50
+ }
51
+
37
52
  // src/interactions/actions/binding.ts
38
53
  function actionBindings(action) {
39
54
  const gs = action.defaultBinding;
@@ -270,13 +285,21 @@ var DepNode = class extends ScopeNode {
270
285
  };
271
286
  },
272
287
  get: (name) => {
288
+ const stacks = [...this.start().chain()].map((n) => n.sources.get(name) ?? []);
289
+ return readFrom(stacks, 0, (stacks[0]?.length ?? 0) - 1);
290
+ },
291
+ subscribe: (listener) => this.tree.listeners.subscribe(listener),
292
+ list: () => {
293
+ const found = /* @__PURE__ */ new Map();
294
+ let depth = 0;
273
295
  for (const n of this.start().chain()) {
274
- const source = n.sources.get(name)?.at(-1);
275
- if (source) return source();
296
+ for (const [name, stack] of n.sources) {
297
+ if (!found.has(name)) found.set(name, { name, depth, stacked: stack.length });
298
+ }
299
+ depth++;
276
300
  }
277
- return void 0;
301
+ return [...found.values()].sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
278
302
  },
279
- subscribe: (listener) => this.tree.listeners.subscribe(listener),
280
303
  changed: () => this.changed()
281
304
  };
282
305
  constructor(parent, descends) {
@@ -284,6 +307,11 @@ var DepNode = class extends ScopeNode {
284
307
  NODES.set(this.registry, this);
285
308
  }
286
309
  };
310
+ function readFrom(stacks, scope, index) {
311
+ if (scope >= stacks.length) return void 0;
312
+ if (index < 0) return readFrom(stacks, scope + 1, (stacks[scope + 1]?.length ?? 0) - 1);
313
+ return stacks[scope][index](() => readFrom(stacks, scope, index - 1));
314
+ }
287
315
  var NODES = /* @__PURE__ */ new WeakMap();
288
316
  function depNodeOf(registry) {
289
317
  return registry ? NODES.get(registry) ?? null : null;
@@ -438,6 +466,49 @@ function tuneAction(action, tunings) {
438
466
  for (const t of tunings) out = tuneOnce(out, t);
439
467
  return out;
440
468
  }
469
+ var NO_OVERRIDES = /* @__PURE__ */ new Map();
470
+ function bindingId(b, ownerId, index) {
471
+ return b.opts?.id ?? (ownerId === null ? `${b.actionId}@${index}` : `${ownerId}#${index}`);
472
+ }
473
+ function resolveBindingOverrides(maps) {
474
+ if (maps.length === 0) return NO_OVERRIDES;
475
+ const out = /* @__PURE__ */ new Map();
476
+ for (const map of maps) {
477
+ for (const [id, input] of Object.entries(map)) {
478
+ try {
479
+ out.set(id, bindingSpec(input));
480
+ } catch (err) {
481
+ console.warn(`weasel: binding override "${id}" is not a route: ${err.message}`);
482
+ }
483
+ }
484
+ }
485
+ return out;
486
+ }
487
+ function overridden(b, id, overrides) {
488
+ if (!overrides.has(id)) return b;
489
+ const spec = overrides.get(id);
490
+ return spec === null ? null : { ...b, spec };
491
+ }
492
+ function overriddenBindings(bindings, ownerId, overrides = NO_OVERRIDES) {
493
+ const out = [];
494
+ bindings.forEach((b, i) => {
495
+ const next = overridden(b, bindingId(b, ownerId, i), overrides);
496
+ if (next) out.push(next);
497
+ });
498
+ return out;
499
+ }
500
+ function overrideActionBindings(action, overrides) {
501
+ if (overrides.size === 0 || action.defaultBinding === void 0) return action;
502
+ const declared = actionBindings(action);
503
+ if (!declared.some((b, i) => overrides.has(bindingId(b, null, i)))) return action;
504
+ const kept = [];
505
+ declared.forEach((b, i) => {
506
+ const id = bindingId(b, null, i);
507
+ const next = overridden(b, id, overrides);
508
+ if (next) kept.push({ spec: next.spec, opts: { ...next.opts, id } });
509
+ });
510
+ return { ...action, defaultBinding: kept };
511
+ }
441
512
 
442
513
  // src/interactions/actions/toolOffhand.ts
443
514
  var TOOL_OFFHAND_ID = "tool.offhand";
@@ -460,7 +531,7 @@ function offhandKeyFor(trigger) {
460
531
  function buildToolOffhandBindings(specs) {
461
532
  return specs.map(({ toolId, key }) => ({
462
533
  spec: { ...heldKeySpec(key), phase: BETWEEN_GESTURES },
463
- opts: { params: { toolId } }
534
+ opts: { id: `${TOOL_OFFHAND_ID}.${toolId}`, params: { toolId } }
464
535
  }));
465
536
  }
466
537
  var BETWEEN_GESTURES = [{ channel: "*", phase: "initial" }];
@@ -520,7 +591,8 @@ function routesForSpec(spec) {
520
591
  const phases = phaseAtomsForSpec("phase" in spec ? spec.phase : void 0);
521
592
  const target = descriptor.hasTarget ? routeTargetForSpec("target" in spec ? spec.target : void 0) ?? "*" : void 0;
522
593
  const args = descriptor.arg ? routeArgsForSpec(spec, descriptor.arg.default) : [void 0];
523
- return args.map((arg) => formatRoute({ phases, gesture, arg, target, modifiers }));
594
+ const held = spec.kind === "hover" && spec.held !== void 0 ? { held: spec.held === true ? "required" : "optional" } : {};
595
+ return args.map((arg) => formatRoute({ phases, gesture, arg, target, modifiers, ...held }));
524
596
  }
525
597
  function entryFor(ownerId, spec, actionId) {
526
598
  const gesture = routeGestureForSpecKind(spec.kind);
@@ -671,11 +743,11 @@ function matchSortedWithBarred(e, bindings, isMac, engagedChannels, opts = {}) {
671
743
  const scopeBarred = [];
672
744
  for (const sb of bindings) {
673
745
  if (sb.scope !== scope) continue;
674
- const admitted = admits(sb);
675
- if (!admitted && !opts.collectBarred) continue;
746
+ const admitted2 = admits(sb);
747
+ if (!admitted2 && !opts.collectBarred) continue;
676
748
  const phaseCtx = { selfChannel: sb.ownerId, engagedChannels: engaged };
677
749
  if (matchSpec(e, sb.binding.spec, isMac, phaseCtx)) {
678
- (admitted ? scopeMatches : scopeBarred).push({ binding: sb.binding, scope, ownerId: sb.ownerId });
750
+ (admitted2 ? scopeMatches : scopeBarred).push({ binding: sb.binding, scope, ownerId: sb.ownerId });
679
751
  }
680
752
  }
681
753
  scopeMatches.sort((a, b) => compareSpecificity(a.binding.spec, b.binding.spec));
@@ -933,33 +1005,14 @@ function buildRuleCtx(args) {
933
1005
  device: args.device
934
1006
  };
935
1007
  }
936
- var DEV2 = isDev();
937
- var TRACE_LIMIT = 200;
938
- var traceLog = DEV2 && typeof window !== "undefined" ? window.__weaselDispatchLog__ ??= [] : [];
939
- function recordTrace(entry) {
940
- if (!DEV2) return;
941
- traceLog.push(entry);
942
- if (traceLog.length > TRACE_LIMIT) traceLog.shift();
943
- }
944
- function publishLiveDispatch(explain2) {
945
- if (!DEV2 || typeof window === "undefined") return;
946
- window.__weaselDispatchLive__ = explain2;
947
- }
948
- function recordModeSwitch(mode, from, to, detail) {
949
- recordTrace({
950
- kind: "mode",
951
- ts: Date.now(),
952
- mode,
953
- from,
954
- to,
955
- ...detail !== void 0 ? { detail } : {}
956
- });
957
- }
958
1008
 
959
1009
  // src/interactions/dispatcher/gestureIds.ts
960
1010
  function pointerGestureId(pointerId) {
961
1011
  return `pointer-${pointerId ?? "mouse"}`;
962
1012
  }
1013
+ function carryGestureId(pointerId) {
1014
+ return `carry-${pointerId ?? "mouse"}`;
1015
+ }
963
1016
  function multiTouchGestureId(fingers) {
964
1017
  return `multitouch-${fingers}`;
965
1018
  }
@@ -977,7 +1030,7 @@ function gestureIdFor(event) {
977
1030
  return multiTouchGestureId(event.fingers);
978
1031
  }
979
1032
  if (event.kind === "carry") {
980
- return `carry-${event.pointerId ?? "mouse"}`;
1033
+ return carryGestureId(event.pointerId);
981
1034
  }
982
1035
  return `ongoing-${event.kind}`;
983
1036
  }
@@ -986,17 +1039,18 @@ function gestureIdFor(event) {
986
1039
  function liveScope(id, eligibility, state) {
987
1040
  const tags = eligibility.capabilities;
988
1041
  if (tags && state.allows && !state.allows(tags)) return null;
1042
+ if (eligibility.keymap) return state.openKeymap === id ? "hotkey" : null;
989
1043
  if (state.engagedIds?.has(id)) return "hotkey";
990
1044
  if (eligibility.focus && state.focusedId === id) return "active";
991
1045
  if (eligibility.always || eligibility.claimed) return "ambient";
992
1046
  return null;
993
1047
  }
994
- function scopeBindings(entries, state) {
1048
+ function scopeBindings(entries, state, overrides = NO_OVERRIDES) {
995
1049
  const out = [];
996
1050
  for (const entry of entries) {
997
1051
  const scope = liveScope(entry.id, entry.eligibility ?? {}, state);
998
1052
  if (scope === null) continue;
999
- for (const binding of entry.bindings ?? []) {
1053
+ for (const binding of overriddenBindings(entry.bindings ?? [], entry.id, overrides)) {
1000
1054
  out.push({ binding, scope, ownerId: entry.id });
1001
1055
  }
1002
1056
  }
@@ -1018,10 +1072,56 @@ function assembleEntries(entries, inputs) {
1018
1072
  state: {
1019
1073
  focusedId: inputs.focusedId,
1020
1074
  engagedIds: new Set(inputs.hotkeyStack),
1075
+ ...inputs.openKeymap ? { openKeymap: inputs.openKeymap } : {},
1021
1076
  ...allowed ? { allows: (tags) => capabilitiesAllowed(allowed, tags) } : {}
1022
1077
  }
1023
1078
  };
1024
1079
  }
1080
+ function createTraceRing(limit = 200, dev = isDev()) {
1081
+ const entries = [];
1082
+ const pushed = createEmitter();
1083
+ let total = 0;
1084
+ let watchers = 0;
1085
+ const recording = () => dev || watchers > 0;
1086
+ return {
1087
+ recording,
1088
+ push(entry) {
1089
+ if (!recording()) return;
1090
+ entries.push(entry);
1091
+ if (entries.length > limit) entries.shift();
1092
+ total++;
1093
+ pushed.emit();
1094
+ },
1095
+ since(cursor) {
1096
+ const first = total - entries.length;
1097
+ return { entries: entries.slice(Math.max(cursor, first) - first), cursor: total };
1098
+ },
1099
+ watch() {
1100
+ watchers++;
1101
+ let released = false;
1102
+ return () => {
1103
+ if (released) return;
1104
+ released = true;
1105
+ watchers--;
1106
+ };
1107
+ },
1108
+ subscribe: pushed.subscribe
1109
+ };
1110
+ }
1111
+ function createDispatchTrace(limit, dev) {
1112
+ const ring = createTraceRing(limit, dev);
1113
+ let explain2 = null;
1114
+ return {
1115
+ ...ring,
1116
+ recordModeSwitch(mode, from, to, detail) {
1117
+ ring.push({ kind: "mode", ts: Date.now(), mode, from, to, ...detail !== void 0 ? { detail } : {} });
1118
+ },
1119
+ setLive(next) {
1120
+ explain2 = next;
1121
+ },
1122
+ live: () => explain2?.() ?? null
1123
+ };
1124
+ }
1025
1125
 
1026
1126
  // src/interactions/dispatcher/inputFacts.ts
1027
1127
  function modifiersOf(e) {
@@ -1043,6 +1143,7 @@ function worldPointOf(event) {
1043
1143
  }
1044
1144
  }
1045
1145
  function carriedBy(event) {
1146
+ if (event.kind === "carry") return { items: [], carry: { type: event.type, value: event.value } };
1046
1147
  return event.kind === "drop" || event.kind === "paste" ? { items: event.items } : void 0;
1047
1148
  }
1048
1149
  function immediateParams(event, resolved) {
@@ -1109,6 +1210,7 @@ function immediateParams(event, resolved) {
1109
1210
  affordance: event.affordance,
1110
1211
  bodyTarget: event.bodyTarget,
1111
1212
  mods: modifiersOf(event),
1213
+ held: event.held === true,
1112
1214
  ...resolved
1113
1215
  };
1114
1216
  case "carry":
@@ -1118,6 +1220,9 @@ function immediateParams(event, resolved) {
1118
1220
  clientX: event.clientX,
1119
1221
  clientY: event.clientY,
1120
1222
  carry: { type: event.type, value: event.value },
1223
+ affordance: event.affordance,
1224
+ bodyTarget: event.bodyTarget,
1225
+ bodyKind: event.bodyKind,
1121
1226
  mods: modifiersOf(event),
1122
1227
  ...resolved
1123
1228
  };
@@ -1139,6 +1244,10 @@ function liveInView(binding, view) {
1139
1244
  const views = binding.opts?.views;
1140
1245
  return views === void 0 || views.includes(view);
1141
1246
  }
1247
+ function liveForKeys(binding, reach) {
1248
+ if (reach === void 0) return true;
1249
+ return binding.opts?.over ? reach.over : reach.held;
1250
+ }
1142
1251
  function namesView(binding, view) {
1143
1252
  return binding.opts?.views?.includes(view) ?? false;
1144
1253
  }
@@ -1557,7 +1666,7 @@ function pumpCarry(run, event) {
1557
1666
  if (event.stage === "enter") return void 0;
1558
1667
  const gestureId = gestureIdFor(event);
1559
1668
  const handle = run.inFlight.handles.get(gestureId);
1560
- if (!handle) return event.stage === "drop" ? void 0 : "unhandled";
1669
+ if (!handle) return event.stage === "leave" ? "unhandled" : void 0;
1561
1670
  if (event.stage === "move") {
1562
1671
  handle.onMove?.(ctxFor(run, event, {}, gestureId));
1563
1672
  return "handled";
@@ -1566,7 +1675,7 @@ function pumpCarry(run, event) {
1566
1675
  }
1567
1676
  function carryStageFits(event, timing) {
1568
1677
  if (event.kind !== "carry") return true;
1569
- return event.stage === (timing === "immediate" ? "drop" : "enter");
1678
+ return timing === "immediate" ? event.stage === "drop" : event.stage === "enter" || event.stage === "move";
1570
1679
  }
1571
1680
  function invokeAction(run, event, match, action, deps) {
1572
1681
  if (action.invoker && !carryStageFits(event, action.invoker.timing)) return "empty-handle";
@@ -1690,22 +1799,29 @@ function createUiOngoing(inFlight, notify, getAction) {
1690
1799
  // src/interactions/dispatcher/walk.ts
1691
1800
  function assembleScopedBindings(ctx) {
1692
1801
  const allowedCapabilities = ctx.getRuleCtx?.()?.allowedCapabilities;
1802
+ const openKeymap = ctx.keymapPass === "none" ? null : ctx.keymaps?.innermost()?.id ?? null;
1693
1803
  const { ordered, state } = assembleEntries(ctx.entriesById.values(), {
1694
1804
  focusedId: ctx.activeToolId,
1695
1805
  hotkeyStack: ctx.hotkeyStack,
1696
- ...allowedCapabilities ? { allowedCapabilities } : {}
1806
+ ...allowedCapabilities ? { allowedCapabilities } : {},
1807
+ ...openKeymap ? { openKeymap } : {}
1697
1808
  });
1698
1809
  const view = ctx.viewId ?? null;
1699
- const result = scopeBindings(ordered, state).filter((sb) => liveInView(sb.binding, view));
1810
+ const live = (b) => liveInView(b, view) && liveForKeys(b, ctx.keyReach);
1811
+ const overrides = ctx.bindingOverrides?.() ?? NO_OVERRIDES;
1812
+ const result = scopeBindings(ordered, state, overrides).filter((sb) => live(sb.binding));
1813
+ if (ctx.keymapPass === "only") return result.filter((sb) => sb.ownerId === openKeymap);
1700
1814
  for (const action of ctx.actions.list()) {
1701
1815
  const targetScope = action.scope === "hotkey" ? "hotkey" : "ambient";
1702
1816
  for (const binding of actionBindings(action)) {
1703
- if (!liveInView(binding, view)) continue;
1704
- result.push({ binding, scope: targetScope, ownerId: null });
1817
+ if (live(binding)) result.push({ binding, scope: targetScope, ownerId: null });
1705
1818
  }
1706
1819
  }
1707
1820
  return result;
1708
1821
  }
1822
+ function anyBinding(ctx, test) {
1823
+ return assembleScopedBindings(ctx).some((sb) => test(sb.binding.spec));
1824
+ }
1709
1825
  function buildActionMap(registry) {
1710
1826
  const map = /* @__PURE__ */ new Map();
1711
1827
  for (const action of registry.list()) {
@@ -1871,6 +1987,68 @@ function explain(event, ctx, engaged, opts) {
1871
1987
  const walked = walk(r, event, ctx, null, opts?.evaluateShadowed ?? false);
1872
1988
  return buildDispatchRecord(r, walked, event, ctx, true, walked.winner ? "handled" : "unhandled");
1873
1989
  }
1990
+ var MODIFIER_KEYS2 = /* @__PURE__ */ new Set(["Shift", "Control", "Alt", "Meta", "AltGraph", "CapsLock"]);
1991
+ var STROKES = /* @__PURE__ */ new Set([
1992
+ "click",
1993
+ "doubleclick",
1994
+ "longpress",
1995
+ "contextmenu",
1996
+ "multitouch",
1997
+ "multitouchtap"
1998
+ ]);
1999
+ var isPlainEscape = (e) => e.kind === "key" && e.key === "Escape" && !e.altKey && !e.ctrlKey && !e.metaKey && !e.shiftKey;
2000
+ var SETTLES_INTO = ["click", "doubleclick", "longpress", "contextmenu"];
2001
+ function stillLive(id, ctx) {
2002
+ const entry = ctx.entriesById.get(id);
2003
+ if (!entry) return false;
2004
+ const allowed = ctx.getRuleCtx?.()?.allowedCapabilities;
2005
+ const allows = allowed ? (tags) => capabilitiesAllowed(allowed, tags) : void 0;
2006
+ return liveScope(id, entry.eligibility, { focusedId: null, openKeymap: id, ...allows ? { allows } : {} }) !== null;
2007
+ }
2008
+ function routeThroughKeymap(event, ctx, passes) {
2009
+ const stack = ctx.keymaps;
2010
+ const open = stack?.innermost();
2011
+ if (!stack || !open || event.kind === "hover") return void 0;
2012
+ const isKey = event.kind === "key" || event.kind === "key-held";
2013
+ if (isKey && ctx.keyReach && !ctx.keyReach.held) return void 0;
2014
+ if (!stillLive(open.id, ctx)) {
2015
+ stack.closeAll();
2016
+ return void 0;
2017
+ }
2018
+ const verdict = stack.verdict();
2019
+ if (verdict === "taken") return "unhandled";
2020
+ if (verdict === "cascaded") return passes.run("none", event);
2021
+ if (isPlainEscape(event)) {
2022
+ stack.closeInnermost();
2023
+ return "handled";
2024
+ }
2025
+ if (passes.run("only", event) === "handled") {
2026
+ stack.inputSeen();
2027
+ return "handled";
2028
+ }
2029
+ if (isKey) {
2030
+ if (event.kind === "key" && passes.binds({ ...event, kind: "key-held", phase: "down" })) return "unhandled";
2031
+ if (MODIFIER_KEYS2.has(event.key) || event.ctrlKey || event.metaKey || event.key === "Tab") {
2032
+ return passes.run("none", event);
2033
+ }
2034
+ const entry = ctx.entriesById.get(open.id)?.eligibility.keymap;
2035
+ const own = typeof entry === "object" ? entry.unbound : void 0;
2036
+ if ((own ?? ctx.leaderUnbound ?? "modal") === "modal") {
2037
+ stack.swallowed();
2038
+ return "handled";
2039
+ }
2040
+ stack.cascaded();
2041
+ return passes.run("none", event);
2042
+ }
2043
+ if (event.kind === "pointerdown" && SETTLES_INTO.some((kind) => passes.binds({ ...event, kind }))) {
2044
+ return "unhandled";
2045
+ }
2046
+ const outcome = passes.run("none", event);
2047
+ const stroke = STROKES.has(event.kind) || event.kind === "pointerdown" && outcome === "handled";
2048
+ const firstOfDouble = event.kind === "click" && passes.binds({ ...event, kind: "doubleclick" });
2049
+ if (stroke && !firstOfDouble) stack.inputSeen();
2050
+ return outcome;
2051
+ }
1874
2052
 
1875
2053
  // src/interactions/dispatcher/dispatcher.ts
1876
2054
  function createDispatcher(opts) {
@@ -1893,10 +2071,17 @@ function createDispatcher(opts) {
1893
2071
  const pumped = pumpGesture(run, event);
1894
2072
  if (pumped !== void 0) return pumped;
1895
2073
  if (event.kind === "hover") return hover(event, ctx);
1896
- const r = rank(event, ctx, inFlight.engagedOwners(), DEV2);
2074
+ return routeThroughKeymap(event, ctx, {
2075
+ run: (pass, ev) => route(ev, { ...ctx, keymapPass: pass }),
2076
+ binds: (ev) => rank(ev, { ...ctx, keymapPass: "only" }, inFlight.engagedOwners(), false).ordered.length > 0
2077
+ }) ?? route(event, ctx);
2078
+ }
2079
+ function route(event, ctx) {
2080
+ const trace = ctx.trace?.recording() ? ctx.trace : null;
2081
+ const r = rank(event, ctx, inFlight.engagedOwners(), trace !== null);
1897
2082
  const walked = walk(r, event, ctx, invoking(event), false);
1898
2083
  const outcome = walked.stop === "fired" ? "handled" : "unhandled";
1899
- if (DEV2) recordTrace(buildDispatchRecord(r, walked, event, ctx, false, outcome));
2084
+ trace?.push(buildDispatchRecord(r, walked, event, ctx, false, outcome));
1900
2085
  return outcome;
1901
2086
  }
1902
2087
  function hover(event, ctx) {
@@ -2112,6 +2297,229 @@ function startCarry(origin, down, payload, cb = {}) {
2112
2297
  cancel: () => session.cancel()
2113
2298
  };
2114
2299
  }
2300
+ var KEYMAP_HOLD = "hold";
2301
+ function createKeymapStack() {
2302
+ let levels = [];
2303
+ let version = 0;
2304
+ const changed = createEmitter();
2305
+ let depth = 0;
2306
+ let serial = 0;
2307
+ let pending = [];
2308
+ let verdict = null;
2309
+ let snapshot = [];
2310
+ const notify = () => {
2311
+ snapshot = levels.map(({ openedIn: _, ...rest }) => Object.freeze({ ...rest }));
2312
+ version++;
2313
+ changed.emit();
2314
+ };
2315
+ const later = (op) => {
2316
+ if (depth > 0) pending.push(op);
2317
+ else op();
2318
+ };
2319
+ const settle = () => {
2320
+ const before = levels;
2321
+ const opened = (l) => l.openedIn === serial && depth > 0;
2322
+ if (levels.some(opened)) return;
2323
+ for (const l of levels) if (l.heldBy !== void 0) l.usedWhileHeld = true;
2324
+ while (levels.length > 0 && levels.at(-1).heldBy === void 0) levels = levels.slice(0, -1);
2325
+ if (levels !== before) notify();
2326
+ };
2327
+ return {
2328
+ open: () => snapshot,
2329
+ innermost: () => snapshot.at(-1) ?? null,
2330
+ push: (id, label, opts) => {
2331
+ const heldBy = opts?.heldBy;
2332
+ const bindings = opts?.bindings ?? [];
2333
+ const open = levels.findIndex((l) => l.id === id);
2334
+ if (open !== -1) levels = levels.slice(0, open);
2335
+ levels = [...levels, { id, label, bindings, ...heldBy !== void 0 ? { heldBy } : {}, usedWhileHeld: false, openedIn: serial }];
2336
+ if (depth > 0) verdict = "taken";
2337
+ notify();
2338
+ },
2339
+ holdOpened: (heldBy) => {
2340
+ let held = false;
2341
+ levels = levels.map((l) => {
2342
+ if (l.openedIn !== serial || l.heldBy !== void 0) return l;
2343
+ held = true;
2344
+ return { ...l, heldBy };
2345
+ });
2346
+ if (held) notify();
2347
+ return held;
2348
+ },
2349
+ release: (heldBy) => {
2350
+ const i = levels.findIndex((l) => l.heldBy === heldBy);
2351
+ if (i === -1) return;
2352
+ const level = levels[i];
2353
+ if (level.usedWhileHeld) {
2354
+ levels = levels.slice(0, i);
2355
+ while (levels.length > 0 && levels.at(-1).heldBy === void 0) levels = levels.slice(0, -1);
2356
+ } else levels = levels.map((l) => l === level ? { ...l, heldBy: void 0 } : l).map(dropUndefinedHeld);
2357
+ notify();
2358
+ },
2359
+ closeInnermost: () => {
2360
+ if (depth > 0) verdict = "taken";
2361
+ later(() => {
2362
+ if (levels.length === 0) return;
2363
+ levels = levels.slice(0, -1);
2364
+ notify();
2365
+ });
2366
+ },
2367
+ inputSeen: () => {
2368
+ if (depth > 0) verdict ??= "taken";
2369
+ later(settle);
2370
+ },
2371
+ cascaded: () => {
2372
+ if (depth > 0) verdict = "cascaded";
2373
+ later(settle);
2374
+ },
2375
+ swallowed: () => {
2376
+ for (const l of levels) if (l.heldBy !== void 0) l.usedWhileHeld = true;
2377
+ },
2378
+ verdict: () => verdict,
2379
+ closeAll: () => {
2380
+ pending = [];
2381
+ if (levels.length === 0) return;
2382
+ levels = [];
2383
+ notify();
2384
+ },
2385
+ batch: (fn) => {
2386
+ if (depth === 0) {
2387
+ serial++;
2388
+ verdict = null;
2389
+ }
2390
+ depth++;
2391
+ try {
2392
+ return fn();
2393
+ } finally {
2394
+ depth--;
2395
+ if (depth === 0) {
2396
+ const ops = pending;
2397
+ pending = [];
2398
+ depth = 1;
2399
+ try {
2400
+ for (const op of ops) op();
2401
+ } finally {
2402
+ depth = 0;
2403
+ }
2404
+ verdict = null;
2405
+ }
2406
+ }
2407
+ },
2408
+ subscribe: changed.subscribe,
2409
+ getVersion: () => version
2410
+ };
2411
+ }
2412
+ function dropUndefinedHeld(l) {
2413
+ if (l.heldBy !== void 0) return l;
2414
+ const { heldBy: _, ...rest } = l;
2415
+ return rest;
2416
+ }
2417
+
2418
+ // src/keymaps/keymapContribution.ts
2419
+ var keymapLeaderId = (id) => `keymap.${id}`;
2420
+ var keymapLeaderBindingId = (id, index = 0) => index === 0 ? `${keymapLeaderId(id)}.leader` : `${keymapLeaderId(id)}.leader#${index}`;
2421
+ function leaderBindings(def) {
2422
+ return [def.leader].flat().map((spec, i) => ({
2423
+ spec: spec.kind === "key-held" ? { ...spec, kind: "key" } : spec,
2424
+ opts: { id: keymapLeaderBindingId(def.id, i) }
2425
+ }));
2426
+ }
2427
+ var isPlainEscape2 = (spec) => spec.kind === "key" && [spec.key].flat().includes("Escape") && Object.values(spec.mods ?? {}).every((m) => m !== true);
2428
+ function keymapContribution(def) {
2429
+ if (def.bindings.some((b) => isPlainEscape2(b.spec))) {
2430
+ throw new Error(`keymap "${def.id}" binds Escape, which always closes a keymap`);
2431
+ }
2432
+ const open = {
2433
+ id: keymapLeaderId(def.id),
2434
+ label: `Open ${def.label} keys`,
2435
+ scope: "hotkey",
2436
+ defaultBinding: leaderBindings(def),
2437
+ requires: ["keymaps"],
2438
+ enabled: (deps) => deps?.keymaps ? true : ActionDisabledReason.NotApplicable,
2439
+ invoker: {
2440
+ timing: "immediate",
2441
+ run: (deps, params) => {
2442
+ deps.keymaps?.push(def.id, def.label, { bindings: def.bindings, ...params?.hold === true ? { heldBy: KEYMAP_HOLD } : {} });
2443
+ }
2444
+ }
2445
+ };
2446
+ return [
2447
+ {
2448
+ id: def.id,
2449
+ eligibility: { keymap: def.unbound ? { unbound: def.unbound } : true },
2450
+ bindings: [...def.bindings],
2451
+ presentation: { label: def.label },
2452
+ ...def.overlay !== void 0 ? { overlay: def.overlay } : {},
2453
+ ...def.overlayPosition ? { overlayPosition: def.overlayPosition } : {}
2454
+ },
2455
+ {
2456
+ id: `${def.id}.leader`,
2457
+ eligibility: { always: true },
2458
+ actions: [open, ...def.actions ?? []]
2459
+ }
2460
+ ];
2461
+ }
2462
+ var ESCAPE = { shortcut: { key: "Escape", mod: false, alt: false, shift: false }, label: "Close" };
2463
+ var GESTURE_WORDS = {
2464
+ click: "click",
2465
+ doubleClick: "double-click",
2466
+ drag: "drag",
2467
+ longPress: "long-press",
2468
+ contextMenu: "right-click",
2469
+ wheel: "scroll",
2470
+ pinch: "pinch",
2471
+ pointerDown: "press"
2472
+ };
2473
+ var MOD_WORDS = [
2474
+ ["mod", "Mod"],
2475
+ ["ctrl", "Ctrl"],
2476
+ ["meta", "Meta"],
2477
+ ["alt", "Alt"],
2478
+ ["shift", "Shift"]
2479
+ ];
2480
+ function gestureWords(spec) {
2481
+ if (spec.kind === "key-held") {
2482
+ const chip = keySpecShortcut(spec);
2483
+ return chip ? `Hold ${formatShortcut(chip)}` : void 0;
2484
+ }
2485
+ const word = GESTURE_WORDS[spec.kind];
2486
+ if (!word) return void 0;
2487
+ const mods = MOD_WORDS.filter(([m]) => spec.mods?.[m] === true).map(([, w]) => w);
2488
+ const text = [...mods, word].join("-");
2489
+ return text[0].toUpperCase() + text.slice(1);
2490
+ }
2491
+ function describeKeymap(level, actions, overrides = NO_OVERRIDES) {
2492
+ const byId = new Map(actions.map((a) => [a.id, a]));
2493
+ const labelOf = (b) => {
2494
+ const action = byId.get(b.actionId);
2495
+ const params = resolveParams(b.opts?.params);
2496
+ const variant = params && action?.variants?.find((v) => paramsMatch(params, v.params));
2497
+ return variant ? variant.label : action?.label ?? b.actionId;
2498
+ };
2499
+ const rows = [ESCAPE];
2500
+ for (const b of overriddenBindings(level.bindings, level.id, overrides)) {
2501
+ const label = labelOf(b);
2502
+ const shortcut = b.spec.kind === "key" ? keySpecShortcut(b.spec) : void 0;
2503
+ if (shortcut) rows.push({ shortcut, label });
2504
+ else {
2505
+ const gesture = gestureWords(b.spec);
2506
+ if (gesture) rows.push({ gesture, label });
2507
+ }
2508
+ }
2509
+ return { id: level.id, label: level.label, held: level.heldBy !== void 0, rows };
2510
+ }
2511
+ function keymapShortcuts(def, overrides = NO_OVERRIDES) {
2512
+ const leaderChip = overriddenBindings(actionBindings({ id: keymapLeaderId(def.id), defaultBinding: leaderBindings(def) }), null, overrides).map((b) => keySpecShortcut(b.spec)).find((c) => c !== void 0);
2513
+ const out = /* @__PURE__ */ new Map();
2514
+ for (const b of overriddenBindings(def.bindings, def.id, overrides)) {
2515
+ if (b.spec.kind !== "key") continue;
2516
+ const chip = keySpecShortcut(b.spec);
2517
+ if (!chip) continue;
2518
+ const withPath = leaderChip ? { ...chip, leader: [{ label: def.label, shortcut: leaderChip }] } : chip;
2519
+ out.set(b.actionId, [...out.get(b.actionId) ?? [], withPath]);
2520
+ }
2521
+ return out;
2522
+ }
2115
2523
 
2116
2524
  // src/tools/types.ts
2117
2525
  function isTool(entry) {
@@ -2238,7 +2646,10 @@ function eligibleRule(action) {
2238
2646
  return typeof eligible === "function" ? eligible.rule : eligible;
2239
2647
  }
2240
2648
  function findScopedConflicts(scopes) {
2241
- const registry = Array.isArray(scopes.registry) ? scopes.registry : Object.values(scopes.registry);
2649
+ const overrides = scopes.overrides;
2650
+ const asBound = (e) => overrides?.size && e.bindings ? { ...e, bindings: overriddenBindings(e.bindings, e.id, overrides) } : e;
2651
+ const registry = (Array.isArray(scopes.registry) ? scopes.registry : Object.values(scopes.registry)).map(asBound);
2652
+ const declaredAmbient = (scopes.ambient ?? []).map(asBound);
2242
2653
  const actions = scopes.actions ?? [];
2243
2654
  const rules = /* @__PURE__ */ new Map();
2244
2655
  for (const a of actions) {
@@ -2253,7 +2664,9 @@ function findScopedConflicts(scopes) {
2253
2664
  (a.eligible !== void 0 ? gatedActions : ungated).push(actionAsEntry(a));
2254
2665
  }
2255
2666
  const modes = scopes.modes ?? KIT_MODES;
2256
- const ambient = [...scopes.ambient ?? [], ...ungated];
2667
+ const isKeymap = (e) => e.eligibility?.keymap !== void 0;
2668
+ const keymaps = declaredAmbient.filter(isKeymap);
2669
+ const ambient = [...declaredAmbient.filter((e) => !isKeymap(e)), ...ungated];
2257
2670
  const out = [];
2258
2671
  const seen = /* @__PURE__ */ new Set();
2259
2672
  const add = (keyed) => {
@@ -2264,7 +2677,7 @@ function findScopedConflicts(scopes) {
2264
2677
  out.push(conflict);
2265
2678
  }
2266
2679
  };
2267
- for (const tool of [...registry, ...ambient, ...gatedActions, ...hotkeyActions]) {
2680
+ for (const tool of [...registry, ...ambient, ...keymaps, ...gatedActions, ...hotkeyActions]) {
2268
2681
  add(findConflictsKeyed([tool], rules, modes));
2269
2682
  }
2270
2683
  if (ambient.length > 1) add(findConflictsKeyed(ambient, rules, modes));
@@ -2333,6 +2746,20 @@ function normalizeMime(raw) {
2333
2746
  const bare = raw.split(";")[0].trim().toLowerCase();
2334
2747
  return bare || FALLBACK_MIME;
2335
2748
  }
2749
+ var admitted = /* @__PURE__ */ new Map();
2750
+ function admitIngestMime(mime) {
2751
+ const key = normalizeMime(mime);
2752
+ admitted.set(key, (admitted.get(key) ?? 0) + 1);
2753
+ let released = false;
2754
+ return () => {
2755
+ if (released) return;
2756
+ released = true;
2757
+ const n = (admitted.get(key) ?? 1) - 1;
2758
+ if (n > 0) admitted.set(key, n);
2759
+ else admitted.delete(key);
2760
+ };
2761
+ }
2762
+ var keepsString = (mime) => INGEST_STRING_MIMES.has(mime) || admitted.has(mime);
2336
2763
  function itemsFromFiles(files) {
2337
2764
  return files.map((file) => ({ kind: "file", mime: normalizeMime(file.type), file }));
2338
2765
  }
@@ -2346,7 +2773,7 @@ function itemsFromDataTransfer(dt) {
2346
2773
  if (file) files.push({ kind: "file", mime: normalizeMime(file.type), file });
2347
2774
  } else if (item.kind === "string") {
2348
2775
  const mime = normalizeMime(item.type);
2349
- if (INGEST_STRING_MIMES.has(mime)) {
2776
+ if (keepsString(mime)) {
2350
2777
  const slot = strings.length;
2351
2778
  strings.push(null);
2352
2779
  reads.push(
@@ -2372,7 +2799,7 @@ function itemTypesFromDataTransfer(dt) {
2372
2799
  for (const item of Array.from(dt.items ?? [])) {
2373
2800
  const mime = item.type ? normalizeMime(item.type) : "";
2374
2801
  if (item.kind === "file") mimes.push(mime && mime !== "application/x-moz-file" ? mime : UNKNOWN_MIME);
2375
- else if (INGEST_STRING_MIMES.has(mime)) mimes.push(mime);
2802
+ else if (keepsString(mime)) mimes.push(mime);
2376
2803
  }
2377
2804
  if (mimes.length === 0 && Array.from(dt.types ?? []).includes("Files")) mimes.push(UNKNOWN_MIME);
2378
2805
  return mimes.map((mime) => ({ mime }));
@@ -2382,7 +2809,7 @@ function itemsFromClipboardData(cd) {
2382
2809
  for (const file of Array.from(cd.files ?? [])) {
2383
2810
  out.push({ kind: "file", mime: normalizeMime(file.type), file });
2384
2811
  }
2385
- for (const mime of INGEST_STRING_MIMES) {
2812
+ for (const mime of /* @__PURE__ */ new Set([...INGEST_STRING_MIMES, ...admitted.keys()])) {
2386
2813
  const text = cd.getData(mime);
2387
2814
  if (text) out.push({ kind: "string", mime, text });
2388
2815
  }
@@ -2473,6 +2900,7 @@ var sep = (key) => ({ kind: "separator", key });
2473
2900
  function itemOf(ctx, it, key, label, off, access) {
2474
2901
  const deps = ctx.src.depsFor(it.action);
2475
2902
  const point = ctx.at ? { worldX: ctx.at.x, worldY: ctx.at.y } : {};
2903
+ if (it.action.settings) return settingsOf(ctx, it, key, label, off || !evaluateEnabled(it.action, deps, ctx.at).enabled, access);
2476
2904
  return {
2477
2905
  kind: "item",
2478
2906
  key,
@@ -2487,6 +2915,32 @@ function itemOf(ctx, it, key, label, off, access) {
2487
2915
  }
2488
2916
  };
2489
2917
  }
2918
+ function settingsOf(ctx, it, key, label, off, access) {
2919
+ const settings = it.action.settings;
2920
+ const state = off ? null : readActionSettings(it.action, ctx.src.depsFor(it.action));
2921
+ const mixed = new Set(state?.mixed ?? []);
2922
+ const values = (path) => mixed.has(path) ? void 0 : prefValueAtPath(state?.values, path);
2923
+ const onChange = (path, value) => {
2924
+ const params = actionSettingsParams(settings, path, value);
2925
+ if (params) ctx.src.trigger(it.action.id, { ...ctx.params, ...it.params, ...params });
2926
+ };
2927
+ const form = {
2928
+ ...ctx,
2929
+ src: { ...ctx.src, values, onChange, over: settings.schema },
2930
+ root: settings.schema,
2931
+ read: (path, from) => from === "item" ? void 0 : values(path)
2932
+ };
2933
+ const entries = state ? tidy(groupRows(form, settings.schema, "", false)) : [];
2934
+ return {
2935
+ kind: "submenu",
2936
+ key,
2937
+ label,
2938
+ ...it.icon ? { icon: it.icon } : {},
2939
+ ...withAccess(access),
2940
+ ...entries.length === 0 ? { disabled: true } : {},
2941
+ entries
2942
+ };
2943
+ }
2490
2944
  function itemsNamed(ctx, name) {
2491
2945
  const action = ctx.byId.get(name);
2492
2946
  if (action) return actionItems(action);
@@ -2584,9 +3038,23 @@ function colorRows(ctx, leaf, key, path, off) {
2584
3038
  if (!ctx.src.values) return [];
2585
3039
  return [{ kind: "color", key, label: leaf.name, ...withAccess(leaf.access), ...off ? { disabled: true } : {}, value: textAt(ctx, path) }];
2586
3040
  }
2587
- function stringRows(ctx, leaf, key, path) {
2588
- if (!ctx.src.values) return [];
2589
- return [{ kind: "item", key, label: `${leaf.name}: ${textAt(ctx, path) ?? "\u2014"}`, ...withAccess(leaf.access), disabled: true, run: noop }];
3041
+ function stringRows(ctx, leaf, key, path, off) {
3042
+ const { values, onChange } = ctx.src;
3043
+ if (!values) return [];
3044
+ if (leaf.readout || !onChange) {
3045
+ return [{ kind: "item", key, label: `${leaf.name}: ${textAt(ctx, path) ?? "\u2014"}`, ...withAccess(leaf.access), disabled: true, run: noop }];
3046
+ }
3047
+ const stored = values(path);
3048
+ return [{
3049
+ kind: "text",
3050
+ key,
3051
+ label: leaf.name,
3052
+ ...withAccess(leaf.access),
3053
+ ...leaf.icon ? { icon: leaf.icon } : {},
3054
+ ...off ? { disabled: true } : {},
3055
+ value: typeof stored === "string" ? stored : void 0,
3056
+ set: (text) => onChange(path, text)
3057
+ }];
2590
3058
  }
2591
3059
  function leafRows(ctx, leaf, key, path, off) {
2592
3060
  switch (leaf.kind) {
@@ -2605,7 +3073,7 @@ function leafRows(ctx, leaf, key, path, off) {
2605
3073
  case "color":
2606
3074
  return colorRows(ctx, leaf, key, path, off);
2607
3075
  case "string":
2608
- return stringRows(ctx, leaf, key, path);
3076
+ return stringRows(ctx, leaf, key, path, off);
2609
3077
  case "separator":
2610
3078
  return [sep(key)];
2611
3079
  case "label":
@@ -2703,6 +3171,7 @@ function createMenuHost(src) {
2703
3171
  client: req.client,
2704
3172
  world: req.world,
2705
3173
  ...req.under ? { under: req.under } : {},
3174
+ ...req.above ? { above: true } : {},
2706
3175
  source: req.source ?? "pointer"
2707
3176
  };
2708
3177
  emit();
@@ -2720,6 +3189,6 @@ function createMenuHost(src) {
2720
3189
  };
2721
3190
  }
2722
3191
 
2723
- export { ALWAYS, ActionDisabledReason, COARSE_TARGET_SCALE, DEFAULT_ALLOWED_CAPABILITIES, DEFAULT_DEVICE_PROFILE, DEV2 as DEV, DepNode, INGEST_STRING_MIMES, LONG_PRESS_HAPTIC_MS, NEVER, PREDICATE_TARGET, ScopeNode, TOOL_OFFHAND_ID, actionBindings, actionCursor, actionItemTitle, actionItems, actionShortcuts, addCarrySurface, assembleEntries, buildDepsFromRequires, buildRouteRegistry, buildRuleCtx, buildToolOffhandBindings, clientToCanvas, clientToCanvasRect, createDepRegistry, createDispatcher, createLongPressStore, createMenuHost, depNodeOf, describeRule, dlog, dwarn, evaluate, evaluateActive, evaluateEnabled, findConflicts, gestureIdFor, heldKeySpec, historyKey, isDebugEnabled, isTool, itemTypesFromDataTransfer, itemsFromClipboardData, itemsFromDataTransfer, itemsFromFiles, keySpecShortcut, keysHeld, liveScope, makeToolOffhandAction, matchBest, matchSorted, matchSortedWithBarred, matchesKeyBinding, mergeMenuDefs, multiTouchGestureId, offhandKeyFor, openPointerSession, pickMenu, pointerGestureId, publishLiveDispatch, pushOwner, recordModeSwitch, reportRouteConflicts, resolveDeviceProfile, resolveMenu, resolveParams, resolveSchemaMenu, roleReader, routesForSpec, ruleCanHoldIn, rulesExclusive, scopeBindings, startCarry, targetConsultsAffordance, tuneAction, tunedParams, validateActionDefaultBinding, validateActionId };
2724
- //# sourceMappingURL=chunk-QBQQIFPI.js.map
2725
- //# sourceMappingURL=chunk-QBQQIFPI.js.map
3192
+ export { ALWAYS, ActionDisabledReason, COARSE_TARGET_SCALE, DEFAULT_ALLOWED_CAPABILITIES, DEFAULT_DEVICE_PROFILE, DepNode, INGEST_STRING_MIMES, KEYMAP_HOLD, LONG_PRESS_HAPTIC_MS, NEVER, NO_OVERRIDES, PREDICATE_TARGET, ScopeNode, TOOL_OFFHAND_ID, actionBindings, actionCursor, actionItemTitle, actionItems, actionSettingsParams, actionShortcuts, addCarrySurface, admitIngestMime, anyBinding, assembleEntries, bindingId, buildDepsFromRequires, buildRouteRegistry, buildRuleCtx, buildToolOffhandBindings, carryGestureId, clientToCanvas, clientToCanvasRect, createDepRegistry, createDispatchTrace, createDispatcher, createKeymapStack, createLongPressStore, createMenuHost, createTraceRing, depNodeOf, describeKeymap, describeRule, dlog, dwarn, evaluate, evaluateActive, evaluateEnabled, findConflicts, heldKeySpec, historyKey, isDebugEnabled, isTool, itemTypesFromDataTransfer, itemsFromClipboardData, itemsFromDataTransfer, itemsFromFiles, keySpecShortcut, keymapContribution, keymapLeaderBindingId, keymapLeaderId, keymapShortcuts, keysHeld, liveScope, makeToolOffhandAction, matchBest, matchSorted, matchSortedWithBarred, matchesKeyBinding, mergeMenuDefs, multiTouchGestureId, offhandKeyFor, openPointerSession, overriddenBindings, overrideActionBindings, pickMenu, pointerGestureId, pushOwner, readActionSettings, reportRouteConflicts, resolveBindingOverrides, resolveDeviceProfile, resolveMenu, resolveParams, resolveSchemaMenu, roleReader, routesForSpec, ruleCanHoldIn, rulesExclusive, scopeBindings, startCarry, targetConsultsAffordance, tuneAction, tunedParams, validateActionDefaultBinding, validateActionId };
3193
+ //# sourceMappingURL=chunk-ARDHI47M.js.map
3194
+ //# sourceMappingURL=chunk-ARDHI47M.js.map