Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ For advanced gestures like pan or pinch, install dedicated packages that build o
|---------|-------------|
| [@cereb/pan](./packages/pan) | Pan/drag gestures with velocity and direction tracking |
| [@cereb/pinch](./packages/pinch) | Pinch-to-zoom with distance and scale calculations |
| [@cereb/tap](./packages/tap) | Tap gesture recognition |

### Pinch example

Expand Down Expand Up @@ -87,7 +88,7 @@ Transform and compose streams with operators like `filter`, `map`, `merge`, `thr

## The Problems Cereb Solves

- **Spaghetti Event Code** — Scattered handlers, shared mutable state, duplicated logic
- **No Abstraction for Event Flow** — DOM events lack structure for state, dependencies, and composition
- **Lightweight Bundle** — ~77% smaller than Hammer.js (1.73 KB gzipped for pan gesture)
- **Resource Efficiency** — Event listener reuse, single-responsibility operators

Expand Down
53 changes: 46 additions & 7 deletions docs/public/llms-full.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@ Cereb provides a unified abstraction for handling pointer/touch/mouse events thr
| `cereb` | cereb | Core: Stream primitives, operators |
| `@cereb/pan` | @cereb/pan | Pan/drag/swipe gesture |
| `@cereb/pinch` | @cereb/pinch | Pinch/zoom gesture |
| `@cereb/tap` | @cereb/tap | Tap gesture |

### Installation

```bash
npm install cereb
npm install @cereb/pan # optional
npm install @cereb/pinch # optional
npm install @cereb/tap # optional
```

---
Expand Down Expand Up @@ -226,17 +228,19 @@ function pan(target: EventTarget, options?: { threshold?: number; direction?: "h

**Signal Value:**
- `phase`: "start" | "move" | "end" | "cancel"
- `deltaX`, `deltaY`: displacement from start (px)
- `delta`: [number, number] - displacement from start [deltaX, deltaY] (px)
- `velocity`: [number, number] - [velocityX, velocityY] (px/ms)
- `cursor`: [number, number] - current position (client coordinates)
- `pageCursor`: [number, number] - current position (page coordinates)
- `distance`: cumulative distance (px)
- `direction`: "up" | "down" | "left" | "right" | "none"
- `velocityX`, `velocityY`: px/ms
- `x`, `y`, `pageX`, `pageY`

```typescript
import { pan } from "@cereb/pan";

