@rexai/pulse-react 1.1.0 → 2.0.0

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/dist/index.d.mts CHANGED
@@ -2,241 +2,346 @@ import React$1 from 'react';
2
2
 
3
3
  /**
4
4
  * PulseAI SDK Type Definitions
5
+ *
6
+ * Version: 2.1.0
7
+ *
8
+ * IMPORTANT: Many metrics now return `null` when calculation fails.
9
+ * Always check for null before displaying values.
5
10
  */
11
+ interface BloodPressureFeatures {
12
+ rise_time_ms: number | null;
13
+ pulse_amplitude: number | null;
14
+ pulse_width_ms: number | null;
15
+ augmentation_index: number | null;
16
+ pulses_analyzed: number;
17
+ }
6
18
  interface BloodPressure {
7
- systolic: number;
8
- diastolic: number;
19
+ systolic: number | null;
20
+ diastolic: number | null;
21
+ pulse_pressure: number | null;
22
+ confidence: 'high' | 'moderate' | 'low' | 'very_low' | null;
23
+ features?: BloodPressureFeatures;
24
+ methodology?: string;
25
+ note?: string;
26
+ error?: string;
27
+ }
28
+ interface SpO2MethodResult {
29
+ spo2: number;
30
+ ratio: number;
31
+ quality: number;
32
+ }
33
+ interface SpO2Result {
34
+ spo2: number | null;
35
+ confidence: 'high' | 'moderate' | 'low' | 'very_low' | null;
36
+ method_used: 'red_blue' | 'green_red' | null;
37
+ signal_quality: number | null;
38
+ methods?: {
39
+ red_blue?: SpO2MethodResult;
40
+ green_red?: SpO2MethodResult;
41
+ };
42
+ error?: string;
9
43
  }
10
44
  interface ArrhythmiaResult {
11
- has_arrhythmia: boolean;
12
- irregularity_score: number;
13
- details: string;
45
+ has_arrhythmia: boolean | null;
46
+ irregularity_score: number | null;
47
+ confidence: number | null;
48
+ details: string | null;
49
+ }
50
+ interface StressResult {
51
+ score: number | null;
52
+ level: 'low' | 'mild' | 'moderate' | 'high' | null;
53
+ confidence: number | null;
54
+ rmssd_ms: number | null;
55
+ }
56
+ interface RecoveryResult {
57
+ score: number | null;
58
+ level: 'poor' | 'moderate' | 'good' | 'excellent' | null;
59
+ rmssd_ms: number | null;
60
+ }
61
+ interface RespiratoryResult {
62
+ rate: number | null;
63
+ confidence: 'high' | 'moderate' | 'low' | null;
64
+ signal_quality: number | null;
65
+ breaths_detected: number | null;
66
+ interval_variability: number | null;
67
+ error?: string;
68
+ }
69
+ interface VascularAgeResult {
70
+ vascular_age: number | null;
71
+ chronological_age: number | null;
72
+ difference_years: number | null;
73
+ status: 'younger_than_chronological' | 'close_to_chronological' | 'moderately_elevated' | 'significantly_elevated' | null;
74
+ methodology?: string;
75
+ }
76
+ interface BMIEstimate {
77
+ value: number | null;
78
+ category: 'Underweight' | 'Normal' | 'Overweight' | 'Obese' | null;
79
+ confidence: 'high' | 'moderate' | 'low' | 'very_low' | 'invalid' | null;
80
+ fwhr: number | null;
81
+ source?: 'manual_input' | 'facial_estimation';
82
+ methodology?: string;
83
+ note?: string;
84
+ reason?: string;
85
+ }
86
+ interface SkinTemperatureResult {
87
+ value: number | null;
88
+ unit: string;
89
+ ratio: number | null;
90
+ confidence: 'proxy_only' | 'invalid_ratio';
91
+ note?: string;
92
+ }
93
+ interface FatigueIndicators {
94
+ eye_redness: number | null;
95
+ under_eye_darkness: number | null;
96
+ puffiness: number | null;
97
+ overall_fatigue: string | null;
98
+ }
99
+ interface SkinHealth {
100
+ evenness: number | null;
101
+ redness: number | null;
102
+ oiliness_proxy: number | null;
14
103
  }
15
104
  interface VisualAnalysis {
16
- jaundice_risk: 'Low' | 'Medium' | 'High';
17
- anemia_risk: 'Low' | 'Medium' | 'High';
18
- bilirubin_proxy: number;
19
- pallor_index: number;
20
- hydration_level?: string;
21
- hydration_score?: number;
22
- fatigue_indicators?: {
23
- eye_redness: number;
24
- under_eye_darkness: number;
25
- puffiness: number;
26
- overall_fatigue: string;
27
- };
28
- skin_health?: {
29
- evenness: number;
30
- redness: number;
31
- oiliness_proxy: number;
32
- };
105
+ jaundice_risk: 'Low' | 'Medium' | 'High' | null;
106
+ anemia_risk: 'Low' | 'Medium' | 'High' | null;
107
+ bilirubin_proxy: number | null;
108
+ pallor_index: number | null;
109
+ hydration_level?: string | null;
110
+ hydration_score?: number | null;
111
+ texture_score?: number | null;
112
+ fatigue_indicators?: FatigueIndicators;
113
+ skin_health?: SkinHealth;
114
+ }
115
+ interface MentalWellnessComponents {
116
+ blink_score: number | null;
117
+ gaze_score: number | null;
118
+ emotion_score: number | null;
119
+ hrv_score: number | null;
33
120
  }
34
121
  interface MentalWellness {
35
- wellness_score: number;
36
- level: string;
37
- emotion: string;
38
- emotion_confidence?: number;
39
- blink_rate_per_min: number;
40
- gaze_stability: number;
41
- gaze_direction?: string;
42
- components: {
43
- blink_score: number;
44
- gaze_score: number;
45
- emotion_score: number;
46
- hrv_score: number;
47
- };
122
+ wellness_score: number | null;
123
+ level: string | null;
124
+ emotion: string | null;
125
+ emotion_confidence?: number | null;
126
+ blink_rate_per_min: number | null;
127
+ gaze_stability: number | null;
128
+ gaze_direction?: string | null;
129
+ components: MentalWellnessComponents | null;
130
+ }
131
+ interface CompositeScoreDetails {
132
+ cardio?: string[];
133
+ resilience?: string[];
134
+ metabolic?: string[];
135
+ vitality?: string[];
48
136
  }
