@weasel-js/gestures 1.11.0 → 1.11.1
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/index.d.ts +42 -4
- package/dist/index.js +90 -14
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -81,10 +81,13 @@ type RoutePhase = 'initial' | 'engaged';
|
|
|
81
81
|
* argSlot = '(' argValue ')' -- whitespace inside parens is significant
|
|
82
82
|
* targetSlot = '=>' WS targetValue -- omitted slot defaults to '*' for hasTarget
|
|
83
83
|
* modSlot = modAtom (WS modAtom)*
|
|
84
|
-
* modAtom = sigil modName
|
|
84
|
+
* modAtom = sigil (modName | 'held')
|
|
85
85
|
* sigil = '+' | '?' -- ! @ # $ % ^ & * reserved as id-prefix
|
|
86
86
|
* modName = 'mod' | 'shift' | 'alt' | 'ctrl' | 'meta'
|
|
87
87
|
*
|
|
88
|
+
* `held` is a pressed button, read as a modifier is: `?held` a button may be
|
|
89
|
+
* held, `+held` one must be, absent none may. Only `hover` takes it.
|
|
90
|
+
*
|
|
88
91
|
* The truly-loose form (any channel, any phase) is `[*:*]`.
|
|
89
92
|
*
|
|
90
93
|
* Examples:
|
|
@@ -152,6 +155,9 @@ interface ParsedRoute {
|
|
|
152
155
|
target: string | undefined;
|
|
153
156
|
/** Structured modifier requirements; empty map = "no modifiers held". */
|
|
154
157
|
modifiers: ParsedModifiers;
|
|
158
|
+
/** Whether a pressed button may or must be held. Absent, none may. Only on
|
|
159
|
+
* `hover`. */
|
|
160
|
+
held?: ModRequirement;
|
|
155
161
|
}
|
|
156
162
|
/** Parse a route string into its slots, filling in the shorthand defaults the
|
|
157
163
|
* grammar defines (bare phases mean channel `&`; an omitted arg or target
|
|
@@ -338,7 +344,8 @@ interface PointerDownSpec {
|
|
|
338
344
|
}
|
|
339
345
|
/**
|
|
340
346
|
* The pointer moving over the surface with no button pressed. Fires on every
|
|
341
|
-
* such move; a held pointer's moves belong to its drag and fire nothing here
|
|
347
|
+
* such move; a held pointer's moves belong to its drag and fire nothing here,
|
|
348
|
+
* unless `held` says otherwise.
|
|
342
349
|
*
|
|
343
350
|
* With `motion: 'leave'` it fires instead when the pointer passes out of what
|
|
344
351
|
* the binding targets: onto something its `target` does not match, or off the
|
|
@@ -349,11 +356,16 @@ interface PointerDownSpec {
|
|
|
349
356
|
* runs, not only the best one, and the move still reaches the hover-cursor
|
|
350
357
|
* pump. There is no press to own, so bind an immediate action, not an ongoing
|
|
351
358
|
* one. Its params carry `worldX` / `worldY`, `clientX` / `clientY`,
|
|
352
|
-
* `affordance`, `bodyTarget`, and `
|
|
359
|
+
* `affordance`, `bodyTarget`, `mods`, and `held`.
|
|
353
360
|
*/
|
|
354
361
|
interface HoverSpec {
|
|
355
362
|
kind: 'hover';
|
|
356
363
|
motion?: 'move' | 'leave';
|
|
364
|
+
/** Whether a pressed button may (`'optional'`) or must (`true`) be held, as
|
|
365
|
+
* `mods` says of a modifier; omitted, a held pointer's moves are not hovers.
|
|
366
|
+
* Such a binding still claims nothing, so the drag keeps its moves. Leaving
|
|
367
|
+
* the surface is a leave whether or not a button is held. */
|
|
368
|
+
held?: true | 'optional';
|
|
357
369
|
target?: TargetSpec;
|
|
358
370
|
mods?: ModSpec;
|
|
359
371
|
phase?: PhaseSpec;
|
|
@@ -410,10 +422,15 @@ interface DropSpec {
|
|
|
410
422
|
* its moves update it, the release commits it, and leaving the surface or
|
|
411
423
|
* canceling the press cancels it. An immediate action fires once, on the
|
|
412
424
|
* release.
|
|
425
|
+
*
|
|
426
|
+
* `target` is matched against what is under the carry. With one, an ongoing
|
|
427
|
+
* action starts on the first step that is over its target, as the carry comes
|
|
428
|
+
* over or as it moves on, and an immediate action fires only on a release over it.
|
|
413
429
|
*/
|
|
414
430
|
interface CarrySpec {
|
|
415
431
|
kind: 'carry';
|
|
416
432
|
types?: string[];
|
|
433
|
+
target?: TargetSpec;
|
|
417
434
|
mods?: ModSpec;
|
|
418
435
|
phase?: PhaseSpec;
|
|
419
436
|
}
|
|
@@ -795,6 +812,8 @@ interface HoverEvent extends EventModifiers {
|
|
|
795
812
|
from?: HoverWhere;
|
|
796
813
|
/** The pointer has left the surface. Where it is and what it is over are its last move's. */
|
|
797
814
|
off?: boolean;
|
|
815
|
+
/** A button was held through this move. Never set on `off`. */
|
|
816
|
+
held?: boolean;
|
|
798
817
|
/** World-space position of the pointer. */
|
|
799
818
|
x: number;
|
|
800
819
|
y: number;
|
|
@@ -899,6 +918,10 @@ interface CarryEvent extends EventModifiers {
|
|
|
899
918
|
y: number;
|
|
900
919
|
clientX: number;
|
|
901
920
|
clientY: number;
|
|
921
|
+
/** What is under the carry, classified as a press there would be. */
|
|
922
|
+
affordance?: unknown;
|
|
923
|
+
bodyTarget?: BodyTarget;
|
|
924
|
+
bodyKind?: BodyKind;
|
|
902
925
|
}
|
|
903
926
|
/** External content pasted from the system clipboard. Carries no point. */
|
|
904
927
|
interface PasteEvent extends EventModifiers {
|
|
@@ -1168,6 +1191,14 @@ declare function formatShortcut(b: ShortcutInput | undefined, opts?: FormatShort
|
|
|
1168
1191
|
*/
|
|
1169
1192
|
declare function keySpecsFromShortcut(shortcut: ShortcutInput | undefined, opts?: KeySpecsFromModsOptions): readonly KeyLegend[] | undefined;
|
|
1170
1193
|
|
|
1194
|
+
/**
|
|
1195
|
+
* The legend of the physical key a `KeyboardEvent.code` names (`KeyA`, `ShiftLeft`, `ArrowUp`), as
|
|
1196
|
+
* {@link keySpecFromKey} prints that key on the platform: `MetaLeft` is `⌘` on macOS and `⊞` on
|
|
1197
|
+
* Windows. Letters and punctuation print as a US keyboard prints them. `opts.labels` answers by code
|
|
1198
|
+
* first, then as it does for {@link keySpecFromKey} and {@link keySpecsFromMods}.
|
|
1199
|
+
*/
|
|
1200
|
+
declare function keySpecFromCode(code: string, opts?: KeySpecsFromModsOptions): KeyLegend;
|
|
1201
|
+
|
|
1171
1202
|
/**
|
|
1172
1203
|
* The nearest element `from` sits inside that can host a portalled overlay,
|
|
1173
1204
|
* or `null` when there is none and the body is the only answer.
|
|
@@ -1356,6 +1387,13 @@ interface PointerSample extends EventModifiers, PointerSampleStylus {
|
|
|
1356
1387
|
clientY: number;
|
|
1357
1388
|
/** What the originating event was aimed at. */
|
|
1358
1389
|
target?: unknown;
|
|
1390
|
+
/**
|
|
1391
|
+
* When the input happened, on the recognizer clock's timeline: a DOM event's
|
|
1392
|
+
* `timeStamp` beside `performance.now()`. The windows between two inputs are
|
|
1393
|
+
* measured on it, so a long task that delays an event's handling does not
|
|
1394
|
+
* widen them. Read as the clock's `now()` when absent, 0, or ahead of it.
|
|
1395
|
+
*/
|
|
1396
|
+
timeStamp?: number;
|
|
1359
1397
|
}
|
|
1360
1398
|
/** A pointer going down, with what the host found under it. */
|
|
1361
1399
|
interface PressSample extends PointerSample {
|
|
@@ -1485,4 +1523,4 @@ declare function activatesFocusedControl(e: KeyboardEvent): boolean;
|
|
|
1485
1523
|
*/
|
|
1486
1524
|
declare function focusedControlOwnsKey(e: KeyboardEvent): boolean;
|
|
1487
1525
|
|
|
1488
|
-
export { ACTIVE_SIGILS, type BodyClassification, type BodyKind, type BodyTarget, CONTROL_SELECTOR, type CarryEvent, type CarrySpec, type ChannelRef, type ClaimableGesture, type ClickEvent, type ClickMemory, type ClickObserver, type ClickSpec, type ContextMenuEvent, type ContextMenuSpec, DOUBLE_CLICK_MAX_MS, DOUBLE_CLICK_MAX_PX, DRAG_THRESHOLD_PX, type DescribeRouteOptions, type DoubleClickBody, type DoubleClickEvent, type DoubleClickSpec, type DragSpec, type DropEvent, type DropSpec, type EventModifiers, type FixedSeat, type FormatShortcutOptions, GESTURE_DESCRIPTORS, type GestureArgSpec, type GestureDescriptor, type GestureName, type GestureSpec, type HeldPointers, type HeldPress, type HoverEvent, type HoverSpec, type HoverWhere, type IngestItem, type InputEvent, type KeyEvent, type KeyHeldEvent, type KeyHeldSpec, type KeyLabels, type KeyLegend, type KeySpec, type KeySpecsFromModsOptions, LONG_PRESS_MS, type LegendStyle, type LogicalMod, type LogicalModSpec, type LongPressEvent, type LongPressSpec, MODIFIER_LABELS, MOD_NAME_SET, type ModRequirement, type ModSpec, type ModifierCombo, type ModifierKey, type ModifiersEvent, type MultiTouchEvent, type MultiTouchGeometry, type MultiTouchSpec, type MultiTouchTapEvent, type MultiTouchTapSpec, type OptionalMod, type ParsedKeyRoute, type ParsedModifiers, type ParsedRoute, type PasteEvent, type PasteSpec, type PhaseAtom, type PhaseContext, type PhaseSpec, type PinchEvent, type PinchSpec, type Platform, type Point, type PointerCancelEvent, type PointerDownEvent, type PointerDownSpec, type PointerIdentity, type PointerMoveEvent, type PointerRecognizer, type PointerRecognizerOptions, type PointerSample, type PointerSampleStylus, type PointerUpEvent, type PressFacts, type PressSample, RESERVED_ID_NAMES, RESERVED_ID_PREFIXES, RESERVED_SIGILS, ROUTE_FIELD_DEFINITIONS, ROUTE_TERMS, type RecognizerClock, type RecognizerObserver, type RecognizerSink, type ReleaseFacts, type ReleaseOutcome, type RouteDescriptionPart, type RouteFieldName, type RoutePhase, type RouteTermLabel, type ShortcutInput, TAP_THRESHOLD_PX, type TargetPredicate, type TargetSpec, type TargetSpecForm, UNKNOWN_MIME, VALID_MOD_NAMES, type WheelEvent, type WheelSpec, activatesFocusedControl, bodyPredicate, canonicalModifiers, clickEvents, collapseShiftPairs, createPointerRecognizer, describeRoute, describeRouteParts, detectPlatform, fixedSeat, focusedControlOwnsKey, formatKeyRoute, formatPhaseAtom, formatRoute, formatShortcut, formatShortcutParts, getGestureDescriptor, heldPointers, hitPredicate, isApplePlatform, isEditableTarget, isInControlWithin, isKnownGestureName, keyRouteToSpec, keySpecFromKey, keySpecsFromMods, keySpecsFromShortcut, longPressEvents, matchIngestTypes, matchKey, matchModifiers, matchPhase, matchSpec, matchTarget, mimeMatchesGlob, modifierComboToParsed, mods, multiTouchGeometry, nearestPortalHost, parseKeyRoute, parseRoute, parseTargetSpec, pastDragThreshold, routeGestureForSpecKind, routeToSpec, specKindForRouteGesture, specificity, stylusOf };
|
|
1526
|
+
export { ACTIVE_SIGILS, type BodyClassification, type BodyKind, type BodyTarget, CONTROL_SELECTOR, type CarryEvent, type CarrySpec, type ChannelRef, type ClaimableGesture, type ClickEvent, type ClickMemory, type ClickObserver, type ClickSpec, type ContextMenuEvent, type ContextMenuSpec, DOUBLE_CLICK_MAX_MS, DOUBLE_CLICK_MAX_PX, DRAG_THRESHOLD_PX, type DescribeRouteOptions, type DoubleClickBody, type DoubleClickEvent, type DoubleClickSpec, type DragSpec, type DropEvent, type DropSpec, type EventModifiers, type FixedSeat, type FormatShortcutOptions, GESTURE_DESCRIPTORS, type GestureArgSpec, type GestureDescriptor, type GestureName, type GestureSpec, type HeldPointers, type HeldPress, type HoverEvent, type HoverSpec, type HoverWhere, type IngestItem, type InputEvent, type KeyEvent, type KeyHeldEvent, type KeyHeldSpec, type KeyLabels, type KeyLegend, type KeySpec, type KeySpecsFromModsOptions, LONG_PRESS_MS, type LegendStyle, type LogicalMod, type LogicalModSpec, type LongPressEvent, type LongPressSpec, MODIFIER_LABELS, MOD_NAME_SET, type ModRequirement, type ModSpec, type ModifierCombo, type ModifierKey, type ModifiersEvent, type MultiTouchEvent, type MultiTouchGeometry, type MultiTouchSpec, type MultiTouchTapEvent, type MultiTouchTapSpec, type OptionalMod, type ParsedKeyRoute, type ParsedModifiers, type ParsedRoute, type PasteEvent, type PasteSpec, type PhaseAtom, type PhaseContext, type PhaseSpec, type PinchEvent, type PinchSpec, type Platform, type Point, type PointerCancelEvent, type PointerDownEvent, type PointerDownSpec, type PointerIdentity, type PointerMoveEvent, type PointerRecognizer, type PointerRecognizerOptions, type PointerSample, type PointerSampleStylus, type PointerUpEvent, type PressFacts, type PressSample, RESERVED_ID_NAMES, RESERVED_ID_PREFIXES, RESERVED_SIGILS, ROUTE_FIELD_DEFINITIONS, ROUTE_TERMS, type RecognizerClock, type RecognizerObserver, type RecognizerSink, type ReleaseFacts, type ReleaseOutcome, type RouteDescriptionPart, type RouteFieldName, type RoutePhase, type RouteTermLabel, type ShortcutInput, TAP_THRESHOLD_PX, type TargetPredicate, type TargetSpec, type TargetSpecForm, UNKNOWN_MIME, VALID_MOD_NAMES, type WheelEvent, type WheelSpec, activatesFocusedControl, bodyPredicate, canonicalModifiers, clickEvents, collapseShiftPairs, createPointerRecognizer, describeRoute, describeRouteParts, detectPlatform, fixedSeat, focusedControlOwnsKey, formatKeyRoute, formatPhaseAtom, formatRoute, formatShortcut, formatShortcutParts, getGestureDescriptor, heldPointers, hitPredicate, isApplePlatform, isEditableTarget, isInControlWithin, isKnownGestureName, keyRouteToSpec, keySpecFromCode, keySpecFromKey, keySpecsFromMods, keySpecsFromShortcut, longPressEvents, matchIngestTypes, matchKey, matchModifiers, matchPhase, matchSpec, matchTarget, mimeMatchesGlob, modifierComboToParsed, mods, multiTouchGeometry, nearestPortalHost, parseKeyRoute, parseRoute, parseTargetSpec, pastDragThreshold, routeGestureForSpecKind, routeToSpec, specKindForRouteGesture, specificity, stylusOf };
|
package/dist/index.js
CHANGED
|
@@ -18,7 +18,7 @@ var GESTURE_DESCRIPTORS = [
|
|
|
18
18
|
// matches any payload, which is what an omitted arg slot means for a
|
|
19
19
|
// `'free'` arg.
|
|
20
20
|
{ name: "drop", hasTarget: false, arg: { name: "types", values: "free" } },
|
|
21
|
-
{ name: "carry", hasTarget:
|
|
21
|
+
{ name: "carry", hasTarget: true, arg: { name: "types", values: "free" } },
|
|
22
22
|
{ name: "paste", hasTarget: false, arg: { name: "types", values: "free" } }
|
|
23
23
|
];
|
|
24
24
|
var BY_NAME = new Map(
|
|
@@ -107,6 +107,7 @@ function parseRoute(input) {
|
|
|
107
107
|
target = "*";
|
|
108
108
|
}
|
|
109
109
|
const modifiers = {};
|
|
110
|
+
let held;
|
|
110
111
|
while (rest.length > 0) {
|
|
111
112
|
const ch = rest[0];
|
|
112
113
|
if (RESERVED_SIGILS.has(ch)) {
|
|
@@ -120,6 +121,13 @@ function parseRoute(input) {
|
|
|
120
121
|
const nameMatch = /^([a-z]+)/.exec(rest);
|
|
121
122
|
if (!nameMatch) throw new Error(`invalid route (sigil "${sigil}" without modifier name): ${input}`);
|
|
122
123
|
const name = nameMatch[1];
|
|
124
|
+
if (name === HELD) {
|
|
125
|
+
if (gestureName !== "hover") throw new Error(`invalid route (${gestureName} takes no "${HELD}"): ${input}`);
|
|
126
|
+
if (held !== void 0) throw new Error(`invalid route (duplicate "${HELD}"): ${input}`);
|
|
127
|
+
held = sigil === "+" ? "required" : "optional";
|
|
128
|
+
rest = rest.slice(nameMatch[0].length).trimStart();
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
123
131
|
if (!MOD_NAME_SET.has(name)) {
|
|
124
132
|
throw new Error(`invalid route (unknown modifier "${name}"): ${input}`);
|
|
125
133
|
}
|
|
@@ -129,8 +137,9 @@ function parseRoute(input) {
|
|
|
129
137
|
modifiers[name] = sigil === "+" ? "required" : "optional";
|
|
130
138
|
rest = rest.slice(nameMatch[0].length).trimStart();
|
|
131
139
|
}
|
|
132
|
-
return { phases, gesture: gestureName, arg, target, modifiers };
|
|
140
|
+
return { phases, gesture: gestureName, arg, target, modifiers, ...held ? { held } : {} };
|
|
133
141
|
}
|
|
142
|
+
var HELD = "held";
|
|
134
143
|
function parsePhaseList(raw, input) {
|
|
135
144
|
if (raw === "") throw new Error(`invalid route (empty phase list): ${input}`);
|
|
136
145
|
const tokens = raw.split(",").map((p) => p.trim()).filter((p) => p.length > 0);
|
|
@@ -204,6 +213,7 @@ function collapseShiftPairs(routes) {
|
|
|
204
213
|
}
|
|
205
214
|
function isShiftTwin(a, b) {
|
|
206
215
|
if (a.gesture !== b.gesture) return false;
|
|
216
|
+
if (a.held !== b.held) return false;
|
|
207
217
|
if (a.arg !== b.arg) return false;
|
|
208
218
|
if (a.target !== b.target) return false;
|
|
209
219
|
if (!samePhases(a.phases, b.phases)) return false;
|
|
@@ -246,6 +256,8 @@ function formatRoute(r) {
|
|
|
246
256
|
if (req === "required") out += ` +${name}`;
|
|
247
257
|
else if (req === "optional") out += ` ?${name}`;
|
|
248
258
|
}
|
|
259
|
+
if (r.held === "required") out += ` +${HELD}`;
|
|
260
|
+
else if (r.held === "optional") out += ` ?${HELD}`;
|
|
249
261
|
return out;
|
|
250
262
|
}
|
|
251
263
|
|
|
@@ -474,6 +486,7 @@ function matchSpec(e, spec, isMac, phaseCtx) {
|
|
|
474
486
|
case "hover": {
|
|
475
487
|
if (e.kind !== "hover") return false;
|
|
476
488
|
if (!matchModifiers(e, spec.mods, isMac)) return false;
|
|
489
|
+
if (!e.off && (e.held === true ? spec.held === void 0 : spec.held === true)) return false;
|
|
477
490
|
const on = !e.off && matchTarget(e.affordance, spec.target, e.bodyTarget, e.bodyKind);
|
|
478
491
|
if (spec.motion !== "leave") return on;
|
|
479
492
|
return !on && e.from !== void 0 && matchTarget(e.from.affordance, spec.target, e.from.bodyTarget, e.from.bodyKind);
|
|
@@ -503,8 +516,10 @@ function matchSpec(e, spec, isMac, phaseCtx) {
|
|
|
503
516
|
function matchArrival(e, spec, isMac) {
|
|
504
517
|
if (e.kind !== spec.kind) return false;
|
|
505
518
|
if (e.kind === "carry") {
|
|
506
|
-
|
|
519
|
+
const target = "target" in spec ? spec.target : void 0;
|
|
520
|
+
if (e.stage === "leave" || e.stage === "move" && target === void 0) return false;
|
|
507
521
|
if (!matchIngestTypes([{ mime: e.type }], spec.types)) return false;
|
|
522
|
+
if (!matchTarget(e.affordance, target, e.bodyTarget, e.bodyKind)) return false;
|
|
508
523
|
} else if (e.kind === "drop" || e.kind === "paste") {
|
|
509
524
|
if (!matchIngestTypes(e.items, spec.types)) return false;
|
|
510
525
|
}
|
|
@@ -574,7 +589,12 @@ function routeToSpec(parsed) {
|
|
|
574
589
|
case void 0:
|
|
575
590
|
return fail(`${parsed.gesture} has no GestureSpec kind`);
|
|
576
591
|
case "hover":
|
|
577
|
-
return withMods({
|
|
592
|
+
return withMods({
|
|
593
|
+
kind,
|
|
594
|
+
...arg === "leave" ? { motion: "leave" } : {},
|
|
595
|
+
...parsed.held ? { held: parsed.held === "required" ? true : "optional" } : {},
|
|
596
|
+
...t
|
|
597
|
+
});
|
|
578
598
|
case "click":
|
|
579
599
|
case "pointerDown":
|
|
580
600
|
case "doubleClick":
|
|
@@ -598,8 +618,9 @@ function routeToSpec(parsed) {
|
|
|
598
618
|
case "multiTouchTap":
|
|
599
619
|
if (arg === void 0) return fail(`a ${kind} spec needs concrete fingers`);
|
|
600
620
|
return withMods({ kind, fingers: Number(arg) });
|
|
601
|
-
case "drop":
|
|
602
621
|
case "carry":
|
|
622
|
+
return withMods({ kind, ...arg ? { types: arg.split("|") } : {}, ...t });
|
|
623
|
+
case "drop":
|
|
603
624
|
case "paste":
|
|
604
625
|
return withMods({ kind, ...arg ? { types: arg.split("|") } : {} });
|
|
605
626
|
}
|
|
@@ -669,6 +690,11 @@ function targetClause(target, hasTarget) {
|
|
|
669
690
|
if (target === "empty") return " on empty canvas";
|
|
670
691
|
return ` on a ${target}`;
|
|
671
692
|
}
|
|
693
|
+
function carryOnto(target) {
|
|
694
|
+
if (target === void 0 || target === "*") return "onto the canvas";
|
|
695
|
+
if (target === "empty") return "onto empty canvas";
|
|
696
|
+
return `onto a ${target}`;
|
|
697
|
+
}
|
|
672
698
|
function concreteArg(parsed) {
|
|
673
699
|
return parsed.arg === "*" ? void 0 : parsed.arg;
|
|
674
700
|
}
|
|
@@ -709,8 +735,11 @@ function actionClause(parsed, required) {
|
|
|
709
735
|
return userDoes(required, `clicks${target}`);
|
|
710
736
|
case "pointerDown":
|
|
711
737
|
return userDoes(required, `presses${target}`);
|
|
712
|
-
case "hover":
|
|
713
|
-
|
|
738
|
+
case "hover": {
|
|
739
|
+
const held = parsed.held === "required" ? " with a button held" : parsed.held === "optional" ? " whether or not a button is held" : "";
|
|
740
|
+
const where = arg === "leave" ? ` ${leftClause(parsed.target)}` : target;
|
|
741
|
+
return userDoes(required, `moves the pointer${where}${held}`);
|
|
742
|
+
}
|
|
714
743
|
case "dblTap":
|
|
715
744
|
return userDoes(required, `double-taps${target}`);
|
|
716
745
|
case "drag":
|
|
@@ -718,7 +747,7 @@ function actionClause(parsed, required) {
|
|
|
718
747
|
case "drop":
|
|
719
748
|
return userDoes(required, `drops ${arg ?? "any"} content onto the canvas`);
|
|
720
749
|
case "carry":
|
|
721
|
-
return userDoes(required, `carries ${arg ?? "anything"}
|
|
750
|
+
return userDoes(required, `carries ${arg ?? "anything"} ${carryOnto(parsed.target)}`);
|
|
722
751
|
case "paste":
|
|
723
752
|
return userDoes(required, `pastes ${arg ?? "any"} content`);
|
|
724
753
|
}
|
|
@@ -892,6 +921,45 @@ function keySpecsFromShortcut(shortcut, opts = {}) {
|
|
|
892
921
|
return key === void 0 ? keys : [...keys, keySpecFromKey(key, opts)];
|
|
893
922
|
}
|
|
894
923
|
|
|
924
|
+
// src/ui/keySpecFromCode.ts
|
|
925
|
+
var MOD_CODES = {
|
|
926
|
+
ShiftLeft: "shift",
|
|
927
|
+
ShiftRight: "shift",
|
|
928
|
+
ControlLeft: "ctrl",
|
|
929
|
+
ControlRight: "ctrl",
|
|
930
|
+
AltLeft: "alt",
|
|
931
|
+
AltRight: "alt",
|
|
932
|
+
MetaLeft: "meta",
|
|
933
|
+
MetaRight: "meta"
|
|
934
|
+
};
|
|
935
|
+
var PRINTED = {
|
|
936
|
+
Backquote: "`",
|
|
937
|
+
Minus: "-",
|
|
938
|
+
Equal: "=",
|
|
939
|
+
BracketLeft: "[",
|
|
940
|
+
BracketRight: "]",
|
|
941
|
+
Backslash: "\\",
|
|
942
|
+
Semicolon: ";",
|
|
943
|
+
Quote: "'",
|
|
944
|
+
Comma: ",",
|
|
945
|
+
Period: ".",
|
|
946
|
+
Slash: "/",
|
|
947
|
+
IntlBackslash: "\xA7",
|
|
948
|
+
CapsLock: "Caps",
|
|
949
|
+
Fn: "fn"
|
|
950
|
+
};
|
|
951
|
+
function keySpecFromCode(code, opts = {}) {
|
|
952
|
+
const own = opts.labels?.[code];
|
|
953
|
+
if (own !== void 0) return { label: own };
|
|
954
|
+
const mod = MOD_CODES[code];
|
|
955
|
+
if (mod) return keySpecsFromMods([{ name: mod }], opts)[0];
|
|
956
|
+
const char = /^Key([A-Z])$/.exec(code) ?? /^Digit(\d)$/.exec(code);
|
|
957
|
+
if (char) return keySpecFromKey(char[1], opts);
|
|
958
|
+
if (code === "NumpadEnter") return keySpecFromKey("Enter", opts);
|
|
959
|
+
const printed = PRINTED[code];
|
|
960
|
+
return printed !== void 0 ? { label: printed } : keySpecFromKey(code, opts);
|
|
961
|
+
}
|
|
962
|
+
|
|
895
963
|
// src/ui/formatShortcut.ts
|
|
896
964
|
var labels = (b, opts) => b ? keySpecsFromShortcut({ ...b, shift: b.shift === true }, opts)?.map((k) => k.label) : void 0;
|
|
897
965
|
function formatShortcutParts(b, opts = {}) {
|
|
@@ -1191,6 +1259,13 @@ function thresholdsOf(opts) {
|
|
|
1191
1259
|
})
|
|
1192
1260
|
};
|
|
1193
1261
|
}
|
|
1262
|
+
function sampleTime(clock) {
|
|
1263
|
+
return (s) => {
|
|
1264
|
+
const now = clock.now();
|
|
1265
|
+
const t = s.timeStamp;
|
|
1266
|
+
return t !== void 0 && t > 0 && t <= now ? t : now;
|
|
1267
|
+
};
|
|
1268
|
+
}
|
|
1194
1269
|
function createPointerRecognizer(opts) {
|
|
1195
1270
|
const { sink, clock, observer = {}, toSurface = (p) => p } = opts;
|
|
1196
1271
|
const world = (s) => opts.toWorld?.(s.clientX, s.clientY) ?? { x: s.clientX, y: s.clientY };
|
|
@@ -1202,12 +1277,13 @@ function createPointerRecognizer(opts) {
|
|
|
1202
1277
|
observer.holdChanged?.(pending);
|
|
1203
1278
|
});
|
|
1204
1279
|
const geometry = (extra = []) => heldGeometry(held, toSurface, extra);
|
|
1205
|
-
const
|
|
1280
|
+
const happenedAt = sampleTime(clock);
|
|
1281
|
+
const claimForMultiTouch = (s) => {
|
|
1206
1282
|
hold.cancel();
|
|
1207
1283
|
for (const p of held.values()) p.buffered = null;
|
|
1208
1284
|
const g = geometry();
|
|
1209
|
-
touches.join(positionsOf(held), g.centroid,
|
|
1210
|
-
sink.dispatch(multiTouchEvent(held.size,
|
|
1285
|
+
touches.join(positionsOf(held), g.centroid, happenedAt(s));
|
|
1286
|
+
sink.dispatch(multiTouchEvent(held.size, s, g));
|
|
1211
1287
|
};
|
|
1212
1288
|
return {
|
|
1213
1289
|
press(s) {
|
|
@@ -1251,7 +1327,7 @@ function createPointerRecognizer(opts) {
|
|
|
1251
1327
|
if (before >= 2 && held.size < 2) {
|
|
1252
1328
|
const fingers = touches.finish(
|
|
1253
1329
|
geometry([{ x: s.clientX, y: s.clientY }]).centroid,
|
|
1254
|
-
|
|
1330
|
+
happenedAt(s),
|
|
1255
1331
|
longPressMs()
|
|
1256
1332
|
);
|
|
1257
1333
|
if (fingers !== null) sink.dispatch({ kind: "multitouchtap", fingers, ...modifiersOf(s) });
|
|
@@ -1267,7 +1343,7 @@ function createPointerRecognizer(opts) {
|
|
|
1267
1343
|
worldY: at2.y,
|
|
1268
1344
|
...modifiersOf(s)
|
|
1269
1345
|
};
|
|
1270
|
-
return composeClick(rec.down, up, clicks, () =>
|
|
1346
|
+
return composeClick(rec.down, up, clicks, () => happenedAt(s), (ev) => sink.dispatch(ev), observer, doubleClick());
|
|
1271
1347
|
},
|
|
1272
1348
|
cancel(pointerId) {
|
|
1273
1349
|
const rec = held.get(pointerId);
|
|
@@ -1421,6 +1497,6 @@ function focusedControlOwnsKey(e) {
|
|
|
1421
1497
|
return activatesFocusedControl(e) || selectOwnsKey(e);
|
|
1422
1498
|
}
|
|
1423
1499
|
|
|
1424
|
-
export { ACTIVE_SIGILS, CONTROL_SELECTOR, DOUBLE_CLICK_MAX_MS, DOUBLE_CLICK_MAX_PX, DRAG_THRESHOLD_PX, GESTURE_DESCRIPTORS, LONG_PRESS_MS, MODIFIER_LABELS, MOD_NAME_SET, RESERVED_ID_NAMES, RESERVED_ID_PREFIXES, RESERVED_SIGILS, ROUTE_FIELD_DEFINITIONS, ROUTE_TERMS, TAP_THRESHOLD_PX, UNKNOWN_MIME, VALID_MOD_NAMES, activatesFocusedControl, bodyPredicate, canonicalModifiers, clickEvents, collapseShiftPairs, createPointerRecognizer, describeRoute, describeRouteParts, detectPlatform, fixedSeat, focusedControlOwnsKey, formatKeyRoute, formatPhaseAtom, formatRoute, formatShortcut, formatShortcutParts, getGestureDescriptor, heldPointers, hitPredicate, isApplePlatform, isEditableTarget, isInControlWithin, isKnownGestureName, keyRouteToSpec, keySpecFromKey, keySpecsFromMods, keySpecsFromShortcut, longPressEvents, matchIngestTypes, matchKey, matchModifiers, matchPhase, matchSpec, matchTarget, mimeMatchesGlob, modifierComboToParsed, mods, multiTouchGeometry, nearestPortalHost, parseKeyRoute, parseRoute, parseTargetSpec, pastDragThreshold, routeGestureForSpecKind, routeToSpec, specKindForRouteGesture, specificity, stylusOf };
|
|
1500
|
+
export { ACTIVE_SIGILS, CONTROL_SELECTOR, DOUBLE_CLICK_MAX_MS, DOUBLE_CLICK_MAX_PX, DRAG_THRESHOLD_PX, GESTURE_DESCRIPTORS, LONG_PRESS_MS, MODIFIER_LABELS, MOD_NAME_SET, RESERVED_ID_NAMES, RESERVED_ID_PREFIXES, RESERVED_SIGILS, ROUTE_FIELD_DEFINITIONS, ROUTE_TERMS, TAP_THRESHOLD_PX, UNKNOWN_MIME, VALID_MOD_NAMES, activatesFocusedControl, bodyPredicate, canonicalModifiers, clickEvents, collapseShiftPairs, createPointerRecognizer, describeRoute, describeRouteParts, detectPlatform, fixedSeat, focusedControlOwnsKey, formatKeyRoute, formatPhaseAtom, formatRoute, formatShortcut, formatShortcutParts, getGestureDescriptor, heldPointers, hitPredicate, isApplePlatform, isEditableTarget, isInControlWithin, isKnownGestureName, keyRouteToSpec, keySpecFromCode, keySpecFromKey, keySpecsFromMods, keySpecsFromShortcut, longPressEvents, matchIngestTypes, matchKey, matchModifiers, matchPhase, matchSpec, matchTarget, mimeMatchesGlob, modifierComboToParsed, mods, multiTouchGeometry, nearestPortalHost, parseKeyRoute, parseRoute, parseTargetSpec, pastDragThreshold, routeGestureForSpecKind, routeToSpec, specKindForRouteGesture, specificity, stylusOf };
|
|
1425
1501
|
//# sourceMappingURL=index.js.map
|
|
1426
1502
|
//# sourceMappingURL=index.js.map
|