@pose-tracker/react-native-pose-estimation-light 0.3.3 → 0.3.5
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 +9 -9
- package/lib/camera/WebViewPoseView.d.ts +2 -1
- package/lib/camera/WebViewPoseView.js +16 -12
- package/lib/sdkVersion.d.ts +1 -1
- package/lib/sdkVersion.js +1 -1
- package/package.json +1 -1
- package/react-native.config.js +24 -3
- package/src/camera/WebViewPoseView.tsx +31 -17
- package/src/sdkVersion.ts +1 -1
package/README.md
CHANGED
|
@@ -36,10 +36,10 @@ package stays tiny.
|
|
|
36
36
|
download at session start.
|
|
37
37
|
**Choose light** when app install / OTA size matters and devices are online.
|
|
38
38
|
|
|
39
|
-
Full comparison: [LIGHT_SDK.md](
|
|
39
|
+
Full comparison: [LIGHT_SDK.md](docs/LIGHT_SDK.md).
|
|
40
40
|
|
|
41
41
|
**Agents:** shared UX/API/bugfixes → mirror to offline (or ask first). See
|
|
42
|
-
[`DUAL_SDK_CHANGES.md`](
|
|
42
|
+
[`DUAL_SDK_CHANGES.md`](docs/DUAL_SDK_CHANGES.md).
|
|
43
43
|
|
|
44
44
|
## Install
|
|
45
45
|
|
|
@@ -54,10 +54,10 @@ npx expo install react-native-webview expo-camera
|
|
|
54
54
|
> **Offline sibling:** [`@pose-tracker/react-native-pose-estimation`](https://www.npmjs.com/package/@pose-tracker/react-native-pose-estimation)
|
|
55
55
|
|
|
56
56
|
**Required:** host app must declare camera permissions — see
|
|
57
|
-
[PERMISSIONS.md](
|
|
57
|
+
[PERMISSIONS.md](docs/PERMISSIONS.md).
|
|
58
58
|
|
|
59
59
|
**Media inputs (v0.2):** camera (default), uploaded video, still image — host
|
|
60
|
-
picks the file. See [MEDIA_SOURCES.md](
|
|
60
|
+
picks the file. See [MEDIA_SOURCES.md](docs/MEDIA_SOURCES.md) and
|
|
61
61
|
https://docs.posetracker.com/media-sources.
|
|
62
62
|
|
|
63
63
|
## Quick start (keypoints — needs network, no API key)
|
|
@@ -144,11 +144,11 @@ Same contract as the offline SDK / web tracking URL:
|
|
|
144
144
|
|
|
145
145
|
| Doc | Topic |
|
|
146
146
|
|-----|--------|
|
|
147
|
-
| [LIGHT_SDK.md](
|
|
148
|
-
| [PERMISSIONS.md](
|
|
149
|
-
| [PRELOAD.md](
|
|
150
|
-
| [FEATURES.md](
|
|
151
|
-
| [EVENTS.md](
|
|
147
|
+
| [LIGHT_SDK.md](docs/LIGHT_SDK.md) | Offline vs light, sizes, model URL |
|
|
148
|
+
| [PERMISSIONS.md](docs/PERMISSIONS.md) | Camera permission setup (required) |
|
|
149
|
+
| [PRELOAD.md](docs/PRELOAD.md) | Preload / warm-up / lifecycle |
|
|
150
|
+
| [FEATURES.md](docs/FEATURES.md) | Plan gating, watermark, loading text |
|
|
151
|
+
| [EVENTS.md](docs/EVENTS.md) | Typed events + classic `onMessage` |
|
|
152
152
|
|
|
153
153
|
## FAQ
|
|
154
154
|
|
|
@@ -28,8 +28,9 @@ export interface WebViewPoseViewProps {
|
|
|
28
28
|
*/
|
|
29
29
|
drawSkeleton?: boolean;
|
|
30
30
|
/**
|
|
31
|
-
* Show
|
|
31
|
+
* Show the placement zone (iframe `placementOverlay` parity) while the
|
|
32
32
|
* active exercise reports `posture.ready === false`. Default `true`.
|
|
33
|
+
* Gray masks sit outside the box; the frame is the PoseTracker stroke.
|
|
33
34
|
* Drawn as an RN sibling overlay (reliable on iOS; Android WebView may
|
|
34
35
|
* composite above it — hosts can also render from `onPosture`).
|
|
35
36
|
*/
|
|
@@ -316,26 +316,30 @@ function WebViewPoseView(props) {
|
|
|
316
316
|
type: 'error',
|
|
317
317
|
message: e.nativeEvent.description ?? 'WebView error',
|
|
318
318
|
}));
|
|
319
|
-
} }), showPlacementBox ? ((0, jsx_runtime_1.jsx)(
|
|
319
|
+
} }), showPlacementBox ? ((0, jsx_runtime_1.jsx)(PlacementZone, { paddingPercent: placementPaddingPercent })) : null, props.children] }));
|
|
320
|
+
}
|
|
321
|
+
/** Iframe V4 placement: outside dim `#000` at 0.55, demo frame `#4DD21D`. */
|
|
322
|
+
const PLACEMENT_DIM = 'rgba(0,0,0,0.55)';
|
|
323
|
+
const PLACEMENT_STROKE = '#4DD21D';
|
|
324
|
+
function PlacementZone({ paddingPercent }) {
|
|
325
|
+
const pad = `${paddingPercent}%`;
|
|
326
|
+
return ((0, jsx_runtime_1.jsxs)(react_native_1.View, { pointerEvents: "none", style: react_native_1.StyleSheet.absoluteFill, children: [(0, jsx_runtime_1.jsx)(react_native_1.View, { style: [styles.placementDim, { top: 0, left: 0, right: 0, height: pad }] }), (0, jsx_runtime_1.jsx)(react_native_1.View, { style: [styles.placementDim, { bottom: 0, left: 0, right: 0, height: pad }] }), (0, jsx_runtime_1.jsx)(react_native_1.View, { style: [styles.placementDim, { top: pad, bottom: pad, left: 0, width: pad }] }), (0, jsx_runtime_1.jsx)(react_native_1.View, { style: [styles.placementDim, { top: pad, bottom: pad, right: 0, width: pad }] }), (0, jsx_runtime_1.jsx)(react_native_1.View, { style: [
|
|
320
327
|
styles.placementBox,
|
|
321
|
-
{
|
|
322
|
-
|
|
323
|
-
bottom: `${placementPaddingPercent}%`,
|
|
324
|
-
left: `${placementPaddingPercent}%`,
|
|
325
|
-
right: `${placementPaddingPercent}%`,
|
|
326
|
-
},
|
|
327
|
-
] })) : null, props.children] }));
|
|
328
|
+
{ top: pad, bottom: pad, left: pad, right: pad },
|
|
329
|
+
] })] }));
|
|
328
330
|
}
|
|
329
331
|
const styles = react_native_1.StyleSheet.create({
|
|
330
332
|
fill: { flex: 1, backgroundColor: '#000' },
|
|
331
333
|
center: { alignItems: 'center', justifyContent: 'center', padding: 16 },
|
|
332
334
|
error: { color: '#FE8370', textAlign: 'center', fontSize: 13 },
|
|
333
|
-
|
|
335
|
+
placementDim: {
|
|
336
|
+
position: 'absolute',
|
|
337
|
+
backgroundColor: PLACEMENT_DIM,
|
|
338
|
+
},
|
|
334
339
|
placementBox: {
|
|
335
340
|
position: 'absolute',
|
|
336
|
-
borderWidth:
|
|
337
|
-
borderColor:
|
|
338
|
-
borderRadius: 8,
|
|
341
|
+
borderWidth: 2,
|
|
342
|
+
borderColor: PLACEMENT_STROKE,
|
|
339
343
|
backgroundColor: 'transparent',
|
|
340
344
|
},
|
|
341
345
|
});
|
package/lib/sdkVersion.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** AUTO-GENERATED by scripts/sync-sdk-version.mjs — do not edit. */
|
|
2
|
-
export declare const SDK_VERSION = "0.3.
|
|
2
|
+
export declare const SDK_VERSION = "0.3.5";
|
package/lib/sdkVersion.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pose-tracker/react-native-pose-estimation-light",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.5",
|
|
4
4
|
"description": "Human pose estimation SDK for React Native (light / online) — MoveNet Lightning via CDN + model URL each session, no bundled weights. iOS & Android (Expo Go). Optional API-key exercise engine.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
package/react-native.config.js
CHANGED
|
@@ -1,12 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Autolinking
|
|
3
|
-
*
|
|
2
|
+
* Autolinking for the Apple Vision frame-processor plugin.
|
|
3
|
+
*
|
|
4
|
+
* Android has no native project. On iOS the plugin compiles against the
|
|
5
|
+
* VisionCamera pod, so it is linked only when the host app installed
|
|
6
|
+
* react-native-vision-camera. Apps that only use the WebView camera must
|
|
7
|
+
* not fail `pod install` looking for a pod they never added.
|
|
4
8
|
*/
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
|
|
12
|
+
function directoryHasVisionCamera(dir) {
|
|
13
|
+
return fs.existsSync(path.join(dir, 'node_modules', 'react-native-vision-camera', 'package.json'));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function hostHasVisionCamera() {
|
|
17
|
+
const cwd = process.cwd();
|
|
18
|
+
const candidates = [cwd];
|
|
19
|
+
const base = path.basename(cwd);
|
|
20
|
+
if (base === 'ios' || base === 'android') {
|
|
21
|
+
candidates.push(path.dirname(cwd));
|
|
22
|
+
}
|
|
23
|
+
return candidates.some(directoryHasVisionCamera);
|
|
24
|
+
}
|
|
25
|
+
|
|
5
26
|
module.exports = {
|
|
6
27
|
dependency: {
|
|
7
28
|
platforms: {
|
|
8
29
|
android: null,
|
|
9
|
-
ios: {},
|
|
30
|
+
ios: hostHasVisionCamera() ? {} : null,
|
|
10
31
|
},
|
|
11
32
|
},
|
|
12
33
|
};
|
|
@@ -76,8 +76,9 @@ export interface WebViewPoseViewProps {
|
|
|
76
76
|
*/
|
|
77
77
|
drawSkeleton?: boolean;
|
|
78
78
|
/**
|
|
79
|
-
* Show
|
|
79
|
+
* Show the placement zone (iframe `placementOverlay` parity) while the
|
|
80
80
|
* active exercise reports `posture.ready === false`. Default `true`.
|
|
81
|
+
* Gray masks sit outside the box; the frame is the PoseTracker stroke.
|
|
81
82
|
* Drawn as an RN sibling overlay (reliable on iOS; Android WebView may
|
|
82
83
|
* composite above it — hosts can also render from `onPosture`).
|
|
83
84
|
*/
|
|
@@ -475,18 +476,7 @@ export function WebViewPoseView(props: WebViewPoseViewProps): React.ReactElement
|
|
|
475
476
|
}}
|
|
476
477
|
/>
|
|
477
478
|
{showPlacementBox ? (
|
|
478
|
-
<
|
|
479
|
-
pointerEvents="none"
|
|
480
|
-
style={[
|
|
481
|
-
styles.placementBox,
|
|
482
|
-
{
|
|
483
|
-
top: `${placementPaddingPercent}%`,
|
|
484
|
-
bottom: `${placementPaddingPercent}%`,
|
|
485
|
-
left: `${placementPaddingPercent}%`,
|
|
486
|
-
right: `${placementPaddingPercent}%`,
|
|
487
|
-
},
|
|
488
|
-
]}
|
|
489
|
-
/>
|
|
479
|
+
<PlacementZone paddingPercent={placementPaddingPercent} />
|
|
490
480
|
) : null}
|
|
491
481
|
{/* Optional RN overlay (works on iOS; usually hidden under Android WebView surface). */}
|
|
492
482
|
{props.children}
|
|
@@ -494,16 +484,40 @@ export function WebViewPoseView(props: WebViewPoseViewProps): React.ReactElement
|
|
|
494
484
|
);
|
|
495
485
|
}
|
|
496
486
|
|
|
487
|
+
/** Iframe V4 placement: outside dim `#000` at 0.55, demo frame `#4DD21D`. */
|
|
488
|
+
const PLACEMENT_DIM = 'rgba(0,0,0,0.55)';
|
|
489
|
+
const PLACEMENT_STROKE = '#4DD21D';
|
|
490
|
+
|
|
491
|
+
function PlacementZone({ paddingPercent }: { paddingPercent: number }) {
|
|
492
|
+
const pad = `${paddingPercent}%` as `${number}%`;
|
|
493
|
+
return (
|
|
494
|
+
<View pointerEvents="none" style={StyleSheet.absoluteFill}>
|
|
495
|
+
<View style={[styles.placementDim, { top: 0, left: 0, right: 0, height: pad }]} />
|
|
496
|
+
<View style={[styles.placementDim, { bottom: 0, left: 0, right: 0, height: pad }]} />
|
|
497
|
+
<View style={[styles.placementDim, { top: pad, bottom: pad, left: 0, width: pad }]} />
|
|
498
|
+
<View style={[styles.placementDim, { top: pad, bottom: pad, right: 0, width: pad }]} />
|
|
499
|
+
<View
|
|
500
|
+
style={[
|
|
501
|
+
styles.placementBox,
|
|
502
|
+
{ top: pad, bottom: pad, left: pad, right: pad },
|
|
503
|
+
]}
|
|
504
|
+
/>
|
|
505
|
+
</View>
|
|
506
|
+
);
|
|
507
|
+
}
|
|
508
|
+
|
|
497
509
|
const styles = StyleSheet.create({
|
|
498
510
|
fill: { flex: 1, backgroundColor: '#000' },
|
|
499
511
|
center: { alignItems: 'center', justifyContent: 'center', padding: 16 },
|
|
500
512
|
error: { color: '#FE8370', textAlign: 'center', fontSize: 13 },
|
|
501
|
-
|
|
513
|
+
placementDim: {
|
|
514
|
+
position: 'absolute',
|
|
515
|
+
backgroundColor: PLACEMENT_DIM,
|
|
516
|
+
},
|
|
502
517
|
placementBox: {
|
|
503
518
|
position: 'absolute',
|
|
504
|
-
borderWidth:
|
|
505
|
-
borderColor:
|
|
506
|
-
borderRadius: 8,
|
|
519
|
+
borderWidth: 2,
|
|
520
|
+
borderColor: PLACEMENT_STROKE,
|
|
507
521
|
backgroundColor: 'transparent',
|
|
508
522
|
},
|
|
509
523
|
});
|
package/src/sdkVersion.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** AUTO-GENERATED by scripts/sync-sdk-version.mjs — do not edit. */
|
|
2
|
-
export const SDK_VERSION = '0.3.
|
|
2
|
+
export const SDK_VERSION = '0.3.5';
|