cereb 0.11.4 → 0.11.6
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 +23 -132
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Cereb
|
|
1
|
+
# [Cereb](https://cereb.dev)
|
|
2
2
|
|
|
3
3
|
**User input handling and orchestration** libray,
|
|
4
4
|
From low-level events (keyboard, wheel, pointer, ...) to high-level gestures (pan, pinch, ...)
|
|
@@ -63,148 +63,39 @@ pinch(element)
|
|
|
63
63
|
|
|
64
64
|
<br>
|
|
65
65
|
|
|
66
|
-
##
|
|
66
|
+
## Documentation
|
|
67
67
|
|
|
68
|
-
|
|
69
|
-
In the meantime, check the source—it's well-typed and commented:
|
|
68
|
+
### Stream API
|
|
70
69
|
|
|
71
|
-
|
|
72
|
-
- [Operators](https://github.com/devphilip21/cereb/tree/main/packages/cereb/src/operators)
|
|
70
|
+
Create streams from various input sources:
|
|
73
71
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
72
|
+
| API | Description |
|
|
73
|
+
|-----|-------------|
|
|
74
|
+
| [pan](https://cereb.dev/stream-api/pan) | Pan gesture with velocity and direction |
|
|
75
|
+
| [pinch](https://cereb.dev/stream-api/pinch) | Pinch gesture with distance and center |
|
|
76
|
+
| [singlePointer](https://cereb.dev/stream-api/single-pointer) | Unified pointer (mouse/touch/pen) |
|
|
77
|
+
| [multiPointer](https://cereb.dev/stream-api/multi-pointer) | Multi-touch tracking |
|
|
78
|
+
| [keyboard](https://cereb.dev/stream-api/keyboard) | Keyboard events (keydown + keyup) |
|
|
79
|
+
| [keydown](https://cereb.dev/stream-api/keydown) | Keydown events only |
|
|
80
|
+
| [keyheld](https://cereb.dev/stream-api/keyheld) | Track if a key is held |
|
|
81
|
+
| [wheel](https://cereb.dev/stream-api/wheel) | Wheel/scroll events |
|
|
82
|
+
| [domEvent](https://cereb.dev/stream-api/dom-event) | Any DOM event |
|
|
77
83
|
|
|
78
|
-
###
|
|
84
|
+
### Operator API
|
|
79
85
|
|
|
80
|
-
|
|
81
|
-
See how this plays out in a multi-input zoom implementation:
|
|
86
|
+
Transform and compose streams with operators like `filter`, `map`, `merge`, `throttle`, `debounce`, and more.
|
|
82
87
|
|
|
83
|
-
|
|
84
|
-
// Before: Scattered handlers, shared state, duplicated logic
|
|
85
|
-
let currentScale = 1;
|
|
86
|
-
let isZoomMode = false;
|
|
87
|
-
let initialPinchDistance = 0;
|
|
88
|
-
|
|
89
|
-
window.addEventListener('keydown', e => {
|
|
90
|
-
if (e.key === 'z') { isZoomMode = true; toggleZoomModeIndicator(true); }
|
|
91
|
-
if (isZoomMode && (e.key === '+' || e.key === '=' || e.key === '-')) {
|
|
92
|
-
e.preventDefault();
|
|
93
|
-
currentScale = Math.max(MIN, Math.min(MAX, currentScale + ...));
|
|
94
|
-
render(currentScale); // min/max logic here
|
|
95
|
-
}
|
|
96
|
-
});
|
|
97
|
-
window.addEventListener('keyup', e => { /* isZoomMode = false ... */ });
|
|
98
|
-
|
|
99
|
-
box.addEventListener('wheel', e => {
|
|
100
|
-
if (!isZoomMode) return;
|
|
101
|
-
currentScale = Math.max(MIN, Math.min(MAX, ...)); // duplicated
|
|
102
|
-
render(currentScale);
|
|
103
|
-
}, { passive: false });
|
|
104
|
-
|
|
105
|
-
// Pinch: touchstart/touchmove/touchend, track two fingers, calculate distance...
|
|
106
|
-
box.addEventListener('touchstart', e => { /* ... */ });
|
|
107
|
-
box.addEventListener('touchmove', e => {
|
|
108
|
-
// ... 10+ lines: distance calculation, ratio, min/max again
|
|
109
|
-
});
|
|
110
|
-
box.addEventListener('touchend', () => { /* cleanup */ });
|
|
111
|
-
|
|
112
|
-
slider.addEventListener('input', e => { /* ... min/max again */ });
|
|
113
|
-
// 8 handlers, 3+ shared states, min/max duplicated everywhere
|
|
114
|
-
```
|
|
88
|
+
[See all operators →](https://cereb.dev/operator-api/compose)
|
|
115
89
|
|
|
116
90
|
<br>
|
|
117
91
|
|
|
118
|
-
Cereb
|
|
119
|
-
Model events as streams, and you get readable, reusable, extensible declarative pipelines.
|
|
120
|
-
|
|
121
|
-
```typescript
|
|
122
|
-
// After: Clear flow, no side effects, composable
|
|
123
|
-
import { keydown, keyheld, wheel, domEvent } from "cereb";
|
|
124
|
-
import { zoom as createZoom, when, extend, spy } from "cereb/operators";
|
|
125
|
-
import { pinch } from "@cereb/pinch";
|
|
126
|
-
|
|
127
|
-
const zoomMode$ = keyheld(window, { code: "KeyZ" });
|
|
128
|
-
const zoom = (op) => createZoom({ minScale: 0.5, maxScale: 3.0, baseScale: getScale, ...op });
|
|
129
|
-
|
|
130
|
-
// Pinch zoom - phase-based session: baseScale captured at start, reset at end
|
|
131
|
-
pinch(element)
|
|
132
|
-
.pipe(zoom())
|
|
133
|
-
.on(applyScale);
|
|
134
|
-
|
|
135
|
-
// z + wheel zoom - ratio as absolute scale (current × factor)
|
|
136
|
-
wheel(element, { passive: false })
|
|
137
|
-
.pipe(
|
|
138
|
-
when(zoomMode$),
|
|
139
|
-
spy((signal) => signal.value.originalEvent.preventDefault()),
|
|
140
|
-
extend((signal) => ({ ratio: getScale() * Math.exp(-signal.value.deltaY * 0.005) })),
|
|
141
|
-
zoom({ baseScale: 1.0 }),
|
|
142
|
-
)
|
|
143
|
-
.on(applyScale);
|
|
144
|
-
|
|
145
|
-
// z + '+/-' zoom - ratio as absolute scale (current × factor)
|
|
146
|
-
keydown(window, { code: ["Equal", "Minus"] })
|
|
147
|
-
.pipe(
|
|
148
|
-
when(zoomMode$),
|
|
149
|
-
spy((signal) => signal.value.originalEvent.preventDefault()),
|
|
150
|
-
extend((signal) => ({ ratio: getScale() * (signal.value.code === "Equal" ? 1.2 : 1 / 1.2) })),
|
|
151
|
-
zoom({ baseScale: 1.0 }),
|
|
152
|
-
)
|
|
153
|
-
.on(applyScale);
|
|
154
|
-
|
|
155
|
-
// 'Slider Input' - sets absolute scale, so ratio is the target scale itself
|
|
156
|
-
domEvent(slider, "input")
|
|
157
|
-
.pipe(
|
|
158
|
-
extend<DomEventSignal<Event>, ZoomInput>((signal) => {
|
|
159
|
-
const inputElement = signal.value.target as HTMLInputElement;
|
|
160
|
-
const value = Number(inputElement.value);
|
|
161
|
-
const logScale = logMin + (value / 100) * (logMax - logMin);
|
|
162
|
-
const scale = Math.exp(logScale);
|
|
163
|
-
return {
|
|
164
|
-
ratio: clamp(scale, MIN_SCALE, MAX_SCALE),
|
|
165
|
-
};
|
|
166
|
-
}),
|
|
167
|
-
zoom({ baseScale: 1.0 }), // baseScale = 1.0 for absolute scale
|
|
168
|
-
).on(render);
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
### 2. Lightweight Bundle Size
|
|
172
|
-
|
|
173
|
-
Benchmark: Equivalent pan gesture implementation
|
|
174
|
-
|
|
175
|
-
| | Minified | Gzipped |
|
|
176
|
-
|--|----------|---------|
|
|
177
|
-
| cereb + @cereb/pan | 4.58 KB | **1.73 KB** |
|
|
178
|
-
| Hammer.js | 20.98 KB | 7.52 KB |
|
|
179
|
-
|
|
180
|
-
**~77% smaller** than Hammer.js for equivalent pan gesture functionality.
|
|
181
|
-
|
|
182
|
-
### 3. Performance & Resource Efficiency
|
|
183
|
-
|
|
184
|
-
**3.1. Event Listener Reuse**
|
|
185
|
-
|
|
186
|
-
```typescript
|
|
187
|
-
// Before: Multiple addEventListener calls
|
|
188
|
-
window.addEventListener('keydown', handler1);
|
|
189
|
-
window.addEventListener('keydown', handler2);
|
|
190
|
-
window.addEventListener('keydown', handler3);
|
|
191
|
-
|
|
192
|
-
// After: Shared stream, single listener
|
|
193
|
-
// addEventListener called once
|
|
194
|
-
keyboard(window).on(handler1);
|
|
195
|
-
keyboard(window).on(handler2);
|
|
196
|
-
keyboard(window).on(handler3);
|
|
197
|
-
```
|
|
92
|
+
## The Problems Cereb Solves
|
|
198
93
|
|
|
199
|
-
**
|
|
94
|
+
- **Spaghetti Event Code** — Scattered handlers, shared mutable state, duplicated logic
|
|
95
|
+
- **Lightweight Bundle** — ~77% smaller than Hammer.js (1.73 KB gzipped for pan gesture)
|
|
96
|
+
- **Resource Efficiency** — Event listener reuse, single-responsibility operators
|
|
200
97
|
|
|
201
|
-
|
|
202
|
-
pan(element) // Pan gesture recognition
|
|
203
|
-
.pipe(
|
|
204
|
-
offset({ target }), // Element-relative coordinates
|
|
205
|
-
axisLock() // Lock to horizontal/vertical
|
|
206
|
-
)
|
|
207
|
-
```
|
|
98
|
+
[See detailed examples →](https://cereb.dev/core-concepts/the-problem-solves)
|
|
208
99
|
|
|
209
100
|
<br>
|
|
210
101
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cereb",
|
|
3
3
|
"description": "User input modeling and orchestration with a lightweight reactive stream library.",
|
|
4
|
-
"version": "0.11.
|
|
4
|
+
"version": "0.11.6",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "devphilip21 <philip21.dev@gmail.com>",
|
|
7
7
|
"repository": {
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"url": "https://github.com/devphilip21/cereb.git",
|
|
10
10
|
"directory": "packages/core"
|
|
11
11
|
},
|
|
12
|
-
"homepage": "https://
|
|
12
|
+
"homepage": "https://cereb.dev",
|
|
13
13
|
"bugs": {
|
|
14
14
|
"url": "https://github.com/devphilip21/cereb/issues"
|
|
15
15
|
},
|