@weasel-js/routing 1.11.1 → 1.13.0-rc.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/{chunk-KLBH7VFF.js → chunk-CRF3ROBB.js} +476 -131
- package/dist/chunk-CRF3ROBB.js.map +1 -0
- package/dist/{index-Cb7ehEks.d.ts → index-HWqV4VxU.d.ts} +286 -15
- package/dist/index.d.ts +1 -1
- package/dist/index.js +200 -34
- package/dist/index.js.map +1 -1
- package/dist/{internal-Dcyz_cJv.d.ts → internal-Bs9fhIXH.d.ts} +1 -1
- package/dist/internal.d.ts +2 -2
- package/dist/react.d.ts +13 -5
- package/dist/react.js +145 -46
- package/dist/react.js.map +1 -1
- package/package.json +13 -13
- package/dist/chunk-KLBH7VFF.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { actionItems, actionItemTitle, ActionDisabledReason } from './chunk-
|
|
2
|
-
export { ALWAYS, ActionDisabledReason, COARSE_TARGET_SCALE, DEFAULT_ALLOWED_CAPABILITIES, DEFAULT_DEVICE_PROFILE, GESTURE_DESCRIPTORS, INGEST_STRING_MIMES, LONG_PRESS_MS, NEVER, PREDICATE_TARGET, RESERVED_ID_NAMES, RESERVED_ID_PREFIXES, ROUTE_FIELD_DEFINITIONS, ROUTE_TERMS, TOOL_OFFHAND_ID, actionBindings, actionCursor, actionItemTitle, actionItems, actionSettingsParams, actionShortcuts, activatesFocusedControl, admitIngestMime, assembleEntries, buildDepsFromRequires, buildRouteRegistry, buildRuleCtx, buildToolOffhandBindings, canonicalModifiers, clientToCanvas, clientToCanvasRect, collapseShiftPairs, createDepRegistry, createDispatchTrace, createDispatcher, createLongPressStore, createMenuHost, createTraceRing, describeRoute, describeRouteParts, describeRule, dlog, dwarn, evaluate, evaluateActive, evaluateEnabled, findConflicts, focusedControlOwnsKey, formatPhaseAtom, formatRoute, getGestureDescriptor, heldKeySpec, historyKey, isDebugEnabled, isEditableTarget, isKnownGestureName, isTool, itemTypesFromDataTransfer, itemsFromClipboardData, itemsFromDataTransfer, itemsFromFiles, keySpecShortcut, keysHeld, liveScope, makeToolOffhandAction, matchBest, matchKey, matchModifiers, matchPhase, matchSorted, matchSortedWithBarred, matchSpec, matchTarget, matchesKeyBinding, mergeMenuDefs, multiTouchGestureId, offhandKeyFor, openPointerSession, parseRoute, pickMenu, pointerGestureId, readActionSettings, reportRouteConflicts, resolveDeviceProfile, resolveMenu, resolveParams, resolveSchemaMenu, roleReader, routeGestureForSpecKind, routesForSpec, ruleCanHoldIn, rulesExclusive, scopeBindings, specKindForRouteGesture, specificity, startCarry, targetConsultsAffordance, tuneAction, validateActionDefaultBinding, validateActionId } from './chunk-
|
|
1
|
+
import { actionItems, actionItemTitle, ActionDisabledReason } from './chunk-CRF3ROBB.js';
|
|
2
|
+
export { ALWAYS, ActionDisabledReason, COARSE_TARGET_SCALE, DEFAULT_ALLOWED_CAPABILITIES, DEFAULT_DEVICE_PROFILE, GESTURE_DESCRIPTORS, INGEST_STRING_MIMES, KEYMAP_HOLD, LONG_PRESS_MS, NEVER, PREDICATE_TARGET, RESERVED_ID_NAMES, RESERVED_ID_PREFIXES, ROUTE_FIELD_DEFINITIONS, ROUTE_TERMS, TOOL_OFFHAND_ID, actionBindings, actionCursor, actionItemTitle, actionItems, actionSettingsParams, actionShortcuts, activatesFocusedControl, admitIngestMime, assembleEntries, bindingId, buildDepsFromRequires, buildRouteRegistry, buildRuleCtx, buildToolOffhandBindings, canonicalModifiers, clientToCanvas, clientToCanvasRect, collapseShiftPairs, createDepRegistry, createDispatchTrace, createDispatcher, createKeymapStack, createLongPressStore, createMenuHost, createTraceRing, describeKeymap, describeRoute, describeRouteParts, describeRule, dlog, dwarn, evaluate, evaluateActive, evaluateEnabled, findConflicts, focusedControlOwnsKey, formatPhaseAtom, formatRoute, getGestureDescriptor, heldKeySpec, historyKey, isDebugEnabled, isEditableTarget, isKnownGestureName, isTool, itemTypesFromDataTransfer, itemsFromClipboardData, itemsFromDataTransfer, itemsFromFiles, keySpecShortcut, keymapContribution, keymapLeaderBindingId, keymapLeaderId, keymapShortcuts, keysHeld, liveScope, makeToolOffhandAction, matchBest, matchKey, matchModifiers, matchPhase, matchSorted, matchSortedWithBarred, matchSpec, matchTarget, matchesKeyBinding, mergeMenuDefs, modifierStateOf, multiTouchGestureId, offhandKeyFor, openPointerSession, overriddenBindings, parseRoute, pickMenu, pointerGestureId, readActionSettings, reportRouteConflicts, resolveBindingOverrides, resolveDeviceProfile, resolveMenu, resolveParams, resolveSchemaMenu, roleReader, routeGestureForSpecKind, routesForSpec, ruleCanHoldIn, rulesExclusive, scopeBindings, specKindForRouteGesture, specificity, startCarry, targetConsultsAffordance, tuneAction, validateActionDefaultBinding, validateActionId } from './chunk-CRF3ROBB.js';
|
|
3
3
|
import { hasTag, matchQuery } from '@weasel-js/registry';
|
|
4
|
-
import { bodyPredicate, hitPredicate, RESERVED_ID_PREFIXES, RESERVED_ID_NAMES } from '@weasel-js/gestures';
|
|
4
|
+
import { bodyPredicate, hitPredicate, key, isApplePlatform, createPointerRecognizer, RESERVED_ID_PREFIXES, RESERVED_ID_NAMES, DOUBLE_CLICK_MAX_MS } from '@weasel-js/gestures';
|
|
5
5
|
export { CONTROL_SELECTOR, DRAG_THRESHOLD_PX, isInControlWithin, pastDragThreshold } from '@weasel-js/gestures';
|
|
6
6
|
import { modeLabel } from '@weasel-js/modes';
|
|
7
7
|
|
|
@@ -93,28 +93,8 @@ var VERB = {
|
|
|
93
93
|
commit: "Commit",
|
|
94
94
|
cancel: "Cancel"
|
|
95
95
|
};
|
|
96
|
-
var MODIFIERS = {
|
|
97
|
-
meta: "meta",
|
|
98
|
-
cmd: "meta",
|
|
99
|
-
command: "meta",
|
|
100
|
-
ctrl: "ctrl",
|
|
101
|
-
control: "ctrl",
|
|
102
|
-
alt: "alt",
|
|
103
|
-
option: "alt",
|
|
104
|
-
shift: "shift",
|
|
105
|
-
mod: "mod"
|
|
106
|
-
};
|
|
107
96
|
function modeShortcutSpec(shortcut) {
|
|
108
|
-
|
|
109
|
-
const key = parts.pop();
|
|
110
|
-
if (!key) throw new Error(`mode shortcut "${shortcut}" names no key`);
|
|
111
|
-
const mods = {};
|
|
112
|
-
for (const part of parts) {
|
|
113
|
-
const mod = MODIFIERS[part.toLowerCase()];
|
|
114
|
-
if (!mod) throw new Error(`mode shortcut "${shortcut}": unknown modifier "${part}"`);
|
|
115
|
-
mods[mod] = true;
|
|
116
|
-
}
|
|
117
|
-
return Object.keys(mods).length > 0 ? { kind: "key", key, mods } : { kind: "key", key };
|
|
97
|
+
return key(shortcut);
|
|
118
98
|
}
|
|
119
99
|
function modeShortcuts(registry, handlers) {
|
|
120
100
|
const actions = [];
|
|
@@ -156,7 +136,7 @@ function shortcutAction(mode, role, shortcut, eligible, live, run, yields) {
|
|
|
156
136
|
scope: "hotkey",
|
|
157
137
|
defaultBinding: [{
|
|
158
138
|
spec: { ...modeShortcutSpec(shortcut), phase: [{ channel: "*", phase: "initial" }] },
|
|
159
|
-
opts: { yields }
|
|
139
|
+
opts: { id: `mode.${mode.id}.${role}.key`, yields }
|
|
160
140
|
}],
|
|
161
141
|
eligible,
|
|
162
142
|
// `eligible` is the gate the dispatcher and palettes read, but a canvas
|
|
@@ -166,6 +146,192 @@ function shortcutAction(mode, role, shortcut, eligible, live, run, yields) {
|
|
|
166
146
|
invoker: { timing: "immediate", run: () => run() }
|
|
167
147
|
};
|
|
168
148
|
}
|
|
149
|
+
|
|
150
|
+
// src/keymaps/captureSpec.ts
|
|
151
|
+
function modSpecOf(e, apple) {
|
|
152
|
+
const mods = {};
|
|
153
|
+
if (apple ? e.metaKey : e.ctrlKey) mods.mod = true;
|
|
154
|
+
if (e.shiftKey) mods.shift = true;
|
|
155
|
+
if (e.altKey) mods.alt = true;
|
|
156
|
+
if (apple ? e.ctrlKey : e.metaKey) mods[apple ? "ctrl" : "meta"] = true;
|
|
157
|
+
return Object.keys(mods).length > 0 ? mods : void 0;
|
|
158
|
+
}
|
|
159
|
+
function specOf(kind, e, apple) {
|
|
160
|
+
const mods = modSpecOf(e, apple);
|
|
161
|
+
return mods ? { kind, mods } : { kind };
|
|
162
|
+
}
|
|
163
|
+
var take = (e) => {
|
|
164
|
+
e.preventDefault();
|
|
165
|
+
e.stopPropagation();
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
// src/keymaps/capturePointer.ts
|
|
169
|
+
var TRAILING = ["click", "auxclick", "dblclick", "contextmenu"];
|
|
170
|
+
var sampleOf = (e) => ({
|
|
171
|
+
pointerId: e.pointerId,
|
|
172
|
+
clientX: e.clientX,
|
|
173
|
+
clientY: e.clientY,
|
|
174
|
+
target: e.target,
|
|
175
|
+
timeStamp: e.timeStamp,
|
|
176
|
+
altKey: e.altKey,
|
|
177
|
+
ctrlKey: e.ctrlKey,
|
|
178
|
+
metaKey: e.metaKey,
|
|
179
|
+
shiftKey: e.shiftKey
|
|
180
|
+
});
|
|
181
|
+
var browserClock = {
|
|
182
|
+
now: () => performance.now(),
|
|
183
|
+
setTimer: (fn, ms) => setTimeout(fn, ms),
|
|
184
|
+
clearTimer: (t) => {
|
|
185
|
+
clearTimeout(t);
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
function capturePointer(target, kinds, apple, thresholds, listen, done) {
|
|
189
|
+
let pendingClick = null;
|
|
190
|
+
let dragMods = null;
|
|
191
|
+
const recognized = (ev) => {
|
|
192
|
+
switch (ev.kind) {
|
|
193
|
+
case "pointerdown":
|
|
194
|
+
if (!("stage" in ev && ev.stage === "press")) dragMods = ev;
|
|
195
|
+
return "unhandled";
|
|
196
|
+
case "click": {
|
|
197
|
+
if (!kinds.has("click")) return "unhandled";
|
|
198
|
+
const spec = specOf("click", ev, apple);
|
|
199
|
+
if (!kinds.has("doubleClick")) {
|
|
200
|
+
done(spec);
|
|
201
|
+
return "handled";
|
|
202
|
+
}
|
|
203
|
+
if (pendingClick) clearTimeout(pendingClick);
|
|
204
|
+
pendingClick = setTimeout(() => {
|
|
205
|
+
done(spec);
|
|
206
|
+
}, thresholds.doubleClickMs ?? DOUBLE_CLICK_MAX_MS);
|
|
207
|
+
return "handled";
|
|
208
|
+
}
|
|
209
|
+
case "doubleclick":
|
|
210
|
+
case "contextmenu": {
|
|
211
|
+
const kind = ev.kind === "doubleclick" ? "doubleClick" : "contextMenu";
|
|
212
|
+
if (!kinds.has(kind)) return "unhandled";
|
|
213
|
+
done(specOf(kind, ev, apple));
|
|
214
|
+
return "handled";
|
|
215
|
+
}
|
|
216
|
+
default:
|
|
217
|
+
return "unhandled";
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
const recognizer = createPointerRecognizer({
|
|
221
|
+
clock: browserClock,
|
|
222
|
+
dragPx: () => thresholds.dragPx,
|
|
223
|
+
doubleClickMs: () => thresholds.doubleClickMs,
|
|
224
|
+
doubleClickPx: () => thresholds.doubleClickPx,
|
|
225
|
+
sink: { dispatch: recognized, multiTouchInFlight: () => false }
|
|
226
|
+
});
|
|
227
|
+
const held = (e) => {
|
|
228
|
+
const p = e;
|
|
229
|
+
if (recognizer.positionOf(p.pointerId) === void 0) return null;
|
|
230
|
+
take(p);
|
|
231
|
+
return p;
|
|
232
|
+
};
|
|
233
|
+
listen("pointerdown", (e) => {
|
|
234
|
+
const p = e;
|
|
235
|
+
take(p);
|
|
236
|
+
if ((p.button ?? 0) !== 0) return;
|
|
237
|
+
if (target instanceof Element) {
|
|
238
|
+
try {
|
|
239
|
+
target.setPointerCapture(p.pointerId);
|
|
240
|
+
} catch {
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
recognizer.press({ ...sampleOf(p), x: p.clientX, y: p.clientY, pointerType: p.pointerType });
|
|
244
|
+
});
|
|
245
|
+
listen("pointermove", (e) => {
|
|
246
|
+
const p = held(e);
|
|
247
|
+
if (p) recognizer.move(sampleOf(p));
|
|
248
|
+
});
|
|
249
|
+
listen("pointerup", (e) => {
|
|
250
|
+
const p = held(e);
|
|
251
|
+
if (!p) return;
|
|
252
|
+
const drag = dragMods;
|
|
253
|
+
dragMods = null;
|
|
254
|
+
recognizer.release(sampleOf(p));
|
|
255
|
+
if (drag && kinds.has("drag")) done(specOf("drag", drag, apple));
|
|
256
|
+
});
|
|
257
|
+
listen("pointercancel", (e) => {
|
|
258
|
+
const p = held(e);
|
|
259
|
+
if (!p) return;
|
|
260
|
+
dragMods = null;
|
|
261
|
+
recognizer.cancel(p.pointerId);
|
|
262
|
+
});
|
|
263
|
+
for (const type of TRAILING) {
|
|
264
|
+
listen(type, (e) => {
|
|
265
|
+
take(e);
|
|
266
|
+
if (type === "contextmenu" && kinds.has("contextMenu")) done(specOf("contextMenu", e, apple));
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
return () => {
|
|
270
|
+
if (pendingClick) clearTimeout(pendingClick);
|
|
271
|
+
recognizer.reset();
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// src/keymaps/captureGesture.ts
|
|
276
|
+
var DEFAULT_KINDS = ["key", "click", "doubleClick", "drag", "contextMenu"];
|
|
277
|
+
var POINTER_KINDS = ["click", "doubleClick", "drag", "contextMenu"];
|
|
278
|
+
var MODIFIER_KEYS = /* @__PURE__ */ new Set(["Shift", "Control", "Alt", "Meta", "AltGraph", "CapsLock"]);
|
|
279
|
+
function captureGesture(target, opts = {}) {
|
|
280
|
+
const apple = opts.apple ?? isApplePlatform();
|
|
281
|
+
const kinds = new Set(opts.kinds ?? DEFAULT_KINDS);
|
|
282
|
+
const keyKind = kinds.has("key") ? "key" : kinds.has("key-held") ? "key-held" : null;
|
|
283
|
+
const pointer = POINTER_KINDS.some((k) => kinds.has(k));
|
|
284
|
+
return new Promise((resolve) => {
|
|
285
|
+
if (opts.signal?.aborted) {
|
|
286
|
+
resolve(null);
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
let settled = false;
|
|
290
|
+
let stopPointer = () => {
|
|
291
|
+
};
|
|
292
|
+
const listeners = [];
|
|
293
|
+
const listen = (type, fn) => {
|
|
294
|
+
listeners.push([type, fn]);
|
|
295
|
+
target.addEventListener(type, fn, true);
|
|
296
|
+
};
|
|
297
|
+
const done = (spec) => {
|
|
298
|
+
if (settled) return;
|
|
299
|
+
settled = true;
|
|
300
|
+
stopPointer();
|
|
301
|
+
opts.signal?.removeEventListener("abort", onAbort);
|
|
302
|
+
for (const [type, fn] of listeners) target.removeEventListener(type, fn, true);
|
|
303
|
+
if (pointer) {
|
|
304
|
+
for (const type of TRAILING) target.addEventListener(type, take, true);
|
|
305
|
+
setTimeout(() => {
|
|
306
|
+
for (const type of TRAILING) target.removeEventListener(type, take, true);
|
|
307
|
+
}, 0);
|
|
308
|
+
}
|
|
309
|
+
resolve(spec);
|
|
310
|
+
};
|
|
311
|
+
const onAbort = () => {
|
|
312
|
+
done(null);
|
|
313
|
+
};
|
|
314
|
+
opts.signal?.addEventListener("abort", onAbort);
|
|
315
|
+
listen("keydown", (e) => {
|
|
316
|
+
const k = e;
|
|
317
|
+
if (MODIFIER_KEYS.has(k.key)) return;
|
|
318
|
+
const escape = k.key === "Escape" && !k.metaKey && !k.ctrlKey && !k.altKey && !k.shiftKey;
|
|
319
|
+
if (!escape && !keyKind) return;
|
|
320
|
+
take(k);
|
|
321
|
+
done(escape || !keyKind ? null : { ...specOf(keyKind, k, apple), key: k.key });
|
|
322
|
+
});
|
|
323
|
+
if (pointer) stopPointer = capturePointer(target, kinds, apple, opts, listen, done);
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// src/keymaps/captureKey.ts
|
|
328
|
+
function captureKey(target, opts = {}) {
|
|
329
|
+
return captureGesture(target, {
|
|
330
|
+
kinds: [opts.held ? "key-held" : "key"],
|
|
331
|
+
...opts.signal ? { signal: opts.signal } : {},
|
|
332
|
+
...opts.apple !== void 0 ? { apple: opts.apple } : {}
|
|
333
|
+
});
|
|
334
|
+
}
|
|
169
335
|
function validateId(id, kind) {
|
|
170
336
|
if (id.length === 0) {
|
|
171
337
|
throw new Error(`weasel: ${kind} id may not be empty`);
|
|
@@ -239,7 +405,7 @@ function toolSetHas(set, id) {
|
|
|
239
405
|
}
|
|
240
406
|
|
|
241
407
|
// src/interactions/browserReservedKeys.ts
|
|
242
|
-
var chord = (keys, mods, use) => [...keys].map((
|
|
408
|
+
var chord = (keys, mods, use) => [...keys].map((key2) => ({ key: key2, ...mods, use }));
|
|
243
409
|
var BROWSER_RESERVED_CHORDS = [
|
|
244
410
|
...chord("nqtwlrpmh", { mod: true }, "new window, quit, new or close tab, address bar, reload, print, minimize, hide"),
|
|
245
411
|
...chord("ntwrbo", { mod: true, shift: true }, "private window, reopen or close tab, hard reload, bookmarks, bookmark manager"),
|
|
@@ -265,20 +431,20 @@ function browserReservedChord(spec) {
|
|
|
265
431
|
function scratchKey(name) {
|
|
266
432
|
return { name };
|
|
267
433
|
}
|
|
268
|
-
function getScratch(store,
|
|
269
|
-
return store[
|
|
434
|
+
function getScratch(store, key2) {
|
|
435
|
+
return store[key2.name];
|
|
270
436
|
}
|
|
271
|
-
function setScratch(store,
|
|
272
|
-
store[
|
|
437
|
+
function setScratch(store, key2, value) {
|
|
438
|
+
store[key2.name] = value;
|
|
273
439
|
}
|
|
274
|
-
function deleteScratch(store,
|
|
275
|
-
if (Object.prototype.hasOwnProperty.call(store,
|
|
276
|
-
delete store[
|
|
440
|
+
function deleteScratch(store, key2) {
|
|
441
|
+
if (Object.prototype.hasOwnProperty.call(store, key2.name)) {
|
|
442
|
+
delete store[key2.name];
|
|
277
443
|
return true;
|
|
278
444
|
}
|
|
279
445
|
return false;
|
|
280
446
|
}
|
|
281
447
|
|
|
282
|
-
export { BROWSER_RESERVED_CHORDS, actionsTagged, browserReservedChord, defineTool, deleteScratch, getScratch, isAnchor, isAnchorOrControl, isBalanceGrip, isBody, isControlHandle, isCornerWidget, isEmpty, isPathEditPart, isResizeHandle, isRotateHandle, isSegment, isSelectedBody, isToolSet, isUnselectedBody, matchActionItem, mergeContributions, modeShortcutSpec, modeShortcuts, overlaysOf, scratchKey, setScratch, taggedActionItems, toolIdsOf, toolSet, toolSetHas, withoutTools };
|
|
448
|
+
export { BROWSER_RESERVED_CHORDS, actionsTagged, browserReservedChord, captureGesture, captureKey, defineTool, deleteScratch, getScratch, isAnchor, isAnchorOrControl, isBalanceGrip, isBody, isControlHandle, isCornerWidget, isEmpty, isPathEditPart, isResizeHandle, isRotateHandle, isSegment, isSelectedBody, isToolSet, isUnselectedBody, matchActionItem, mergeContributions, modeShortcutSpec, modeShortcuts, overlaysOf, scratchKey, setScratch, taggedActionItems, toolIdsOf, toolSet, toolSetHas, withoutTools };
|
|
283
449
|
//# sourceMappingURL=index.js.map
|
|
284
450
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/interactions/actions/actionTags.ts","../src/interactions/actions/overlay.ts","../src/interactions/dispatcher/predicates.ts","../src/contributions/merge.ts","../src/contributions/modeShortcuts.ts","../src/tools/defineTool.ts","../src/tools/toolSet.ts","../src/interactions/browserReservedKeys.ts","../src/interactions/scratchKey.ts"],"names":["RESERVED_ID_PREFIXES","RESERVED_ID_NAMES"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Finding actions by tag: gathering the ones that carry it, and a person's\n * search matching it as it matches a label.\n */\nimport { hasTag, matchQuery, type QueryMatch } from '@weasel-js/registry';\nimport type { Action } from './action';\nimport { actionItems, actionItemTitle, type ActionItem } from './actionItems';\n\n/** The actions carrying `tag`, themselves or on any variant, in\n * the order given. Drags included, which have no entries to show. */\nexport function actionsTagged(actions: readonly Action[], tag: string): Action[] {\n return actions.filter((a) => hasTag(a.tags, tag) || (a.variants?.some((v) => hasTag(v.tags, tag)) ?? false));\n}\n\n/** The entries carrying `tag`: what a bar or a menu built from\n * a tag shows. A variant that does not carry it is left out. */\nexport function taggedActionItems(actions: readonly Action[], tag: string): ActionItem[] {\n return actionsTagged(actions, tag).flatMap(actionItems).filter((i) => hasTag(i.tags, tag));\n}\n\n/** Whether `item` answers a search for `query`, by its palette title or\n * by a tag, and which. */\nexport function matchActionItem(item: ActionItem, query: string): QueryMatch | null {\n return matchQuery(query, { text: [actionItemTitle(item)], tags: item.tags });\n}\n","/** The chrome an in-flight gesture paints beside the scene. */\nimport type { OngoingHandle } from './invoker';\n\n/**\n * What a `polyline` overlay is, in a word — the narrowest thing an action can\n * say about how its run should look without naming a paint.\n *\n * The named roles are the kit's; a painter maps each to a style and falls back\n * to plain chrome for one it does not know, so a package outside core can coin\n * its own and still be drawn.\n */\nexport type OverlayRole =\n /** Generic in-flight chrome — the marquee/lasso paint. */\n | 'chrome'\n /** A cut the gesture would make. */\n | 'cut'\n /** An edge the gesture would author between two points. */\n | 'connector'\n /** The stretch of a path a soft-selection drag reaches. */\n | 'falloff'\n /** What a lock holds a dragged point to — a line, a circle. */\n | 'lock'\n /** Where a dragged item would land: a reorder's insertion bar. */\n | 'insert'\n /** Where a dragged item is over and cannot land. */\n | 'refused'\n | (string & {});\n\n/**\n * What an in-flight gesture proposes to paint *beside* the scene, returned by\n * `OngoingHandle.overlay()` — a marquee rect, a lasso trail, the outline of a\n * shape being dragged out, the line a slice would cut along.\n *\n * Every variant is world geometry and nothing else — no `DrawCommand`, no\n * color, no coordinate space to choose — so a surface rendering the same\n * gesture some other way can still read it. The painter owns every style\n * decision.\n */\nexport type OngoingOverlay =\n | {\n kind: 'marquee';\n start: { x: number; y: number };\n current: { x: number; y: number };\n shiftHeld: boolean;\n }\n | {\n kind: 'lasso';\n vertices: ReadonlyArray<{ x: number; y: number }>;\n current: { x: number; y: number };\n shiftHeld: boolean;\n }\n | {\n /**\n * An open run of world points the gesture is proposing — a cut line, a\n * routed connector. `role` is the whole of what an action says about\n * appearance.\n */\n kind: 'polyline';\n /** At least two points. Anything shorter is dropped in resolution. */\n points: ReadonlyArray<{ x: number; y: number }>;\n /** What the run means. Omitted reads as {@link OverlayRole} `'chrome'`. */\n role?: OverlayRole;\n }\n | {\n /**\n * A round brush dragged through world points: the area it has swept so\n * far, and its footprint at the last point. The radius is in screen\n * pixels, so the footprint keeps its size at every zoom.\n */\n kind: 'brush';\n /** The brush's path so far, at least one point; the last is where it is now. */\n points: ReadonlyArray<{ x: number; y: number }>;\n radiusPx: number;\n }\n | {\n /**\n * Live insert-drag preview. Pre-commit there is no scene node to ghost\n * via `previewIds()`/`previewPose()`, so insert paints its preview\n * through the overlay instead.\n *\n * `bounds` is the AABB of the current drag (start/current normalized).\n * `extras` is the per-kind extras the action already collected; the\n * overlay renderer narrows on `shape` and casts the field shape it\n * expects.\n */\n kind: 'insertPreview';\n /** Which preview the dispatcher's overlay draws. The kit's own shape\n * kinds are the ones it knows how to render; a consumer-defined kind\n * is legal and simply gets no live preview. */\n shape: string;\n bounds: { x: number; y: number; width: number; height: number };\n extras: unknown;\n /** World-space point to paint a small \"anchor\" dot at, marking the\n * click point — for radial shapes (polygon/star), where no vertex\n * sits on it, and for any shape in center mode. */\n anchorPoint?: { x: number; y: number };\n /** World affines the shape will also be drawn under once it lands, by\n * the container it is drawn into: the preview is painted under each. */\n copies?: readonly (readonly [number, number, number, number, number, number])[];\n };\n\n/** A handle's overlays as a list: empty when it has none. */\nexport function overlaysOf(handle: OngoingHandle): readonly OngoingOverlay[] {\n const ov = handle.overlay?.();\n if (!ov) return [];\n return isOverlayList(ov) ? ov : [ov];\n}\n\nfunction isOverlayList(ov: OngoingOverlay | readonly OngoingOverlay[]): ov is readonly OngoingOverlay[] {\n return Array.isArray(ov);\n}\n","/**\n * Named predicates for `defaultBinding.target.kindOf`. Each matches the\n * `TargetPredicate` shape, declaring whether it reads the hit,\n * so they drop into action descriptors without a wrapper:\n *\n * target: { kindOf: isAnchor }\n *\n * Single source of truth for \"what does this affordance kind mean\" — adding\n * a new predicate here is what enables every action that needs the same\n * shape to read it. Drift prevention.\n */\nimport { bodyPredicate, hitPredicate, type TargetPredicate } from '@weasel-js/gestures';\n\n// ─── Body-class predicates (read the second arg) ───────────────────────\n\n/** A predicate that resolves from `bodyTarget` alone. */\nexport type BodyPredicate = TargetPredicate & { readsAffordance: false };\n\n/** Matches any body hit — selected or unselected node body. */\nexport const isBody: BodyPredicate = bodyPredicate((bodyTarget) =>\n bodyTarget === 'selected-body' || bodyTarget === 'unselected-body');\n\n/** Body hit specifically already in the selection. */\nexport const isSelectedBody: BodyPredicate = bodyPredicate((bodyTarget) =>\n bodyTarget === 'selected-body');\n\n/** Body hit specifically NOT in the selection. */\nexport const isUnselectedBody: BodyPredicate = bodyPredicate((bodyTarget) =>\n bodyTarget === 'unselected-body');\n\n/** Empty-canvas hit — no node beneath cursor. */\nexport const isEmpty: BodyPredicate = bodyPredicate((bodyTarget) =>\n bodyTarget === 'empty');\n\n// ─── Affordance-kind predicates (read the first arg) ───────────────────\n\nfunction kindOf(target: unknown): string | undefined {\n if (typeof target !== 'object' || target === null) return undefined;\n const k = (target as { kind?: unknown }).kind;\n return typeof k === 'string' ? k : undefined;\n}\n\n/** Any resize handle: a corner (`handle:top-left`, …) or an edge (`handle:top`, …). */\nexport const isResizeHandle = hitPredicate((target) => {\n const k = kindOf(target);\n return k !== undefined && k.startsWith('handle:');\n});\n\n/** The rotate-around-center handle above the bounding box. */\nexport const isRotateHandle = hitPredicate((target) =>\n kindOf(target) === 'rotate-handle');\n\n/** Any path anchor (the on-curve dot). */\nexport const isAnchor = hitPredicate((target) => {\n const k = kindOf(target);\n return k !== undefined && /^anchor:\\d+$/.test(k);\n});\n\n/** Either control handle (controlIn or controlOut). */\nexport const isControlHandle = hitPredicate((target) => {\n const k = kindOf(target);\n return k !== undefined && /^(controlIn|controlOut):\\d+$/.test(k);\n});\n\n/** A corner-shape widget, set inside a corner anchor of the edited path. */\nexport const isCornerWidget = hitPredicate((target) => {\n const k = kindOf(target);\n return k !== undefined && /^corner:\\d+$/.test(k);\n});\n\n/** Any of the three anchor-editing affordances (anchor + both controls). */\nexport const isAnchorOrControl = hitPredicate((target) =>\n isAnchor(target) || isControlHandle(target));\n\n/** The outline of the path being edited, between its anchors. */\nexport const isSegment = hitPredicate((target) => kindOf(target) === 'segment');\n\n/** The grip midway along a curved segment's balance line, `balance:N`, where\n * N is the flat index of the anchor the segment starts at. */\nexport const isBalanceGrip = hitPredicate((target) => {\n const k = kindOf(target);\n return k !== undefined && /^balance:\\d+$/.test(k);\n});\n\n/** Anything path edit puts on the path: an anchor, a control, a segment, a\n * segment's balance grip, or a corner widget. */\nexport const isPathEditPart = hitPredicate((target) =>\n isAnchorOrControl(target) || isSegment(target) || isBalanceGrip(target) || isCornerWidget(target));\n","import type { Contribution } from './types';\n\n/**\n * Concatenate contribution bundles into one registry, preserving order —\n * entry order decides which of two same-specificity bindings in one scope\n * tier wins, so it is part of the result, not an accident of it.\n *\n * Throws on a duplicate id or dep name rather than dropping one: a feature\n * silently losing its bindings, or reading another feature's dep, is the\n * failure this registry exists to make loud.\n */\nexport function mergeContributions<T extends Contribution<unknown>>(\n ...bundles: readonly (readonly T[])[]\n): T[] {\n const out: T[] = [];\n const seen = new Set<string>();\n const depOwner = new Map<string, string>();\n for (const bundle of bundles) {\n for (const entry of bundle) {\n if (seen.has(entry.id)) {\n throw new Error(\n `mergeContributions: duplicate contribution id \"${entry.id}\". `\n + `Two bundles registered the same id; rename one or merge them by hand.`,\n );\n }\n seen.add(entry.id);\n for (const dep of Object.keys(entry.deps ?? {})) {\n const owner = depOwner.get(dep);\n if (owner !== undefined) {\n throw new Error(\n `mergeContributions: dep \"${dep}\" is provided by both \"${owner}\" and \"${entry.id}\". `\n + `One registry answers each dep name; drop one source.`,\n );\n }\n depOwner.set(dep, entry.id);\n }\n out.push(entry);\n }\n }\n return out;\n}\n","import { modeLabel, type ModeDefinition, type ModeRegistry } from '@weasel-js/modes';\nimport type { KeySpec, ModSpec } from '@weasel-js/gestures';\nimport { ActionDisabledReason, type Action } from '../interactions/actions/action';\nimport type { Rule } from '../eligibility';\nimport type { Contribution } from './types';\n\n/**\n * What each mode shortcut does. A role left out binds nothing, so its key\n * falls through to whatever else the dispatcher has on it.\n */\nexport interface ModeShortcutHandlers {\n /** Enter mode `id` — the `entry` shortcut. */\n enter?: (id: string) => void;\n /** Whether mode `id` can be entered now. A mode that needs a target it\n * doesn't have answers no, and its entry key falls through. Default yes. */\n canEnter?: (id: string) => boolean;\n /** Leave the active soft mode, keeping its session to resume. */\n exit?: () => void;\n /** Leave the active soft mode and throw its session away. */\n discard?: () => void;\n /** Commit the active strict mode's transaction. */\n commit?: () => void;\n /** Abandon the active strict mode's transaction. */\n cancel?: () => void;\n}\n\ntype Role = 'exit' | 'discard' | 'commit' | 'cancel';\nconst LEAVING: readonly Role[] = ['exit', 'discard', 'commit', 'cancel'];\nconst VERB: Record<Role | 'entry', string> = {\n entry: 'Enter', exit: 'Exit', discard: 'Discard', commit: 'Commit', cancel: 'Cancel',\n};\n\nconst MODIFIERS: Record<string, keyof ModSpec> = {\n meta: 'meta', cmd: 'meta', command: 'meta',\n ctrl: 'ctrl', control: 'ctrl',\n alt: 'alt', option: 'alt',\n shift: 'shift',\n mod: 'mod',\n};\n\n/**\n * A `ModeDefinition` shortcut chord — `'Escape'`, `'Meta+T'` — as a key spec.\n * Modifier names are case-insensitive; the last segment is the key.\n */\nexport function modeShortcutSpec(shortcut: string): KeySpec {\n const parts = shortcut.split('+');\n const key = parts.pop();\n if (!key) throw new Error(`mode shortcut \"${shortcut}\" names no key`);\n const mods: ModSpec = {};\n for (const part of parts) {\n const mod = MODIFIERS[part.toLowerCase()];\n if (!mod) throw new Error(`mode shortcut \"${shortcut}\": unknown modifier \"${part}\"`);\n mods[mod] = true;\n }\n return Object.keys(mods).length > 0 ? { kind: 'key', key, mods } : { kind: 'key', key };\n}\n\n/**\n * The registry's declared mode shortcuts as an always-on contribution: one\n * action per shortcut, bound to its chord and gated on the mode it acts on —\n * `exit` / `discard` / `commit` / `cancel` while that mode is active, `entry`\n * while it is not. Install it with `<SceneCanvas ambient>`.\n *\n * An entry key one mode shares with another mode's leaving key is reported as\n * a route conflict unless `canEnter` is given: that is what keeps the entry\n * key from firing inside the other mode.\n *\n * The bindings ride the hotkey tier, so leaving a mode outranks what the same\n * key does otherwise (Escape clearing the selection), and they yield while a\n * gesture is in flight, so Escape mid-drag still cancels the drag first. Keys\n * typed into an editable element never reach them.\n */\nexport function modeShortcuts(\n registry: ModeRegistry,\n handlers: ModeShortcutHandlers,\n): Contribution<never> {\n const actions: Action[] = [];\n for (const mode of registry.list()) {\n const entry = mode.entry?.shortcut;\n const enter = handlers.enter;\n if (entry && enter) {\n // Without `canEnter` an entry key is live in every other mode, so it does not yield there.\n actions.push(shortcutAction(mode, 'entry', entry, { mode: { not: mode.id } },\n () => registry.current().id !== mode.id && (handlers.canEnter?.(mode.id) ?? true),\n () => enter(mode.id), handlers.canEnter !== undefined));\n }\n for (const role of LEAVING) {\n const shortcut = mode[role]?.shortcut;\n const run = handlers[role];\n if (!shortcut || !run) continue;\n actions.push(shortcutAction(mode, role, shortcut, { mode: mode.id },\n () => registry.current().id === mode.id,\n run, true));\n }\n }\n return { id: 'modes.shortcuts', eligibility: { always: true }, actions };\n}\n\nfunction shortcutAction(\n mode: ModeDefinition,\n role: Role | 'entry',\n shortcut: string,\n eligible: Rule,\n live: () => boolean,\n run: () => void,\n yields: boolean,\n): Action {\n return {\n id: `mode.${mode.id}.${role}`,\n label: `${VERB[role]} ${modeLabel(mode)}`,\n scope: 'hotkey',\n defaultBinding: [{\n spec: { ...modeShortcutSpec(shortcut), phase: [{ channel: '*', phase: 'initial' }] },\n opts: { yields },\n }],\n eligible,\n // `eligible` is the gate the dispatcher and palettes read, but a canvas\n // with no `modes` evaluates none; without this the key is\n // swallowed in every mode.\n enabled: () => (live() ? true : ActionDisabledReason.NotApplicable),\n invoker: { timing: 'immediate', run: () => run() },\n };\n}\n","// src/tools/defineTool.ts\nimport type { Tool } from './types';\nimport type { ToolDef } from './routeTypes';\nimport { RESERVED_ID_NAMES, RESERVED_ID_PREFIXES } from '@weasel-js/gestures';\nimport type { CursorSpec } from '@weasel-js/cursor';\nimport type { KernelOverlay } from '../index';\n\n/** Validate that `id` is usable as a tool / channel id in the route\n * grammar. Rejects ids that start with a reserved sigil (would shadow\n * future grammar extensions) and ids that collide with phase keywords\n * (would parse as the bare-phase shorthand). */\nfunction validateId(id: string, kind: 'tool' | 'action'): void {\n if (id.length === 0) {\n throw new Error(`weasel: ${kind} id may not be empty`);\n }\n if (RESERVED_ID_PREFIXES.has(id[0]!)) {\n throw new Error(\n `weasel: ${kind} id \"${id}\" starts with reserved sigil \"${id[0]}\" ` +\n `(reserved set: ${[...RESERVED_ID_PREFIXES].join(' ')})`,\n );\n }\n if (RESERVED_ID_NAMES.has(id)) {\n throw new Error(\n `weasel: ${kind} id \"${id}\" collides with a reserved phase keyword ` +\n `(reserved: ${[...RESERVED_ID_NAMES].join(', ')})`,\n );\n }\n}\n\n/**\n * Build a `Tool` from a declarative `ToolDef`: validates the id, applies the\n * `cursor` default, and keeps the authored form on `Tool.def` for reflection.\n */\nexport function defineTool<TOverlay = KernelOverlay>(\n def: ToolDef<TOverlay>,\n): Tool<TOverlay> {\n validateId(def.id, 'tool');\n\n const resolveCursor = (): CursorSpec => {\n if (def.cursor == null) return '';\n return typeof def.cursor === 'function' ? def.cursor() : def.cursor;\n };\n\n return {\n id: def.id,\n eligibility: {\n focus: true,\n capabilities: def.capabilities,\n ...(def.hotkey ? { offhand: def.hotkey } : {}),\n },\n actions: def.actions,\n menus: def.menus,\n def,\n presentation: def.presentation,\n keybinding: def.keybinding,\n onActivate: def.onActivate,\n onDeactivate: def.onDeactivate,\n cursor: resolveCursor,\n bindings: def.bindings,\n overlay: def.overlay,\n overlayPosition: def.overlayPosition,\n };\n}\n","/**\n * Tool sets: a named group of tool ids, the unit a consumer opts into whole.\n * A set names ids, never tools, because a tool is built by a hook that holds\n * its state; whatever mounts the set supplies the tool for each id.\n */\n\n/** A named group of tool ids. A member is an id or another set, whose ids it takes in order. */\nexport interface ToolSet<TId extends string = string> {\n readonly id: string;\n readonly members: readonly (TId | ToolSet<TId>)[];\n}\n\n/** One entry of a list of tools to mount: an id, or a set of them. */\nexport type ToolEntry<TId extends string = string> = TId | ToolSet<TId>;\n\n/** A set named `id` of `members`, in palette order. */\nexport function toolSet<TId extends string>(id: string, members: readonly ToolEntry<TId>[]): ToolSet<TId> {\n return { id, members };\n}\n\n/** Whether `entry` is a set rather than a single id. */\nexport function isToolSet<TId extends string>(entry: ToolEntry<TId>): entry is ToolSet<TId> {\n return typeof entry !== 'string';\n}\n\n/** Every id `entries` name, sets opened in place, each id once at its first place. */\nexport function toolIdsOf<TId extends string>(entries: readonly ToolEntry<TId>[]): TId[] {\n const out: TId[] = [];\n const seen = new Set<string>();\n const walk = (list: readonly ToolEntry<TId>[]): void => {\n for (const entry of list) {\n if (isToolSet(entry)) walk(entry.members);\n else if (!seen.has(entry)) {\n seen.add(entry);\n out.push(entry);\n }\n }\n };\n walk(entries);\n return out;\n}\n\n/** `set` less every id `omit` names, sets opened. Keeps `set`'s id with a `-without` suffix. */\nexport function withoutTools<TId extends string>(set: ToolSet<TId>, ...omit: readonly ToolEntry<TId>[]): ToolSet<TId> {\n const gone = new Set<string>(toolIdsOf(omit));\n return { id: `${set.id}-without`, members: toolIdsOf([set]).filter((id) => !gone.has(id)) };\n}\n\n/** Whether `set` names `id`, directly or through a set inside it. */\nexport function toolSetHas<TId extends string>(set: ToolSet<TId>, id: string): boolean {\n return (toolIdsOf([set]) as string[]).includes(id);\n}\n","/**\n * Key chords a major browser or the desktop under it takes before a page can:\n * reload, devtools, tab and window commands, menu accelerators. A binding on\n * one never fires for some users, so kit defaults steer clear of them.\n *\n * `mod` is Cmd on macOS and Ctrl elsewhere, as in a `KeySpec`. The list is\n * the union across Chrome, Safari, Firefox and Edge on macOS, Windows and\n * Linux, and errs toward listing a chord.\n */\nimport type { KeySpec } from '@weasel-js/gestures';\n\n/** One reserved chord, and what takes it. */\nexport interface ReservedChord {\n key: string;\n mod?: boolean;\n alt?: boolean;\n shift?: boolean;\n /** Who takes it, for a message. */\n use: string;\n}\n\nconst chord = (keys: string, mods: Omit<ReservedChord, 'key' | 'use'>, use: string): ReservedChord[] =>\n [...keys].map((key) => ({ key, ...mods, use }));\n\n/** Every chord the module's header describes, one entry per key. */\nexport const BROWSER_RESERVED_CHORDS: readonly ReservedChord[] = [\n ...chord('nqtwlrpmh', { mod: true }, 'new window, quit, new or close tab, address bar, reload, print, minimize, hide'),\n ...chord('ntwrbo', { mod: true, shift: true }, 'private window, reopen or close tab, hard reload, bookmarks, bookmark manager'),\n ...chord('ijck', { mod: true, shift: true }, 'devtools, console and inspector on Windows and Linux; Firefox Browser and Web Console'),\n ...chord('ijcukbrlemhdwfn', { mod: true, alt: true }, 'devtools, console, inspector, view source, bookmarks, reload from origin, downloads, empty caches, minimize all, hide others, Dock, close all, search field'),\n ...chord('fevsbthd', { alt: true }, 'menu accelerators and address bar on Windows and Linux'),\n ...chord('ita', { alt: true, shift: true }, 'feedback, toolbar focus and accessibility commands'),\n];\n\nconst lower = (k: string | readonly string[]): string[] => (typeof k === 'string' ? [k] : [...k]).map((x) => x.toLowerCase());\n\n/** Whether a modifier policy can be satisfied with the modifier held (`true`)\n * or released (`false`). */\nconst allows = (policy: boolean | 'optional' | undefined, held: boolean): boolean =>\n policy === 'optional' || (policy === true) === held;\n\n/** The first reserved chord `spec` can fire on, or `null` when none. */\nexport function browserReservedChord(spec: KeySpec): ReservedChord | null {\n const keys = lower(spec.key);\n const m = spec.mods ?? {};\n const mod = m.mod ?? (m.meta === true || m.ctrl === true ? true : m.meta ?? m.ctrl);\n for (const c of BROWSER_RESERVED_CHORDS) {\n if (!keys.includes(c.key)) continue;\n if (allows(mod, c.mod === true) && allows(m.alt, c.alt === true) && allows(m.shift, c.shift === true)) return c;\n }\n return null;\n}\n","/**\n * Typed keys for the gesture/behavior scratch store, `ctx.scratch`.\n * `ScratchKey<T>` carries its payload type at the typing layer; at runtime\n * the key is just its underlying string and the store remains a plain `Record`.\n *\n * @example\n * ```ts\n * // Module-level constant, shared by writer + reader:\n * const LASSO_VERTICES = scratchKey<readonly { x: number; y: number }[]>('lasso.vertices');\n * setScratch(ctx.scratch, LASSO_VERTICES, vertices);\n * const vertices = getScratch(ctx.scratch, LASSO_VERTICES) ?? [];\n * ```\n */\n\n/** Phantom-typed key for a scratch slot. The `__scratchKeyPayload` phantom\n * field carries the value type without occupying any runtime memory. */\nexport interface ScratchKey<T> {\n readonly name: string;\n /** Phantom — never read at runtime. Only present so TypeScript can\n * recover `T` at use sites. */\n readonly __scratchKeyPayload?: (_: T) => T;\n}\n\n/** Compatible scratch store shape. The kit's gesture context's `scratch`\n * field already satisfies this; consumers don't need to construct one. */\nexport type ScratchStore = Record<string, unknown>;\n\n/**\n * Make a typed scratch key. Two keys with the same `name` refer to the same\n * slot at runtime — the type parameter is a compile-time contract, not a\n * uniqueness guarantee — so namespace the name (`'behavior.field'`).\n */\nexport function scratchKey<T>(name: string): ScratchKey<T> {\n return { name };\n}\n\n/** Read a typed slot from the scratch store. Returns `undefined` if\n * nothing has been written under the key. */\nexport function getScratch<T>(\n store: ScratchStore,\n key: ScratchKey<T>,\n): T | undefined {\n return store[key.name] as T | undefined;\n}\n\n/** Write a value to a typed slot. Overwrites whatever was there. */\nexport function setScratch<T>(\n store: ScratchStore,\n key: ScratchKey<T>,\n value: T,\n): void {\n store[key.name] = value;\n}\n\n/** Remove a slot from the scratch store. Returns `true` if it was set,\n * `false` if it wasn't. */\nexport function deleteScratch<T>(\n store: ScratchStore,\n key: ScratchKey<T>,\n): boolean {\n if (Object.prototype.hasOwnProperty.call(store, key.name)) {\n delete store[key.name];\n return true;\n }\n return false;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/interactions/actions/actionTags.ts","../src/interactions/actions/overlay.ts","../src/interactions/dispatcher/predicates.ts","../src/contributions/merge.ts","../src/contributions/modeShortcuts.ts","../src/keymaps/captureSpec.ts","../src/keymaps/capturePointer.ts","../src/keymaps/captureGesture.ts","../src/keymaps/captureKey.ts","../src/tools/defineTool.ts","../src/tools/toolSet.ts","../src/interactions/browserReservedKeys.ts","../src/interactions/scratchKey.ts"],"names":["RESERVED_ID_PREFIXES","RESERVED_ID_NAMES","key"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Finding actions by tag: gathering the ones that carry it, and a person's\n * search matching it as it matches a label.\n */\nimport { hasTag, matchQuery, type QueryMatch } from '@weasel-js/registry';\nimport type { Action } from './action';\nimport { actionItems, actionItemTitle, type ActionItem } from './actionItems';\n\n/** The actions carrying `tag`, themselves or on any variant, in\n * the order given. Drags included, which have no entries to show. */\nexport function actionsTagged(actions: readonly Action[], tag: string): Action[] {\n return actions.filter((a) => hasTag(a.tags, tag) || (a.variants?.some((v) => hasTag(v.tags, tag)) ?? false));\n}\n\n/** The entries carrying `tag`: what a bar or a menu built from\n * a tag shows. A variant that does not carry it is left out. */\nexport function taggedActionItems(actions: readonly Action[], tag: string): ActionItem[] {\n return actionsTagged(actions, tag).flatMap(actionItems).filter((i) => hasTag(i.tags, tag));\n}\n\n/** Whether `item` answers a search for `query`, by its palette title or\n * by a tag, and which. */\nexport function matchActionItem(item: ActionItem, query: string): QueryMatch | null {\n return matchQuery(query, { text: [actionItemTitle(item)], tags: item.tags });\n}\n","/** The chrome an in-flight gesture paints beside the scene. */\nimport type { OngoingHandle } from './invoker';\n\n/**\n * What a `polyline` overlay is, in a word — the narrowest thing an action can\n * say about how its run should look without naming a paint.\n *\n * The named roles are the kit's; a painter maps each to a style and falls back\n * to plain chrome for one it does not know, so a package outside core can coin\n * its own and still be drawn.\n */\nexport type OverlayRole =\n /** Generic in-flight chrome — the marquee/lasso paint. */\n | 'chrome'\n /** A cut the gesture would make. */\n | 'cut'\n /** An edge the gesture would author between two points. */\n | 'connector'\n /** The stretch of a path a soft-selection drag reaches. */\n | 'falloff'\n /** What a lock holds a dragged point to — a line, a circle. */\n | 'lock'\n /** Where a dragged item would land: a reorder's insertion bar. */\n | 'insert'\n /** Where a dragged item is over and cannot land. */\n | 'refused'\n | (string & {});\n\n/**\n * What an in-flight gesture proposes to paint *beside* the scene, returned by\n * `OngoingHandle.overlay()` — a marquee rect, a lasso trail, the outline of a\n * shape being dragged out, the line a slice would cut along.\n *\n * Every variant is world geometry and nothing else — no `DrawCommand`, no\n * color, no coordinate space to choose — so a surface rendering the same\n * gesture some other way can still read it. The painter owns every style\n * decision.\n */\nexport type OngoingOverlay =\n | {\n kind: 'marquee';\n start: { x: number; y: number };\n current: { x: number; y: number };\n shiftHeld: boolean;\n }\n | {\n kind: 'lasso';\n vertices: ReadonlyArray<{ x: number; y: number }>;\n current: { x: number; y: number };\n shiftHeld: boolean;\n }\n | {\n /**\n * An open run of world points the gesture is proposing — a cut line, a\n * routed connector. `role` is the whole of what an action says about\n * appearance.\n */\n kind: 'polyline';\n /** At least two points. Anything shorter is dropped in resolution. */\n points: ReadonlyArray<{ x: number; y: number }>;\n /** What the run means. Omitted reads as {@link OverlayRole} `'chrome'`. */\n role?: OverlayRole;\n }\n | {\n /**\n * A round brush dragged through world points: the area it has swept so\n * far, and its footprint at the last point. The radius is in screen\n * pixels, so the footprint keeps its size at every zoom.\n */\n kind: 'brush';\n /** The brush's path so far, at least one point; the last is where it is now. */\n points: ReadonlyArray<{ x: number; y: number }>;\n radiusPx: number;\n }\n | {\n /**\n * Live insert-drag preview. Pre-commit there is no scene node to ghost\n * via `previewIds()`/`previewPose()`, so insert paints its preview\n * through the overlay instead.\n *\n * `bounds` is the AABB of the current drag (start/current normalized).\n * `extras` is the per-kind extras the action already collected; the\n * overlay renderer narrows on `shape` and casts the field shape it\n * expects.\n */\n kind: 'insertPreview';\n /** Which preview the dispatcher's overlay draws. The kit's own shape\n * kinds are the ones it knows how to render; a consumer-defined kind\n * is legal and simply gets no live preview. */\n shape: string;\n bounds: { x: number; y: number; width: number; height: number };\n extras: unknown;\n /** World-space point to paint a small \"anchor\" dot at, marking the\n * click point — for radial shapes (polygon/star), where no vertex\n * sits on it, and for any shape in center mode. */\n anchorPoint?: { x: number; y: number };\n /** World affines the shape will also be drawn under once it lands, by\n * the container it is drawn into: the preview is painted under each. */\n copies?: readonly (readonly [number, number, number, number, number, number])[];\n };\n\n/** A handle's overlays as a list: empty when it has none. */\nexport function overlaysOf(handle: OngoingHandle): readonly OngoingOverlay[] {\n const ov = handle.overlay?.();\n if (!ov) return [];\n return isOverlayList(ov) ? ov : [ov];\n}\n\nfunction isOverlayList(ov: OngoingOverlay | readonly OngoingOverlay[]): ov is readonly OngoingOverlay[] {\n return Array.isArray(ov);\n}\n","/**\n * Named predicates for `defaultBinding.target.kindOf`. Each matches the\n * `TargetPredicate` shape, declaring whether it reads the hit,\n * so they drop into action descriptors without a wrapper:\n *\n * target: { kindOf: isAnchor }\n *\n * Single source of truth for \"what does this affordance kind mean\" — adding\n * a new predicate here is what enables every action that needs the same\n * shape to read it. Drift prevention.\n */\nimport { bodyPredicate, hitPredicate, type TargetPredicate } from '@weasel-js/gestures';\n\n// ─── Body-class predicates (read the second arg) ───────────────────────\n\n/** A predicate that resolves from `bodyTarget` alone. */\nexport type BodyPredicate = TargetPredicate & { readsAffordance: false };\n\n/** Matches any body hit — selected or unselected node body. */\nexport const isBody: BodyPredicate = bodyPredicate((bodyTarget) =>\n bodyTarget === 'selected-body' || bodyTarget === 'unselected-body');\n\n/** Body hit specifically already in the selection. */\nexport const isSelectedBody: BodyPredicate = bodyPredicate((bodyTarget) =>\n bodyTarget === 'selected-body');\n\n/** Body hit specifically NOT in the selection. */\nexport const isUnselectedBody: BodyPredicate = bodyPredicate((bodyTarget) =>\n bodyTarget === 'unselected-body');\n\n/** Empty-canvas hit — no node beneath cursor. */\nexport const isEmpty: BodyPredicate = bodyPredicate((bodyTarget) =>\n bodyTarget === 'empty');\n\n// ─── Affordance-kind predicates (read the first arg) ───────────────────\n\nfunction kindOf(target: unknown): string | undefined {\n if (typeof target !== 'object' || target === null) return undefined;\n const k = (target as { kind?: unknown }).kind;\n return typeof k === 'string' ? k : undefined;\n}\n\n/** Any resize handle: a corner (`handle:top-left`, …) or an edge (`handle:top`, …). */\nexport const isResizeHandle = hitPredicate((target) => {\n const k = kindOf(target);\n return k !== undefined && k.startsWith('handle:');\n});\n\n/** The rotate-around-center handle above the bounding box. */\nexport const isRotateHandle = hitPredicate((target) =>\n kindOf(target) === 'rotate-handle');\n\n/** Any path anchor (the on-curve dot). */\nexport const isAnchor = hitPredicate((target) => {\n const k = kindOf(target);\n return k !== undefined && /^anchor:\\d+$/.test(k);\n});\n\n/** Either control handle (controlIn or controlOut). */\nexport const isControlHandle = hitPredicate((target) => {\n const k = kindOf(target);\n return k !== undefined && /^(controlIn|controlOut):\\d+$/.test(k);\n});\n\n/** A corner-shape widget, set inside a corner anchor of the edited path. */\nexport const isCornerWidget = hitPredicate((target) => {\n const k = kindOf(target);\n return k !== undefined && /^corner:\\d+$/.test(k);\n});\n\n/** Any of the three anchor-editing affordances (anchor + both controls). */\nexport const isAnchorOrControl = hitPredicate((target) =>\n isAnchor(target) || isControlHandle(target));\n\n/** The outline of the path being edited, between its anchors. */\nexport const isSegment = hitPredicate((target) => kindOf(target) === 'segment');\n\n/** The grip midway along a curved segment's balance line, `balance:N`, where\n * N is the flat index of the anchor the segment starts at. */\nexport const isBalanceGrip = hitPredicate((target) => {\n const k = kindOf(target);\n return k !== undefined && /^balance:\\d+$/.test(k);\n});\n\n/** Anything path edit puts on the path: an anchor, a control, a segment, a\n * segment's balance grip, or a corner widget. */\nexport const isPathEditPart = hitPredicate((target) =>\n isAnchorOrControl(target) || isSegment(target) || isBalanceGrip(target) || isCornerWidget(target));\n","import type { Contribution } from './types';\n\n/**\n * Concatenate contribution bundles into one registry, preserving order —\n * entry order decides which of two same-specificity bindings in one scope\n * tier wins, so it is part of the result, not an accident of it.\n *\n * Throws on a duplicate id or dep name rather than dropping one: a feature\n * silently losing its bindings, or reading another feature's dep, is the\n * failure this registry exists to make loud.\n */\nexport function mergeContributions<T extends Contribution<unknown>>(\n ...bundles: readonly (readonly T[])[]\n): T[] {\n const out: T[] = [];\n const seen = new Set<string>();\n const depOwner = new Map<string, string>();\n for (const bundle of bundles) {\n for (const entry of bundle) {\n if (seen.has(entry.id)) {\n throw new Error(\n `mergeContributions: duplicate contribution id \"${entry.id}\". `\n + `Two bundles registered the same id; rename one or merge them by hand.`,\n );\n }\n seen.add(entry.id);\n for (const dep of Object.keys(entry.deps ?? {})) {\n const owner = depOwner.get(dep);\n if (owner !== undefined) {\n throw new Error(\n `mergeContributions: dep \"${dep}\" is provided by both \"${owner}\" and \"${entry.id}\". `\n + `One registry answers each dep name; drop one source.`,\n );\n }\n depOwner.set(dep, entry.id);\n }\n out.push(entry);\n }\n }\n return out;\n}\n","import { modeLabel, type ModeDefinition, type ModeRegistry } from '@weasel-js/modes';\nimport { key, type KeySpec } from '@weasel-js/gestures';\nimport { ActionDisabledReason, type Action } from '../interactions/actions/action';\nimport type { Rule } from '../eligibility';\nimport type { Contribution } from './types';\n\n/**\n * What each mode shortcut does. A role left out binds nothing, so its key\n * falls through to whatever else the dispatcher has on it.\n */\nexport interface ModeShortcutHandlers {\n /** Enter mode `id` — the `entry` shortcut. */\n enter?: (id: string) => void;\n /** Whether mode `id` can be entered now. A mode that needs a target it\n * doesn't have answers no, and its entry key falls through. Default yes. */\n canEnter?: (id: string) => boolean;\n /** Leave the active soft mode, keeping its session to resume. */\n exit?: () => void;\n /** Leave the active soft mode and throw its session away. */\n discard?: () => void;\n /** Commit the active strict mode's transaction. */\n commit?: () => void;\n /** Abandon the active strict mode's transaction. */\n cancel?: () => void;\n}\n\ntype Role = 'exit' | 'discard' | 'commit' | 'cancel';\nconst LEAVING: readonly Role[] = ['exit', 'discard', 'commit', 'cancel'];\nconst VERB: Record<Role | 'entry', string> = {\n entry: 'Enter', exit: 'Exit', discard: 'Discard', commit: 'Commit', cancel: 'Cancel',\n};\n\n/**\n * A `ModeDefinition` shortcut chord — `'Escape'`, `'Meta+T'` — as a key spec.\n * Modifier names are case-insensitive; the last segment is the key.\n */\nexport function modeShortcutSpec(shortcut: string): KeySpec {\n return key(shortcut);\n}\n\n/**\n * The registry's declared mode shortcuts as an always-on contribution: one\n * action per shortcut, bound to its chord and gated on the mode it acts on —\n * `exit` / `discard` / `commit` / `cancel` while that mode is active, `entry`\n * while it is not. Install it with `<SceneCanvas ambient>`.\n *\n * An entry key one mode shares with another mode's leaving key is reported as\n * a route conflict unless `canEnter` is given: that is what keeps the entry\n * key from firing inside the other mode.\n *\n * The bindings ride the hotkey tier, so leaving a mode outranks what the same\n * key does otherwise (Escape clearing the selection), and they yield while a\n * gesture is in flight, so Escape mid-drag still cancels the drag first. Keys\n * typed into an editable element never reach them.\n */\nexport function modeShortcuts(\n registry: ModeRegistry,\n handlers: ModeShortcutHandlers,\n): Contribution<never> {\n const actions: Action[] = [];\n for (const mode of registry.list()) {\n const entry = mode.entry?.shortcut;\n const enter = handlers.enter;\n if (entry && enter) {\n // Without `canEnter` an entry key is live in every other mode, so it does not yield there.\n actions.push(shortcutAction(mode, 'entry', entry, { mode: { not: mode.id } },\n () => registry.current().id !== mode.id && (handlers.canEnter?.(mode.id) ?? true),\n () => enter(mode.id), handlers.canEnter !== undefined));\n }\n for (const role of LEAVING) {\n const shortcut = mode[role]?.shortcut;\n const run = handlers[role];\n if (!shortcut || !run) continue;\n actions.push(shortcutAction(mode, role, shortcut, { mode: mode.id },\n () => registry.current().id === mode.id,\n run, true));\n }\n }\n return { id: 'modes.shortcuts', eligibility: { always: true }, actions };\n}\n\nfunction shortcutAction(\n mode: ModeDefinition,\n role: Role | 'entry',\n shortcut: string,\n eligible: Rule,\n live: () => boolean,\n run: () => void,\n yields: boolean,\n): Action {\n return {\n id: `mode.${mode.id}.${role}`,\n label: `${VERB[role]} ${modeLabel(mode)}`,\n scope: 'hotkey',\n defaultBinding: [{\n spec: { ...modeShortcutSpec(shortcut), phase: [{ channel: '*', phase: 'initial' }] },\n opts: { id: `mode.${mode.id}.${role}.key`, yields },\n }],\n eligible,\n // `eligible` is the gate the dispatcher and palettes read, but a canvas\n // with no `modes` evaluates none; without this the key is\n // swallowed in every mode.\n enabled: () => (live() ? true : ActionDisabledReason.NotApplicable),\n invoker: { timing: 'immediate', run: () => run() },\n };\n}\n","import type {\n ClickSpec, ContextMenuSpec, DoubleClickSpec, DragSpec, EventModifiers, KeyHeldSpec, KeySpec, ModSpec,\n} from '@weasel-js/gestures';\n\n/** A spec kind a binding editor can capture. */\nexport type CaptureKind = 'key' | 'key-held' | 'click' | 'doubleClick' | 'drag' | 'contextMenu';\n\n/** What `captureGesture` resolves to. */\nexport type CapturedSpec = KeySpec | KeyHeldSpec | ClickSpec | DoubleClickSpec | DragSpec | ContextMenuSpec;\n\n/** An event's modifiers as a spec's, with the platform's primary one as `mod`. */\nfunction modSpecOf(e: EventModifiers, apple: boolean): ModSpec | undefined {\n const mods: ModSpec = {};\n if (apple ? e.metaKey : e.ctrlKey) mods.mod = true;\n if (e.shiftKey) mods.shift = true;\n if (e.altKey) mods.alt = true;\n if (apple ? e.ctrlKey : e.metaKey) mods[apple ? 'ctrl' : 'meta'] = true;\n return Object.keys(mods).length > 0 ? mods : undefined;\n}\n\nexport function specOf<K extends CapturedSpec['kind']>(kind: K, e: EventModifiers, apple: boolean): { kind: K; mods?: ModSpec } {\n const mods = modSpecOf(e, apple);\n return mods ? { kind, mods } : { kind };\n}\n\n/** Keep an event from the page. */\nexport const take = (e: Event): void => { e.preventDefault(); e.stopPropagation(); };\n","import {\n createPointerRecognizer, DOUBLE_CLICK_MAX_MS,\n type EventModifiers, type InputEvent, type PointerSample, type RecognizerClock,\n} from '@weasel-js/gestures';\nimport { specOf, take, type CaptureKind, type CapturedSpec } from './captureSpec';\n\n/** The click-and-drag thresholds a capture reads, each defaulting to its constant. */\nexport interface CaptureThresholds {\n dragPx?: number;\n doubleClickMs?: number;\n doubleClickPx?: number;\n}\n\n/** What a browser follows a press with; taken too, or the page acts on a gesture already captured. */\nexport const TRAILING = ['click', 'auxclick', 'dblclick', 'contextmenu'] as const;\n\nconst sampleOf = (e: PointerEvent): PointerSample => ({\n pointerId: e.pointerId, clientX: e.clientX, clientY: e.clientY, target: e.target, timeStamp: e.timeStamp,\n altKey: e.altKey, ctrlKey: e.ctrlKey, metaKey: e.metaKey, shiftKey: e.shiftKey,\n});\n\nconst browserClock: RecognizerClock = {\n now: () => performance.now(),\n setTimer: (fn, ms) => setTimeout(fn, ms),\n clearTimer: (t) => { clearTimeout(t as ReturnType<typeof setTimeout>); },\n};\n\n/**\n * Listen, through `listen`, for the next pointer gesture of `kinds` and hand\n * its spec to `done`. Returns what stops it. A press goes through the\n * dispatcher's recognizer, so a click and a drag part where they do on a canvas.\n */\nexport function capturePointer(\n target: EventTarget,\n kinds: ReadonlySet<CaptureKind>,\n apple: boolean,\n thresholds: CaptureThresholds,\n listen: (type: string, fn: (e: Event) => void) => void,\n done: (spec: CapturedSpec) => void,\n): () => void {\n let pendingClick: ReturnType<typeof setTimeout> | null = null;\n let dragMods: EventModifiers | null = null;\n\n const recognized = (ev: InputEvent): 'handled' | 'unhandled' => {\n switch (ev.kind) {\n case 'pointerdown':\n // Without `stage` it is the press held back until it crossed the drag threshold.\n if (!('stage' in ev && ev.stage === 'press')) dragMods = ev;\n return 'unhandled';\n case 'click': {\n if (!kinds.has('click')) return 'unhandled';\n const spec = specOf('click', ev, apple);\n if (!kinds.has('doubleClick')) { done(spec); return 'handled'; }\n if (pendingClick) clearTimeout(pendingClick);\n pendingClick = setTimeout(() => { done(spec); }, thresholds.doubleClickMs ?? DOUBLE_CLICK_MAX_MS);\n return 'handled';\n }\n case 'doubleclick':\n case 'contextmenu': {\n const kind = ev.kind === 'doubleclick' ? 'doubleClick' : 'contextMenu';\n if (!kinds.has(kind)) return 'unhandled';\n done(specOf(kind, ev, apple));\n return 'handled';\n }\n default:\n return 'unhandled';\n }\n };\n\n const recognizer = createPointerRecognizer({\n clock: browserClock,\n dragPx: () => thresholds.dragPx,\n doubleClickMs: () => thresholds.doubleClickMs,\n doubleClickPx: () => thresholds.doubleClickPx,\n sink: { dispatch: recognized, multiTouchInFlight: () => false },\n });\n\n /** A pointer event for a press this capture holds, taken from the page; otherwise `null`. */\n const held = (e: Event): PointerEvent | null => {\n const p = e as PointerEvent;\n if (recognizer.positionOf(p.pointerId) === undefined) return null;\n take(p);\n return p;\n };\n\n listen('pointerdown', (e) => {\n const p = e as PointerEvent;\n take(p);\n // Only the primary button presses as the dispatcher sees it; a secondary\n // one reaches a binding as its `contextmenu`.\n if ((p.button ?? 0) !== 0) return;\n // An element hears a held pointer's moves and release only while it captures them.\n if (target instanceof Element) {\n try { target.setPointerCapture(p.pointerId); } catch { /* the pointer is already gone */ }\n }\n recognizer.press({ ...sampleOf(p), x: p.clientX, y: p.clientY, pointerType: p.pointerType });\n });\n listen('pointermove', (e) => {\n const p = held(e);\n if (p) recognizer.move(sampleOf(p));\n });\n listen('pointerup', (e) => {\n const p = held(e);\n if (!p) return;\n const drag = dragMods;\n dragMods = null;\n recognizer.release(sampleOf(p));\n if (drag && kinds.has('drag')) done(specOf('drag', drag, apple));\n });\n listen('pointercancel', (e) => {\n const p = held(e);\n if (!p) return;\n dragMods = null;\n recognizer.cancel(p.pointerId);\n });\n for (const type of TRAILING) {\n listen(type, (e) => {\n take(e);\n if (type === 'contextmenu' && kinds.has('contextMenu')) done(specOf('contextMenu', e as MouseEvent, apple));\n });\n }\n\n return () => {\n if (pendingClick) clearTimeout(pendingClick);\n recognizer.reset();\n };\n}\n","import { isApplePlatform } from '@weasel-js/gestures';\nimport { capturePointer, TRAILING, type CaptureThresholds } from './capturePointer';\nimport { specOf, take, type CaptureKind, type CapturedSpec } from './captureSpec';\n\nexport type { CaptureKind, CapturedSpec } from './captureSpec';\n\n/** Options for {@link captureGesture}. */\nexport interface CaptureGestureOptions extends CaptureThresholds {\n /** The kinds to take; input of any other kind is waited past. A keystroke\n * is taken as `key` when both `key` and `key-held` are listed. Defaults to\n * `key`, `click`, `doubleClick`, `drag` and `contextMenu`. */\n kinds?: readonly CaptureKind[];\n /** Stop listening and resolve `null`. */\n signal?: AbortSignal;\n /** Whether Cmd is Mod. Defaults to the detected platform. */\n apple?: boolean;\n /** Travel that makes a press a drag, in CSS px: pass the `gestures.dragPx`\n * kit setting. Defaults to `DRAG_THRESHOLD_PX`. */\n dragPx?: number;\n /** The `gestures.doubleClickMs` kit setting. Defaults to `DOUBLE_CLICK_MAX_MS`. */\n doubleClickMs?: number;\n /** The `gestures.doubleClickPx` kit setting. Defaults to `DOUBLE_CLICK_MAX_PX`. */\n doubleClickPx?: number;\n}\n\nconst DEFAULT_KINDS: readonly CaptureKind[] = ['key', 'click', 'doubleClick', 'drag', 'contextMenu'];\nconst POINTER_KINDS: readonly CaptureKind[] = ['click', 'doubleClick', 'drag', 'contextMenu'];\nconst MODIFIER_KEYS: ReadonlySet<string> = new Set(['Shift', 'Control', 'Alt', 'Meta', 'AltGraph', 'CapsLock']);\n\n/**\n * The next input on `target` of one of `opts.kinds`, as a gesture spec, for a\n * binding editor: its modifiers with the platform's primary one as `mod`. A\n * press is told a click or a drag by the dispatcher's own recognizer, at its\n * drag threshold; a click is held back for a double click only when both are\n * asked for. A bare modifier key is waited past. Escape, or an abort, resolves\n * `null`. What it takes is `preventDefault`ed and stopped, the click a browser\n * follows a press with included, so nothing else acts on it. The pointer is\n * left alone when no pointer kind is asked for, and keys other than Escape\n * when no key kind is.\n */\nexport function captureGesture(target: EventTarget, opts: CaptureGestureOptions = {}): Promise<CapturedSpec | null> {\n const apple = opts.apple ?? isApplePlatform();\n const kinds = new Set(opts.kinds ?? DEFAULT_KINDS);\n const keyKind = kinds.has('key') ? 'key' : kinds.has('key-held') ? 'key-held' : null;\n const pointer = POINTER_KINDS.some((k) => kinds.has(k));\n\n return new Promise((resolve) => {\n if (opts.signal?.aborted) { resolve(null); return; }\n let settled = false;\n let stopPointer = (): void => {};\n const listeners: [string, (e: Event) => void][] = [];\n const listen = (type: string, fn: (e: Event) => void): void => {\n listeners.push([type, fn]);\n target.addEventListener(type, fn, true);\n };\n\n const done = (spec: CapturedSpec | null): void => {\n if (settled) return;\n settled = true;\n stopPointer();\n opts.signal?.removeEventListener('abort', onAbort);\n for (const [type, fn] of listeners) target.removeEventListener(type, fn, true);\n // The click and dblclick a release goes on to fire arrive in the same task.\n if (pointer) {\n for (const type of TRAILING) target.addEventListener(type, take, true);\n setTimeout(() => { for (const type of TRAILING) target.removeEventListener(type, take, true); }, 0);\n }\n resolve(spec);\n };\n const onAbort = (): void => { done(null); };\n\n opts.signal?.addEventListener('abort', onAbort);\n listen('keydown', (e) => {\n const k = e as KeyboardEvent;\n if (MODIFIER_KEYS.has(k.key)) return;\n const escape = k.key === 'Escape' && !k.metaKey && !k.ctrlKey && !k.altKey && !k.shiftKey;\n if (!escape && !keyKind) return;\n take(k);\n done(escape || !keyKind ? null : { ...specOf(keyKind, k, apple), key: k.key });\n });\n if (pointer) stopPointer = capturePointer(target, kinds, apple, opts, listen, done);\n });\n}\n","import type { KeyHeldSpec, KeySpec } from '@weasel-js/gestures';\nimport { captureGesture } from './captureGesture';\n\n/** Options for {@link captureKey}. */\nexport interface CaptureKeyOptions {\n /** Capture the held form, `key-held`, rather than the keystroke. */\n held?: boolean;\n /** Stop listening and resolve `null`. */\n signal?: AbortSignal;\n /** Whether Cmd is Mod. Defaults to the detected platform. */\n apple?: boolean;\n}\n\n/**\n * The next keystroke on `target` as a key spec: {@link captureGesture} taking\n * a keystroke alone, and leaving the pointer to the page. A bare modifier is\n * waited past. Write the result with `keySpecRoute` to persist it as a binding\n * override.\n */\nexport function captureKey(target: EventTarget, opts: CaptureKeyOptions = {}): Promise<KeySpec | KeyHeldSpec | null> {\n return captureGesture(target, {\n kinds: [opts.held ? 'key-held' : 'key'],\n ...(opts.signal ? { signal: opts.signal } : {}),\n ...(opts.apple !== undefined ? { apple: opts.apple } : {}),\n }) as Promise<KeySpec | KeyHeldSpec | null>;\n}\n","// src/tools/defineTool.ts\nimport type { Tool } from './types';\nimport type { ToolDef } from './routeTypes';\nimport { RESERVED_ID_NAMES, RESERVED_ID_PREFIXES } from '@weasel-js/gestures';\nimport type { CursorSpec } from '@weasel-js/cursor';\nimport type { KernelOverlay } from '../index';\n\n/** Validate that `id` is usable as a tool / channel id in the route\n * grammar. Rejects ids that start with a reserved sigil (would shadow\n * future grammar extensions) and ids that collide with phase keywords\n * (would parse as the bare-phase shorthand). */\nfunction validateId(id: string, kind: 'tool' | 'action'): void {\n if (id.length === 0) {\n throw new Error(`weasel: ${kind} id may not be empty`);\n }\n if (RESERVED_ID_PREFIXES.has(id[0]!)) {\n throw new Error(\n `weasel: ${kind} id \"${id}\" starts with reserved sigil \"${id[0]}\" ` +\n `(reserved set: ${[...RESERVED_ID_PREFIXES].join(' ')})`,\n );\n }\n if (RESERVED_ID_NAMES.has(id)) {\n throw new Error(\n `weasel: ${kind} id \"${id}\" collides with a reserved phase keyword ` +\n `(reserved: ${[...RESERVED_ID_NAMES].join(', ')})`,\n );\n }\n}\n\n/**\n * Build a `Tool` from a declarative `ToolDef`: validates the id, applies the\n * `cursor` default, and keeps the authored form on `Tool.def` for reflection.\n */\nexport function defineTool<TOverlay = KernelOverlay>(\n def: ToolDef<TOverlay>,\n): Tool<TOverlay> {\n validateId(def.id, 'tool');\n\n const resolveCursor = (): CursorSpec => {\n if (def.cursor == null) return '';\n return typeof def.cursor === 'function' ? def.cursor() : def.cursor;\n };\n\n return {\n id: def.id,\n eligibility: {\n focus: true,\n capabilities: def.capabilities,\n ...(def.hotkey ? { offhand: def.hotkey } : {}),\n },\n actions: def.actions,\n menus: def.menus,\n def,\n presentation: def.presentation,\n keybinding: def.keybinding,\n onActivate: def.onActivate,\n onDeactivate: def.onDeactivate,\n cursor: resolveCursor,\n bindings: def.bindings,\n overlay: def.overlay,\n overlayPosition: def.overlayPosition,\n };\n}\n","/**\n * Tool sets: a named group of tool ids, the unit a consumer opts into whole.\n * A set names ids, never tools, because a tool is built by a hook that holds\n * its state; whatever mounts the set supplies the tool for each id.\n */\n\n/** A named group of tool ids. A member is an id or another set, whose ids it takes in order. */\nexport interface ToolSet<TId extends string = string> {\n readonly id: string;\n readonly members: readonly (TId | ToolSet<TId>)[];\n}\n\n/** One entry of a list of tools to mount: an id, or a set of them. */\nexport type ToolEntry<TId extends string = string> = TId | ToolSet<TId>;\n\n/** A set named `id` of `members`, in palette order. */\nexport function toolSet<TId extends string>(id: string, members: readonly ToolEntry<TId>[]): ToolSet<TId> {\n return { id, members };\n}\n\n/** Whether `entry` is a set rather than a single id. */\nexport function isToolSet<TId extends string>(entry: ToolEntry<TId>): entry is ToolSet<TId> {\n return typeof entry !== 'string';\n}\n\n/** Every id `entries` name, sets opened in place, each id once at its first place. */\nexport function toolIdsOf<TId extends string>(entries: readonly ToolEntry<TId>[]): TId[] {\n const out: TId[] = [];\n const seen = new Set<string>();\n const walk = (list: readonly ToolEntry<TId>[]): void => {\n for (const entry of list) {\n if (isToolSet(entry)) walk(entry.members);\n else if (!seen.has(entry)) {\n seen.add(entry);\n out.push(entry);\n }\n }\n };\n walk(entries);\n return out;\n}\n\n/** `set` less every id `omit` names, sets opened. Keeps `set`'s id with a `-without` suffix. */\nexport function withoutTools<TId extends string>(set: ToolSet<TId>, ...omit: readonly ToolEntry<TId>[]): ToolSet<TId> {\n const gone = new Set<string>(toolIdsOf(omit));\n return { id: `${set.id}-without`, members: toolIdsOf([set]).filter((id) => !gone.has(id)) };\n}\n\n/** Whether `set` names `id`, directly or through a set inside it. */\nexport function toolSetHas<TId extends string>(set: ToolSet<TId>, id: string): boolean {\n return (toolIdsOf([set]) as string[]).includes(id);\n}\n","/**\n * Key chords a major browser or the desktop under it takes before a page can:\n * reload, devtools, tab and window commands, menu accelerators. A binding on\n * one never fires for some users, so kit defaults steer clear of them.\n *\n * `mod` is Cmd on macOS and Ctrl elsewhere, as in a `KeySpec`. The list is\n * the union across Chrome, Safari, Firefox and Edge on macOS, Windows and\n * Linux, and errs toward listing a chord.\n */\nimport type { KeySpec } from '@weasel-js/gestures';\n\n/** One reserved chord, and what takes it. */\nexport interface ReservedChord {\n key: string;\n mod?: boolean;\n alt?: boolean;\n shift?: boolean;\n /** Who takes it, for a message. */\n use: string;\n}\n\nconst chord = (keys: string, mods: Omit<ReservedChord, 'key' | 'use'>, use: string): ReservedChord[] =>\n [...keys].map((key) => ({ key, ...mods, use }));\n\n/** Every chord the module's header describes, one entry per key. */\nexport const BROWSER_RESERVED_CHORDS: readonly ReservedChord[] = [\n ...chord('nqtwlrpmh', { mod: true }, 'new window, quit, new or close tab, address bar, reload, print, minimize, hide'),\n ...chord('ntwrbo', { mod: true, shift: true }, 'private window, reopen or close tab, hard reload, bookmarks, bookmark manager'),\n ...chord('ijck', { mod: true, shift: true }, 'devtools, console and inspector on Windows and Linux; Firefox Browser and Web Console'),\n ...chord('ijcukbrlemhdwfn', { mod: true, alt: true }, 'devtools, console, inspector, view source, bookmarks, reload from origin, downloads, empty caches, minimize all, hide others, Dock, close all, search field'),\n ...chord('fevsbthd', { alt: true }, 'menu accelerators and address bar on Windows and Linux'),\n ...chord('ita', { alt: true, shift: true }, 'feedback, toolbar focus and accessibility commands'),\n];\n\nconst lower = (k: string | readonly string[]): string[] => (typeof k === 'string' ? [k] : [...k]).map((x) => x.toLowerCase());\n\n/** Whether a modifier policy can be satisfied with the modifier held (`true`)\n * or released (`false`). */\nconst allows = (policy: boolean | 'optional' | undefined, held: boolean): boolean =>\n policy === 'optional' || (policy === true) === held;\n\n/** The first reserved chord `spec` can fire on, or `null` when none. */\nexport function browserReservedChord(spec: KeySpec): ReservedChord | null {\n const keys = lower(spec.key);\n const m = spec.mods ?? {};\n const mod = m.mod ?? (m.meta === true || m.ctrl === true ? true : m.meta ?? m.ctrl);\n for (const c of BROWSER_RESERVED_CHORDS) {\n if (!keys.includes(c.key)) continue;\n if (allows(mod, c.mod === true) && allows(m.alt, c.alt === true) && allows(m.shift, c.shift === true)) return c;\n }\n return null;\n}\n","/**\n * Typed keys for the gesture/behavior scratch store, `ctx.scratch`.\n * `ScratchKey<T>` carries its payload type at the typing layer; at runtime\n * the key is just its underlying string and the store remains a plain `Record`.\n *\n * @example\n * ```ts\n * // Module-level constant, shared by writer + reader:\n * const LASSO_VERTICES = scratchKey<readonly { x: number; y: number }[]>('lasso.vertices');\n * setScratch(ctx.scratch, LASSO_VERTICES, vertices);\n * const vertices = getScratch(ctx.scratch, LASSO_VERTICES) ?? [];\n * ```\n */\n\n/** Phantom-typed key for a scratch slot. The `__scratchKeyPayload` phantom\n * field carries the value type without occupying any runtime memory. */\nexport interface ScratchKey<T> {\n readonly name: string;\n /** Phantom — never read at runtime. Only present so TypeScript can\n * recover `T` at use sites. */\n readonly __scratchKeyPayload?: (_: T) => T;\n}\n\n/** Compatible scratch store shape. The kit's gesture context's `scratch`\n * field already satisfies this; consumers don't need to construct one. */\nexport type ScratchStore = Record<string, unknown>;\n\n/**\n * Make a typed scratch key. Two keys with the same `name` refer to the same\n * slot at runtime — the type parameter is a compile-time contract, not a\n * uniqueness guarantee — so namespace the name (`'behavior.field'`).\n */\nexport function scratchKey<T>(name: string): ScratchKey<T> {\n return { name };\n}\n\n/** Read a typed slot from the scratch store. Returns `undefined` if\n * nothing has been written under the key. */\nexport function getScratch<T>(\n store: ScratchStore,\n key: ScratchKey<T>,\n): T | undefined {\n return store[key.name] as T | undefined;\n}\n\n/** Write a value to a typed slot. Overwrites whatever was there. */\nexport function setScratch<T>(\n store: ScratchStore,\n key: ScratchKey<T>,\n value: T,\n): void {\n store[key.name] = value;\n}\n\n/** Remove a slot from the scratch store. Returns `true` if it was set,\n * `false` if it wasn't. */\nexport function deleteScratch<T>(\n store: ScratchStore,\n key: ScratchKey<T>,\n): boolean {\n if (Object.prototype.hasOwnProperty.call(store, key.name)) {\n delete store[key.name];\n return true;\n }\n return false;\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { p as Dispatcher, d as ActionsRegistry, C as Contribution, q as AffordanceHit, r as DispatchTrace, L as LongPressOptions, R as RuleCtx, s as DepSchema } from './index-HWqV4VxU.js';
|
|
2
2
|
import { RefObject } from 'react';
|
|
3
3
|
import { BodyClassification } from '@weasel-js/gestures';
|
|
4
4
|
import { PaintedCursorState, CursorSink } from '@weasel-js/cursor';
|
package/dist/internal.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { a as DispatcherViewTarget, V as ViewIdResolver } from './internal-
|
|
2
|
-
import './index-
|
|
1
|
+
export { a as DispatcherViewTarget, V as ViewIdResolver } from './internal-Bs9fhIXH.js';
|
|
2
|
+
import './index-HWqV4VxU.js';
|
|
3
3
|
import '@weasel-js/gestures';
|
|
4
4
|
import '@weasel-js/geom';
|
|
5
5
|
import '@weasel-js/cursor';
|
package/dist/react.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { U as UseGestureDispatcherOptions } from './internal-
|
|
2
|
-
export { D as DispatcherChannels } from './internal-
|
|
1
|
+
import { U as UseGestureDispatcherOptions } from './internal-Bs9fhIXH.js';
|
|
2
|
+
export { D as DispatcherChannels } from './internal-Bs9fhIXH.js';
|
|
3
3
|
import * as react from 'react';
|
|
4
4
|
import { ReactNode, ReactElement } from 'react';
|
|
5
|
-
import { D as DepRegistry, a as DepName, b as DepSource, S as ScopeNode, A as Action, c as ActionDeps, M as MenuHost, d as ActionsRegistry, e as ActionDisabledReason, B as BoundGesture, f as ActionVariant, g as MenuDef, h as DepNode, T as ToolNode, N as NodeId,
|
|
6
|
-
export {
|
|
5
|
+
import { D as DepRegistry, a as DepName, b as DepSource, S as ScopeNode, A as Action, c as ActionDeps, M as MenuHost, d as ActionsRegistry, e as ActionDisabledReason, B as BoundGesture, f as ActionVariant, g as MenuDef, h as DepNode, T as ToolNode, K as KeymapDescription, N as NodeId, i as KernelOverlay, C as Contribution, j as Tool, O as OverlayPosition } from './index-HWqV4VxU.js';
|
|
6
|
+
export { k as ActiveToolContextProvider, l as ActiveToolContextProviderIfRoot, m as ActiveToolContextProviderProps, n as ActiveToolContextValue, u as useActiveToolContext, o as useOptionalActiveToolContext } from './index-HWqV4VxU.js';
|
|
7
7
|
import { IconRef } from '@weasel-js/icons';
|
|
8
8
|
import { ModeRegistry } from '@weasel-js/modes';
|
|
9
9
|
import '@weasel-js/gestures';
|
|
@@ -53,6 +53,8 @@ declare class ActionsNode extends ScopeNode<ActionsNode> {
|
|
|
53
53
|
private readonly actions;
|
|
54
54
|
private readonly muted;
|
|
55
55
|
private readonly tunings;
|
|
56
|
+
private readonly overrides;
|
|
57
|
+
private overrideCache;
|
|
56
58
|
private readonly dispatchers;
|
|
57
59
|
private cache;
|
|
58
60
|
private host;
|
|
@@ -64,6 +66,8 @@ declare class ActionsNode extends ScopeNode<ActionsNode> {
|
|
|
64
66
|
private tuningsOf;
|
|
65
67
|
/** `a` under every tuning for its id from the root down to here. */
|
|
66
68
|
private tuned;
|
|
69
|
+
/** Every binding override from the root down to here, read into specs. */
|
|
70
|
+
private overridesHere;
|
|
67
71
|
private snapshot;
|
|
68
72
|
private deps;
|
|
69
73
|
/** The actions registered at this node itself, live, unmuted and tuned —
|
|
@@ -220,6 +224,10 @@ interface OngoingAction {
|
|
|
220
224
|
*/
|
|
221
225
|
declare function useOngoingAction(actionId: string): OngoingAction;
|
|
222
226
|
|
|
227
|
+
/** The innermost keymap open on the canvas in scope, described for a hint, or
|
|
228
|
+
* `null` while none is. Re-renders as keymaps open and close. */
|
|
229
|
+
declare function useOpenKeymap(): KeymapDescription | null;
|
|
230
|
+
|
|
223
231
|
/** World-space pointer position and the view it is over — a
|
|
224
232
|
* view id, or `null` for a surface's own camera. `null` as a whole when the
|
|
225
233
|
* pointer is over no publishing surface. */
|
|
@@ -412,4 +420,4 @@ declare function useContributions<TOverlay = KernelOverlay>(opts: UseContributio
|
|
|
412
420
|
*/
|
|
413
421
|
declare function useOffhandAction(entries: readonly Contribution<unknown>[]): void;
|
|
414
422
|
|
|
415
|
-
export { ActionsProvider, type CommandOptions, type ContributionsApi, DepRegistry, DepRegistryProvider, InputScope, type InputScopeProps, type OngoingAction, PointerContextProvider, type PointerContextValue, type PointerWorldPos, SelectionContextProvider, SelectionContextProviderIfRoot, type SelectionContextValue, type ToolsApi, type UseContributionsOptions, UseGestureDispatcherOptions, type UseToolsOptions, Yoke, type YokeProps, createPointerStore, useAction, useActionsRegistry, useCommand, useContributions, useDepRegistry, useDepSource, useGestureDispatcher, useMenuHost, useMenus, useOffhandAction, useOngoingAction, useOptionalDepRegistry, usePointerContext, usePointerPosition, usePublishSelection, useSelectionContext, useTools, useYoke };
|
|
423
|
+
export { ActionsProvider, type CommandOptions, type ContributionsApi, DepRegistry, DepRegistryProvider, InputScope, type InputScopeProps, type OngoingAction, PointerContextProvider, type PointerContextValue, type PointerWorldPos, SelectionContextProvider, SelectionContextProviderIfRoot, type SelectionContextValue, type ToolsApi, type UseContributionsOptions, UseGestureDispatcherOptions, type UseToolsOptions, Yoke, type YokeProps, createPointerStore, useAction, useActionsRegistry, useCommand, useContributions, useDepRegistry, useDepSource, useGestureDispatcher, useMenuHost, useMenus, useOffhandAction, useOngoingAction, useOpenKeymap, useOptionalDepRegistry, usePointerContext, usePointerPosition, usePublishSelection, useSelectionContext, useTools, useYoke };
|