49
137
  interface CompositeScores {
50
- cardio_score: number;
51
- resilience_score: number;
52
- metabolic_score: number;
53
- vitality_score: number;
54
- }
55
- interface BMIEstimate {
56
- value: number;
57
- category: string;
58
- fwhr: number;
59
- confidence?: string;
60
- method?: string;
138
+ cardio_score: number | null;
139
+ resilience_score: number | null;
140
+ metabolic_score: number | null;
141
+ vitality_score: number | null;
142
+ calculation_details?: CompositeScoreDetails;
143
+ bmi_used?: number;
61
144
  }
62
145
  interface VitalsResult {
63
- heart_rate: number;
64
- respiratory_rate: number;
65
- hrv_sdnn: number;
66
- hrv_rmssd: number;
67
- recovery_score: number;
68
- stress_index: number;
69
- arrhythmia: ArrhythmiaResult;
70
- rsa_amplitude: number;
71
- blood_pressure: BloodPressure;
72
- spo2: number;
73
- signal_snippet: number[];
74
- vascular_age: number;
75
- bmi_est: BMIEstimate;
146
+ heart_rate: number | null;
147
+ hr_confidence?: 'high' | 'moderate' | 'low' | 'very_low' | null;
148
+ hr_snr_db?: number | null;
149
+ respiratory_rate: RespiratoryResult | number | null;
150
+ hrv_sdnn: number | null;
151
+ hrv_rmssd: number | null;
152
+ stress_index: StressResult | number | null;
153
+ recovery_score: RecoveryResult | number | null;
154
+ arrhythmia: ArrhythmiaResult | null;
155
+ rsa_amplitude: number | null;
156
+ blood_pressure: BloodPressure | null;
157
+ spo2: SpO2Result | number | null;
158
+ vascular_age: VascularAgeResult | number | null;
159
+ bmi_est: BMIEstimate | null;
76
160
  manual_bmi?: number;
77
- metabolic_score: number;
78
- skin_temperature: number;
79
- composite_scores: CompositeScores;
80
- visual_analysis?: VisualAnalysis;
81
- mental_wellness?: MentalWellness;
82
- fusion_weights: Record<string, number>;
161
+ skin_temperature: SkinTemperatureResult | number | null;
162
+ composite_scores: CompositeScores | null;
163
+ visual_analysis?: VisualAnalysis | null;
164
+ mental_wellness?: MentalWellness | null;
165
+ signal_snippet?: number[];
166
+ fusion_weights?: Record<string, number>;
167
+ metadata?: {
168
+ video_fps?: number;
169
+ frames_analyzed?: number;
170
+ };
171
+ error?: string | null;
83
172
  }
84
173
  interface BeautySummary {
85
- overall_score: number;
86
- skin_age: number;
174
+ overall_score: number | null;
175
+ skin_age: number | null;
176
+ age_provided: boolean;
177
+ age_difference?: number;
178
+ calculation_details?: Record<string, number>;
179
+ skin_age_note?: string;
180
+ error?: string;
87
181
  }
88
182
  interface BeautySurface {
89
- texture: number;
90
- hydration: number;
91
- foundation_hex: string;
92
- undertone: string;
93
- acne_count: number;
94
- acne_severity: string;
95
- wrinkle_severity: string;
96
- wrinkle_density: number;
97
- oiliness_index: number;
98
- matches: string;
99
- skin_health: {
100
- evenness: number;
101
- redness: number;
102
- oiliness_proxy: number;
103
- };
183
+ texture: number | null;
184
+ hydration: number | null;
185
+ foundation_hex: string | null;
186
+ undertone: 'warm' | 'cool' | null;
187
+ acne_count: number | null;
188
+ acne_severity: 'minimal' | 'mild' | 'moderate' | 'significant' | null;
189
+ wrinkle_severity: 'minimal' | 'mild' | 'moderate' | 'significant' | null;
190
+ wrinkle_density: number | null;
191
+ oiliness_index: number | null;
192
+ matches: string | null;
193
+ skin_health: SkinHealth | null;
194
+ }
195
+ interface PtosisIndices {
196
+ status: 'none' | 'mild' | 'significant' | null;
197
+ youth_ratio?: number | null;
198
+ eye_openness?: number | null;
104
199
  }
105
200
  interface BeautyGeometry {
106
- symmetry_score: number;
107
- face_shape: string;
108
- eye_openness: number;
109
- ptosis_indices: {
110
- status: string;
111
- youth_ratio?: number;
112
- };
201
+ symmetry_score: number | null;
202
+ face_shape: 'oval' | 'round' | 'square' | 'oblong' | null;
203
+ landmarks?: any;
204
+ ptosis_indices: PtosisIndices;
205
+ analysis_confidence?: 'high' | 'moderate' | 'low';
206
+ error?: string;
113
207
  }
114
208
  interface BeautyPhysiology {
115
- glow_index: number;
116
- stress_level: string;
117
- elasticity: number;
209
+ glow_index: number | null;
210
+ stress_level: 'low' | 'moderate' | 'high' | null;
211
+ elasticity: number | null;
212
+ heart_rate?: number | null;
118
213
  }
119
214
  interface BeautyRecommendations {
120
215
  routine: string[];
121
216
  tips: string[];
217
+ foundation?: string | null;
122
218
  }
123
219
  interface BeautyResult {
124
- summary: BeautySummary;
125
- surface: BeautySurface;
126
- geometry: BeautyGeometry;
127
- physiology: BeautyPhysiology;
128
- recommendations: BeautyRecommendations;
220
+ summary: BeautySummary | null;
221
+ surface: BeautySurface | null;
222
+ geometry: BeautyGeometry | null;
223
+ physiology: BeautyPhysiology | null;
224
+ recommendations: BeautyRecommendations | null;
225
+ meta?: {
226
+ rppg_source: string;
227
+ beauty_engine: string;
228
+ };
229
+ error?: string | null;
129
230
  }
130
231
  interface VoiceCompositeScores {
131
- mental_score: number;
132
- physical_score: number;
133
- cognitive_score: number;
134
- resilience_score: number;
232
+ mental_score: number | null;
233
+ physical_score: number | null;
234
+ cognitive_score: number | null;
235
+ resilience_score: number | null;
135
236
  }
136
237
  interface VoiceMoodIndicators {
137
- monotone_speech?: boolean;
138
- reduced_prosody?: boolean;
139
- normal_prosody?: boolean;
140
- slow_speech?: boolean;
141
- slightly_slow?: boolean;
142
- normal_rate?: boolean;
238
+ pitch_monotony?: 'high' | 'moderate' | 'low';
239
+ speech_slowness?: 'high' | 'moderate' | 'low';
143
240
  excessive_pauses?: boolean;
144
- frequent_pauses?: boolean;
145
- normal_pauses?: boolean;
146
- low_energy?: boolean;
147
- reduced_energy?: boolean;
148
- normal_energy?: boolean;
149
- low_pitch?: boolean;
241
+ flat_affect?: boolean | 'partial';
150
242
  }
