Skip to content

Commit 5ddd472

Browse files
committed
feat(signal, single-pointer): sperate package single-pointer from package signal
1 parent b3ce6ae commit 5ddd472

34 files changed

+3696
-1517
lines changed

.github/workflows/publish-package.yml

Lines changed: 0 additions & 47 deletions
This file was deleted.

.github/workflows/release.yml

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
name: Release
2+
run-name: "Release packages @${{ github.sha }}"
3+
4+
on:
5+
workflow_dispatch:
6+
inputs:
7+
dry-run:
8+
description: 'Dry-run mode (no publish)'
9+
required: false
10+
default: 'false'
11+
type: boolean
12+
first-release:
13+
description: 'First release (no git tags exist yet)'
14+
required: false
15+
default: 'false'
16+
type: boolean
17+
18+
permissions:
19+
contents: write
20+
id-token: write
21+
22+
jobs:
23+
release:
24+
runs-on: ubuntu-latest
25+
26+
steps:
27+
- name: Checkout
28+
uses: actions/checkout@v4
29+
with:
30+
fetch-depth: 0
31+
token: ${{ secrets.GITHUB_TOKEN }}
32+
33+
- name: Setup Git
34+
run: |
35+
git config user.name "github-actions[bot]"
36+
git config user.email "github-actions[bot]@users.noreply.github.com"
37+
38+
- name: Setup pnpm
39+
uses: pnpm/action-setup@v4
40+
with:
41+
version: 9
42+
43+
- name: Setup Node.js
44+
uses: actions/setup-node@v4
45+
with:
46+
node-version: '24'
47+
cache: 'pnpm'
48+
registry-url: 'https://registry.npmjs.org'
49+
50+
- name: Install dependencies
51+
run: pnpm install
52+
53+
- name: Run tests
54+
run: npx nx run-many -t test --projects=packages/*
55+
56+
- name: Build packages
57+
run: npx nx run-many -t build --projects=packages/*
58+
59+
- name: Set release flags
60+
id: flags
61+
run: |
62+
FLAGS=""
63+
if [ "${{ inputs.first-release }}" == "true" ]; then
64+
FLAGS="$FLAGS --first-release"
65+
fi
66+
echo "flags=$FLAGS" >> $GITHUB_OUTPUT
67+
68+
- name: Release (dry-run)
69+
if: ${{ inputs.dry-run == 'true' }}
70+
run: npx nx release --skip-publish --dry-run ${{ steps.flags.outputs.flags }}
71+
72+
- name: Release
73+
if: ${{ inputs.dry-run != 'true' }}
74+
run: npx nx release ${{ steps.flags.outputs.flags }}
75+
env:
76+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
77+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
78+
NPM_CONFIG_PROVENANCE: true
79+
80+
- name: Push changes and tags
81+
if: ${{ inputs.dry-run != 'true' }}
82+
run: git push --follow-tags

nx.json

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,37 @@
33
"targetDefaults": {
44
"build": {
55
"dependsOn": ["^build"]
6+
},
7+
"nx-release-publish": {
8+
"dependsOn": ["build"],
9+
"options": {
10+
"packageRoot": "{projectRoot}"
11+
}
12+
}
13+
},
14+
"release": {
15+
"projects": ["packages/*"],
16+
"projectsRelationship": "independent",
17+
"releaseTagPattern": "{projectName}@{version}",
18+
"changelog": {
19+
"automaticFromRef": true,
20+
"workspaceChangelog": false,
21+
"projectChangelogs": {
22+
"file": "{projectRoot}/CHANGELOG.md",
23+
"createRelease": "github"
24+
}
25+
},
26+
"version": {
27+
"conventionalCommits": true,
28+
"generatorOptions": {
29+
"currentVersionResolver": "registry",
30+
"fallbackCurrentVersionResolver": "disk"
31+
}
32+
},
33+
"git": {
34+
"commit": true,
35+
"commitMessage": "chore(release): publish {version}",
36+
"tag": true
637
}
738
}
839
}

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"postinstall": "[ -n \"$SKIP_POSTINSTALL\" ] || (npx nx build @gesturejs/builder && SKIP_POSTINSTALL=1 pnpm rebuild)"
55
},
66
"devDependencies": {
7+
"@nx/js": "^22.3.3",
78
"@vitest/coverage-v8": "^2.0.0",
89
"jsdom": "^25.0.0",
910
"nx": "^22.2",

packages/signal/README.md

Lines changed: 28 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -2,76 +2,51 @@
22

33
**Signal** is a higher-level abstraction over events that merges and refines disparate inputs into a single, composable stream.
44

5-
## Why @gesturejs/signal?
6-
7-
- **Unified Interface** - Subscribe to diverse event sources through one consistent API by normalizing them into a unified signal stream.
8-
- **GC Optimized** - Built-in object pooling prevents garbage collection pauses during high-frequency input (60+ events/sec)
9-
- **Observable-Based** - Works seamlessly with reactive patterns via `@gesturejs/stream`.
10-
115
## Installation
126

137
```bash
14-
npm install @gesturejs/signal
8+
npm install --save @gesturejs/signal
159
```
1610

17-
## Quick Start
11+
## Core Concepts
1812

19-
### Single Pointer
13+
### Signal
2014

21-
```typescript
22-
import { singlePointer } from "@gesturejs/signal";
15+
A `Signal` is the base interface for all normalized event data:
2316

24-
const stream = singlePointer(canvasElement);
25-
const unsub = stream.subscribe((pointer) => {
26-
console.log(pointer.x, pointer.y);
27-
console.log(pointer.phase); // start, move, end, cancel
28-
});
17+
```typescript
18+
interface Signal<T extends string = string> {
19+
type: T;
20+
timestamp: number;
21+
deviceId: string;
22+
}
2923
```
3024

31-
## Recipes
25+
### SignalPool
3226

33-
### Use Other Events
27+
Built-in object pooling for Signal types to prevent garbage collection pauses during high-frequency input (60+ events/sec):
3428

3529
```typescript
36-
import { touchEventsToSinglePointer } from "@gesturejs/signal";
37-
import { fromEvent, merge, pipe, filter } from "@gesturejs/stream";
38-
39-
/**
40-
* The `singlePointer()` factory is primarily designed for PointerEvents.
41-
* If you're working with TouchEvents, you can convert a TouchEvent stream via
42-
* `touchEventsToSinglePointer()` and keep using the same SinglePointer pipeline.
43-
*/
44-
const stream = pipe(
45-
merge(
46-
fromEvent(el, "touchstart"),
47-
fromEvent(el, "touchmove"),
48-
fromEvent(el, "touchend"),
49-
fromEvent(el, "touchcancel")
50-
),
51-
touchEventsToSinglePointer(),
52-
filter((p) => p.phase === "move")
30+
import { createSignalPool, type Signal } from "@gesturejs/signal";
31+
32+
interface MySignal extends Signal<"custom"> {
33+
type: "custom";
34+
x: number;
35+
y: number;
36+
}
37+
38+
const pool = createSignalPool<MySignal>(
39+
() => ({ type: "custom", timestamp: 0, deviceId: "", x: 0, y: 0 }),
40+
(obj) => { obj.timestamp = 0; obj.deviceId = ""; obj.x = 0; obj.y = 0; },
41+
20, // initial size
42+
100 // max size
5343
);
54-
const unsub = stream.subscribe((pointer) => {
55-
draw(pointer.x, pointer.y);
56-
});
57-
```
58-
59-
### Object Pooling
6044

61-
```typescript
62-
/**
63-
* Pooling reduces allocations/GC pressure for high-frequency input
64-
* - but emitted objects are reused (mutated/reset). Don't keep references.
65-
* - If you need to persist data, copy the fields you need.
66-
*/
67-
const spStream = singlePointer(canvasElement, { pooling: true });
45+
const signal = pool.acquire();
46+
// use signal...
47+
pool.release(signal);
6848
```
6949

70-
## Documentation
71-
72-
- [API Reference](./docs/api.md)
73-
- [Signal Structure](./docs/signal.md)
74-
7550
## License
7651

7752
MIT

packages/signal/package.json

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@gesturejs/signal",
33
"description": "A higher-level abstraction over events that merges and refines disparate inputs into a single, composable stream",
4-
"version": "0.1.0",
4+
"version": "0.2.0",
55
"license": "MIT",
66
"author": "devphilip21 <philip21.dev@gmail.com>",
77
"repository": {
@@ -35,16 +35,6 @@
3535
"types": "./dist/index.d.ts",
3636
"import": "./dist/index.js",
3737
"require": "./dist/index.cjs"
38-
},
39-
"./core": {
40-
"types": "./dist/core/index.d.ts",
41-
"import": "./dist/core/index.js",
42-
"require": "./dist/core/index.cjs"
43-
},
44-
"./single-pointer": {
45-
"types": "./dist/single-pointer/index.d.ts",
46-
"import": "./dist/single-pointer/index.js",
47-
"require": "./dist/single-pointer/index.cjs"
4838
}
4939
},
5040
"files": [
@@ -59,10 +49,10 @@
5949
"test:coverage": "vitest run --coverage"
6050
},
6151
"dependencies": {
62-
"@gesturejs/stream": "^0.1.0"
52+
"@gesturejs/stream": "workspace:^"
6353
},
6454
"devDependencies": {
65-
"@gesturejs/builder": "workspace:*",
55+
"@gesturejs/builder": "workspace:^",
6656
"@vitest/coverage-v8": "*",
6757
"jsdom": "*",
6858
"vite": "*",

packages/signal/src/core/index.ts

Lines changed: 0 additions & 10 deletions
This file was deleted.

packages/signal/src/index.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
1-
export * from "./core/index.js";
1+
export type {
2+
Signal,
3+
SignalWithMetadata,
4+
CancellableSignal,
5+
SignalPhase,
6+
} from "./signal.js";
7+
export { createSignal } from "./signal.js";
28

3-
export * from "./single-pointer/index.js";
9+
export type { SignalPool } from "./pool.js";
10+
export { createSignalPool } from "./pool.js";
411

5-
export const VERSION = "0.1.0";
12+
export const VERSION = "0.2.0";

0 commit comments

Comments
 (0)