@nuralogix.ai/web-measurement-embedded-app 0.1.0-beta.7 → 0.1.0-beta.8

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/LICENSE CHANGED
@@ -1,12 +1,12 @@
1
- Copyright (c) 2025, Nuralogix Corp.
2
- All Rights reserved
3
-
4
- THIS SOFTWARE IS LICENSED BY AND IS THE CONFIDENTIAL AND
5
- PROPRIETARY PROPERTY OF NURALOGIX CORP. IT IS
6
- PROTECTED UNDER THE COPYRIGHT LAWS OF THE USA, CANADA
7
- AND OTHER FOREIGN COUNTRIES. THIS SOFTWARE OR ANY
8
- PART THEREOF, SHALL NOT, WITHOUT THE PRIOR WRITTEN CONSENT
9
- OF NURALOGIX CORP, BE USED, COPIED, DISCLOSED,
10
- DECOMPILED, DISASSEMBLED, MODIFIED OR OTHERWISE TRANSFERRED
11
- EXCEPT IN ACCORDANCE WITH THE TERMS AND CONDITIONS OF A
1
+ Copyright (c) 2025, Nuralogix Corp.
2
+ All Rights reserved
3
+
4
+ THIS SOFTWARE IS LICENSED BY AND IS THE CONFIDENTIAL AND
5
+ PROPRIETARY PROPERTY OF NURALOGIX CORP. IT IS
6
+ PROTECTED UNDER THE COPYRIGHT LAWS OF THE USA, CANADA
7
+ AND OTHER FOREIGN COUNTRIES. THIS SOFTWARE OR ANY
8
+ PART THEREOF, SHALL NOT, WITHOUT THE PRIOR WRITTEN CONSENT
9
+ OF NURALOGIX CORP, BE USED, COPIED, DISCLOSED,
10
+ DECOMPILED, DISASSEMBLED, MODIFIED OR OTHERWISE TRANSFERRED
11
+ EXCEPT IN ACCORDANCE WITH THE TERMS AND CONDITIONS OF A
12
12
  NURALOGIX CORP SOFTWARE LICENSE AGREEMENT.