151
243
  interface VoiceResult {
152
- stress_score: number;
153
- fatigue_score: number;
154
- anxiety_level: 'low' | 'mild' | 'moderate' | 'high' | 'unknown';
155
- anxiety_confidence: number;
156
- voice_quality: 'normal' | 'slightly_strained' | 'strained' | 'unknown';
157
- pitch_variability: number;
158
- speech_rate: number;
159
- pause_ratio: number;
160
- tremor_index: number;
161
- energy_variability: number;
162
- respiratory_rate: number;
163
- breathing_regularity: number;
164
- breath_depth: 'shallow' | 'normal' | 'deep' | 'unknown';
165
- respiratory_health: number;
166
- cough_detected: boolean;
167
- cough_count: number;
168
- wheeze_detected: boolean;
169
- respiratory_concern: 'none' | 'mild' | 'moderate' | 'high' | 'unknown';
170
- depression_risk: 'low' | 'mild' | 'moderate' | 'elevated' | 'unknown';
171
- depression_score: number;
172
- mood_indicators: VoiceMoodIndicators;
173
- cognitive_load: 'low' | 'normal' | 'moderate' | 'high' | 'unknown';
174
- cognitive_score: number;
175
- focus_indicator: 'relaxed' | 'stable' | 'engaged' | 'distracted' | 'unknown';
176
- composite_scores: VoiceCompositeScores;
177
- wellness_score: number;
178
- wellness_level: 'excellent' | 'good' | 'fair' | 'needs_attention' | 'concerning' | 'unknown';
179
- pitch_mean: number;
180
- pitch_range: number;
181
- energy_dynamics: number;
182
- rhythm_regularity: number;
183
- jitter: number;
184
- shimmer: number;
185
- duration_seconds: number;
186
- analysis_confidence: number;
244
+ status: 'success' | 'error' | null;
245
+ error?: string | null;
246
+ stress_score: number | null;
247
+ fatigue_score: number | null;
248
+ anxiety_level: 'low' | 'mild' | 'moderate' | 'high' | null;
249
+ anxiety_confidence: number | null;
250
+ voice_quality: 'healthy' | 'mild_strain' | 'moderate_strain' | 'significant_strain' | null;
251
+ pitch_variability: number | null;
252
+ speech_rate: number | null;
253
+ pause_ratio: number | null;
254
+ tremor_index: number | null;
255
+ energy_variability: number | null;
256
+ respiratory_rate: number | null;
257
+ breathing_regularity: number | null;
258
+ breath_depth: 'shallow' | 'normal' | 'deep' | null;
259
+ respiratory_health: number | null;
260
+ cough_detected: boolean | null;
261
+ cough_count: number | null;
262
+ wheeze_detected: boolean | null;
263
+ respiratory_concern: 'none' | 'mild' | 'elevated' | null;
264
+ depression_risk: 'low' | 'mild' | 'moderate' | 'elevated' | null;
265
+ depression_score: number | null;
266
+ mood_indicators: VoiceMoodIndicators | null;
267
+ cognitive_load: 'low' | 'normal' | 'moderate' | 'high' | null;
268
+ cognitive_score: number | null;
269
+ focus_indicator: 'relaxed' | 'stable' | 'engaged' | 'strained' | null;
270
+ composite_scores: VoiceCompositeScores | null;
271
+ wellness_score: number | null;
272
+ wellness_level: 'excellent' | 'good' | 'moderate' | 'fair' | 'poor' | null;
273
+ pitch_mean: number | null;
274
+ pitch_range: number | null;
275
+ energy_dynamics: number | null;
276
+ rhythm_regularity: number | null;
277
+ jitter: number | null;
278
+ shimmer: number | null;
279
+ duration_seconds: number | null;
280
+ analysis_confidence: number | null;
187
281
  analysis_version: string;
188
282
  }
189
283
  interface EyeCataract {
190
- opacity_score: number;
191
- risk_level: 'low' | 'mild' | 'moderate' | 'elevated' | 'high' | 'unknown';
192
- risk_confidence: number;
193
- description: string;
194
- recommendation: string;
284
+ opacity_score: number | null;
285
+ risk_level: 'low' | 'mild' | 'moderate' | 'elevated' | null;
286
+ confidence: 'high' | 'moderate' | 'low' | null;
287
+ description: string | null;
288
+ recommendation: string | null;
195
289
  }
196
290
  interface EyeRedEye {
197
- redness_score: number;
198
- risk_level: 'low' | 'mild' | 'moderate' | 'elevated' | 'high' | 'unknown';
199
- is_inflamed: boolean;
200
- description: string;
291
+ redness_score: number | null;
292
+ risk_level: 'low' | 'mild' | 'moderate' | 'elevated' | null;
293
+ is_inflamed: boolean | null;
294
+ confidence: 'high' | 'moderate' | 'low' | null;
295
+ description: string | null;
201
296
  }
202
297
  interface EyeLensClarity {
203
- score: number;
204
- level: 'clear' | 'moderate' | 'cloudy' | 'unknown';
298
+ score: number | null;
299
+ level: 'clear' | 'good' | 'moderate' | 'reduced' | null;
300
+ samples?: number;
205
301
  }
206
302
  interface EyePupil {
207
- regularity_score: number;
208
- status: 'normal' | 'irregular' | 'unknown';
303
+ regularity_score: number | null;
304
+ circularity: number | null;
305
+ status: 'normal' | 'irregular' | null;
306
+ samples_analyzed?: number;
307
+ detected?: boolean;
209
308
  }
210
309
  interface EyePterygium {
211
- detected: boolean;
212
- confidence: number;
213
- severity?: 'mild' | 'moderate' | 'severe';
310
+ detected: boolean | null;
311
+ confidence: number | null;
312
+ severity?: 'minimal' | 'mild' | 'moderate' | 'significant' | null;
214
313
  description?: string;
314
+ error?: string;
215
315
  }
216
316
  interface EyeStye {
217
- detected: boolean;
218
- confidence: number;
317
+ detected: boolean | null;
318
+ confidence: number | null;
319
+ note?: string;
219
320
  }
220
321
  interface EyeSclera {
221
- yellowing_score: number;
222
- jaundice_risk: 'low' | 'moderate' | 'high' | 'unknown';
223
- color_health: 'healthy' | 'monitor' | 'unknown';
322
+ score: number | null;
323
+ risk: 'low' | 'moderate' | 'elevated' | null;
324
+ color_health: 'healthy' | 'monitor' | null;
325
+ samples?: number;
326
+ error?: string;
224
327
  }