pan(element).on((signal) => {
const { phase, deltaX, deltaY } = signal.value;
const { phase, delta } = signal.value;
const [deltaX, deltaY] = delta;
if (phase === "move") {
element.style.transform = `translate(${deltaX}px, ${deltaY}px)`;
}
Expand Down Expand Up @@ -266,19 +270,54 @@ function pinch(target: EventTarget, options?: { threshold?: number }): Stream<Pi
- `ratio`: distance / initialDistance
- `deltaDistance`: change since last event (px)
- `velocity`: px/ms
- `centerX`, `centerY`: center between pointers
- `center`: [number, number] - center between pointers (client coordinates)
- `pageCenter`: [number, number] - center between pointers (page coordinates)

```typescript
import { pinch } from "@cereb/pinch";

pinch(element).on((signal) => {
const { phase, ratio, centerX, centerY } = signal.value;
const { phase, ratio, center } = signal.value;
const [centerX, centerY] = center;
if (phase === "change") {
element.style.transform = `scale(${ratio})`;
}
});
```

### tap (from @cereb/tap)

Tap gesture recognition with multi-tap support.

```typescript
function tap(target: EventTarget, options?: {
movementThreshold?: number;
durationThreshold?: number;
chainMovementThreshold?: number;
chainIntervalThreshold?: number;
}): Stream<TapSignal>
```

**Signal Value:**
- `phase`: "start" | "end" | "cancel"
- `cursor`: [number, number] - tap position (client coordinates)
- `pageCursor`: [number, number] - tap position (page coordinates)
- `tapCount`: number - consecutive tap count (1=single, 2=double, etc.)
- `duration`: number - how long the pointer was pressed (ms)
- `pointerType`: "mouse" | "touch" | "pen" | "unknown"

```typescript
import { tap } from "@cereb/tap";

tap(element).on((signal) => {
const { tapCount, cursor } = signal.value;
const [x, y] = cursor;
if (tapCount === 2) {
console.log(`Double tap at (${x}, ${y})`);
}
});
```

### keyboard

Both keydown and keyup events.
Expand Down Expand Up @@ -695,6 +734,6 @@ pan(container)

## Links

- GitHub: https://github.com/niceplugin/cereb
- GitHub: https://github.com/devphilip21/cereb
- Documentation: https://cereb.dev
- npm: https://www.npmjs.com/package/cereb
4 changes: 3 additions & 1 deletion docs/public/llms.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
- cereb: Core library with stream primitives and operators
- @cereb/pan: Pan/drag/swipe gesture recognition
- @cereb/pinch: Pinch/zoom gesture recognition
- @cereb/tap: Tap gesture recognition

## Getting Started

Expand All @@ -25,6 +26,7 @@
- [multiPointer](https://cereb.dev/stream-api/multi-pointer): Multi-touch tracking
- [pan](https://cereb.dev/stream-api/pan): Pan gesture with velocity/direction
- [pinch](https://cereb.dev/stream-api/pinch): Two-finger pinch/zoom
- [tap](https://cereb.dev/stream-api/tap): Tap gesture with multi-tap support
- [keyboard](https://cereb.dev/stream-api/keyboard): Keyboard events
- [keydown](https://cereb.dev/stream-api/keydown): Keydown only
- [keyheld](https://cereb.dev/stream-api/keyheld): Key hold state tracking
Expand Down Expand Up @@ -59,5 +61,5 @@

## Links

- GitHub: https://github.com/niceplugin/cereb
- GitHub: https://github.com/devphilip21/cereb
- npm: https://www.npmjs.com/package/cereb
6 changes: 3 additions & 3 deletions docs/src/content/core-concepts/the-problem-solves.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

> **Note:** These are the problems Cereb solves.

## 1. Event-Driven Code Becomes Spaghetti
## 1. No Abstraction for Event Flow

Traditional event handlers create scattered logic, shared mutable state, and duplicated code. Consider a multi-input zoom implementation:
DOM events are just callbacks—there's no structure for managing state, expressing dependencies between events, or composing multiple inputs. Consider a multi-input zoom implementation:

```typescript
// Before: Scattered handlers, shared state, duplicated logic
Expand Down Expand Up @@ -39,7 +39,7 @@ box.addEventListener('touchend', () => { /* cleanup */ });
Cereb models events as streams, creating readable and composable pipelines:

```typescript
// After: Clear flow, no shared state, composable
// After: Stream abstraction—composable, stateless, explicit
import { keydown, keyheld, wheel } from "cereb";
import { zoom, when, extend, spy } from "cereb/operators";
import { pinch } from "@cereb/pinch";
Expand Down
126 changes: 14 additions & 112 deletions docs/src/content/getting-started/quick-start.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,110 +7,24 @@ Let's build it step by step.

Cereb is modular—install only what you need.

<div class="table-container">
<table>
<thead>
<tr>
<th>Package</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>cereb</code></td>
<td>Stream generators & operators</td>
</tr>
<tr>
<td><code>@cereb/pan</code></td>
<td>Pan/drag/swipe gesture</td>
</tr>
<tr>
<td><code>@cereb/pinch</code></td>
<td>Pinch/zoom gesture</td>
</tr>
</tbody>
</table>
</div>
| Package | Description |
|---------|-------------|
| `cereb` | Native events & operators |
| `@cereb/pan` | Pan/drag/swipe gesture |
| `@cereb/pinch` | Pinch/zoom gesture |
| `@cereb/tap` | Tap gesture |

For our pinch example:

<div class="tabs">
<div class="tab-buttons">
<button class="tab-button active" data-tab="npm">npm</button>
<button class="tab-button" data-tab="pnpm">pnpm</button>
<button class="tab-button" data-tab="yarn">yarn</button>
</div>
<div class="tab-content active" id="npm">
```bash
npm install @cereb/pinch
```
</div>
<div class="tab-content" id="pnpm">
```bash
pnpm add @cereb/pinch
```
</div>
<div class="tab-content" id="yarn">
```bash
yarn add @cereb/pinch
```
</div>
</div>

## 2. Create a Source Stream
```bash
npm install @cereb/pinch
```

The core `cereb` package provides stream generators for various input types:

<div class="table-container">
<table>
<thead>
<tr>
<th>Generator</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>singlePointer(element)</code></td>
<td>Unified pointer input (mouse/touch/pen)</td>
</tr>
<tr>
<td><code>multiPointer(element)</code></td>
<td>Multiple simultaneous pointers</td>
</tr>
<tr>
<td><code>keyboard(target)</code></td>
<td>Keyboard events</td>
</tr>
<tr>
<td><code>keydown(target)</code></td>
<td>Keydown only</td>
</tr>
<tr>
<td><code>keyheld(target, options)</code></td>
<td>Key hold state</td>
</tr>
<tr>
<td><code>wheel(element)</code></td>
<td>Scroll wheel</td>
</tr>
<tr>
<td><code>domEvent(target, eventName)</code></td>
<td>Any DOM event</td>
</tr>
</tbody>
</table>
</div>

For basic pointer tracking:
> Gesture packages include `cereb` core as a dependency.

```typescript
import { singlePointer } from "cereb";

const stream = singlePointer(element);
```
## 2. Create a Source Stream

For gestures, use the convenience functions from gesture packages. They set up the required stream pipeline internally:
Import `pinch` and create a stream from your target element:

```typescript
import { pinch } from "@cereb/pinch";
Expand All @@ -120,22 +34,19 @@ const stream = pinch(element);

## 3. Transform with pipe()

Streams can be transformed by chaining operators with `.pipe()`:
Chain operators to add constraints like scale limits:

```typescript
import { zoom } from "cereb/operators";
import { pinch } from "@cereb/pinch";

const stream = pinch(element).pipe(
zoom({ minScale: 0.5, maxScale: 3 }),
);
```

Operators like `filter`, `offset`, `zoom`, `extend`, and more are available from `cereb/operators`.

## 4. Subscribe with on()

Nothing happens until you subscribe. Call `.on()` to start receiving signals:
Nothing happens until you subscribe:

```typescript
stream.on((signal) => {
Expand All @@ -147,12 +58,3 @@ stream.on((signal) => {
}
});
```

To stop listening:

```typescript
const off = stream.on(handler);

// later:
off();
```
2 changes: 1 addition & 1 deletion docs/src/pages/core-concepts/the-problem-solves.astro
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import DocsLayout from "@/layouts/docs-layout.astro";
import Content from "@/content/core-concepts/the-problem-solves.mdx";

const headings = [
{ depth: 2, slug: "1-event-driven-code-becomes-spaghetti", text: "1. Event-Driven Code Becomes Spaghetti" },
{ depth: 2, slug: "1-no-abstraction-for-event-flow", text: "1. No Abstraction for Event Flow" },
{ depth: 2, slug: "2-lightweight-bundle-size", text: "2. Lightweight Bundle Size" },
{ depth: 2, slug: "3-performance--resource-efficiency", text: "3. Performance & Resource Efficiency" },
];
Expand Down
1 change: 0 additions & 1 deletion docs/src/pages/getting-started/quick-start.astro
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ const headings = [
{ depth: 2, slug: "2-create-a-source-stream", text: "2. Create a Source Stream" },
{ depth: 2, slug: "3-transform-with-pipe", text: "3. Transform with pipe()" },
{ depth: 2, slug: "4-subscribe-with-on", text: "4. Subscribe with on()" },
{ depth: 2, slug: "whats-next", text: "What's Next" },
];
---

Expand Down
5 changes: 3 additions & 2 deletions packages/cereb/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# [Cereb](https://cereb.dev)

**User input handling and orchestration** libray,
**User input handling and orchestration** library,
From low-level events (keyboard, wheel, pointer, ...) to high-level gestures (pan, pinch, ...)

```bash
Expand Down Expand Up @@ -41,6 +41,7 @@ For advanced gestures like pan or pinch, install dedicated packages that build o
|---------|-------------|
| [@cereb/pan](https://www.npmjs.com/package/@cereb/pan) | Pan/drag gestures with velocity and direction tracking |
| [@cereb/pinch](https://www.npmjs.com/package/@cereb/pinch) | Pinch-to-zoom with distance and scale calculations |
| [@cereb/tap](https://www.npmjs.com/package/@cereb/tap) | Tap gesture recognition |

### Pinch example

Expand Down Expand Up @@ -92,7 +93,7 @@ Transform and compose streams with operators like `filter`, `map`, `merge`, `thr

## The Problems Cereb Solves

- **Spaghetti Event Code** — Scattered handlers, shared mutable state, duplicated logic
- **No Abstraction for Event Flow** — DOM events lack structure for state, dependencies, and composition
- **Lightweight Bundle** — ~77% smaller than Hammer.js (1.73 KB gzipped for pan gesture)
- **Resource Efficiency** — Event listener reuse, single-responsibility operators

Expand Down
2 changes: 1 addition & 1 deletion packages/cereb/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "cereb",
"description": "User input modeling and orchestration with a lightweight reactive stream library.",
"version": "1.0.0",
"version": "1.0.1",
"license": "MIT",
"author": "devphilip21 <philip21.dev@gmail.com>",
"repository": {
Expand Down