package/README.md CHANGED
@@ -1,190 +1,190 @@
1
- ### Web Measurement Embedded App
2
-
3
- Need deeper integration details? Check the full docs at [docs.deepaffex.ai/wmea](https://docs.deepaffex.ai/wmea/).
4
-
5
- ```html
6
- <!DOCTYPE html>
7
- <html lang="en">
8
- <head>
9
- <meta charset="UTF-8" />
10
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
11
- <title>Measurement Embedded App Demo</title>
12
- <style>
13
- #measurement-embedded-app-container {
14
- position: fixed;
15
- top: 100px;
16
- left: 0;
17
- width: 100vw;
18
- height: calc(100vh - 100px);
19
- }
20
- </style>
21
- <script type="importmap">
22
- {
23
- "imports": {
24
- "@nuralogix.ai/web-measurement-embedded-app": "https://unpkg.com/@nuralogix.ai/web-measurement-embedded-app"
25
- }
26
- }
27
- </script>
28
- </head>
29
- <body>
30
- <div id="measurement-embedded-app-container"></div>
31
- <script type="module">
32
- import MeasurementEmbeddedApp, {
33
- faceAttributeValue,
34
- } from '@nuralogix.ai/web-measurement-embedded-app';
35
- const {
36
- SEX_ASSIGNED_MALE_AT_BIRTH,
37
- SMOKER_FALSE,
38
- BLOOD_PRESSURE_MEDICATION_FALSE,
39
- DIABETES_NONE,
40
- } = faceAttributeValue;
41
- const measurementApp = new MeasurementEmbeddedApp();
42
- const container = document.getElementById('measurement-embedded-app-container');
43
- if (container) {
44
- const apiUrl = '/api';
45
- const studyId = await fetch(`${apiUrl}/studyId`);
46
- const studyIdResponse = await studyId.json();
47
- const token = await fetch(`${apiUrl}/token`);
48
- const tokenResponse = await token.json();
49
- if (studyIdResponse.status === '200' && tokenResponse.status === '200') {
50
- measurementApp.on.results = (results) => {
51
- console.log('Results received', results);
52
- measurementApp.destroy();
53
- };
54
- measurementApp.on.error = (error) => {
55
- console.log('error received', error);
56
- };
57
- measurementApp.on.event = (appEvent) => {
58
- console.log('App Event received', appEvent);
59
- };
60
-
61
- try {
62
- await measurementApp.init({
63
- container,
64
- appPath: 'https://unpkg.com/@nuralogix.ai/web-measurement-embedded-app/dist',
65
- settings: {
66
- token: tokenResponse.token,
67
- refreshToken: tokenResponse.refreshToken,
68
- studyId: studyIdResponse.studyId,
69
- },
70
- profile: {
71
- age: 40,
72
- height: 180,
73
- weight: 60,
74
- sex: SEX_ASSIGNED_MALE_AT_BIRTH,
75
- smoking: SMOKER_FALSE,
76
- bloodPressureMedication: BLOOD_PRESSURE_MEDICATION_FALSE,
77
- diabetes: DIABETES_NONE,
78
- bypassProfile: false,
79
- },
80
- // Optional configuration overrides (defaults shown)
81
- config: {
82
- checkConstraints: true,
83
- cameraFacingMode: 'user', // or 'environment' for back camera
84
- cameraAutoStart: false,
85
- measurementAutoStart: false,
86
- cancelWhenLowSNR: true,
87
- },
88
- // Optional language/api overrides
89
- // language: 'fr'
90
- apiUrl: 'api.na-east.deepaffex.ai', // optional for region specific data processing
91
- });
92
- } catch (error) {
93
- console.error('Failed to initialize:', error);
94
- }
95
- } else {
96
- console.error('Failed to get Study ID and Token pair');
97
- }
98
- }
99
- </script>
100
- </body>
101
- </html>
102
- ```
103
-
104
- **Notes:**
105
-
106
- - Set `appPath` to `'.'` when you bundle the assets yourself.
107
- - Profile handling: when `bypassProfile` remains `true` (default) we skip demographic submission and emit an `ERROR` event with `PROFILE_INFO_NOT_SET`; set it to `false` once you supply real profile data.
108
- - Style the container you pass to `init` (e.g., position, top, width).
109
- - Optional `apiUrl` enables region-specific processing; omitted values follow the backend token's region automatically. When set explicitly, frontend calls your URL (processing where that endpoint runs) while results continue to store in the token's region—verify the combination suits your deployment.
110
- - Config options:
111
- - `checkConstraints` (default: `true`) – enables constraint validation pre-measurement
112
- - `cameraFacingMode` (default: `'user'`) – use `'user'` for front camera or `'environment'` for back camera.
113
- - `cameraAutoStart` (default: `false`) – automatically starts the camera once permission is granted.
114
- - `measurementAutoStart` (default: `false`) – automatically starts the measurement once constraints are satisfied.
115
- - `cancelWhenLowSNR` (default: `true`) – cancels the measurement if signal-to-noise ratio falls below threshold.
116
- - Language support: `en`, `ja`, `zh`, `es`, `pt`, `pt-BR`, `it`, `fr`, `de`.
117
- - Unsupported browser locales fall back to base language (e.g., `zh-TW` → `zh`), then to English.
118
-
119
- **Methods:**
120
-
121
- ```typescript
122
- init(options: MeasurementEmbeddedAppOptions): Promise<void>;
123
- destroy(): Promise<void>;
124
- cancel(reset: boolean): Promise<boolean>;
125
- setTheme(theme: 'light' | 'dark'): void;
126
- setLanguage(language: SupportedLanguage): void;
127
- getLogs(): Promise<Log[]>;
128
- ```
129
-
130
- **Events:**
131
-
132
- ```typescript
133
- /**
134
- * when measurement results are received
135
- * @param {results} Results - measurement results
136
- */
137
- results: ((results: Results) => void) | null;
138
-
139
- /**
140
- * when there is an error in the measurement embedded app
141
- * @param {error} MeasurementEmbeddedAppError - measurement embedded app error
142
- */
143
- error: ((error: MeasurementEmbeddedAppError) => void) | null;
144
-
145
- /**
146
- * when an AppEvent is received
147
- * @param {appEvent} AppEvent - app event
148
- */
149
- event: ((appEvent: AppEvent) => void) | null;
150
- ```
151
-
152
- **App events dispatched through `measurementApp.on.event`:**
153
-
154
- - `APP_LOADED` – the embedded app finished its startup sequence.
155
- - `MEASUREMENT_PREPARED` - Measurement has been prepared
156
- - `ASSETS_DOWNLOADED` - Assets have been downloaded
157
- - `CAMERA_PERMISSION_GRANTED` – the user granted camera access.
158
- - `CAMERA_STARTED` – a camera stream opened successfully.
159
- - `MEASUREMENT_STARTED` – a measurement run begins.
160
- - `MEASUREMENT_COMPLETED` – the measurement finished and results are stable.
161
- - `INTERMEDIATE_RESULTS` – partial results are available during an active run.
162
- - `RESULTS_RECEIVED` – the final measurement results are available.
163
- - `MEASUREMENT_CANCELED` – the active measurement was canceled (user action or constraint).
164
- - `CONSTRAINT_VIOLATION` – a constraint (e.g., face distance) failed.
165
- - `PAGE_VISIBILITY_CHANGE` – the page changed visibility (e.g., tab switch or minimize).
166
- - `PAGE_UNLOADED` – the page is unloading.
167
-
168
- **Other runtime helpers:**
169
-
170
- ```typescript
171
- await measurementApp.cancel(true); // cancel current run
172
- const logs = await measurementApp.getLogs();
173
- measurementApp.setTheme('dark');
174
- measurementApp.setLanguage('es');
175
- ```
176
-
177
- **Error codes emitted through `measurementApp.on.error`:**
178
-
179
- | Code | Meaning |
180
- | ---------------------------- | ----------------------------------------------------------------- |
181
- | `CAMERA_PERMISSION_DENIED` | Camera access prompt was rejected. |
182
- | `CAMERA_START_FAILED` | Camera hardware failed to start after permission. |
183
- | `NO_DEVICES_FOUND` | No video input devices detected during enumeration. |
184
- | `PAGE_NOT_VISIBLE` | Measurement was running while the tab or window became hidden. |
185
- | `MEASUREMENT_LOW_SNR` | Signal-to-noise ratio dropped below the acceptable threshold. |
186
- | `WORKER_ERROR` | SDK worker encountered a fatal processing error. |
187
- | `PROFILE_INFO_NOT_SET` | Profile bypass stayed enabled, so demographics were not provided. |
188
- | `COLLECTOR` | Frame collection reported an error |
189
- | `WEBSOCKET_DISCONNECTED` | Realtime WebSocket connection closed or dropped. |
190
- | `MEASUREMENT_PREPARE_FAILED` | Measurement preparation failed - invalid or missing credentials |
1
+ ### Web Measurement Embedded App
2
+
3
+ Need deeper integration details? Check the full docs at [docs.deepaffex.ai/wmea](https://docs.deepaffex.ai/wmea/).
4
+
5
+ ```html
6
+ <!DOCTYPE html>
7
+ <html lang="en">
8
+ <head>
9
+ <meta charset="UTF-8" />
10
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
11
+ <title>Measurement Embedded App Demo</title>
12
+ <style>
13
+ #measurement-embedded-app-container {
14
+ position: fixed;
15
+ top: 100px;
16
+ left: 0;
17
+ width: 100vw;
18
+ height: calc(100vh - 100px);
19
+ }
20
+ </style>
21
+ <script type="importmap">
22
+ {
23
+ "imports": {
24
+ "@nuralogix.ai/web-measurement-embedded-app": "https://unpkg.com/@nuralogix.ai/web-measurement-embedded-app"
25
+ }
26
+ }
27
+ </script>
28
+ </head>
29
+ <body>
30
+ <div id="measurement-embedded-app-container"></div>
31
+ <script type="module">
32
+ import MeasurementEmbeddedApp, {
33
+ faceAttributeValue,
34
+ } from '@nuralogix.ai/web-measurement-embedded-app';
35
+ const {
36
+ SEX_ASSIGNED_MALE_AT_BIRTH,
37
+ SMOKER_FALSE,
38
+ BLOOD_PRESSURE_MEDICATION_FALSE,
39
+ DIABETES_NONE,
40
+ } = faceAttributeValue;
41
+ const measurementApp = new MeasurementEmbeddedApp();
42
+ const container = document.getElementById('measurement-embedded-app-container');
43
+ if (container) {
44
+ const apiUrl = '/api';
45
+ const studyId = await fetch(`${apiUrl}/studyId`);
46
+ const studyIdResponse = await studyId.json();
47
+ const token = await fetch(`${apiUrl}/token`);
48
+ const tokenResponse = await token.json();
49
+ if (studyIdResponse.status === '200' && tokenResponse.status === '200') {
50
+ measurementApp.on.results = (results) => {
51
+ console.log('Results received', results);
52
+ measurementApp.destroy();
53
+ };
54
+ measurementApp.on.error = (error) => {
55
+ console.log('error received', error);
56
+ };
57
+ measurementApp.on.event = (appEvent) => {
58
+ console.log('App Event received', appEvent);
59
+ };
60
+
61
+ try {
62
+ await measurementApp.init({
63
+ container,
64
+ appPath: 'https://unpkg.com/@nuralogix.ai/web-measurement-embedded-app/dist',
65
+ settings: {
66
+ token: tokenResponse.token,
67
+ refreshToken: tokenResponse.refreshToken,
68
+ studyId: studyIdResponse.studyId,
69
+ },
70
+ profile: {
71
+ age: 40,
72
+ height: 180,
73
+ weight: 60,
74
+ sex: SEX_ASSIGNED_MALE_AT_BIRTH,
75
+ smoking: SMOKER_FALSE,
76
+ bloodPressureMedication: BLOOD_PRESSURE_MEDICATION_FALSE,
77
+ diabetes: DIABETES_NONE,
78
+ bypassProfile: false,
79
+ },
80
+ // Optional configuration overrides (defaults shown)
81
+ config: {
82
+ checkConstraints: true,
83
+ cameraFacingMode: 'user', // or 'environment' for back camera
84
+ cameraAutoStart: false,
85
+ measurementAutoStart: false,
86
+ cancelWhenLowSNR: true,
87
+ },
88
+ // Optional language/api overrides
89
+ // language: 'fr'
90
+ apiUrl: 'api.na-east.deepaffex.ai', // optional for region specific data processing
91
+ });
92
+ } catch (error) {
93
+ console.error('Failed to initialize:', error);
94
+ }
95
+ } else {
96
+ console.error('Failed to get Study ID and Token pair');
97
+ }
98
+ }
99
+ </script>
100
+ </body>
101
+ </html>
102
+ ```
103
+
104
+ **Notes:**
105
+
106
+ - Set `appPath` to `'.'` when you bundle the assets yourself.
107
+ - Profile handling: when `bypassProfile` remains `true` (default) we skip demographic submission and emit an `ERROR` event with `PROFILE_INFO_NOT_SET`; set it to `false` once you supply real profile data.
108
+ - Style the container you pass to `init` (e.g., position, top, width).
109
+ - Optional `apiUrl` enables region-specific processing; omitted values follow the backend token's region automatically. When set explicitly, frontend calls your URL (processing where that endpoint runs) while results continue to store in the token's region—verify the combination suits your deployment.
110
+ - Config options:
111
+ - `checkConstraints` (default: `true`) – enables constraint validation pre-measurement
112
+ - `cameraFacingMode` (default: `'user'`) – use `'user'` for front camera or `'environment'` for back camera.
113
+ - `cameraAutoStart` (default: `false`) – automatically starts the camera once permission is granted.
114
+ - `measurementAutoStart` (default: `false`) – automatically starts the measurement once constraints are satisfied.
115
+ - `cancelWhenLowSNR` (default: `true`) – cancels the measurement if signal-to-noise ratio falls below threshold.
116
+ - Language support: `en`, `ja`, `zh`, `es`, `pt`, `pt-BR`, `it`, `fr`, `de`.
117
+ - Unsupported browser locales fall back to base language (e.g., `zh-TW` → `zh`), then to English.
118
+
119
+ **Methods:**
120
+
121
+ ```typescript
122
+ init(options: MeasurementEmbeddedAppOptions): Promise<void>;
123
+ destroy(): Promise<void>;
124
+ cancel(reset: boolean): Promise<boolean>;
125
+ setTheme(theme: 'light' | 'dark'): void;
126
+ setLanguage(language: SupportedLanguage): void;
127
+ getLogs(): Promise<Log[]>;
128
+ ```
129
+
130
+ **Events:**
131
+
132
+ ```typescript
133
+ /**
134
+ * when measurement results are received
135
+ * @param {results} Results - measurement results
136
+ */
137
+ results: ((results: Results) => void) | null;
138
+
139
+ /**
140
+ * when there is an error in the measurement embedded app
141
+ * @param {error} MeasurementEmbeddedAppError - measurement embedded app error
142
+ */
143
+ error: ((error: MeasurementEmbeddedAppError) => void) | null;
144
+
145
+ /**
146
+ * when an AppEvent is received
147
+ * @param {appEvent} AppEvent - app event
148
+ */
149
+ event: ((appEvent: AppEvent) => void) | null;
150
+ ```
151
+
152
+ **App events dispatched through `measurementApp.on.event`:**
153
+
154
+ - `APP_LOADED` – the embedded app finished its startup sequence.
155
+ - `MEASUREMENT_PREPARED` - Measurement has been prepared
156
+ - `ASSETS_DOWNLOADED` - Assets have been downloaded
157
+ - `CAMERA_PERMISSION_GRANTED` – the user granted camera access.
158
+ - `CAMERA_STARTED` – a camera stream opened successfully.
159
+ - `MEASUREMENT_STARTED` – a measurement run begins.
160
+ - `MEASUREMENT_COMPLETED` – the measurement finished and results are stable.
161
+ - `INTERMEDIATE_RESULTS` – partial results are available during an active run.
162
+ - `RESULTS_RECEIVED` – the final measurement results are available.
163
+ - `MEASUREMENT_CANCELED` – the user canceled the active measurement.
164
+ - `CONSTRAINT_VIOLATION` – a constraint (e.g., face distance) failed.
165
+ - `PAGE_VISIBILITY_CHANGE` – the page changed visibility (e.g., tab switch or minimize).
166
+ - `PAGE_UNLOADED` – the page is unloading.
167
+
168
+ **Other runtime helpers:**
169
+
170
+ ```typescript
171
+ await measurementApp.cancel(true); // cancel current run
172
+ const logs = await measurementApp.getLogs();
173
+ measurementApp.setTheme('dark');
174
+ measurementApp.setLanguage('es');
175
+ ```
176
+
177
+ **Error codes emitted through `measurementApp.on.error`:**
178
+
179
+ | Code | Meaning |
180
+ | ---------------------------- | ----------------------------------------------------------------- |
181
+ | `CAMERA_PERMISSION_DENIED` | Camera access prompt was rejected. |
182
+ | `CAMERA_START_FAILED` | Camera hardware failed to start after permission. |
183
+ | `NO_DEVICES_FOUND` | No video input devices detected during enumeration. |
184
+ | `PAGE_NOT_VISIBLE` | Measurement was running while the tab or window became hidden. |
185
+ | `MEASUREMENT_LOW_SNR` | Signal-to-noise ratio dropped below the acceptable threshold. |
186
+ | `WORKER_ERROR` | SDK worker encountered a fatal processing error. |
187
+ | `PROFILE_INFO_NOT_SET` | Profile bypass stayed enabled, so demographics were not provided. |
188
+ | `COLLECTOR` | Frame collection reported an error |
189
+ | `WEBSOCKET_DISCONNECTED` | Realtime WebSocket connection closed or dropped. |
190
+ | `MEASUREMENT_PREPARE_FAILED` | Measurement preparation failed - invalid or missing credentials |
package/dist/app.css CHANGED
@@ -1,5 +1,5 @@
1
- @import url('https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap');
2
-
1
+ @import url('https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap');
2
+
3
3
  @layer priority1 {
4
4
  @keyframes nuraqng64z-B {
5
5
  0% {
@@ -10,8 +10,8 @@
10
10
  transform: rotate(360deg);
11
11
  }
12
12
  }
13
- }
14
-
13
+ }
14
+
15
15
  @layer priority2 {
16
16
  .nura164fk60 {
17
17
  background: initial;
@@ -84,8 +84,8 @@
84
84
  .nura6rcfto {
85
85
  padding: var(--padding);
86
86
  }
87
- }
88
-
87
+ }
88
+
89
89
  @layer priority3 {
90
90
  .nura196p5u9 {
91
91
  border-bottom: 1px solid #0000;
@@ -226,8 +226,8 @@
226
226
  .nura1uvtmcs:focus {
227
227
  outline: none;
228
228
  }
229
- }
230
-
229
+ }
230
+
231
231
  @layer priority4 {
232
232
  .nura1lugfcp {
233
233
  -webkit-appearance: none;
@@ -655,8 +655,8 @@
655
655
  align-items: end;
656
656
  }
657
657
  }
658
- }
659
-
658
+ }
659
+
660
660
  @layer priority5 {
661
661
  .nura1szun9y {
662
662
  bottom: 1rem;
@@ -803,8 +803,8 @@
803
803
  padding-bottom: 1rem;
804
804
  }
805
805
  }