225
328
  interface EyeResult {
226
- status: 'success' | 'partial' | 'error';
227
- overall_score: number;
228
- health_level: 'Excellent' | 'Good' | 'Fair' | 'Needs Attention' | 'Unknown';
229
- cataract: EyeCataract;
230
- red_eye: EyeRedEye;
231
- lens_clarity: EyeLensClarity;
232
- pupil: EyePupil;
233
- pterygium: EyePterygium;
234
- stye: EyeStye;
235
- sclera: EyeSclera;
236
- recommendations: string[];
329
+ status: 'success' | 'error' | null;
330
+ overall_score: number | null;
331
+ health_level: 'Excellent' | 'Good' | 'Fair' | 'Needs Attention' | 'Consult Specialist' | null;
332
+ cataract: EyeCataract | null;
333
+ red_eye: EyeRedEye | null;
334
+ lens_clarity: EyeLensClarity | null;
335
+ pupil: EyePupil | null;
336
+ pterygium: EyePterygium | null;
337
+ stye: EyeStye | null;
338
+ sclera: EyeSclera | null;
339
+ recommendations: string[] | null;
237
340
  frames_analyzed: number;
238
- analysis_confidence: number;
341
+ eyes_detected: number;
342
+ analysis_confidence: 'high' | 'moderate' | 'low' | null;
239
343
  analysis_version?: string;
344
+ error?: string | null;
240
345
  }
