cereb 0.8.1 → 0.9.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/README.md +145 -123
- package/dist/browser/dom-event/dom-event.d.ts +16 -1
- package/dist/browser/dom-event/dom-event.d.ts.map +1 -1
- package/dist/browser/keyboard/keyboard-held.d.ts +18 -30
- package/dist/browser/keyboard/keyboard-held.d.ts.map +1 -1
- package/dist/browser/keyboard/keyboard.d.ts +8 -26
- package/dist/browser/keyboard/keyboard.d.ts.map +1 -1
- package/dist/browser/keyboard/shared.d.ts +7 -0
- package/dist/browser/keyboard/shared.d.ts.map +1 -0
- package/dist/core/signal.d.ts +3 -1
- package/dist/core/signal.d.ts.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +244 -205
- package/dist/index.js.map +1 -1
- package/dist/operators/index.d.ts +0 -2
- package/dist/operators/index.d.ts.map +1 -1
- package/dist/operators/offset.d.ts +4 -2
- package/dist/operators/offset.d.ts.map +1 -1
- package/dist/operators/when.d.ts +1 -1
- package/dist/operators/when.d.ts.map +1 -1
- package/dist/operators.cjs +1 -1
- package/dist/operators.cjs.map +1 -1
- package/dist/operators.js +121 -142
- package/dist/operators.js.map +1 -1
- package/dist/recognizer-CGZKcxpa.js.map +1 -1
- package/dist/recognizer-DbiEtBOM.cjs.map +1 -1
- package/package.json +1 -1
- package/dist/operators/scan.d.ts +0 -31
- package/dist/operators/scan.d.ts.map +0 -1
- package/dist/operators/session-join.d.ts +0 -46
- package/dist/operators/session-join.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -1,175 +1,197 @@
|
|
|
1
1
|
# Cereb
|
|
2
2
|
|
|
3
|
-
User input
|
|
4
|
-
|
|
5
|
-
## Installation
|
|
3
|
+
**User input handling and orchestration** libray,
|
|
4
|
+
From low-level events (keyboard, wheel, pointer) to high-level gestures (pan, pinch)
|
|
6
5
|
|
|
7
6
|
```bash
|
|
8
|
-
npm install cereb
|
|
7
|
+
npm install --save cereb
|
|
9
8
|
```
|
|
10
9
|
|
|
11
|
-
##
|
|
10
|
+
## Getting started
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
Below is a minimal example for a **single pointer** stream.
|
|
12
|
+
The example below moves an element by tracking pointer position:
|
|
15
13
|
|
|
16
14
|
```typescript
|
|
17
15
|
import { singlePointer } from "cereb";
|
|
18
16
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
break;
|
|
32
|
-
}
|
|
33
|
-
});
|
|
17
|
+
// Create a stream from pointer events
|
|
18
|
+
singlePointer(canvas)
|
|
19
|
+
// Subscribe to monitor stream changes
|
|
20
|
+
.subscribe((signal) => {
|
|
21
|
+
// Receive signals from the stream
|
|
22
|
+
const { phase, x, y } = signal.value;
|
|
23
|
+
switch (phase){
|
|
24
|
+
case "move":
|
|
25
|
+
element.style.transform = `translate(${x}px, ${y}px)`;
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
});
|
|
34
29
|
```
|
|
35
30
|
|
|
36
|
-
##
|
|
31
|
+
## High-level gestures packages
|
|
37
32
|
|
|
38
|
-
|
|
39
|
-
- **Composable Pipelines** - Transform streams with operators like `filter`, `map`, `throttle`, and more
|
|
40
|
-
- **Stream Orchestration** - Schedule and coordinate multiple streams (coming soon)
|
|
41
|
-
- **Lightweight** - Minimal overhead for high-frequency input handling
|
|
33
|
+
For advanced gestures like pan or pinch, install dedicated packages that build on top of Cereb's core:
|
|
42
34
|
|
|
43
|
-
|
|
35
|
+
| Package | Description |
|
|
36
|
+
|---------|-------------|
|
|
37
|
+
| [@cereb/pan](https://www.npmjs.com/package/@cereb/pan) | Pan/drag gestures with velocity and direction tracking |
|
|
38
|
+
| [@cereb/pinch](https://www.npmjs.com/package/@cereb/pinch) | Pinch-to-zoom with distance and scale calculations |
|
|
44
39
|
|
|
45
|
-
###
|
|
40
|
+
### Pinch example
|
|
46
41
|
|
|
47
|
-
|
|
42
|
+
```bash
|
|
43
|
+
npm install --save cereb @cereb/pinch
|
|
44
|
+
```
|
|
48
45
|
|
|
49
46
|
```typescript
|
|
50
|
-
import { pipe
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
47
|
+
import { pipe } from "cereb";
|
|
48
|
+
import { zoom } from "cereb/operators";
|
|
49
|
+
import { pinch } from "@cereb/pinch";
|
|
50
|
+
|
|
51
|
+
// pipe creates a pipeline where signals flow through operators
|
|
52
|
+
// Each operator extends the signal (signals are immutable)
|
|
53
|
+
pipe(
|
|
54
|
+
pinch(element), // Create stream: a pinch gesture
|
|
55
|
+
zoom({ minScale: 0.5, maxScale: 3.0 }), // Operator: Determine scale value.
|
|
56
|
+
).subscribe((signal) => {
|
|
57
|
+
// The scale property is extended from the value.
|
|
58
|
+
// - pinch emits distance → zoom calculates scale
|
|
59
|
+
// - zoom also works with other inputs (keyboard, wheel, etc.)
|
|
60
|
+
element.style.transform = `scale(${signal.value.scale})`;
|
|
61
61
|
});
|
|
62
62
|
```
|
|
63
63
|
|
|
64
|
-
|
|
64
|
+
## API overview
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
const stream = pipe(
|
|
70
|
-
someStream,
|
|
71
|
-
session({
|
|
72
|
-
start: (signal) => signal.value.phase === "start",
|
|
73
|
-
end: (signal) => signal.value.phase === "end",
|
|
74
|
-
})
|
|
75
|
-
);
|
|
76
|
-
```
|
|
66
|
+
Full API docs are coming soon.
|
|
67
|
+
In the meantime, check the source—it's well-typed and commented:
|
|
77
68
|
|
|
78
|
-
|
|
69
|
+
- [Stream Factories](https://github.com/devphilip21/cereb/tree/main/packages/cereb/src/browser)
|
|
70
|
+
- [Operators](https://github.com/devphilip21/cereb/tree/main/packages/cereb/src/operators)
|
|
79
71
|
|
|
80
|
-
|
|
72
|
+
## The Problems Cereb Solves
|
|
81
73
|
|
|
82
|
-
|
|
83
|
-
import { domEvent, mouseEvents } from "cereb";
|
|
74
|
+
### 1. Event-Driven Code Becomes Spaghetti
|
|
84
75
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
You can also build a `singlePointer` stream from touch events:
|
|
76
|
+
Traditional event handlers create **scattered logic, side effects, and duplicated code** that's hard to maintain.
|
|
77
|
+
See how this plays out in a multi-input zoom implementation:
|
|
90
78
|
|
|
91
79
|
```typescript
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
);
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
80
|
+
// Before: Scattered handlers, shared state, duplicated logic
|
|
81
|
+
let currentScale = 1;
|
|
82
|
+
let isCtrlPressed = false;
|
|
83
|
+
|
|
84
|
+
// Track Ctrl key
|
|
85
|
+
window.addEventListener('keydown', e => {
|
|
86
|
+
if (e.key === 'Control' || e.key === 'Meta') isCtrlPressed = true;
|
|
87
|
+
|
|
88
|
+
if (isCtrlPressed && (e.key === '+' || e.key === '-')) {
|
|
89
|
+
e.preventDefault();
|
|
90
|
+
currentScale = Math.max(0.2, Math.min(5, currentScale + (e.key === '+' ? 0.15 : -0.15)));
|
|
91
|
+
applyScale(currentScale); // Duplicated min/max logic
|
|
92
|
+
}
|
|
93
|
+
});
|
|
104
94
|
|
|
105
|
-
|
|
95
|
+
window.addEventListener('keyup', e => {
|
|
96
|
+
if (e.key === 'Control' || e.key === 'Meta') isCtrlPressed = false;
|
|
97
|
+
});
|
|
106
98
|
|
|
107
|
-
|
|
108
|
-
|
|
99
|
+
// Ctrl + Wheel
|
|
100
|
+
canvas.addEventListener('wheel', e => {
|
|
101
|
+
if (!isCtrlPressed) return;
|
|
102
|
+
e.preventDefault();
|
|
103
|
+
currentScale = Math.max(0.2, Math.min(5, currentScale + (-e.deltaY * 0.005)));
|
|
104
|
+
applyScale(currentScale); // Duplicated min/max logic again
|
|
105
|
+
});
|
|
109
106
|
|
|
110
|
-
|
|
107
|
+
// Pinch gesture (touchstart/touchmove/touchend)
|
|
108
|
+
// ... 20+ lines: track two fingers, calculate distance, apply scale
|
|
109
|
+
// ... min/max logic duplicated yet again
|
|
111
110
|
|
|
112
|
-
|
|
113
|
-
stream$.block(); // Pause event processing
|
|
114
|
-
stream$.unblock(); // Resume event processing
|
|
111
|
+
// Problem: 6+ scattered handlers, shared state, logic duplicated 3 times
|
|
115
112
|
```
|
|
116
113
|
|
|
117
|
-
|
|
114
|
+
<br>
|
|
118
115
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
| `offset` | Add element-relative `offsetX`, `offsetY` to pointer signals |
|
|
116
|
+
Cereb's solution:
|
|
117
|
+
Model events as streams, and you get readable, reusable, extensible declarative pipelines.
|
|
122
118
|
|
|
123
119
|
```typescript
|
|
124
|
-
|
|
120
|
+
// After: Clear flow, no side effects, composable
|
|
121
|
+
import { pipe, keyboard, keyboardHeld, wheel } from "cereb";
|
|
122
|
+
import { zoom, extend, when } from "cereb/operators";
|
|
123
|
+
import { pinch } from "@cereb/pinch";
|
|
124
|
+
|
|
125
|
+
const MIN_SCALE = 0.2, MAX_SCALE = 5;
|
|
126
|
+
let currentScale = 1;
|
|
127
|
+
|
|
128
|
+
// Pinch-to-zoom (touch)
|
|
129
|
+
pipe(
|
|
130
|
+
pinch(canvas),
|
|
131
|
+
zoom({ minScale: MIN_SCALE, maxScale: MAX_SCALE })
|
|
132
|
+
).subscribe(applyZoom);
|
|
133
|
+
|
|
134
|
+
// Ctrl/Cmd + Plus/Minus (keyboard)
|
|
135
|
+
pipe(
|
|
136
|
+
keyboard(window, { key: ["+", "-"], preventDefault: true }),
|
|
137
|
+
when(keyboardHeld(window, { modifiers: ["meta", "ctrl"] })),
|
|
138
|
+
extend((signal) => ({
|
|
139
|
+
ratio: currentScale + (signal.value.key === "+" ? 0.15 : -0.15)
|
|
140
|
+
})),
|
|
141
|
+
zoom({ minScale: MIN_SCALE, maxScale: MAX_SCALE })
|
|
142
|
+
).subscribe(applyZoom);
|
|
143
|
+
|
|
144
|
+
// Ctrl/Cmd + Wheel (mouse)
|
|
145
|
+
pipe(
|
|
146
|
+
wheel(canvas, { modifiers: ["meta", "ctrl"], preventDefault: true }),
|
|
147
|
+
extend((signal) => ({
|
|
148
|
+
ratio: currentScale + (-signal.value.deltaY * 0.005)
|
|
149
|
+
})),
|
|
150
|
+
zoom({ minScale: MIN_SCALE, maxScale: MAX_SCALE })
|
|
151
|
+
).subscribe(applyZoom);
|
|
152
|
+
|
|
153
|
+
function applyZoom(signal) {
|
|
154
|
+
currentScale = signal.value.scale;
|
|
155
|
+
canvas.style.transform = `scale(${currentScale})`;
|
|
156
|
+
}
|
|
157
|
+
```
|
|
125
158
|
|
|
126
|
-
|
|
127
|
-
singlePointer(element),
|
|
128
|
-
offset({ target: element }) // includes offsetX, offsetY relative to target element
|
|
129
|
-
);
|
|
159
|
+
### 2. Lightweight Bundle Size
|
|
130
160
|
|
|
131
|
-
|
|
132
|
-
const { x, y, offsetX, offsetY } = signal.value;
|
|
133
|
-
});
|
|
134
|
-
```
|
|
161
|
+
Benchmark: Equivalent pan gesture implementation
|
|
135
162
|
|
|
136
|
-
|
|
163
|
+
| | Minified | Gzipped |
|
|
164
|
+
|--|----------|---------|
|
|
165
|
+
| cereb + @cereb/pan | 4.58 KB | **1.73 KB** |
|
|
166
|
+
| Hammer.js | 20.98 KB | 7.52 KB |
|
|
137
167
|
|
|
138
|
-
|
|
168
|
+
**~77% smaller** than Hammer.js for equivalent pan gesture functionality.
|
|
139
169
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
| `map` | Transform each value |
|
|
144
|
-
| `throttle` | Limit emission rate |
|
|
145
|
-
| `debounce` | Delay until quiet period |
|
|
146
|
-
| `take` / `skip` | Control emission count |
|
|
147
|
-
| `merge` | Combine multiple streams |
|
|
148
|
-
| `share` | Multicast to multiple subscribers |
|
|
149
|
-
| `distinctUntilChanged` | Skip consecutive duplicates |
|
|
170
|
+
### 3. Performance & Resource Efficiency
|
|
171
|
+
|
|
172
|
+
**1. Event Listener Reuse**
|
|
150
173
|
|
|
151
174
|
```typescript
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
);
|
|
175
|
+
// Before: Multiple addEventListener calls
|
|
176
|
+
window.addEventListener('keydown', handler1);
|
|
177
|
+
window.addEventListener('keydown', handler2);
|
|
178
|
+
window.addEventListener('keydown', handler3);
|
|
179
|
+
|
|
180
|
+
// After: Shared stream, single listener
|
|
181
|
+
// addEventListener called once
|
|
182
|
+
keyboard(window).subscribe(handler1);
|
|
183
|
+
keyboard(window).subscribe(handler2);
|
|
184
|
+
keyboard(window).subscribe(handler3);
|
|
160
185
|
```
|
|
161
186
|
|
|
162
|
-
|
|
187
|
+
**2. Single Responsibility Operators**
|
|
163
188
|
|
|
164
189
|
```typescript
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
// You can subscribe to events from multiple sources as one stream.
|
|
171
|
-
// This example simply merges, but you can orchestrate behavior with pipelines and operators.
|
|
172
|
-
const combined$ = merge(keyboard$, pointer$);
|
|
190
|
+
pipe(
|
|
191
|
+
pan(element), // Pan gesture recognition
|
|
192
|
+
offset({ target }), // Element-relative coordinates
|
|
193
|
+
axisLock() // Lock to horizontal/vertical
|
|
194
|
+
)
|
|
173
195
|
```
|
|
174
196
|
|
|
175
197
|
## License
|
|
@@ -1,4 +1,19 @@
|
|
|
1
1
|
import { Stream } from '../../core/stream.js';
|
|
2
2
|
import { DomEventSignal } from './dom-event-signal.js';
|
|
3
|
-
|
|
3
|
+
type AnyEventMap = Record<string, Event>;
|
|
4
|
+
/**
|
|
5
|
+
* Strongly-typed event target for custom event maps.
|
|
6
|
+
* Useful for non-DOM EventTargets that still have named events.
|
|
7
|
+
*/
|
|
8
|
+
export type TypedEventTarget<M extends AnyEventMap> = EventTarget & {
|
|
9
|
+
addEventListener<K extends keyof M>(type: K, listener: (event: M[K]) => void, options?: AddEventListenerOptions): void;
|
|
10
|
+
removeEventListener<K extends keyof M>(type: K, listener: (event: M[K]) => void, options?: AddEventListenerOptions): void;
|
|
11
|
+
};
|
|
12
|
+
export declare function domEvent<K extends keyof WindowEventMap>(target: Window, eventName: K, options?: AddEventListenerOptions): Stream<DomEventSignal<WindowEventMap[K]>>;
|
|
13
|
+
export declare function domEvent<K extends keyof DocumentEventMap>(target: Document, eventName: K, options?: AddEventListenerOptions): Stream<DomEventSignal<DocumentEventMap[K]>>;
|
|
14
|
+
export declare function domEvent<K extends keyof HTMLElementEventMap>(target: HTMLElement, eventName: K, options?: AddEventListenerOptions): Stream<DomEventSignal<HTMLElementEventMap[K]>>;
|
|
15
|
+
export declare function domEvent<K extends keyof SVGElementEventMap>(target: SVGElement, eventName: K, options?: AddEventListenerOptions): Stream<DomEventSignal<SVGElementEventMap[K]>>;
|
|
16
|
+
export declare function domEvent<M extends AnyEventMap, K extends keyof M>(target: TypedEventTarget<M>, eventName: K, options?: AddEventListenerOptions): Stream<DomEventSignal<M[K]>>;
|
|
17
|
+
export declare function domEvent<E extends Event = Event>(target: EventTarget, eventName: string, options?: AddEventListenerOptions): Stream<DomEventSignal<E>>;
|
|
18
|
+
export {};
|
|
4
19
|
//# sourceMappingURL=dom-event.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dom-event.d.ts","sourceRoot":"","sources":["../../../src/browser/dom-event/dom-event.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EAAwB,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAElF,wBAAgB,QAAQ,
|
|
1
|
+
{"version":3,"file":"dom-event.d.ts","sourceRoot":"","sources":["../../../src/browser/dom-event/dom-event.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EAAwB,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAElF,KAAK,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AAEzC;;;GAGG;AACH,MAAM,MAAM,gBAAgB,CAAC,CAAC,SAAS,WAAW,IAAI,WAAW,GAAG;IAClE,gBAAgB,CAAC,CAAC,SAAS,MAAM,CAAC,EAChC,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,EAC/B,OAAO,CAAC,EAAE,uBAAuB,GAChC,IAAI,CAAC;IACR,mBAAmB,CAAC,CAAC,SAAS,MAAM,CAAC,EACnC,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,EAC/B,OAAO,CAAC,EAAE,uBAAuB,GAChC,IAAI,CAAC;CACT,CAAC;AAEF,wBAAgB,QAAQ,CAAC,CAAC,SAAS,MAAM,cAAc,EACrD,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,CAAC,EACZ,OAAO,CAAC,EAAE,uBAAuB,GAChC,MAAM,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7C,wBAAgB,QAAQ,CAAC,CAAC,SAAS,MAAM,gBAAgB,EACvD,MAAM,EAAE,QAAQ,EAChB,SAAS,EAAE,CAAC,EACZ,OAAO,CAAC,EAAE,uBAAuB,GAChC,MAAM,CAAC,cAAc,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC/C,wBAAgB,QAAQ,CAAC,CAAC,SAAS,MAAM,mBAAmB,EAC1D,MAAM,EAAE,WAAW,EACnB,SAAS,EAAE,CAAC,EACZ,OAAO,CAAC,EAAE,uBAAuB,GAChC,MAAM,CAAC,cAAc,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAClD,wBAAgB,QAAQ,CAAC,CAAC,SAAS,MAAM,kBAAkB,EACzD,MAAM,EAAE,UAAU,EAClB,SAAS,EAAE,CAAC,EACZ,OAAO,CAAC,EAAE,uBAAuB,GAChC,MAAM,CAAC,cAAc,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACjD,wBAAgB,QAAQ,CAAC,CAAC,SAAS,WAAW,EAAE,CAAC,SAAS,MAAM,CAAC,EAC/D,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAC3B,SAAS,EAAE,CAAC,EACZ,OAAO,CAAC,EAAE,uBAAuB,GAChC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChC,wBAAgB,QAAQ,CAAC,CAAC,SAAS,KAAK,GAAG,KAAK,EAC9C,MAAM,EAAE,WAAW,EACnB,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,uBAAuB,GAChC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC"}
|
|
@@ -1,55 +1,43 @@
|
|
|
1
1
|
import { Signal } from '../../core/signal.js';
|
|
2
2
|
import { Stream } from '../../core/stream.js';
|
|
3
3
|
import { ModifierKey } from './keyboard.js';
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
interface HeldValue {
|
|
5
|
+
opened: boolean;
|
|
6
6
|
}
|
|
7
|
-
export interface HeldSignal extends Signal<"held", HeldValue> {
|
|
7
|
+
export interface HeldSignal extends Signal<"keyboard-held", HeldValue> {
|
|
8
8
|
}
|
|
9
|
-
export declare const HELD_SIGNAL_KIND: "held";
|
|
9
|
+
export declare const HELD_SIGNAL_KIND: "keyboard-held";
|
|
10
10
|
export interface KeyboardHeldOptions {
|
|
11
11
|
/**
|
|
12
12
|
* The key to track. Case-insensitive.
|
|
13
|
-
* @example 'z', '
|
|
13
|
+
* @example 'z', 'Space', 'Escape'
|
|
14
14
|
*/
|
|
15
15
|
key: string;
|
|
16
16
|
/**
|
|
17
17
|
* Modifier keys that must also be held. Uses OR logic.
|
|
18
|
+
*
|
|
19
|
+
* ⚠️ WARNING: On macOS, OS-level modifiers (especially Meta/Command) can swallow
|
|
20
|
+
* keyup events. This is a known platform limitation, not a bug. For reliable
|
|
21
|
+
* "hold to activate" behavior, prefer using non-modifier keys (Space, Shift, etc.)
|
|
22
|
+
* as the primary key instead of relying on modifier combinations.
|
|
23
|
+
*
|
|
18
24
|
* @example ['meta', 'ctrl'] - matches if metaKey OR ctrlKey is pressed
|
|
19
25
|
*/
|
|
20
26
|
modifiers?: ModifierKey[];
|
|
21
27
|
}
|
|
22
28
|
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* Automatically shares the keyboard stream for the same EventTarget, so multiple
|
|
26
|
-
* keyboardHeld calls on the same target reuse the same underlying event listeners.
|
|
27
|
-
*
|
|
28
|
-
* This function correctly handles the case where modifier keys are released before
|
|
29
|
-
* the main key. It tracks the main key's down/up state independently and checks
|
|
30
|
-
* modifier states from each keyboard event.
|
|
31
|
-
*
|
|
32
|
-
* @param target - EventTarget to listen for keyboard events (e.g., window, document, element)
|
|
33
|
-
* @param options - Key and modifier configuration
|
|
34
|
-
* @returns Stream that emits { held: true } when conditions are met, { held: false } otherwise
|
|
29
|
+
* Tracks whether a specific key (with optional modifiers) is being held down.
|
|
30
|
+
* Emits only when state changes.
|
|
35
31
|
*
|
|
36
32
|
* @example
|
|
37
33
|
* ```typescript
|
|
38
|
-
* //
|
|
39
|
-
* const
|
|
40
|
-
* key: 'z',
|
|
41
|
-
* modifiers: ['meta', 'ctrl']
|
|
42
|
-
* });
|
|
43
|
-
*
|
|
44
|
-
* // Multiple calls on same target share the keyboard stream
|
|
45
|
-
* const isXHeld$ = keyboardHeld(window, { key: 'x' });
|
|
34
|
+
* // Prefer: use non-modifier key for reliable hold detection
|
|
35
|
+
* const spaceHeld$ = keyboardHeld(window, { key: 'Space' });
|
|
46
36
|
*
|
|
47
|
-
* //
|
|
48
|
-
*
|
|
49
|
-
* wheel(element),
|
|
50
|
-
* when(isZoomModeHeld$)
|
|
51
|
-
* ).subscribe(...)
|
|
37
|
+
* // Caution: modifier combos may miss keyup on macOS
|
|
38
|
+
* const cmdZHeld$ = keyboardHeld(window, { key: 'z', modifiers: ['meta'] });
|
|
52
39
|
* ```
|
|
53
40
|
*/
|
|
54
41
|
export declare function keyboardHeld(target: EventTarget, options: KeyboardHeldOptions): Stream<HeldSignal>;
|
|
42
|
+
export {};
|
|
55
43
|
//# sourceMappingURL=keyboard-held.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keyboard-held.d.ts","sourceRoot":"","sources":["../../../src/browser/keyboard/keyboard-held.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAEnD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"keyboard-held.d.ts","sourceRoot":"","sources":["../../../src/browser/keyboard/keyboard-held.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAEnD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAEnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAIjD,UAAU,SAAS;IACjB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,UAAW,SAAQ,MAAM,CAAC,eAAe,EAAE,SAAS,CAAC;CAAG;AAEzE,eAAO,MAAM,gBAAgB,EAAG,eAAwB,CAAC;AAEzD,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;;;;;;;;OASG;IACH,SAAS,CAAC,EAAE,WAAW,EAAE,CAAC;CAC3B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,mBAAmB,GAC3B,MAAM,CAAC,UAAU,CAAC,CA+EpB"}
|
|
@@ -2,39 +2,21 @@ import { Stream } from '../../core/stream.js';
|
|
|
2
2
|
import { KeyboardSignal } from './keyboard-signal.js';
|
|
3
3
|
export type ModifierKey = "meta" | "ctrl" | "alt" | "shift";
|
|
4
4
|
export interface KeyboardOptions {
|
|
5
|
-
/**
|
|
6
|
-
* Filter by key value(s). Uses OR logic if array.
|
|
7
|
-
* Comparison is case-insensitive.
|
|
8
|
-
* @example 'z' or ['+', '-', '=']
|
|
9
|
-
*/
|
|
5
|
+
/** Filter by key value(s). Case-insensitive. Uses OR logic if array. */
|
|
10
6
|
key?: string | string[];
|
|
11
|
-
/**
|
|
12
|
-
* Filter by modifier keys. Uses OR logic (matches if any is pressed).
|
|
13
|
-
* @example ['meta', 'ctrl'] - matches if metaKey OR ctrlKey is pressed
|
|
14
|
-
*/
|
|
7
|
+
/** Filter by modifier keys. Uses OR logic. */
|
|
15
8
|
modifiers?: ModifierKey[];
|
|
16
|
-
/**
|
|
17
|
-
* If true, calls preventDefault() on matching events.
|
|
18
|
-
* @default false
|
|
19
|
-
*/
|
|
9
|
+
/** If true, calls preventDefault() on matching events. @default false */
|
|
20
10
|
preventDefault?: boolean;
|
|
11
|
+
/** If true, allows repeated keydown events. @default false */
|
|
12
|
+
allowRepeat?: boolean;
|
|
21
13
|
}
|
|
22
14
|
/**
|
|
23
|
-
* Creates a
|
|
24
|
-
* Optionally filters by key and/or modifier keys.
|
|
15
|
+
* Creates a keyboard signal stream. Shares underlying listeners per EventTarget.
|
|
25
16
|
*
|
|
26
17
|
* @example
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
* keyboard(window).subscribe(signal => {
|
|
30
|
-
* console.log(signal.value.key, signal.value.phase);
|
|
31
|
-
* });
|
|
32
|
-
*
|
|
33
|
-
* // Only +/- keys with Ctrl or Cmd
|
|
34
|
-
* keyboard(window, { key: ['+', '-'], modifiers: ['meta', 'ctrl'] }).subscribe(signal => {
|
|
35
|
-
* // zoom in/out
|
|
36
|
-
* });
|
|
37
|
-
* ```
|
|
18
|
+
* keyboard(window).subscribe(signal => console.log(signal.value.key));
|
|
19
|
+
* keyboard(window, { key: 'z', modifiers: ['meta'] }).subscribe(handleUndo);
|
|
38
20
|
*/
|
|
39
21
|
export declare function keyboard(target: EventTarget, options?: KeyboardOptions): Stream<KeyboardSignal>;
|
|
40
22
|
//# sourceMappingURL=keyboard.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keyboard.d.ts","sourceRoot":"","sources":["../../../src/browser/keyboard/keyboard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,
|
|
1
|
+
{"version":3,"file":"keyboard.d.ts","sourceRoot":"","sources":["../../../src/browser/keyboard/keyboard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG3D,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,CAAC;AAE5D,MAAM,WAAW,eAAe;IAC9B,wEAAwE;IACxE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACxB,8CAA8C;IAC9C,SAAS,CAAC,EAAE,WAAW,EAAE,CAAC;IAC1B,yEAAyE;IACzE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,8DAA8D;IAC9D,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,MAAM,CAAC,cAAc,CAAC,CA2D/F"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Stream } from '../../core/stream.js';
|
|
2
|
+
import { KeyboardSignal } from './keyboard-signal.js';
|
|
3
|
+
/** Shared keyboard stream for the given target. */
|
|
4
|
+
export declare function getSharedKeyboard(target: EventTarget): Stream<KeyboardSignal>;
|
|
5
|
+
/** Shared keyboard stream filtered by a specific key. Filters out repeated events. */
|
|
6
|
+
export declare function getSharedKeyboardForKey(target: EventTarget, key: string): Stream<KeyboardSignal>;
|
|
7
|
+
//# sourceMappingURL=shared.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../../src/browser/keyboard/shared.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAEjE,OAAO,EAAiC,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAyB1F,mDAAmD;AACnD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAAC,cAAc,CAAC,CAO7E;AAED,sFAAsF;AACtF,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC,cAAc,CAAC,CA4BhG"}
|
package/dist/core/signal.d.ts
CHANGED
|
@@ -9,7 +9,9 @@ export interface Signal<K extends string = string, V = unknown> {
|
|
|
9
9
|
* Utility type to extend a Signal's value type with additional properties.
|
|
10
10
|
* Used by operators that add computed properties to signals.
|
|
11
11
|
*/
|
|
12
|
-
export type ExtendSignalValue<T extends Signal, Additional> =
|
|
12
|
+
export type ExtendSignalValue<T extends Signal, Additional> = Omit<T, "value"> & {
|
|
13
|
+
readonly value: T["value"] & Additional;
|
|
14
|
+
};
|
|
13
15
|
/**
|
|
14
16
|
* Utility type to constrain a Signal to have specific value properties.
|
|
15
17
|
* Used by operators that require certain properties in the input signal.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signal.d.ts","sourceRoot":"","sources":["../../src/core/signal.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,MAAM,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,CAAC,GAAG,OAAO;IAC5D,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IACjB,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;IAClB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;GAGG;AACH,MAAM,MAAM,iBAAiB,CAAC,CAAC,SAAS,MAAM,EAAE,UAAU,IAAI,
|
|
1
|
+
{"version":3,"file":"signal.d.ts","sourceRoot":"","sources":["../../src/core/signal.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,MAAM,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,CAAC,GAAG,OAAO;IAC5D,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IACjB,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;IAClB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;GAGG;AACH,MAAM,MAAM,iBAAiB,CAAC,CAAC,SAAS,MAAM,EAAE,UAAU,IAAI,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG;IAC/E,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,UAAU,CAAC;CACzC,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,UAAU,CAAC,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;AAE9C,wBAAgB,YAAY,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,CAAC,GAAG,OAAO,EACjE,IAAI,EAAE,CAAC,EACP,KAAK,EAAE,CAAC,GACP,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAOd"}
|
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const d=require("./stream-Cp6eCZs2.cjs"),m=require("./recognizer-DbiEtBOM.cjs"),I=require("./share-DT0L7vCb.cjs"),F=require("./types-BGR5Mhw9.cjs"),q=require("./single-pointer/pointer.cjs"),$="dom-event";function L(e){return m.createSignal($,e)}function U(e,r,o){return d.createStream(t=>{const n=a=>{t.next(L(a))};return e.addEventListener(r,n,o),()=>{e.removeEventListener(r,n,o)}})}const K=["mousedown","mousemove","mouseup"];function V(e,r){return d.createStream(o=>{const t=n=>{o.next(L(n))};for(let n=0;n<K.length;n++){const a=K[n];e.addEventListener(a,t,r)}return()=>{for(let n=0;n<K.length;n++){const a=K[n];e.removeEventListener(a,t,r)}}})}const S=["pointerdown","pointermove","pointerup","pointercancel"];function N(e,r){return d.createStream(o=>{const t=n=>{o.next(L(n))};for(let n=0;n<S.length;n++){const a=S[n];e.addEventListener(a,t,r)}return()=>{for(let n=0;n<S.length;n++){const a=S[n];e.removeEventListener(a,t,r)}}})}const E=["touchstart","touchmove","touchend","touchcancel"];function B(e,r){return d.createStream(o=>{const t=n=>{o.next(L(n))};for(let n=0;n<E.length;n++){const a=E[n];e.addEventListener(a,t,r)}return()=>{for(let n=0;n<E.length;n++){const a=E[n];e.removeEventListener(a,t,r)}}})}const _="keyboard";function M(e){return m.createSignal(_,e)}function P(e,r){return M({phase:r,key:e.key,code:e.code,repeat:e.repeat,altKey:e.altKey,ctrlKey:e.ctrlKey,metaKey:e.metaKey,shiftKey:e.shiftKey,originalEvent:e})}const b=new WeakMap,x=new WeakMap;function Z(e){return d.createStream(r=>{const o=n=>{r.next(P(n,"down"))},t=n=>{r.next(P(n,"up"))};return e.addEventListener("keydown",o),e.addEventListener("keyup",t),()=>{e.removeEventListener("keydown",o),e.removeEventListener("keyup",t)}})}function w(e){let r=b.get(e);return r||(r=I.share()(Z(e)),b.set(e,r)),r}function T(e,r){const o=r.toLowerCase();let t=x.get(e);t||(t=new Map,x.set(e,t));let n=t.get(o);if(!n){const a=w(e),s=d.createStream(i=>a.subscribe({next(u){u.value.repeat||u.value.key.toLowerCase()===o&&i.next(u)},error:i.error?.bind(i),complete:i.complete?.bind(i)}));n=I.share()(s),t.set(o,n)}return n}function j(e,r){if(!r)return w(e);const o=r.modifiers,t=r.preventDefault??!1,n=r.allowRepeat??!1,a=typeof r.key=="string",s=r.key&&Array.isArray(r.key)?r.key.map(c=>c.toLowerCase()):null,i=a?T(e,r.key):w(e);if(a&&!o&&!t&&!n)return i;const u=c=>s?s.includes(c.toLowerCase()):!0,f=c=>!o||o.length===0?!0:o.some(l=>{switch(l){case"meta":return c.metaKey;case"ctrl":return c.ctrlKey;case"alt":return c.altKey;case"shift":return c.shiftKey;default:return!1}});return d.createStream(c=>i.subscribe({next(l){const{key:y,repeat:k}=l.value;!n&&k||u(y)&&f(l.value)&&(t&&l.value.originalEvent.preventDefault(),c.next(l))},error:c.error?.bind(c),complete:c.complete?.bind(c)}))}const A="keyboard-held";function J(e,r){const{key:o,modifiers:t}=r,n=o.toLowerCase(),s=t&&t.length>0?w(e):T(e,o),i=new Set;if(t)for(const c of t)c==="meta"&&i.add("meta"),c==="ctrl"&&i.add("control"),c==="alt"&&i.add("alt"),c==="shift"&&i.add("shift");const u=c=>i.has(c.toLowerCase()),f=c=>!t||t.length===0?!0:t.some(l=>{switch(l){case"meta":return c.metaKey;case"ctrl":return c.ctrlKey;case"alt":return c.altKey;case"shift":return c.shiftKey;default:return!1}});return d.createStream(c=>{let l=!1,y;const k=h=>{h!==y&&(y=h,c.next(m.createSignal(A,{opened:h})))};return s.subscribe({next(h){try{const{key:p,phase:v,repeat:z}=h.value;if(z)return;const G=p.toLowerCase()===n,O=u(p);G?l=v==="down":(v==="down"||O&&v==="up")&&(l=!1);const X=f(h.value);k(l&&X)}catch(p){c.error?.(p)}},error:c.error?.bind(c),complete:c.complete?.bind(c)})})}const Q="multi-pointer";function ee(e){return m.createSignal(Q,e)}function te(e,r={}){const o={maxPointers:r.maxPointers??2},t=new Map;let n="idle";function a(s,i){return s===0?n==="active"&&i>0?"ended":"idle":"active"}return{process(s){const i=e(s,t,o);if(i===null)return null;const u=i.endedPointerIds;for(const y of u)t.delete(y);const f=Array.from(t.values()),c=a(f.length,u.length);n=c==="ended"?"idle":c;const l={phase:c,pointers:f,count:f.length};return ee(l)},get isActive(){return t.size>0},get activeCount(){return t.size},reset(){t.clear(),n="idle"},dispose(){this.reset()}}}function re(e={}){function r(o,t,n){const a=o.value,s=`${a.pointerType}-${a.pointerId}`,i=[];switch(a.type){case"pointerdown":{if(t.size>=n.maxPointers)return null;t.set(s,g(a,"start"));break}case"pointermove":{if(!t.has(s))return null;t.set(s,g(a,"move"));break}case"pointerup":{if(!t.has(s))return null;t.set(s,g(a,"end")),i.push(s);break}case"pointercancel":{if(!t.has(s))return null;t.set(s,g(a,"cancel")),i.push(s);break}default:return null}return{pointers:t,endedPointerIds:i}}return te(r,e)}function C(e={}){return r=>d.createStream(o=>{const t=re(e),n=r.subscribe({next(a){const s=t.process(a);s&&o.next(s)},error(a){o.error?.(a)},complete(){o.complete?.()}});return()=>{n(),t.dispose()}})}function g(e,r){const o=r==="start"||r==="end"?F.toSinglePointerButton(e.button):"none";return{id:`${e.pointerType}-${e.pointerId}`,phase:r,x:e.clientX,y:e.clientY,pageX:e.pageX,pageY:e.pageY,pointerType:ne(e.pointerType),button:o,pressure:e.pressure}}function ne(e){switch(e){case"mouse":return"mouse";case"touch":return"touch";case"pen":return"pen";default:return"unknown"}}function oe(e,r={}){const o=N(e);return C(r)(o)}function ce(e,r={}){const o=N(e);return q.singlePointerRecognizer(r)(o)}const W="wheel";function H(e){return m.createSignal(W,e)}function ae(e){switch(e){case 0:return"pixel";case 1:return"line";case 2:return"page";default:return"pixel"}}function R(e){return H({deltaX:e.deltaX,deltaY:e.deltaY,deltaZ:e.deltaZ,deltaMode:ae(e.deltaMode),x:e.clientX,y:e.clientY,pageX:e.pageX,pageY:e.pageY,altKey:e.altKey,ctrlKey:e.ctrlKey,metaKey:e.metaKey,shiftKey:e.shiftKey,originalEvent:e})}const D=new WeakMap;function ie(e,r){let o=D.get(e);o||(o=new Map,D.set(e,o));let t=o.get(r);return t||(t=I.share()(se(e,r)),o.set(r,t)),t}function se(e,r){return d.createStream(o=>{const t=n=>{o.next(R(n))};return e.addEventListener("wheel",t,{passive:r}),()=>{e.removeEventListener("wheel",t)}})}function ue(e,r){const o=r?.passive??!0,t=r?.modifiers,n=r?.preventDefault??!1,a=ie(e,o);if(!t?.length&&!n)return a;const s=i=>!t||t.length===0?!0:t.some(u=>{switch(u){case"meta":return i.metaKey;case"ctrl":return i.ctrlKey;case"alt":return i.altKey;case"shift":return i.shiftKey;default:return!1}});return d.createStream(i=>a.subscribe({next(u){try{s(u.value)&&(n&&u.value.originalEvent.preventDefault(),i.next(u))}catch(f){i.error?.(f)}},error:i.error?.bind(i),complete:i.complete?.bind(i)}))}function le(...e){return r=>Y(r,...e)}function Y(e,...r){return r.reduce((o,t)=>t(o),e)}exports.createStream=d.createStream;exports.createSignal=m.createSignal;exports.setCerebDeviceId=m.setCerebDeviceId;exports.HELD_SIGNAL_KIND=A;exports.KEYBOARD_SIGNAL_KIND=_;exports.WHEEL_SIGNAL_KIND=W;exports.compose=le;exports.createKeyboardSignal=M;exports.createKeyboardSignalFromEvent=P;exports.createWheelSignal=H;exports.createWheelSignalFromEvent=R;exports.domEvent=U;exports.keyboard=j;exports.keyboardHeld=J;exports.mouseEvents=V;exports.multiPointer=oe;exports.multiPointerFromPointer=C;exports.pipe=Y;exports.pointerEvents=N;exports.singlePointer=ce;exports.touchEvents=B;exports.wheel=ue;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|