@maxr0ssi/glide-web-ui 0.1.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 +75 -0
- package/dist/components/GlideDemo.d.ts +16 -0
- package/dist/components/GlideDemo.d.ts.map +1 -0
- package/dist/components/ScrollArea.d.ts +15 -0
- package/dist/components/ScrollArea.d.ts.map +1 -0
- package/dist/components/Visualizer.d.ts +20 -0
- package/dist/components/Visualizer.d.ts.map +1 -0
- package/dist/core/collections.d.ts +22 -0
- package/dist/core/collections.d.ts.map +1 -0
- package/dist/core/config.d.ts +68 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/types.d.ts +35 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/features/alignment.d.ts +36 -0
- package/dist/features/alignment.d.ts.map +1 -0
- package/dist/features/kinematics.d.ts +31 -0
- package/dist/features/kinematics.d.ts.map +1 -0
- package/dist/features/poses.d.ts +14 -0
- package/dist/features/poses.d.ts.map +1 -0
- package/dist/gestures/touchproof-detector.d.ts +37 -0
- package/dist/gestures/touchproof-detector.d.ts.map +1 -0
- package/dist/gestures/touchproof-scoring.d.ts +30 -0
- package/dist/gestures/touchproof-scoring.d.ts.map +1 -0
- package/dist/gestures/touchproof-signals.d.ts +16 -0
- package/dist/gestures/touchproof-signals.d.ts.map +1 -0
- package/dist/gestures/velocity-controller.d.ts +24 -0
- package/dist/gestures/velocity-controller.d.ts.map +1 -0
- package/dist/gestures/velocity-tracker.d.ts +23 -0
- package/dist/gestures/velocity-tracker.d.ts.map +1 -0
- package/dist/glide-demo.cjs.js +15 -0
- package/dist/glide-demo.es.js +4441 -0
- package/dist/hooks/useGlide.d.ts +31 -0
- package/dist/hooks/useGlide.d.ts.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/perception/hand-detector.d.ts +21 -0
- package/dist/perception/hand-detector.d.ts.map +1 -0
- package/package.json +57 -0
package/README.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Glide Web UI
|
|
2
|
+
|
|
3
|
+
Browser-based demo of Glide's hand gesture detection algorithms. Runs the full TouchProof detection pipeline in-browser using MediaPipe's WebAssembly hand landmarker.
|
|
4
|
+
|
|
5
|
+
## Standalone (Dev Server)
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
make web-setup # npm install
|
|
9
|
+
make web-dev # starts Vite at localhost:5173
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Open in browser, grant camera access. You'll see a split-view with the algorithm visualizer (webcam + landmarks + signal scores) and a scrollable demo area that responds to gestures.
|
|
13
|
+
|
|
14
|
+
## As a Library (Embeddable Component)
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
make web-build # produces dist/glide-demo.es.js + types
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
import { GlideDemo } from '@glide/web-ui';
|
|
22
|
+
import '@glide/web-ui/dist/style.css';
|
|
23
|
+
|
|
24
|
+
function App() {
|
|
25
|
+
return <GlideDemo showVisualizer={true} />;
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### `<GlideDemo />` Props
|
|
30
|
+
|
|
31
|
+
| Prop | Type | Default | Description |
|
|
32
|
+
|------|------|---------|-------------|
|
|
33
|
+
| `modelPath` | `string` | Google CDN | Override MediaPipe model URL |
|
|
34
|
+
| `config` | `Partial<AppConfig>` | `defaults.yaml` values | Override detection config |
|
|
35
|
+
| `showVisualizer` | `boolean` | `true` | Show webcam + signal dashboard |
|
|
36
|
+
| `scrollContent` | `ReactNode` | Demo paragraphs | Custom scroll area content |
|
|
37
|
+
| `className` | `string` | `''` | Additional CSS class |
|
|
38
|
+
| `style` | `CSSProperties` | — | Inline styles |
|
|
39
|
+
|
|
40
|
+
### `useGlide` Hook
|
|
41
|
+
|
|
42
|
+
For full control, use the hook directly:
|
|
43
|
+
|
|
44
|
+
```tsx
|
|
45
|
+
import { useGlide } from '@glide/web-ui';
|
|
46
|
+
|
|
47
|
+
function Custom() {
|
|
48
|
+
const { videoRef, signals, gestureState, landmarks, fps } = useGlide();
|
|
49
|
+
// Build your own UI with the pipeline outputs
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Testing
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
make web-test # vitest run
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Architecture
|
|
60
|
+
|
|
61
|
+
The TypeScript code mirrors the Python module structure:
|
|
62
|
+
|
|
63
|
+
| Python | TypeScript | Purpose |
|
|
64
|
+
|--------|-----------|---------|
|
|
65
|
+
| `glide/core/types.py` | `src/core/types.ts` | GateState, Landmark, HandDet, PoseFlags |
|
|
66
|
+
| `glide/core/config_models.py` | `src/core/config.ts` | AppConfig + factory |
|
|
67
|
+
| `glide/features/alignment.py` | `src/features/alignment.ts` | HandAligner |
|
|
68
|
+
| `glide/features/kinematics.py` | `src/features/kinematics.ts` | KinematicsTracker |
|
|
69
|
+
| `glide/features/poses.py` | `src/features/poses.ts` | checkHandPose |
|
|
70
|
+
| `glide/gestures/touchproof_scoring.py` | `src/gestures/touchproof-scoring.ts` | Pure scoring functions |
|
|
71
|
+
| `glide/gestures/touchproof_detector.py` | `src/gestures/touchproof-detector.ts` | TouchProofDetector |
|
|
72
|
+
| `glide/gestures/velocity_tracker.py` | `src/gestures/velocity-tracker.ts` | VelocityTracker |
|
|
73
|
+
| `glide/gestures/velocity_controller.py` | `src/gestures/velocity-controller.ts` | VelocityController |
|
|
74
|
+
|
|
75
|
+
MFC (optical flow) is excluded from the web port — `mfcScore` is hardcoded to 0.5 (neutral).
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GlideDemo — top-level exportable component.
|
|
3
|
+
* Split-view: algorithm visualizer + scrollable demo content.
|
|
4
|
+
*/
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import type { AppConfig } from '../core/config';
|
|
7
|
+
export interface GlideDemoProps {
|
|
8
|
+
modelPath?: string;
|
|
9
|
+
config?: Partial<AppConfig>;
|
|
10
|
+
showVisualizer?: boolean;
|
|
11
|
+
scrollContent?: React.ReactNode;
|
|
12
|
+
className?: string;
|
|
13
|
+
style?: React.CSSProperties;
|
|
14
|
+
}
|
|
15
|
+
export declare const GlideDemo: React.FC<GlideDemoProps>;
|
|
16
|
+
//# sourceMappingURL=GlideDemo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GlideDemo.d.ts","sourceRoot":"","sources":["../../src/components/GlideDemo.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAKhD,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IAC5B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAC7B;AAED,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,CAqC9C,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ScrollArea — scrollable demo content that responds to Glide gestures.
|
|
3
|
+
*/
|
|
4
|
+
import React from 'react';
|
|
5
|
+
import { GestureState } from '../gestures/velocity-controller';
|
|
6
|
+
import type { Vec2D } from '../gestures/velocity-tracker';
|
|
7
|
+
interface ScrollAreaProps {
|
|
8
|
+
velocity: Vec2D | null;
|
|
9
|
+
gestureState: GestureState;
|
|
10
|
+
isActive: boolean;
|
|
11
|
+
children?: React.ReactNode;
|
|
12
|
+
}
|
|
13
|
+
export declare const ScrollArea: React.FC<ScrollAreaProps>;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=ScrollArea.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ScrollArea.d.ts","sourceRoot":"","sources":["../../src/components/ScrollArea.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAA4B,MAAM,OAAO,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC/D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,8BAA8B,CAAC;AAE1D,UAAU,eAAe;IACvB,QAAQ,EAAE,KAAK,GAAG,IAAI,CAAC;IACvB,YAAY,EAAE,YAAY,CAAC;IAC3B,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AA6BD,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CA0BhD,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Visualizer — webcam canvas with hand landmarks, signal dashboard, and FPS counter.
|
|
3
|
+
*/
|
|
4
|
+
import React from 'react';
|
|
5
|
+
import type { Landmark } from '../core/types';
|
|
6
|
+
import type { TouchProofSignals } from '../gestures/touchproof-signals';
|
|
7
|
+
import { GestureState } from '../gestures/velocity-controller';
|
|
8
|
+
interface VisualizerProps {
|
|
9
|
+
videoRef: React.RefObject<HTMLVideoElement | null>;
|
|
10
|
+
canvasRef: React.RefObject<HTMLCanvasElement | null>;
|
|
11
|
+
landmarks: Landmark[] | null;
|
|
12
|
+
signals: TouchProofSignals;
|
|
13
|
+
gestureState: GestureState;
|
|
14
|
+
fps: number;
|
|
15
|
+
isLoading: boolean;
|
|
16
|
+
error: string | null;
|
|
17
|
+
}
|
|
18
|
+
export declare const Visualizer: React.FC<VisualizerProps>;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=Visualizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Visualizer.d.ts","sourceRoot":"","sources":["../../src/components/Visualizer.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAoB,MAAM,OAAO,CAAC;AACzC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAY/D,UAAU,eAAe;IACvB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IACnD,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;IACrD,SAAS,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;IAC7B,OAAO,EAAE,iBAAiB,CAAC;IAC3B,YAAY,EAAE,YAAY,CAAC;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAgJhD,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BoundedDeque — fixed-capacity ring buffer replacing Python's deque(maxlen=N).
|
|
3
|
+
*/
|
|
4
|
+
export declare class BoundedDeque<T> {
|
|
5
|
+
private _buf;
|
|
6
|
+
private _head;
|
|
7
|
+
private _size;
|
|
8
|
+
private _capacity;
|
|
9
|
+
constructor(capacity: number);
|
|
10
|
+
get length(): number;
|
|
11
|
+
get capacity(): number;
|
|
12
|
+
push(item: T): void;
|
|
13
|
+
at(index: number): T;
|
|
14
|
+
/** Access from end: -1 = last, -2 = second to last, etc. */
|
|
15
|
+
fromEnd(offset: number): T;
|
|
16
|
+
first(): T | undefined;
|
|
17
|
+
last(): T | undefined;
|
|
18
|
+
clear(): void;
|
|
19
|
+
toArray(): T[];
|
|
20
|
+
[Symbol.iterator](): Iterator<T>;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=collections.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collections.d.ts","sourceRoot":"","sources":["../../src/core/collections.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,YAAY,CAAC,CAAC;IACzB,OAAO,CAAC,IAAI,CAAM;IAClB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,SAAS,CAAS;gBAEd,QAAQ,EAAE,MAAM;IAQ5B,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,IAAI,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI;IAUnB,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,CAAC;IAOpB,4DAA4D;IAC5D,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC;IAO1B,KAAK,IAAI,CAAC,GAAG,SAAS;IAItB,IAAI,IAAI,CAAC,GAAG,SAAS;IAIrB,KAAK,IAAI,IAAI;IAKb,OAAO,IAAI,CAAC,EAAE;IAQb,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC;CAKlC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration models for Glide web UI.
|
|
3
|
+
* Ported from glide/core/config_models.py + configs/defaults.yaml
|
|
4
|
+
*
|
|
5
|
+
* Uses plain TS interfaces + factory function (no runtime validation library).
|
|
6
|
+
* Default values come from configs/defaults.yaml where they differ from Pydantic defaults.
|
|
7
|
+
*/
|
|
8
|
+
export interface GatesConfig {
|
|
9
|
+
presenceConf: number;
|
|
10
|
+
poses: string[];
|
|
11
|
+
preStillMs: number;
|
|
12
|
+
maxIdleRmsSpeed: number;
|
|
13
|
+
}
|
|
14
|
+
export interface KinematicsConfig {
|
|
15
|
+
emaAlpha: number;
|
|
16
|
+
bufferFrames: number;
|
|
17
|
+
frameLookback: number;
|
|
18
|
+
}
|
|
19
|
+
export interface ScrollConfig {
|
|
20
|
+
enabled: boolean;
|
|
21
|
+
pixelsPerDegree: number;
|
|
22
|
+
maxVelocity: number;
|
|
23
|
+
accelerationCurve: number;
|
|
24
|
+
}
|
|
25
|
+
export interface TouchProofConfig {
|
|
26
|
+
proximityEnter: number;
|
|
27
|
+
proximityExit: number;
|
|
28
|
+
proximityHardCap: number;
|
|
29
|
+
angleEnterDeg: number;
|
|
30
|
+
angleExitDeg: number;
|
|
31
|
+
angleHardCapDeg: number;
|
|
32
|
+
correlationFrames: number;
|
|
33
|
+
correlationMin: number;
|
|
34
|
+
visibilityAsymmetryMin: number;
|
|
35
|
+
framesToEnter: number;
|
|
36
|
+
framesToExit: number;
|
|
37
|
+
fusedEnterThreshold: number;
|
|
38
|
+
fusedExitThreshold: number;
|
|
39
|
+
emaAlpha: number;
|
|
40
|
+
smoothProximity: boolean;
|
|
41
|
+
proximityMode: 'fixed' | 'adaptive' | 'logarithmic';
|
|
42
|
+
baselineLearningRate: number;
|
|
43
|
+
relativeTouchThreshold: number;
|
|
44
|
+
distanceNearPx: number;
|
|
45
|
+
distanceFarPx: number;
|
|
46
|
+
kD: number;
|
|
47
|
+
kTheta: number;
|
|
48
|
+
mfcWindowFrames: number;
|
|
49
|
+
mfcPatchSize: number;
|
|
50
|
+
mfcCorrMin: number;
|
|
51
|
+
mfcMagRatioMin: number;
|
|
52
|
+
mfcMagRatioMax: number;
|
|
53
|
+
}
|
|
54
|
+
export interface AppConfig {
|
|
55
|
+
cameraIndex: number;
|
|
56
|
+
frameWidth: number;
|
|
57
|
+
mirror: boolean;
|
|
58
|
+
touchThresholdPixels: number;
|
|
59
|
+
gates: GatesConfig;
|
|
60
|
+
kinematics: KinematicsConfig;
|
|
61
|
+
touchproof: TouchProofConfig;
|
|
62
|
+
scroll: ScrollConfig;
|
|
63
|
+
}
|
|
64
|
+
/** Create default config matching configs/defaults.yaml tuned values. */
|
|
65
|
+
export declare function createDefaultConfig(): AppConfig;
|
|
66
|
+
/** Deep-merge a partial config over defaults. */
|
|
67
|
+
export declare function mergeConfig(overrides: Partial<AppConfig>): AppConfig;
|
|
68
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAE/B,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IAGzB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IAGxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IAGvB,sBAAsB,EAAE,MAAM,CAAC;IAG/B,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IAGrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,kBAAkB,EAAE,MAAM,CAAC;IAG3B,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,OAAO,CAAC;IAGzB,aAAa,EAAE,OAAO,GAAG,UAAU,GAAG,aAAa,CAAC;IACpD,oBAAoB,EAAE,MAAM,CAAC;IAC7B,sBAAsB,EAAE,MAAM,CAAC;IAG/B,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IAGf,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,SAAS;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,oBAAoB,EAAE,MAAM,CAAC;IAE7B,KAAK,EAAE,WAAW,CAAC;IACnB,UAAU,EAAE,gBAAgB,CAAC;IAC7B,UAAU,EAAE,gBAAgB,CAAC;IAC7B,MAAM,EAAE,YAAY,CAAC;CACtB;AAED,yEAAyE;AACzE,wBAAgB,mBAAmB,IAAI,SAAS,CAkE/C;AAED,iDAAiD;AACjD,wBAAgB,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,SAAS,CAUpE"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core data types for Glide web UI.
|
|
3
|
+
* Ported from glide/core/types.py
|
|
4
|
+
*/
|
|
5
|
+
export declare enum GateState {
|
|
6
|
+
UNARMED = "UNARMED",
|
|
7
|
+
READY = "READY",
|
|
8
|
+
ARMED = "ARMED",
|
|
9
|
+
COOLDOWN = "COOLDOWN"
|
|
10
|
+
}
|
|
11
|
+
export interface Landmark {
|
|
12
|
+
x: number;
|
|
13
|
+
y: number;
|
|
14
|
+
visibility?: number;
|
|
15
|
+
presence?: number;
|
|
16
|
+
}
|
|
17
|
+
export interface BBox {
|
|
18
|
+
x: number;
|
|
19
|
+
y: number;
|
|
20
|
+
w: number;
|
|
21
|
+
h: number;
|
|
22
|
+
}
|
|
23
|
+
export interface HandDet {
|
|
24
|
+
landmarks: Landmark[];
|
|
25
|
+
handedness: string;
|
|
26
|
+
confidence: number;
|
|
27
|
+
bbox?: BBox;
|
|
28
|
+
}
|
|
29
|
+
export interface PoseFlags {
|
|
30
|
+
openPalm: boolean;
|
|
31
|
+
pointingIndex: boolean;
|
|
32
|
+
twoUp: boolean;
|
|
33
|
+
}
|
|
34
|
+
export declare function createPoseFlags(): PoseFlags;
|
|
35
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,oBAAY,SAAS;IACnB,OAAO,YAAY;IACnB,KAAK,UAAU;IACf,KAAK,UAAU;IACf,QAAQ,aAAa;CACtB;AAED,MAAM,WAAW,QAAQ;IACvB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,IAAI;IACnB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,OAAO;IACtB,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,IAAI,CAAC;CACb;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,OAAO,CAAC;IAClB,aAAa,EAAE,OAAO,CAAC;IACvB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,wBAAgB,eAAe,IAAI,SAAS,CAE3C"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hand-aligned coordinate system.
|
|
3
|
+
* Ported from glide/features/alignment.py
|
|
4
|
+
*/
|
|
5
|
+
import type { Landmark } from '../core/types';
|
|
6
|
+
export declare class HandAligner {
|
|
7
|
+
palmCenter: [number, number] | null;
|
|
8
|
+
thetaRad: number | null;
|
|
9
|
+
scale: number | null;
|
|
10
|
+
imageWidth: number | null;
|
|
11
|
+
imageHeight: number | null;
|
|
12
|
+
/**
|
|
13
|
+
* Update alignment parameters from hand landmarks.
|
|
14
|
+
* Returns true if successful.
|
|
15
|
+
*/
|
|
16
|
+
update(landmarks: Landmark[], imageWidth: number, imageHeight: number): boolean;
|
|
17
|
+
normalizedToPixel(xNorm: number, yNorm: number): [number, number];
|
|
18
|
+
pixelToNormalized(xPx: number, yPx: number): [number, number];
|
|
19
|
+
/** Transform normalized coordinates to hand-aligned coordinates. */
|
|
20
|
+
toHandAligned(xNorm: number, yNorm: number): [number, number];
|
|
21
|
+
/** Inverse: hand-aligned → normalized coordinates. */
|
|
22
|
+
fromHandAligned(xAligned: number, yAligned: number): [number, number];
|
|
23
|
+
/** Get fingertip pixel positions: [[indexX, indexY], [middleX, middleY]]. */
|
|
24
|
+
getFingertipPixels(landmarks: Landmark[]): [[number, number], [number, number]];
|
|
25
|
+
/** Normalized distance between index and middle fingertips (0 = touching). */
|
|
26
|
+
getNormalizedDistance(landmarks: Landmark[]): number;
|
|
27
|
+
/** Log-normalized distance (more stable across camera distances). */
|
|
28
|
+
getNormalizedDistanceLog(landmarks: Landmark[]): number;
|
|
29
|
+
/** Angle between index and middle fingers from palm center (degrees). */
|
|
30
|
+
getFingertipAngle(landmarks: Landmark[]): number;
|
|
31
|
+
/** Distance factor: 0.0 = very close, 1.0 = far away. */
|
|
32
|
+
getHandDistanceFactor(): number;
|
|
33
|
+
/** Finger length in pixels. */
|
|
34
|
+
getFingerLengthPixels(): number;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=alignment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alignment.d.ts","sourceRoot":"","sources":["../../src/features/alignment.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,qBAAa,WAAW;IACtB,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAQ;IAC3C,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC/B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC5B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAQ;IACjC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAQ;IAElC;;;OAGG;IACH,MAAM,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO;IAgC/E,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IAKjE,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IAK7D,oEAAoE;IACpE,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IAgB7D,sDAAsD;IACtD,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IAgBrE,6EAA6E;IAC7E,kBAAkB,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAY/E,8EAA8E;IAC9E,qBAAqB,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,MAAM;IAYpD,qEAAqE;IACrE,wBAAwB,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,MAAM;IAevD,yEAAyE;IACzE,iBAAiB,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,MAAM;IAoBhD,yDAAyD;IACzD,qBAAqB,IAAI,MAAM;IAS/B,+BAA+B;IAC/B,qBAAqB,IAAI,MAAM;CAMhC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Kinematics tracking — EMA-smoothed fingertip positions.
|
|
3
|
+
* Ported from glide/features/kinematics.py
|
|
4
|
+
*/
|
|
5
|
+
import { BoundedDeque } from '../core/collections';
|
|
6
|
+
import type { Landmark } from '../core/types';
|
|
7
|
+
export interface HandKinematics {
|
|
8
|
+
palmX: number;
|
|
9
|
+
palmY: number;
|
|
10
|
+
thetaRad: number;
|
|
11
|
+
indexTipRel: [number, number];
|
|
12
|
+
middleTipRel: [number, number] | null;
|
|
13
|
+
fingerLengthIdx: number;
|
|
14
|
+
fingerLengthMid: number | null;
|
|
15
|
+
}
|
|
16
|
+
export declare class KinematicsTracker {
|
|
17
|
+
private emaAlpha;
|
|
18
|
+
private _idxTipEma;
|
|
19
|
+
private _midTipEma;
|
|
20
|
+
trail: BoundedDeque<[number, number]>;
|
|
21
|
+
trailMid: BoundedDeque<[number, number]>;
|
|
22
|
+
trailMean: BoundedDeque<[number, number]>;
|
|
23
|
+
constructor(emaAlpha?: number, bufferFrames?: number);
|
|
24
|
+
private static mean;
|
|
25
|
+
private static rot;
|
|
26
|
+
private static ema;
|
|
27
|
+
compute(landmarks: Landmark[]): HandKinematics | null;
|
|
28
|
+
getMeanFingertip(): [number, number] | null;
|
|
29
|
+
getFingerSpeeds(lookback?: number): [number | null, number | null];
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=kinematics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kinematics.d.ts","sourceRoot":"","sources":["../../src/features/kinematics.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;IACtC,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,UAAU,CAAiC;IACnD,OAAO,CAAC,UAAU,CAAiC;IAEnD,KAAK,EAAE,YAAY,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACtC,QAAQ,EAAE,YAAY,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACzC,SAAS,EAAE,YAAY,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;gBAE9B,QAAQ,SAAO,EAAE,YAAY,SAAK;IAO9C,OAAO,CAAC,MAAM,CAAC,IAAI;IAOnB,OAAO,CAAC,MAAM,CAAC,GAAG;IAMlB,OAAO,CAAC,MAAM,CAAC,GAAG;IASlB,OAAO,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,cAAc,GAAG,IAAI;IAmDrD,gBAAgB,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAQ3C,eAAe,CAAC,QAAQ,SAAI,GAAG,CAAC,MAAM,GAAG,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAkB9D"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hand pose detection.
|
|
3
|
+
* Ported from glide/features/poses.py
|
|
4
|
+
*/
|
|
5
|
+
import type { Landmark, PoseFlags } from '../core/types';
|
|
6
|
+
/**
|
|
7
|
+
* Check hand pose for common gestures.
|
|
8
|
+
*
|
|
9
|
+
* - openPalm: spread between index MCP and pinky MCP is large
|
|
10
|
+
* - pointingIndex: index tip beyond middle tip in pointing direction
|
|
11
|
+
* - twoUp: index and middle tips above ring tip (y smaller in image coords)
|
|
12
|
+
*/
|
|
13
|
+
export declare function checkHandPose(landmarks: Landmark[]): PoseFlags;
|
|
14
|
+
//# sourceMappingURL=poses.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"poses.d.ts","sourceRoot":"","sources":["../../src/features/poses.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAGzD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,SAAS,CAkB9D"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TouchProof detector — multi-signal fusion for fingertip contact detection.
|
|
3
|
+
* Ported from glide/gestures/touchproof_detector.py
|
|
4
|
+
*
|
|
5
|
+
* MFC (optical flow) is excluded: mfcScore hardcoded to 0.5 (neutral).
|
|
6
|
+
*/
|
|
7
|
+
import type { TouchProofConfig } from '../core/config';
|
|
8
|
+
import { GateState } from '../core/types';
|
|
9
|
+
import type { Landmark } from '../core/types';
|
|
10
|
+
import { HandAligner } from '../features/alignment';
|
|
11
|
+
import type { TouchProofSignals } from './touchproof-signals';
|
|
12
|
+
export declare class TouchProofDetector {
|
|
13
|
+
config: TouchProofConfig;
|
|
14
|
+
aligner: HandAligner;
|
|
15
|
+
state: GateState;
|
|
16
|
+
private _enterCounter;
|
|
17
|
+
private _exitCounter;
|
|
18
|
+
private _idxPositions;
|
|
19
|
+
private _midPositions;
|
|
20
|
+
private _proximityEma;
|
|
21
|
+
private _angleEma;
|
|
22
|
+
private _baselineClose;
|
|
23
|
+
private _baselineFar;
|
|
24
|
+
private _baselineAlpha;
|
|
25
|
+
/** Hardcoded MFC score (no optical flow in browser). */
|
|
26
|
+
private _lastMfcScore;
|
|
27
|
+
constructor(config: TouchProofConfig);
|
|
28
|
+
/**
|
|
29
|
+
* Update touch detection with new landmarks.
|
|
30
|
+
* Note: no frame_bgr param (MFC excluded).
|
|
31
|
+
*/
|
|
32
|
+
update(landmarks: Landmark[], imageWidth: number, imageHeight: number): TouchProofSignals;
|
|
33
|
+
private _updateState;
|
|
34
|
+
private _updateBaseline;
|
|
35
|
+
private _getBaselineDistance;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=touchproof-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"touchproof-detector.d.ts","sourceRoot":"","sources":["../../src/gestures/touchproof-detector.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAUpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAG9D,qBAAa,kBAAkB;IAC7B,MAAM,EAAE,gBAAgB,CAAC;IACzB,OAAO,EAAE,WAAW,CAAC;IACrB,KAAK,EAAE,SAAS,CAAqB;IAErC,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,YAAY,CAAK;IAEzB,OAAO,CAAC,aAAa,CAAiC;IACtD,OAAO,CAAC,aAAa,CAAiC;IAEtD,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,SAAS,CAAuB;IAExC,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,cAAc,CAAS;IAE/B,wDAAwD;IACxD,OAAO,CAAC,aAAa,CAAO;gBAEhB,MAAM,EAAE,gBAAgB;IAQpC;;;OAGG;IACH,MAAM,CACJ,SAAS,EAAE,QAAQ,EAAE,EACrB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,GAClB,iBAAiB;IAgJpB,OAAO,CAAC,YAAY;IAgCpB,OAAO,CAAC,eAAe;IAoBvB,OAAO,CAAC,oBAAoB;CAS7B"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure scoring functions for TouchProof detection.
|
|
3
|
+
* Ported from glide/gestures/touchproof_scoring.py
|
|
4
|
+
*
|
|
5
|
+
* All functions are stateless and side-effect free.
|
|
6
|
+
*/
|
|
7
|
+
import type { Landmark } from '../core/types';
|
|
8
|
+
import type { TouchProofConfig } from '../core/config';
|
|
9
|
+
/** Convert normalized distance to proximity score (0-1). */
|
|
10
|
+
export declare function scoreProximity(distanceNorm: number, enterThreshold: number, exitThreshold: number): number;
|
|
11
|
+
/** Convert angle to score (0-1). More parallel = higher. */
|
|
12
|
+
export declare function scoreAngle(angleDeg: number, enterDeg: number, exitDeg: number): number;
|
|
13
|
+
/** Score based on visibility asymmetry (occlusion indicator). */
|
|
14
|
+
export declare function scoreVisibility(indexTip: Landmark, middleTip: Landmark, asymmetryMin: number): number;
|
|
15
|
+
/** Compute velocity correlation between fingers. */
|
|
16
|
+
export declare function computeCorrelation(idxPositions: [number, number][], midPositions: [number, number][], correlationFrames: number, correlationMin: number): number;
|
|
17
|
+
/** Pearson correlation coefficient. Returns null if cannot compute. */
|
|
18
|
+
export declare function pearsonCorrelation(a: number[], b: number[]): number | null;
|
|
19
|
+
/** Score proximity with distance-aware thresholds and relative baseline. */
|
|
20
|
+
export declare function scoreProximityAdjusted(distanceNorm: number, distanceFactor: number, config: TouchProofConfig, baseline: number | null): number;
|
|
21
|
+
/** Score angle with distance-aware thresholds. */
|
|
22
|
+
export declare function scoreAngleAdjusted(angleDeg: number, distanceFactor: number, config: TouchProofConfig): number;
|
|
23
|
+
/** Get fusion weights based on hand distance. */
|
|
24
|
+
export declare function getAdaptiveWeights(distanceFactor: number): {
|
|
25
|
+
proximity: number;
|
|
26
|
+
angle: number;
|
|
27
|
+
mfc: number;
|
|
28
|
+
occlusion: number;
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=touchproof-scoring.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"touchproof-scoring.d.ts","sourceRoot":"","sources":["../../src/gestures/touchproof-scoring.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEvD,4DAA4D;AAC5D,wBAAgB,cAAc,CAC5B,YAAY,EAAE,MAAM,EACpB,cAAc,EAAE,MAAM,EACtB,aAAa,EAAE,MAAM,GACpB,MAAM,CAIR;AAED,4DAA4D;AAC5D,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAItF;AAED,iEAAiE;AACjE,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAE,QAAQ,EACnB,YAAY,EAAE,MAAM,GACnB,MAAM,CAMR;AAED,oDAAoD;AACpD,wBAAgB,kBAAkB,CAChC,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,EAChC,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,EAChC,iBAAiB,EAAE,MAAM,EACzB,cAAc,EAAE,MAAM,GACrB,MAAM,CA+BR;AAED,uEAAuE;AACvE,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAwB1E;AAED,4EAA4E;AAC5E,wBAAgB,sBAAsB,CACpC,YAAY,EAAE,MAAM,EACpB,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,gBAAgB,EACxB,QAAQ,EAAE,MAAM,GAAG,IAAI,GACtB,MAAM,CAgBR;AAED,kDAAkD;AAClD,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,gBAAgB,GACvB,MAAM,CAQR;AAED,iDAAiD;AACjD,wBAAgB,kBAAkB,CAChC,cAAc,EAAE,MAAM,GACrB;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAkBtE"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TouchProof signals data structure.
|
|
3
|
+
* Ported from glide/gestures/touchproof_signals.py (dataclass only; MicroFlowTracker excluded).
|
|
4
|
+
*/
|
|
5
|
+
export interface TouchProofSignals {
|
|
6
|
+
proximityScore: number;
|
|
7
|
+
angleScore: number;
|
|
8
|
+
correlationScore: number;
|
|
9
|
+
visibilityScore: number;
|
|
10
|
+
mfcScore: number;
|
|
11
|
+
distanceFactor: number;
|
|
12
|
+
fusedScore: number;
|
|
13
|
+
isTouching: boolean;
|
|
14
|
+
}
|
|
15
|
+
export declare function emptySignals(): TouchProofSignals;
|
|
16
|
+
//# sourceMappingURL=touchproof-signals.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"touchproof-signals.d.ts","sourceRoot":"","sources":["../../src/gestures/touchproof-signals.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,iBAAiB;IAChC,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,wBAAgB,YAAY,IAAI,iBAAiB,CAWhD"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Velocity-based scroll controller.
|
|
3
|
+
* Ported from glide/gestures/velocity_controller.py
|
|
4
|
+
*/
|
|
5
|
+
import type { Vec2D } from './velocity-tracker';
|
|
6
|
+
export declare enum GestureState {
|
|
7
|
+
IDLE = "idle",
|
|
8
|
+
SCROLLING = "scrolling"
|
|
9
|
+
}
|
|
10
|
+
export interface VelocityUpdate {
|
|
11
|
+
velocity: Vec2D;
|
|
12
|
+
state: GestureState;
|
|
13
|
+
isActive: boolean;
|
|
14
|
+
}
|
|
15
|
+
export declare class VelocityController {
|
|
16
|
+
private minVelocity;
|
|
17
|
+
private scrollDelayMs;
|
|
18
|
+
state: GestureState;
|
|
19
|
+
private wasTouching;
|
|
20
|
+
private touchStartMs;
|
|
21
|
+
constructor(minVelocity?: number, scrollDelayMs?: number);
|
|
22
|
+
update(velocity: Vec2D | null, isTouching: boolean, isHighFive: boolean, timestampMs: number): VelocityUpdate;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=velocity-controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"velocity-controller.d.ts","sourceRoot":"","sources":["../../src/gestures/velocity-controller.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAGhD,oBAAY,YAAY;IACtB,IAAI,SAAS;IACb,SAAS,cAAc;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,KAAK,CAAC;IAChB,KAAK,EAAE,YAAY,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,aAAa,CAAS;IAC9B,KAAK,EAAE,YAAY,CAAqB;IACxC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,YAAY,CAAuB;gBAE/B,WAAW,SAAQ,EAAE,aAAa,SAAM;IAKpD,MAAM,CACJ,QAAQ,EAAE,KAAK,GAAG,IAAI,EACtB,UAAU,EAAE,OAAO,EACnB,UAAU,EAAE,OAAO,EACnB,WAAW,EAAE,MAAM,GAClB,cAAc;CAiClB"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Velocity tracking for smooth scrolling gestures.
|
|
3
|
+
* Ported from glide/gestures/velocity_tracker.py
|
|
4
|
+
*/
|
|
5
|
+
export interface Vec2D {
|
|
6
|
+
x: number;
|
|
7
|
+
y: number;
|
|
8
|
+
}
|
|
9
|
+
export declare function vec2dMagnitude(v: Vec2D): number;
|
|
10
|
+
export declare function vec2dZero(): Vec2D;
|
|
11
|
+
export declare class VelocityTracker {
|
|
12
|
+
private windowMs;
|
|
13
|
+
private smoothingFactor;
|
|
14
|
+
private samples;
|
|
15
|
+
private lastVelocity;
|
|
16
|
+
private minSamples;
|
|
17
|
+
private noiseThreshold;
|
|
18
|
+
constructor(windowMs?: number, smoothingFactor?: number);
|
|
19
|
+
update(indexTip: [number, number], middleTip: [number, number], isTouching: boolean, timestampMs: number): Vec2D | null;
|
|
20
|
+
private _calculateVelocity;
|
|
21
|
+
reset(): void;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=velocity-tracker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"velocity-tracker.d.ts","sourceRoot":"","sources":["../../src/gestures/velocity-tracker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,KAAK;IACpB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,wBAAgB,cAAc,CAAC,CAAC,EAAE,KAAK,GAAG,MAAM,CAE/C;AAED,wBAAgB,SAAS,IAAI,KAAK,CAEjC;AAQD,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,YAAY,CAAsB;IAC1C,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,cAAc,CAAO;gBAEjB,QAAQ,SAAM,EAAE,eAAe,SAAM;IAKjD,MAAM,CACJ,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAC1B,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAC3B,UAAU,EAAE,OAAO,EACnB,WAAW,EAAE,MAAM,GAClB,KAAK,GAAG,IAAI;IAiCf,OAAO,CAAC,kBAAkB;IAkB1B,KAAK,IAAI,IAAI;CAId"}
|