241
346
  interface APIResponse<T> {
242
347
  status: 'success' | 'error';
@@ -310,21 +415,21 @@ declare const PulseScanner: React$1.FC<PulseScannerProps>;
310
415
  */
311
416
  interface VitalsCardProps {
312
417
  /** Heart rate in BPM */
313
- heartRate?: number;
418
+ heartRate?: number | null;
314
419
  /** Oxygen saturation percentage */
315
- spo2?: number;
420
+ spo2?: number | null;
316
421
  /** Stress index (0-100) */
317
- stressIndex?: number;
422
+ stressIndex?: number | null;
318
423
  /** HRV SDNN in milliseconds */
319
- hrvSdnn?: number;
424
+ hrvSdnn?: number | null;
320
425
  /** HRV RMSSD in milliseconds */
321
- hrvRmssd?: number;
426
+ hrvRmssd?: number | null;
322
427
  /** Respiratory rate per minute */
323
- respiratoryRate?: number;
428
+ respiratoryRate?: number | null;
324
429
  /** Blood pressure readings */
325
- bloodPressure?: BloodPressure;
430
+ bloodPressure?: BloodPressure | null;
326
431
  /** Recovery score percentage */
327
- recoveryScore?: number;
432
+ recoveryScore?: number | null;
328
433
  /** Show loading state */
329
434
  loading?: boolean;
330
435
  /** Error message to display */
package/dist/index.d.ts CHANGED
@@ -2,241 +2,346 @@ import React$1 from 'react';
2
2
 
3
3
  /**
4
4
  * PulseAI SDK Type Definitions
5
+ *
6
+ * Version: 2.1.0
7
+ *
8
+ * IMPORTANT: Many metrics now return `null` when calculation fails.
9
+ * Always check for null before displaying values.
5
10
  */
11
+ interface BloodPressureFeatures {
12
+ rise_time_ms: number | null;
13
+ pulse_amplitude: number | null;
14
+ pulse_width_ms: number | null;
15
+ augmentation_index: number | null;
16
+ pulses_analyzed: number;
17
+ }
6
18
  interface BloodPressure {
7
- systolic: number;
8
- diastolic: number;
19
+ systolic: number | null;
20
+ diastolic: number | null;
21
+ pulse_pressure: number | null;
22
+ confidence: 'high' | 'moderate' | 'low' | 'very_low' | null;
23
+ features?: BloodPressureFeatures;
24
+ methodology?: string;
25
+ note?: string;
26
+ error?: string;
27
+ }
28
+ interface SpO2MethodResult {
29
+ spo2: number;
30
+ ratio: number;
31
+ quality: number;
32
+ }
33
+ interface SpO2Result {
34
+ spo2: number | null;
35
+ confidence: 'high' | 'moderate' | 'low' | 'very_low' | null;
36
+ method_used: 'red_blue' | 'green_red' | null;
37
+ signal_quality: number | null;
38
+ methods?: {
39
+ red_blue?: SpO2MethodResult;
40
+ green_red?: SpO2MethodResult;
41
+ };
42
+ error?: string;
9
43
  }
10
44
  interface ArrhythmiaResult {
11
- has_arrhythmia: boolean;
12
- irregularity_score: number;
13
- details: string;
45
+ has_arrhythmia: boolean | null;
46
+ irregularity_score: number | null;
47
+ confidence: number | null;
48
+ details: string | null;
49
+ }
50
+ interface StressResult {
51
+ score: number | null;
52
+ level: 'low' | 'mild' | 'moderate' | 'high' | null;
53
+ confidence: number | null;
54
+ rmssd_ms: number | null;
55
+ }
56
+ interface RecoveryResult {
57
+ score: number | null;
58
+ level: 'poor' | 'moderate' | 'good' | 'excellent' | null;
59
+ rmssd_ms: number | null;
60
+ }
61
+ interface RespiratoryResult {
62
+ rate: number | null;
63
+ confidence: 'high' | 'moderate' | 'low' | null;
64
+ signal_quality: number | null;
65
+ breaths_detected: number | null;
66
+ interval_variability: number | null;
67
+ error?: string;
68
+ }
69
+ interface VascularAgeResult {
70
+ vascular_age: number | null;
71
+ chronological_age: number | null;
72
+ difference_years: number | null;
73
+ status: 'younger_than_chronological' | 'close_to_chronological' | 'moderately_elevated' | 'significantly_elevated' | null;
74
+ methodology?: string;
75
+ }
76
+ interface BMIEstimate {
77
+ value: number | null;
78
+ category: 'Underweight' | 'Normal' | 'Overweight' | 'Obese' | null;
79
+ confidence: 'high' | 'moderate' | 'low' | 'very_low' | 'invalid' | null;
80
+ fwhr: number | null;
81
+ source?: 'manual_input' | 'facial_estimation';
82
+ methodology?: string;
83
+ note?: string;
84
+ reason?: string;
85
+ }
86
+ interface SkinTemperatureResult {
87
+ value: number | null;
88
+ unit: string;
89
+ ratio: number | null;
90
+ confidence: 'proxy_only' | 'invalid_ratio';
91
+ note?: string;
92
+ }
93
+ interface FatigueIndicators {
94
+ eye_redness: number | null;
95
+ under_eye_darkness: number | null;
96
+ puffiness: number | null;
97
+ overall_fatigue: string | null;
98
+ }
99
+ interface SkinHealth {
100
+ evenness: number | null;
101
+ redness: number | null;
102
+ oiliness_proxy: number | null;
14
103
  }
15
104
  interface VisualAnalysis {
16
- jaundice_risk: 'Low' | 'Medium' | 'High';
17
- anemia_risk: 'Low' | 'Medium' | 'High';
18
- bilirubin_proxy: number;
19
- pallor_index: number;
20
- hydration_level?: string;
21
- hydration_score?: number;
22
- fatigue_indicators?: {
23
- eye_redness: number;
24
- under_eye_darkness: number;
25
- puffiness: number;
26
- overall_fatigue: string;
27
- };
28
- skin_health?: {
29
- evenness: number;
30
- redness: number;
31
- oiliness_proxy: number;
32
- };
105
+ jaundice_risk: 'Low' | 'Medium' | 'High' | null;
106
+ anemia_risk: 'Low' | 'Medium' | 'High' | null;
107
+ bilirubin_proxy: number | null;
108
+ pallor_index: number | null;
109
+ hydration_level?: string | null;
110
+ hydration_score?: number | null;
111
+ texture_score?: number | null;
112
+ fatigue_indicators?: FatigueIndicators;
113
+ skin_health?: SkinHealth;
114
+ }
115
+ interface MentalWellnessComponents {
116
+ blink_score: number | null;
117
+ gaze_score: number | null;
118
+ emotion_score: number | null;
119
+ hrv_score: number | null;
33
120
  }
34
121
  interface MentalWellness {
35
- wellness_score: number;
36
- level: string;
37
- emotion: string;
38
- emotion_confidence?: number;
39
- blink_rate_per_min: number;
40
- gaze_stability: number;
41
- gaze_direction?: string;
42
- components: {
43
- blink_score: number;
44
- gaze_score: number;
45
- emotion_score: number;
46
- hrv_score: number;
47
- };
122
+ wellness_score: number | null;
123
+ level: string | null;
124
+ emotion: string | null;
125
+ emotion_confidence?: number | null;
126
+ blink_rate_per_min: number | null;
127
+ gaze_stability: number | null;
128
+ gaze_direction?: string | null;
129
+ components: MentalWellnessComponents | null;
130
+ }
131
+ interface CompositeScoreDetails {
132
+ cardio?: string[];
133
+ resilience?: string[];
134
+ metabolic?: string[];
135
+ vitality?: string[];
48
136
  }
49
137
  interface CompositeScores {
50
- cardio_score: number;
51
- resilience_score: number;
52
- metabolic_score: number;
53
- vitality_score: number;
54
- }
55
- interface BMIEstimate {
56
- value: number;
57
- category: string;
58
- fwhr: number;
59
- confidence?: string;
60
- method?: string;
138
+ cardio_score: number | null;
139
+ resilience_score: number | null;
140
+ metabolic_score: number | null;
141
+ vitality_score: number | null;
142
+ calculation_details?: CompositeScoreDetails;
143
+ bmi_used?: number;
61
144
  }
62
145
  interface VitalsResult {
63
- heart_rate: number;
64
- respiratory_rate: number;
65
- hrv_sdnn: number;
66
- hrv_rmssd: number;
67
- recovery_score: number;
68
- stress_index: number;
69
- arrhythmia: ArrhythmiaResult;
70
- rsa_amplitude: number;
71
- blood_pressure: BloodPressure;
72
- spo2: number;
73
- signal_snippet: number[];
74
- vascular_age: number;
75
- bmi_est: BMIEstimate;
146
+ heart_rate: number | null;
147
+ hr_confidence?: 'high' | 'moderate' | 'low' | 'very_low' | null;
148
+ hr_snr_db?: number | null;
149
+ respiratory_rate: RespiratoryResult | number | null;
150
+ hrv_sdnn: number | null;
151
+ hrv_rmssd: number | null;
152
+ stress_index: StressResult | number | null;
153
+ recovery_score: RecoveryResult | number | null;
154
+ arrhythmia: ArrhythmiaResult | null;
155
+ rsa_amplitude: number | null;
156
+ blood_pressure: BloodPressure | null;
157
+ spo2: SpO2Result | number | null;
158
+ vascular_age: VascularAgeResult | number | null;
159
+ bmi_est: BMIEstimate | null;
76
160
  manual_bmi?: number;
77
- metabolic_score: number;
78
- skin_temperature: number;
79
- composite_scores: CompositeScores;
80
- visual_analysis?: VisualAnalysis;
81
- mental_wellness?: MentalWellness;
82
- fusion_weights: Record<string, number>;
161
+ skin_temperature: SkinTemperatureResult | number | null;
162
+ composite_scores: CompositeScores | null;
163
+ visual_analysis?: VisualAnalysis | null;
164
+ mental_wellness?: MentalWellness | null;
165
+ signal_snippet?: number[];
166
+ fusion_weights?: Record<string, number>;
167
+ metadata?: {
168
+ video_fps?: number;
169
+ frames_analyzed?: number;
170
+ };
171
+ error?: string | null;
83
172
  }
84
173
  interface BeautySummary {
85
- overall_score: number;
86
- skin_age: number;
174
+ overall_score: number | null;
175
+ skin_age: number | null;
176
+ age_provided: boolean;
177
+ age_difference?: number;
178
+ calculation_details?: Record<string, number>;
179
+ skin_age_note?: string;
180
+ error?: string;
87
181
  }
88
182
  interface BeautySurface {
89
- texture: number;
90
- hydration: number;
91
- foundation_hex: string;
92
- undertone: string;
93
- acne_count: number;
94
- acne_severity: string;
95
- wrinkle_severity: string;
96
- wrinkle_density: number;
97
- oiliness_index: number;
98
- matches: string;
99
- skin_health: {
100
- evenness: number;
101
- redness: number;
102
- oiliness_proxy: number;
103
- };
183
+ texture: number | null;
184
+ hydration: number | null;
185
+ foundation_hex: string | null;
186
+ undertone: 'warm' | 'cool' | null;
187
+ acne_count: number | null;
188
+ acne_severity: 'minimal' | 'mild' | 'moderate' | 'significant' | null;
189
+ wrinkle_severity: 'minimal' | 'mild' | 'moderate' | 'significant' | null;
190
+ wrinkle_density: number | null;
191
+ oiliness_index: number | null;
192
+ matches: string | null;
193
+ skin_health: SkinHealth | null;
194
+ }
195
+ interface PtosisIndices {
196
+ status: 'none' | 'mild' | 'significant' | null;
197
+ youth_ratio?: number | null;
198
+ eye_openness?: number | null;
104
199
  }
105
200
  interface BeautyGeometry {
106
- symmetry_score: number;
107
- face_shape: string;
108
- eye_openness: number;
109
- ptosis_indices: {
110
- status: string;
111
- youth_ratio?: number;
112
- };
201
+ symmetry_score: number | null;
202
+ face_shape: 'oval' | 'round' | 'square' | 'oblong' | null;
203
+ landmarks?: any;
204
+ ptosis_indices: PtosisIndices;
205
+ analysis_confidence?: 'high' | 'moderate' | 'low';
206
+ error?: string;
113
207
  }
114
208
  interface BeautyPhysiology {
115
- glow_index: number;
116
- stress_level: string;
117
- elasticity: number;
209
+ glow_index: number | null;
210
+ stress_level: 'low' | 'moderate' | 'high' | null;
211
+ elasticity: number | null;
212
+ heart_rate?: number | null;
118
213
  }
119
214
  interface BeautyRecommendations {
120
215
  routine: string[];
121
216
  tips: string[];
217
+ foundation?: string | null;
122
218
  }
123
219
  interface BeautyResult {
124
- summary: BeautySummary;
125
- surface: BeautySurface;
126
- geometry: BeautyGeometry;
127
- physiology: BeautyPhysiology;
128
- recommendations: BeautyRecommendations;
220
+ summary: BeautySummary | null;
221
+ surface: BeautySurface | null;
222
+ geometry: BeautyGeometry | null;
223
+ physiology: BeautyPhysiology | null;
224
+ recommendations: BeautyRecommendations | null;
225
+ meta?: {
226
+ rppg_source: string;
227
+ beauty_engine: string;
228
+ };
229
+ error?: string | null;
129
230
  }
130
231
  interface VoiceCompositeScores {
131
- mental_score: number;
132
- physical_score: number;
133
- cognitive_score: number;
134
- resilience_score: number;
232
+ mental_score: number | null;
233
+ physical_score: number | null;
234
+ cognitive_score: number | null;
235
+ resilience_score: number | null;
135
236
  }
136
237
  interface VoiceMoodIndicators {
137
- monotone_speech?: boolean;
138
- reduced_prosody?: boolean;
139
- normal_prosody?: boolean;
140
- slow_speech?: boolean;
141
- slightly_slow?: boolean;
142
- normal_rate?: boolean;
238
+ pitch_monotony?: 'high' | 'moderate' | 'low';
239
+ speech_slowness?: 'high' | 'moderate' | 'low';
143
240
  excessive_pauses?: boolean;
144
- frequent_pauses?: boolean;
145
- normal_pauses?: boolean;
146
- low_energy?: boolean;
147
- reduced_energy?: boolean;
148
- normal_energy?: boolean;
149
- low_pitch?: boolean;
241
+ flat_affect?: boolean | 'partial';
150
242
  }
151
243
  interface VoiceResult {
152
- stress_score: number;
153
- fatigue_score: number;
154
- anxiety_level: 'low' | 'mild' | 'moderate' | 'high' | 'unknown';
155
- anxiety_confidence: number;
156
- voice_quality: 'normal' | 'slightly_strained' | 'strained' | 'unknown';
157
- pitch_variability: number;
158
- speech_rate: number;
159
- pause_ratio: number;
160
- tremor_index: number;
161
- energy_variability: number;
162
- respiratory_rate: number;
163
- breathing_regularity: number;
164
- breath_depth: 'shallow' | 'normal' | 'deep' | 'unknown';
165
- respiratory_health: number;
166
- cough_detected: boolean;
167
- cough_count: number;
168
- wheeze_detected: boolean;
169
- respiratory_concern: 'none' | 'mild' | 'moderate' | 'high' | 'unknown';
170
- depression_risk: 'low' | 'mild' | 'moderate' | 'elevated' | 'unknown';
171
- depression_score: number;
172
- mood_indicators: VoiceMoodIndicators;
173
- cognitive_load: 'low' | 'normal' | 'moderate' | 'high' | 'unknown';
174
- cognitive_score: number;
175
- focus_indicator: 'relaxed' | 'stable' | 'engaged' | 'distracted' | 'unknown';
176
- composite_scores: VoiceCompositeScores;
177
- wellness_score: number;
178
- wellness_level: 'excellent' | 'good' | 'fair' | 'needs_attention' | 'concerning' | 'unknown';
179
- pitch_mean: number;
180
- pitch_range: number;
181
- energy_dynamics: number;
182
- rhythm_regularity: number;
183
- jitter: number;
184
- shimmer: number;
185
- duration_seconds: number;
186
- analysis_confidence: number;
244
+ status: 'success' | 'error' | null;
245
+ error?: string | null;
246
+ stress_score: number | null;
247
+ fatigue_score: number | null;
248
+ anxiety_level: 'low' | 'mild' | 'moderate' | 'high' | null;
249
+ anxiety_confidence: number | null;
250
+ voice_quality: 'healthy' | 'mild_strain' | 'moderate_strain' | 'significant_strain' | null;
251
+ pitch_variability: number | null;
252
+ speech_rate: number | null;
253
+ pause_ratio: number | null;
254
+ tremor_index: number | null;
255
+ energy_variability: number | null;
256
+ respiratory_rate: number | null;
257
+ breathing_regularity: number | null;
258
+ breath_depth: 'shallow' | 'normal' | 'deep' | null;
259
+ respiratory_health: number | null;
260
+ cough_detected: boolean | null;
261
+ cough_count: number | null;
262
+ wheeze_detected: boolean | null;
263
+ respiratory_concern: 'none' | 'mild' | 'elevated' | null;
264
+ depression_risk: 'low' | 'mild' | 'moderate' | 'elevated' | null;
265
+ depression_score: number | null;
266
+ mood_indicators: VoiceMoodIndicators | null;
267
+ cognitive_load: 'low' | 'normal' | 'moderate' | 'high' | null;
268
+ cognitive_score: number | null;
269
+ focus_indicator: 'relaxed' | 'stable' | 'engaged' | 'strained' | null;
270
+ composite_scores: VoiceCompositeScores | null;
271
+ wellness_score: number | null;
272
+ wellness_level: 'excellent' | 'good' | 'moderate' | 'fair' | 'poor' | null;
273
+ pitch_mean: number | null;
274
+ pitch_range: number | null;
275
+ energy_dynamics: number | null;
276
+ rhythm_regularity: number | null;
277
+ jitter: number | null;
278
+ shimmer: number | null;
279
+ duration_seconds: number | null;
280
+ analysis_confidence: number | null;
187
281
  analysis_version: string;
188
282
  }
189
283
  interface EyeCataract {
190
- opacity_score: number;
191
- risk_level: 'low' | 'mild' | 'moderate' | 'elevated' | 'high' | 'unknown';
192
- risk_confidence: number;
193
- description: string;
194
- recommendation: string;
284
+ opacity_score: number | null;
285
+ risk_level: 'low' | 'mild' | 'moderate' | 'elevated' | null;
286
+ confidence: 'high' | 'moderate' | 'low' | null;
287
+ description: string | null;
288
+ recommendation: string | null;
195
289
  }
196
290
  interface EyeRedEye {
197
- redness_score: number;
198
- risk_level: 'low' | 'mild' | 'moderate' | 'elevated' | 'high' | 'unknown';
199
- is_inflamed: boolean;
200
- description: string;
291
+ redness_score: number | null;
292
+ risk_level: 'low' | 'mild' | 'moderate' | 'elevated' | null;
293
+ is_inflamed: boolean | null;
294
+ confidence: 'high' | 'moderate' | 'low' | null;
295
+ description: string | null;
201
296
  }
202
297
  interface EyeLensClarity {
203
- score: number;
204
- level: 'clear' | 'moderate' | 'cloudy' | 'unknown';
298
+ score: number | null;
299
+ level: 'clear' | 'good' | 'moderate' | 'reduced' | null;
300
+ samples?: number;
205
301
  }
206
302
  interface EyePupil {
207
- regularity_score: number;
208
- status: 'normal' | 'irregular' | 'unknown';
303
+ regularity_score: number | null;
304
+ circularity: number | null;
305
+ status: 'normal' | 'irregular' | null;
306
+ samples_analyzed?: number;
307
+ detected?: boolean;
209
308
  }
210
309
  interface EyePterygium {
211
- detected: boolean;
212
- confidence: number;
213
- severity?: 'mild' | 'moderate' | 'severe';
310
+ detected: boolean | null;
311
+ confidence: number | null;
312
+ severity?: 'minimal' | 'mild' | 'moderate' | 'significant' | null;
214
313
  description?: string;
314
+ error?: string;
215
315
  }
216
316
  interface EyeStye {
217
- detected: boolean;
218
- confidence: number;
317
+ detected: boolean | null;
318
+ confidence: number | null;
319
+ note?: string;
219
320
  }
220
321
  interface EyeSclera {
221
- yellowing_score: number;
222
- jaundice_risk: 'low' | 'moderate' | 'high' | 'unknown';
223
- color_health: 'healthy' | 'monitor' | 'unknown';
322
+ score: number | null;
323
+ risk: 'low' | 'moderate' | 'elevated' | null;
324
+ color_health: 'healthy' | 'monitor' | null;
325
+ samples?: number;
326
+ error?: string;
224
327
  }
225
328
  interface EyeResult {
226
- status: 'success' | 'partial' | 'error';
227
- overall_score: number;
228
- health_level: 'Excellent' | 'Good' | 'Fair' | 'Needs Attention' | 'Unknown';
229
- cataract: EyeCataract;
230
- red_eye: EyeRedEye;
231
- lens_clarity: EyeLensClarity;
232
- pupil: EyePupil;
233
- pterygium: EyePterygium;
234
- stye: EyeStye;
235
- sclera: EyeSclera;
236
- recommendations: string[];
329
+ status: 'success' | 'error' | null;
330
+ overall_score: number | null;
331
+ health_level: 'Excellent' | 'Good' | 'Fair' | 'Needs Attention' | 'Consult Specialist' | null;
332
+ cataract: EyeCataract | null;
333
+ red_eye: EyeRedEye | null;
334
+ lens_clarity: EyeLensClarity | null;
335
+ pupil: EyePupil | null;
336
+ pterygium: EyePterygium | null;
337
+ stye: EyeStye | null;
338
+ sclera: EyeSclera | null;
339
+ recommendations: string[] | null;
237
340
  frames_analyzed: number;
238
- analysis_confidence: number;
341
+ eyes_detected: number;
342
+ analysis_confidence: 'high' | 'moderate' | 'low' | null;
239
343
  analysis_version?: string;
344
+ error?: string | null;
240
345
  }
241
346
  interface APIResponse<T> {
242
347
  status: 'success' | 'error';
@@ -310,21 +415,21 @@ declare const PulseScanner: React$1.FC<PulseScannerProps>;
310
415
  */
311
416
  interface VitalsCardProps {
312
417
  /** Heart rate in BPM */
313
- heartRate?: number;
418
+ heartRate?: number | null;
314
419
  /** Oxygen saturation percentage */
315
- spo2?: number;
420
+ spo2?: number | null;
316
421
  /** Stress index (0-100) */
317
- stressIndex?: number;
422
+ stressIndex?: number | null;
318
423
  /** HRV SDNN in milliseconds */
319
- hrvSdnn?: number;
424
+ hrvSdnn?: number | null;
320
425
  /** HRV RMSSD in milliseconds */
321
- hrvRmssd?: number;
426
+ hrvRmssd?: number | null;
322
427
  /** Respiratory rate per minute */
323
- respiratoryRate?: number;
428
+ respiratoryRate?: number | null;
324
429
  /** Blood pressure readings */
325
- bloodPressure?: BloodPressure;
430
+ bloodPressure?: BloodPressure | null;
326
431
  /** Recovery score percentage */
327
- recoveryScore?: number;
432
+ recoveryScore?: number | null;
328
433
  /** Show loading state */
329
434
  loading?: boolean;
330
435
  /** Error message to display */
package/dist/index.js CHANGED
@@ -729,6 +729,15 @@ var PulseScanner = ({
729
729
 
730
730
  // src/components/VitalsCard.tsx
731
731
  var import_jsx_runtime2 = require("react/jsx-runtime");
732
+ function nullToUndefined(value) {
733
+ return value === null ? void 0 : value;
734
+ }
735
+ function extractNumeric(result) {
736
+ if (result === null || result === void 0) return void 0;
737
+ if (typeof result === "number") return result;
738
+ const val = result.score ?? result.value ?? result.spo2 ?? result.rate ?? null;
739
+ return val === null ? void 0 : val;
740
+ }
732
741
  function getHeartRateStatus(hr) {
733
742
  if (hr < 55) return { label: "Low", color: "blue" };
734
743
  if (hr > 100) return { label: "Elevated", color: "orange" };
@@ -749,14 +758,14 @@ function getHrvStatus(hrv) {
749
758
  return { label: "Balanced", color: "blue" };
750
759
  }
751
760
  var VitalsCard = ({
752
- heartRate,
753
- spo2,
754
- stressIndex,
755
- hrvSdnn,
756
- hrvRmssd,
757
- respiratoryRate,
758
- bloodPressure,
759
- recoveryScore,
761
+ heartRate: heartRateProp,
762
+ spo2: spo2Prop,
763
+ stressIndex: stressIndexProp,
764
+ hrvSdnn: hrvSdnnProp,
765
+ hrvRmssd: hrvRmssdProp,
766
+ respiratoryRate: respiratoryRateProp,
767
+ bloodPressure: bloodPressureProp,
768
+ recoveryScore: recoveryScoreProp,
760
769
  loading = false,
761
770
  error = null,
762
771
  compact = false,
@@ -764,6 +773,14 @@ var VitalsCard = ({
764
773
  className = "",
765
774
  theme = "light"
766
775
  }) => {
776
+ const heartRate = nullToUndefined(heartRateProp);
777
+ const spo2 = nullToUndefined(spo2Prop);
778
+ const stressIndex = nullToUndefined(stressIndexProp);
779
+ const hrvSdnn = nullToUndefined(hrvSdnnProp);
780
+ const hrvRmssd = nullToUndefined(hrvRmssdProp);
781
+ const respiratoryRate = nullToUndefined(respiratoryRateProp);
782
+ const bloodPressure = nullToUndefined(bloodPressureProp);
783
+ const recoveryScore = nullToUndefined(recoveryScoreProp);
767
784
  if (loading) {
768
785
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: `vitals-card vitals-card--loading vitals-card--${theme} ${className}`, children: [
769
786
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "vitals-card__spinner" }),
@@ -853,17 +870,21 @@ var VitalsCardFromResult = ({ result, ...props }) => {
853
870
  if (!result) {
854
871
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(VitalsCard, { ...props });
855
872
  }
873
+ const spo2Value = extractNumeric(result.spo2);
874
+ const stressValue = extractNumeric(result.stress_index);
875
+ const respiratoryValue = extractNumeric(result.respiratory_rate);
876
+ const recoveryValue = extractNumeric(result.recovery_score);
856
877
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
857
878
  VitalsCard,
858
879
  {
859
880
  heartRate: result.heart_rate,
860
- spo2: result.spo2,
861
- stressIndex: result.stress_index,
881
+ spo2: spo2Value,
882
+ stressIndex: stressValue,
862
883
  hrvSdnn: result.hrv_sdnn,
863
884
  hrvRmssd: result.hrv_rmssd,
864
- respiratoryRate: result.respiratory_rate,
885
+ respiratoryRate: respiratoryValue,
865
886
  bloodPressure: result.blood_pressure,
866
- recoveryScore: result.recovery_score,
887
+ recoveryScore: recoveryValue,
867
888
  ...props
868
889
  }
869
890
  );
package/dist/index.mjs CHANGED
@@ -685,6 +685,15 @@ var PulseScanner = ({
685
685
 
686
686
  // src/components/VitalsCard.tsx
687
687
  import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
688
+ function nullToUndefined(value) {
689
+ return value === null ? void 0 : value;
690
+ }
691
+ function extractNumeric(result) {
692
+ if (result === null || result === void 0) return void 0;
693
+ if (typeof result === "number") return result;
694
+ const val = result.score ?? result.value ?? result.spo2 ?? result.rate ?? null;
695
+ return val === null ? void 0 : val;
696
+ }
688
697
  function getHeartRateStatus(hr) {
689
698
  if (hr < 55) return { label: "Low", color: "blue" };
690
699
  if (hr > 100) return { label: "Elevated", color: "orange" };
@@ -705,14 +714,14 @@ function getHrvStatus(hrv) {
705
714
  return { label: "Balanced", color: "blue" };
706
715
  }
707
716
  var VitalsCard = ({
708
- heartRate,
709
- spo2,
710
- stressIndex,
711
- hrvSdnn,
712
- hrvRmssd,
713
- respiratoryRate,
714
- bloodPressure,
715
- recoveryScore,
717
+ heartRate: heartRateProp,
718
+ spo2: spo2Prop,
719
+ stressIndex: stressIndexProp,
720
+ hrvSdnn: hrvSdnnProp,
721
+ hrvRmssd: hrvRmssdProp,
722
+ respiratoryRate: respiratoryRateProp,
723
+ bloodPressure: bloodPressureProp,
724
+ recoveryScore: recoveryScoreProp,
716
725
  loading = false,
717
726
  error = null,
718
727
  compact = false,
@@ -720,6 +729,14 @@ var VitalsCard = ({
720
729
  className = "",
721
730
  theme = "light"
722
731
  }) => {
732
+ const heartRate = nullToUndefined(heartRateProp);
733
+ const spo2 = nullToUndefined(spo2Prop);
734
+ const stressIndex = nullToUndefined(stressIndexProp);
735
+ const hrvSdnn = nullToUndefined(hrvSdnnProp);
736
+ const hrvRmssd = nullToUndefined(hrvRmssdProp);
737
+ const respiratoryRate = nullToUndefined(respiratoryRateProp);
738
+ const bloodPressure = nullToUndefined(bloodPressureProp);
739
+ const recoveryScore = nullToUndefined(recoveryScoreProp);
723
740
  if (loading) {
724
741
  return /* @__PURE__ */ jsxs2("div", { className: `vitals-card vitals-card--loading vitals-card--${theme} ${className}`, children: [
725
742
  /* @__PURE__ */ jsx2("div", { className: "vitals-card__spinner" }),
@@ -809,17 +826,21 @@ var VitalsCardFromResult = ({ result, ...props }) => {
809
826
  if (!result) {
810
827
  return /* @__PURE__ */ jsx2(VitalsCard, { ...props });
811
828
  }
829
+ const spo2Value = extractNumeric(result.spo2);
830
+ const stressValue = extractNumeric(result.stress_index);
831
+ const respiratoryValue = extractNumeric(result.respiratory_rate);
832
+ const recoveryValue = extractNumeric(result.recovery_score);
812
833
  return /* @__PURE__ */ jsx2(
813
834
  VitalsCard,
814
835
  {
815
836
  heartRate: result.heart_rate,
816
- spo2: result.spo2,
817
- stressIndex: result.stress_index,
837
+ spo2: spo2Value,
838
+ stressIndex: stressValue,
818
839
  hrvSdnn: result.hrv_sdnn,
819
840
  hrvRmssd: result.hrv_rmssd,
820
- respiratoryRate: result.respiratory_rate,
841
+ respiratoryRate: respiratoryValue,
821
842
  bloodPressure: result.blood_pressure,
822
- recoveryScore: result.recovery_score,
843
+ recoveryScore: recoveryValue,
823
844
  ...props
824
845
  }
825
846
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rexai/pulse-react",
3
- "version": "1.1.0",
3
+ "version": "2.0.0",
4
4
  "description": "React SDK for rPPG health analysis - measure heart rate, HRV, SpO2, voice biomarkers from any camera",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",