806
- }
807
-
806
+ }
807
+
808
808
  @layer priority6 {
809
809
  .nuratb5x6d:before {
810
810
  border-color: var(--1il6zln);
@@ -841,8 +841,8 @@
841
841
  .nuradb2nx::-moz-progress-bar {
842
842
  transition: var(--1nt0dl9);
843
843
  }
844
- }
845
-
844
+ }
845
+
846
846
  @layer priority7 {
847
847
  .nura18j5lt8:after {
848
848
  background-color: var(--15iyedw);
@@ -895,8 +895,8 @@
895
895
  .nura7tg5rq:before {
896
896
  transform-origin: 100%;
897
897
  }
898
- }
899
-
898
+ }
899
+
900
900
  @layer priority8 {
901
901
  .nura171sez1:before {
902
902
  border-bottom-left-radius: var(--ucnkut);
@@ -941,8 +941,8 @@
941
941
  .nuragu5zj8:before {
942
942
  width: var(--nzppn4);
943
943
  }
944
- }
945
-
944
+ }
945
+
946
946
  @layer priority1 {
947
947
  :host, .nura1lutyi5 {
948
948
  --nura137mxtf: blur(0);
@@ -1221,8 +1221,8 @@
1221
1221
  --nurant3gmo: 72px;
1222
1222
  }
1223
1223
  }
1224
- }
1225
-
1224
+ }
1225
+
1226
1226
  @layer priority1 {
1227
1227
  :host, .nurazc319s {
1228
1228
  --nura15kgmj: #4382fb;
@@ -1501,4 +1501,4 @@
1501
1501
  --nura1kc53uu: 0 0 #0000;
1502
1502
  }
1503
1503
  }
1504
- }
1504
+ }