@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 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](../../docs/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`](../../docs/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](../../docs/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](../../docs/MEDIA_SOURCES.md) and
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](../../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` |
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 a placement guide box (WebView `postureBox` parity) while the
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)(react_native_1.View, { pointerEvents: "none", style: [
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
- top: `${placementPaddingPercent}%`,
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
- /** Front drawPostureBox stroke `#FE8370`. */
335
+ placementDim: {
336
+ position: 'absolute',
337
+ backgroundColor: PLACEMENT_DIM,
338
+ },
334
339
  placementBox: {
335
340
  position: 'absolute',
336
- borderWidth: 3,
337
- borderColor: '#FE8370',
338
- borderRadius: 8,
341
+ borderWidth: 2,
342
+ borderColor: PLACEMENT_STROKE,
339
343
  backgroundColor: 'transparent',
340
344
  },
341
345
  });
@@ -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.3";
2
+ export declare const SDK_VERSION = "0.3.5";
package/lib/sdkVersion.js CHANGED
@@ -2,4 +2,4 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SDK_VERSION = void 0;
4
4
  /** AUTO-GENERATED by scripts/sync-sdk-version.mjs — do not edit. */
5
- exports.SDK_VERSION = '0.3.3';
5
+ exports.SDK_VERSION = '0.3.5';
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",
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",
@@ -1,12 +1,33 @@
1
1
  /**
2
- * Autolinking: Apple Vision frame-processor plugin is iOS-only.
3
- * Android hosts skip the native project (JS falls back to TFLite / TF.js).
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 a placement guide box (WebView `postureBox` parity) while the
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
- <View
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
- /** Front drawPostureBox stroke `#FE8370`. */
513
+ placementDim: {
514
+ position: 'absolute',
515
+ backgroundColor: PLACEMENT_DIM,
516
+ },
502
517
  placementBox: {
503
518
  position: 'absolute',
504
- borderWidth: 3,
505
- borderColor: '#FE8370',
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.3';
2
+ export const SDK_VERSION = '0.3.5';