@monkvision/common 4.5.6 → 4.6.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.
@@ -37,11 +37,11 @@ parameters with values that can be fetched from the URL search parameters or the
37
37
  - If `fetchFromSearchParams` is also set to `true`, the token fetched from the search params will always be
38
38
  used in priority over the one fetched from the local storage.
39
39
 
40
- | Prop | Type | Description | Required | Default Value |
41
- |------------------|------------------|-------------------------------------------------------------------------------------------------------------------------------------|----------|---------------|
42
- | config | CaptureAppConfig | The current configuration of the application. | ✔️ | |
43
- | onFetchAuthToken | () => void | Callback called when an authentication token has successfully been fetched from either the local storage, or the URL search params. | | |
44
- | onFetchLanguage | () => void | Callback called when the language of the app must be updated because it has been specified in the URL params. | | |
40
+ | Prop | Type | Description | Required | Default Value |
41
+ |------------------|-----------------------|-------------------------------------------------------------------------------------------------------------------------------------|----------|---------------|
42
+ | config | PhotoCaptureAppConfig | The current configuration of the application. | ✔️ | |
43
+ | onFetchAuthToken | () => void | Callback called when an authentication token has successfully been fetched from either the local storage, or the URL search params. | | |
44
+ | onFetchLanguage | () => void | Callback called when the language of the app must be updated because it has been specified in the URL params. | | |
45
45
 
46
46
  ## useMonkAppState hook
47
47
  This hook simply returns the current value of the `MonkAppStateContext` declared by the `MonkAppStateProvider`component.
package/README/HOOKS.md CHANGED
@@ -58,6 +58,17 @@ This custom hook creates an interval that calls the provided async callback ever
58
58
  call isn't still running. If `delay` is `null` or less than 0, the callback will not be called. The promise handlers
59
59
  provided will only be called while the component is still mounted.
60
60
 
61
+ ### useDeviceOrientation
62
+ ```tsx
63
+ import { useDeviceOrientation } from '@monkvision/common';
64
+
65
+ function TestComponent() {
66
+ const { alpha } = useDeviceOrientation();
67
+ return <div>Current compass angle : { alpha }</div>;
68
+ }
69
+ ```
70
+ This custom hook is used to get the device orientation data using the embedded compass on the device.
71
+
61
72
  ### useInteractiveStatus
62
73
  ```tsx
63
74
  import { useInteractiveStatus } from '@monkvision/common';
@@ -45,6 +45,29 @@ method, available on all versions of JavaScript.
45
45
 
46
46
  ---
47
47
 
48
+ # Browser Utils
49
+ ### isMobileDevice
50
+
51
+ ```typescript
52
+ import { isMobileDevice } from "@monkvision/common";
53
+
54
+ console.log(isMobileDevice());
55
+ // Output : true or false
56
+ ```
57
+ Checks if the current device is a mobile device.
58
+
59
+ ### getAspectRatio
60
+ ```typescript
61
+ import { getAspectRatio } from "@monkvision/common";
62
+
63
+ const streamDimensions = {width: 1920, height: 1080}
64
+ console.log(getAspectRatio(streamDimensions));
65
+ // Output : '1920/1080'
66
+ ```
67
+ Returns the aspect ratio of the stream. If not a mobile device, it will return 16/9 by default.
68
+
69
+ ---
70
+
48
71
  # Color Utils
49
72
  ### getRGBAFromString
50
73
  ```typescript
@@ -109,6 +132,22 @@ const variants = getInteractiveVariants('#FC72A7');
109
132
  Create interactive variants (hovered, active...) for the given color. You can specify as an additional parameter the
110
133
  type of variation to use for the interactive colors (lighten or darken the color, default = lighten).
111
134
 
135
+ ### fullyColorSVG
136
+ ```tsx
137
+ import { useCallback } from 'react';
138
+ import { fullyColorSVG } from '@monkvision/common';
139
+ import { DynamicSVG } from '@monkvision/common-ui-web';
140
+
141
+ function TestComponent() {
142
+ const getAttributes = useCallback((element: Element) => fullyColorSVG(element, '#FFFFFF'), []);
143
+ return (
144
+ <DynamicSVG svg={logoSVG} getAttributes={getAttributes} />
145
+ );
146
+ }
147
+ ```
148
+ This utility function can be passed to the `DynamicSVG` component's `getAttributes` prop to completely color an SVG
149
+ with the given color. This is useful when wanting to color a single-color icon or logo.
150
+
112
151
  ---
113
152
 
114
153
  # Config Utils
@@ -119,7 +158,7 @@ import { getAvailableVehicleTypes } from '@monkvision/common';
119
158
  console.log(getAvailableVehicleTypes(config));
120
159
  // Output : [VehicleType.CITY, VehicleType.SUV]
121
160
  ```
122
- Returns the list of available vehicle types based on the `sights` property of a `CaptureAppConfig` object.
161
+ Returns the list of available vehicle types based on the `sights` property of a `PhotoCaptureAppConfig` object.
123
162
 
124
163
  # Environment Utils
125
164
  ### getEnvOrThrow
@@ -286,6 +325,19 @@ Converts a string to camel case.
286
325
 
287
326
  ---
288
327
 
328
+ # Vehicle
329
+ ### getVehicleModel
330
+ ```typescript
331
+ import { getVehicleModel } from '@monkvision/common'
332
+ import { VehicleType } from '@monkvision/types'
333
+
334
+ console.log(getVehicleModel(VehicleType.SUV))
335
+ output : 'fesc20'
336
+ ```
337
+ Returns the vehicle model corresponding to the given vehicle type.
338
+
339
+ ---
340
+
289
341
  # Zlib Utils
290
342
  ### zlibCompress
291
343
  ```typescript
package/README.md CHANGED
@@ -18,6 +18,6 @@ you can refer to their own README directly :
18
18
  - [State Management](README/STATE_MANAGEMENT.md).
19
19
  - [Theming](README/THEMING.md).
20
20
  - [Internationalization](README/INTERNATIONALIZATION.md).
21
- - [Hooks](README/APP_UTILS).
21
+ - [Hooks](README/APP_UTILS.md).
22
22
  - [Utilities](README/UTILITIES.md).
23
- - [Application Utilities](README/HOOKS).
23
+ - [Application Utilities](README/HOOKS.md).
@@ -1,18 +1,14 @@
1
- import { CaptureAppConfig, Sight, SteeringWheelPosition, VehicleType } from '@monkvision/types';
1
+ import { PhotoCaptureAppConfig, Sight, SteeringWheelPosition, VehicleType, VideoCaptureAppConfig } from '@monkvision/types';
2
2
  import { LoadingState } from '../hooks';
3
3
  /**
4
- * Application state usually used by Monk applications to configure and handle the current user journey.
4
+ * Shared app states values by both photo and video capture workflows.
5
5
  */
6
- export interface MonkAppState {
6
+ export interface SharedMonkAppState {
7
7
  /**
8
8
  * LoadingState indicating if the application state is loading. If it is loading it usually means that the provider
9
9
  * did not have time to fetch the parameter values.
10
10
  */
11
11
  loading: LoadingState;
12
- /**
13
- * The current configuration of the application.
14
- */
15
- config: CaptureAppConfig;
16
12
  /**
17
13
  * The authentication token representing the currently logged-in user. If this param is `null`, it means the user is
18
14
  * not logged in.
@@ -23,6 +19,23 @@ export interface MonkAppState {
23
19
  * param is `null`, it probably means that the inspection must be created by the app.
24
20
  */
25
21
  inspectionId: string | null;
22
+ /**
23
+ * Setter function used to set the current auth token.
24
+ */
25
+ setAuthToken: (value: string | null) => void;
26
+ /**
27
+ * Setter function used to set the current inspection ID.
28
+ */
29
+ setInspectionId: (value: string | null) => void;
30
+ }
31
+ /**
32
+ * App state values available in PhotoCapture applications.
33
+ */
34
+ export interface PhotoCaptureAppState extends SharedMonkAppState {
35
+ /**
36
+ * The current configuration of the application.
37
+ */
38
+ config: PhotoCaptureAppConfig;
26
39
  /**
27
40
  * The current vehicle type of the app. This value usually helps to choose which sights to display to the user, or
28
41
  * which car 360 wireframes to use for the inspection report.
@@ -40,14 +53,6 @@ export interface MonkAppState {
40
53
  * Getter function used to get the current Sights based on the current VehicleType, SteeringWheel position etc.
41
54
  */
42
55
  getCurrentSights: () => Sight[];
43
- /**
44
- * Setter function used to set the current auth token.
45
- */
46
- setAuthToken: (value: string | null) => void;
47
- /**
48
- * Setter function used to set the current inspection ID.
49
- */
50
- setInspectionId: (value: string | null) => void;
51
56
  /**
52
57
  * Setter function used to set the current vehicle type.
53
58
  */
@@ -57,6 +62,19 @@ export interface MonkAppState {
57
62
  */
58
63
  setSteeringWheel: (value: SteeringWheelPosition | null) => void;
59
64
  }
65
+ /**
66
+ * App state values available in PhotoCapture applications.
67
+ */
68
+ export interface VideoCaptureAppState extends SharedMonkAppState {
69
+ /**
70
+ * The current configuration of the application.
71
+ */
72
+ config: VideoCaptureAppConfig;
73
+ }
74
+ /**
75
+ * Application state usually used by Monk applications to configure and handle the current user journey.
76
+ */
77
+ export type MonkAppState = PhotoCaptureAppState | VideoCaptureAppState;
60
78
  /**
61
79
  * React context used to store the current Monk application state.
62
80
  *
@@ -1,6 +1,6 @@
1
- import { CaptureAppConfig } from '@monkvision/types';
1
+ import { CaptureWorkflow, PhotoCaptureAppConfig, VideoCaptureAppConfig } from '@monkvision/types';
2
2
  import { PropsWithChildren } from 'react';
3
- import { MonkAppState } from './appState';
3
+ import { MonkAppState, PhotoCaptureAppState, VideoCaptureAppState } from './appState';
4
4
  /**
5
5
  * Local storage key used within Monk web applications to store the authentication token.
6
6
  */
@@ -12,7 +12,7 @@ export type MonkAppStateProviderProps = {
12
12
  /**
13
13
  * The current configuration of the application.
14
14
  */
15
- config: CaptureAppConfig;
15
+ config: PhotoCaptureAppConfig | VideoCaptureAppConfig;
16
16
  /**
17
17
  * Callback called when an authentication token has successfully been fetched from either the local storage, or the
18
18
  * URL search params.
@@ -43,6 +43,25 @@ export interface UseMonkAppStateOptions {
43
43
  * params, at the cost of throwing an error if either one of these param is `null`.
44
44
  */
45
45
  requireInspection?: boolean;
46
+ /**
47
+ * The required capture workflow. If this option is passed, the hook will return a MonkState value already type
48
+ * checked and cast into the proper capture workflo, at the cost of throwing an error if the required worfklow does
49
+ * not match the one in the current state config.
50
+ */
51
+ requireWorkflow?: CaptureWorkflow;
52
+ }
53
+ /**
54
+ * Custom type used when using the `requireInspection` option with the `useMonkAppState` hook.
55
+ */
56
+ export interface RequiredInspectionAppState {
57
+ /**
58
+ * The authentication token representing the currently logged-in user.
59
+ */
60
+ authToken: string;
61
+ /**
62
+ * The ID of the current inspection being handled (picture taking, report viewing...) by the application.
63
+ */
64
+ inspectionId: string;
46
65
  }
47
66
  /**
48
67
  * Custom hook used to get the current Monk application state (described in the `MonkAppState` interface) for the
@@ -53,12 +72,43 @@ export interface UseMonkAppStateOptions {
53
72
  * @see MonkAppStateProvider
54
73
  */
55
74
  export declare function useMonkAppState(): MonkAppState;
75
+ export declare function useMonkAppState(o: Record<string, never>): MonkAppState;
56
76
  export declare function useMonkAppState(o: {
57
77
  requireInspection: false | undefined;
58
78
  }): MonkAppState;
59
79
  export declare function useMonkAppState(o: {
60
80
  requireInspection: true;
61
- }): MonkAppState & {
62
- authToken: string;
63
- inspectionId: string;
64
- };
81
+ }): MonkAppState & RequiredInspectionAppState;
82
+ export declare function useMonkAppState(o: {
83
+ requireWorkflow: undefined;
84
+ }): MonkAppState;
85
+ export declare function useMonkAppState(o: {
86
+ requireWorkflow: undefined;
87
+ requireInspection: false | undefined;
88
+ }): MonkAppState;
89
+ export declare function useMonkAppState(o: {
90
+ requireWorkflow: undefined;
91
+ requireInspection: true;
92
+ }): MonkAppState & RequiredInspectionAppState;
93
+ export declare function useMonkAppState(o: {
94
+ requireWorkflow: CaptureWorkflow.PHOTO;
95
+ }): PhotoCaptureAppState;
96
+ export declare function useMonkAppState(o: {
97
+ requireWorkflow: CaptureWorkflow.PHOTO;
98
+ requireInspection: false | undefined;
99
+ }): PhotoCaptureAppState;
100
+ export declare function useMonkAppState(o: {
101
+ requireWorkflow: CaptureWorkflow.PHOTO;
102
+ requireInspection: true;
103
+ }): PhotoCaptureAppState & RequiredInspectionAppState;
104
+ export declare function useMonkAppState(o: {
105
+ requireWorkflow: CaptureWorkflow.VIDEO;
106
+ }): VideoCaptureAppState;
107
+ export declare function useMonkAppState(o: {
108
+ requireWorkflow: CaptureWorkflow.VIDEO;
109
+ requireInspection: false | undefined;
110
+ }): VideoCaptureAppState;
111
+ export declare function useMonkAppState(o: {
112
+ requireWorkflow: CaptureWorkflow.VIDEO;
113
+ requireInspection: true;
114
+ }): VideoCaptureAppState & RequiredInspectionAppState;
@@ -13,6 +13,7 @@ var __assign = (this && this.__assign) || function () {
13
13
  Object.defineProperty(exports, "__esModule", { value: true });
14
14
  exports.useMonkAppState = exports.MonkAppStateProvider = exports.STORAGE_KEY_AUTH_TOKEN = void 0;
15
15
  var jsx_runtime_1 = require("react/jsx-runtime");
16
+ var types_1 = require("@monkvision/types");
16
17
  var sights_1 = require("@monkvision/sights");
17
18
  var react_1 = require("react");
18
19
  var hooks_1 = require("../hooks");
@@ -61,7 +62,9 @@ function MonkAppStateProvider(_a) {
61
62
  var _c = (0, react_1.useState)(null), inspectionId = _c[0], setInspectionId = _c[1];
62
63
  var _d = (0, react_1.useState)(null), vehicleType = _d[0], setVehicleType = _d[1];
63
64
  var _e = (0, react_1.useState)(null), steeringWheel = _e[0], setSteeringWheel = _e[1];
64
- var availableVehicleTypes = (0, react_1.useMemo)(function () { return (0, utils_1.getAvailableVehicleTypes)(config); }, [config]);
65
+ var availableVehicleTypes = (0, react_1.useMemo)(function () {
66
+ return config.workflow === types_1.CaptureWorkflow.PHOTO ? (0, utils_1.getAvailableVehicleTypes)(config) : undefined;
67
+ }, [config]);
65
68
  var monkSearchParams = (0, searchParams_1.useMonkSearchParams)({ availableVehicleTypes: availableVehicleTypes });
66
69
  var isMounted = (0, hooks_1.useIsMounted)();
67
70
  (0, monitoring_1.useAppStateMonitoring)({ authToken: authToken, inspectionId: inspectionId, vehicleType: vehicleType, steeringWheel: steeringWheel });
@@ -85,21 +88,49 @@ function MonkAppStateProvider(_a) {
85
88
  onFetchAuthToken === null || onFetchAuthToken === void 0 ? void 0 : onFetchAuthToken();
86
89
  }
87
90
  }, [monkSearchParams, config]);
88
- var getCurrentSights = (0, react_1.useCallback)(function () { return getSights(config, vehicleType, steeringWheel); }, [config, vehicleType, steeringWheel]);
89
- var appState = (0, hooks_1.useObjectMemo)({
90
- loading: loading,
91
- config: config,
92
- authToken: authToken,
93
- inspectionId: inspectionId,
94
- vehicleType: vehicleType,
95
- availableVehicleTypes: availableVehicleTypes,
96
- steeringWheel: steeringWheel,
97
- getCurrentSights: getCurrentSights,
98
- setAuthToken: setAuthToken,
99
- setInspectionId: setInspectionId,
100
- setVehicleType: setVehicleType,
101
- setSteeringWheel: setSteeringWheel,
102
- });
91
+ var getCurrentSights = (0, react_1.useMemo)(function () {
92
+ return config.workflow === types_1.CaptureWorkflow.PHOTO
93
+ ? function () { return getSights(config, vehicleType, steeringWheel); }
94
+ : undefined;
95
+ }, [config, vehicleType, steeringWheel]);
96
+ var appState = (0, react_1.useMemo)(function () {
97
+ return config.workflow === types_1.CaptureWorkflow.VIDEO
98
+ ? {
99
+ loading: loading,
100
+ config: config,
101
+ authToken: authToken,
102
+ inspectionId: inspectionId,
103
+ setAuthToken: setAuthToken,
104
+ setInspectionId: setInspectionId,
105
+ }
106
+ : {
107
+ loading: loading,
108
+ config: config,
109
+ authToken: authToken,
110
+ inspectionId: inspectionId,
111
+ vehicleType: vehicleType,
112
+ availableVehicleTypes: availableVehicleTypes,
113
+ steeringWheel: steeringWheel,
114
+ getCurrentSights: getCurrentSights,
115
+ setAuthToken: setAuthToken,
116
+ setInspectionId: setInspectionId,
117
+ setVehicleType: setVehicleType,
118
+ setSteeringWheel: setSteeringWheel,
119
+ };
120
+ }, [
121
+ loading,
122
+ config,
123
+ authToken,
124
+ inspectionId,
125
+ vehicleType,
126
+ availableVehicleTypes,
127
+ steeringWheel,
128
+ getCurrentSights,
129
+ setAuthToken,
130
+ setInspectionId,
131
+ setVehicleType,
132
+ setSteeringWheel,
133
+ ]);
103
134
  return (0, jsx_runtime_1.jsx)(appState_1.MonkAppStateContext.Provider, __assign({ value: appState }, { children: children }));
104
135
  }
105
136
  exports.MonkAppStateProvider = MonkAppStateProvider;
@@ -114,6 +145,9 @@ function useMonkAppState(options) {
114
145
  if ((options === null || options === void 0 ? void 0 : options.requireInspection) && !value.inspectionId) {
115
146
  throw new Error('Inspection ID is null but was required by the current component.');
116
147
  }
148
+ if ((options === null || options === void 0 ? void 0 : options.requireWorkflow) && value.config.workflow !== (options === null || options === void 0 ? void 0 : options.requireWorkflow)) {
149
+ throw new Error('The capture workflow is different than the one required by the current component.');
150
+ }
117
151
  return value;
118
152
  }
119
153
  exports.useMonkAppState = useMonkAppState;
@@ -1,2 +1,2 @@
1
- import { MonkAppState } from './appState';
2
- export declare function useAppStateMonitoring({ authToken, inspectionId, vehicleType, steeringWheel, }: Pick<MonkAppState, 'authToken' | 'inspectionId' | 'vehicleType' | 'steeringWheel'>): void;
1
+ import { MonkAppState, PhotoCaptureAppState } from './appState';
2
+ export declare function useAppStateMonitoring({ authToken, inspectionId, vehicleType, steeringWheel, }: Partial<Pick<MonkAppState, 'authToken' | 'inspectionId'> & Pick<PhotoCaptureAppState, 'vehicleType' | 'steeringWheel'>>): void;
@@ -12,3 +12,4 @@ export * from './useAsyncInterval';
12
12
  export * from './useObjectMemo';
13
13
  export * from './useForm';
14
14
  export * from './useIsMounted';
15
+ export * from './useDeviceOrientation';
@@ -28,3 +28,4 @@ __exportStar(require("./useAsyncInterval"), exports);
28
28
  __exportStar(require("./useObjectMemo"), exports);
29
29
  __exportStar(require("./useForm"), exports);
30
30
  __exportStar(require("./useIsMounted"), exports);
31
+ __exportStar(require("./useDeviceOrientation"), exports);
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Options accepted by the useDeviceOrientation hook.
3
+ */
4
+ export interface UseDeviceOrientationOptions {
5
+ /**
6
+ * Custom event handler that will be called every time a device orientation event is fired by the device.
7
+ */
8
+ onDeviceOrientationEvent?: (event: DeviceOrientationEvent) => void;
9
+ }
10
+ /**
11
+ * Handle used to mcontrol the device orientation.
12
+ */
13
+ export interface DeviceOrientationHandle {
14
+ /**
15
+ * Boolean indicating if the permission for the device's compass data has been granted. It is equal to `false` by
16
+ * default, and will be equal to true once the `requestCompassPermission` method has successfuly resolved.
17
+ */
18
+ isPermissionGranted: boolean;
19
+ /**
20
+ * Async function used to ask for the compass permission on the device.
21
+ * - On iOS, a pop-up will appear asking for the user confirmation. This function will reject if something goes wrong
22
+ * or if the user declines.
23
+ * - On Android and other devices, this function will resolve directly and the process will be seemless for the user.
24
+ */
25
+ requestCompassPermission: () => Promise<void>;
26
+ /**
27
+ * The current `alpha` value of the device. This value is a number in degrees (between 0 and 360), and represents the
28
+ * orientation of the device on the compass (AKA on the Z axis or "yaw", 0 = pointing North, 90 = pointing East etc.).
29
+ * This value starts being updated once the permissions for the compass has been granted using the
30
+ * `requestCompassPermission` method.
31
+ */
32
+ alpha: number;
33
+ /**
34
+ * A number representing the motion of the device around the X axis, expressed in degrees with values ranging from
35
+ * -180 (inclusive) to 180 (exclusive). This represents a front to back motion of the device AKA the "pitch".
36
+ */
37
+ beta: number;
38
+ /**
39
+ * A number representing the motion of the device around the Y axis, express in degrees with values ranging from -90
40
+ * (inclusive) to 90 (exclusive). This represents a left to right motion of the device AKA the "roll".
41
+ */
42
+ gamma: number;
43
+ }
44
+ /**
45
+ * Custom hook used to get the device orientation data using the embedded compass on the device.
46
+ */
47
+ export declare function useDeviceOrientation(options?: UseDeviceOrientationOptions): DeviceOrientationHandle;
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __generator = (this && this.__generator) || function (thisArg, body) {
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
+ function verb(n) { return function (v) { return step([n, v]); }; }
15
+ function step(op) {
16
+ if (f) throw new TypeError("Generator is already executing.");
17
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
18
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
19
+ if (y = 0, t) op = [op[0] & 2, t.value];
20
+ switch (op[0]) {
21
+ case 0: case 1: t = op; break;
22
+ case 4: _.label++; return { value: op[1], done: false };
23
+ case 5: _.label++; y = op[1]; op = [0]; continue;
24
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
+ default:
26
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
+ if (t[2]) _.ops.pop();
31
+ _.trys.pop(); continue;
32
+ }
33
+ op = body.call(thisArg, _);
34
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
+ }
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.useDeviceOrientation = void 0;
40
+ var react_1 = require("react");
41
+ var useObjectMemo_1 = require("./useObjectMemo");
42
+ var DeviceOrientationPermissionResponse;
43
+ (function (DeviceOrientationPermissionResponse) {
44
+ DeviceOrientationPermissionResponse["GRANTED"] = "granted";
45
+ DeviceOrientationPermissionResponse["DENIED"] = "denied";
46
+ })(DeviceOrientationPermissionResponse || (DeviceOrientationPermissionResponse = {}));
47
+ /**
48
+ * Custom hook used to get the device orientation data using the embedded compass on the device.
49
+ */
50
+ function useDeviceOrientation(options) {
51
+ var _this = this;
52
+ var _a = (0, react_1.useState)(false), isPermissionGranted = _a[0], setIsPermissionGranted = _a[1];
53
+ var _b = (0, react_1.useState)(0), alpha = _b[0], setAlpha = _b[1];
54
+ var _c = (0, react_1.useState)(0), beta = _c[0], setBeta = _c[1];
55
+ var _d = (0, react_1.useState)(0), gamma = _d[0], setGamma = _d[1];
56
+ var handleDeviceOrientationEvent = (0, react_1.useCallback)(function (event) {
57
+ var _a, _b, _c, _d, _e;
58
+ var value = (_b = (_a = event.webkitCompassHeading) !== null && _a !== void 0 ? _a : event.alpha) !== null && _b !== void 0 ? _b : 0;
59
+ setAlpha(value);
60
+ setBeta((_c = event.beta) !== null && _c !== void 0 ? _c : 0);
61
+ setGamma((_d = event.gamma) !== null && _d !== void 0 ? _d : 0);
62
+ (_e = options === null || options === void 0 ? void 0 : options.onDeviceOrientationEvent) === null || _e === void 0 ? void 0 : _e.call(options, event);
63
+ }, [options === null || options === void 0 ? void 0 : options.onDeviceOrientationEvent]);
64
+ var requestCompassPermission = (0, react_1.useCallback)(function () { return __awaiter(_this, void 0, void 0, function () {
65
+ var requestPermission, response;
66
+ return __generator(this, function (_a) {
67
+ switch (_a.label) {
68
+ case 0:
69
+ if (!DeviceOrientationEvent) return [3 /*break*/, 2];
70
+ requestPermission = DeviceOrientationEvent.requestPermission;
71
+ if (!(typeof requestPermission === 'function')) return [3 /*break*/, 2];
72
+ return [4 /*yield*/, requestPermission()];
73
+ case 1:
74
+ response = _a.sent();
75
+ if (response !== DeviceOrientationPermissionResponse.GRANTED) {
76
+ throw new Error('Device orientation permission request denied.');
77
+ }
78
+ _a.label = 2;
79
+ case 2:
80
+ setIsPermissionGranted(true);
81
+ return [2 /*return*/];
82
+ }
83
+ });
84
+ }); }, []);
85
+ (0, react_1.useEffect)(function () {
86
+ if (isPermissionGranted) {
87
+ window.addEventListener('deviceorientation', handleDeviceOrientationEvent);
88
+ }
89
+ return function () {
90
+ if (isPermissionGranted) {
91
+ window.removeEventListener('deviceorientation', handleDeviceOrientationEvent);
92
+ }
93
+ };
94
+ }, [isPermissionGranted, handleDeviceOrientationEvent]);
95
+ return (0, useObjectMemo_1.useObjectMemo)({ alpha: alpha, beta: beta, gamma: gamma, isPermissionGranted: isPermissionGranted, requestCompassPermission: requestCompassPermission });
96
+ }
97
+ exports.useDeviceOrientation = useDeviceOrientation;
@@ -1,4 +1,9 @@
1
+ import { PixelDimensions } from '@monkvision/types';
1
2
  /**
2
3
  * Checks if the current device is a mobile device.
3
4
  */
4
5
  export declare function isMobileDevice(): boolean;
6
+ /**
7
+ * Returns the aspect ratio of the stream. If not a mobile device, it will return 16/9 by default.
8
+ */
9
+ export declare function getAspectRatio(streamDimensions?: PixelDimensions | null): string;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isMobileDevice = void 0;
3
+ exports.getAspectRatio = exports.isMobileDevice = void 0;
4
4
  /**
5
5
  * Checks if the current device is a mobile device.
6
6
  */
@@ -13,3 +13,13 @@ function isMobileDevice() {
13
13
  userAgent.includes('windows phone'));
14
14
  }
15
15
  exports.isMobileDevice = isMobileDevice;
16
+ /**
17
+ * Returns the aspect ratio of the stream. If not a mobile device, it will return 16/9 by default.
18
+ */
19
+ function getAspectRatio(streamDimensions) {
20
+ if (isMobileDevice() && streamDimensions) {
21
+ return "".concat(streamDimensions === null || streamDimensions === void 0 ? void 0 : streamDimensions.width, "/").concat(streamDimensions === null || streamDimensions === void 0 ? void 0 : streamDimensions.height);
22
+ }
23
+ return '16/9';
24
+ }
25
+ exports.getAspectRatio = getAspectRatio;
@@ -1,4 +1,5 @@
1
1
  import { InteractiveStatus, RGBA } from '@monkvision/types';
2
+ import { SVGProps } from 'react';
2
3
  /**
3
4
  * Returns the RGBA values of the given color. The accepted formats are :
4
5
  * - RGB : rgb(167, 224, 146)
@@ -49,3 +50,16 @@ export declare enum InteractiveVariation {
49
50
  * Create interactive variants (hovered, active...) for the given color.
50
51
  */
51
52
  export declare function getInteractiveVariants(color: string, variant?: InteractiveVariation): Record<InteractiveStatus, string>;
53
+ /**
54
+ * This utility function can be passed to the `DynamicSVG` component's `getAttributes` prop to completely color an SVG
55
+ * with the given color. This is useful when wanting to color a single-color icon or logo.
56
+ *
57
+ * @example
58
+ * function TestComponent() {
59
+ * const getAttributes = useCallback((element: Element) => fullyColorSVG(element, '#FFFFFF'), []);
60
+ * return (
61
+ * <DynamicSVG svg={logoSVG} getAttributes={getAttributes} />
62
+ * );
63
+ * }
64
+ */
65
+ export declare function fullyColorSVG(element: Element, color: string): SVGProps<SVGElement>;
@@ -22,7 +22,7 @@ var __rest = (this && this.__rest) || function (s, e) {
22
22
  return t;
23
23
  };
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
- exports.getInteractiveVariants = exports.InteractiveVariation = exports.changeAlpha = exports.shadeColor = exports.getHexFromRGBA = exports.getRGBAFromString = void 0;
25
+ exports.fullyColorSVG = exports.getInteractiveVariants = exports.InteractiveVariation = exports.changeAlpha = exports.shadeColor = exports.getHexFromRGBA = exports.getRGBAFromString = void 0;
26
26
  var types_1 = require("@monkvision/types");
27
27
  var RGBA_REGEXP = /^rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)$/i;
28
28
  var HEX_REGEXP = /^#(?:(?:[0-9a-f]{3}){1,2}|(?:[0-9a-f]{4}){1,2})$/i;
@@ -152,3 +152,27 @@ function getInteractiveVariants(color, variant) {
152
152
  _a;
153
153
  }
154
154
  exports.getInteractiveVariants = getInteractiveVariants;
155
+ var COLOR_ATTRIBUTES = ['fill', 'stroke'];
156
+ /**
157
+ * This utility function can be passed to the `DynamicSVG` component's `getAttributes` prop to completely color an SVG
158
+ * with the given color. This is useful when wanting to color a single-color icon or logo.
159
+ *
160
+ * @example
161
+ * function TestComponent() {
162
+ * const getAttributes = useCallback((element: Element) => fullyColorSVG(element, '#FFFFFF'), []);
163
+ * return (
164
+ * <DynamicSVG svg={logoSVG} getAttributes={getAttributes} />
165
+ * );
166
+ * }
167
+ */
168
+ function fullyColorSVG(element, color) {
169
+ return COLOR_ATTRIBUTES.reduce(function (customAttributes, colorAttribute) {
170
+ var _a;
171
+ var attr = element.getAttribute(colorAttribute);
172
+ if (attr && !['transparent', 'none'].includes(attr)) {
173
+ return __assign(__assign({}, customAttributes), (_a = {}, _a[colorAttribute] = color, _a));
174
+ }
175
+ return customAttributes;
176
+ }, {});
177
+ }
178
+ exports.fullyColorSVG = fullyColorSVG;
@@ -1,5 +1,5 @@
1
- import { CaptureAppConfig, VehicleType } from '@monkvision/types';
1
+ import { PhotoCaptureAppConfig, VehicleType } from '@monkvision/types';
2
2
  /**
3
3
  * Util function used to extract the list of available vehicle types in a CaptureAppConfig object.
4
4
  */
5
- export declare function getAvailableVehicleTypes(config: CaptureAppConfig): VehicleType[];
5
+ export declare function getAvailableVehicleTypes(config: PhotoCaptureAppConfig): VehicleType[];
@@ -9,3 +9,4 @@ export * from './env.utils';
9
9
  export * from './state.utils';
10
10
  export * from './config.utils';
11
11
  export * from './formValidation.utils';
12
+ export * from './vehicle.utils';
@@ -25,3 +25,4 @@ __exportStar(require("./env.utils"), exports);
25
25
  __exportStar(require("./state.utils"), exports);
26
26
  __exportStar(require("./config.utils"), exports);
27
27
  __exportStar(require("./formValidation.utils"), exports);
28
+ __exportStar(require("./vehicle.utils"), exports);
@@ -1,9 +1,10 @@
1
- import { Image } from '@monkvision/types';
1
+ import { Image, ImageType } from '@monkvision/types';
2
2
  /**
3
3
  * Utility function that extracts the images of the given inspection.
4
4
  *
5
5
  * @param inspectionId The ID of the inspection to get the images of.
6
6
  * @param images Array containing every image existing in the current local state.
7
+ * @param filterImageType The specific image type to filter by. If not provided, no type-based filtering is applied.
7
8
  * @param filterRetakes Boolean indicating if retaken pictures should be filtered out or not (default: false).
8
9
  */
9
- export declare function getInspectionImages(inspectionId: string, images: Image[], filterRetakes?: boolean): Image[];
10
+ export declare function getInspectionImages(inspectionId: string, images: Image[], filterImageType?: ImageType, filterRetakes?: boolean): Image[];
@@ -6,29 +6,31 @@ exports.getInspectionImages = void 0;
6
6
  *
7
7
  * @param inspectionId The ID of the inspection to get the images of.
8
8
  * @param images Array containing every image existing in the current local state.
9
+ * @param filterImageType The specific image type to filter by. If not provided, no type-based filtering is applied.
9
10
  * @param filterRetakes Boolean indicating if retaken pictures should be filtered out or not (default: false).
10
11
  */
11
- function getInspectionImages(inspectionId, images, filterRetakes) {
12
+ function getInspectionImages(inspectionId, images, filterImageType, filterRetakes) {
12
13
  if (filterRetakes === void 0) { filterRetakes = false; }
13
14
  var inspectionImages = images.filter(function (image) { return image.inspectionId === inspectionId; });
15
+ if (filterImageType) {
16
+ inspectionImages = inspectionImages.filter(function (image) { return filterImageType === image.type; });
17
+ }
14
18
  if (!filterRetakes) {
15
19
  return inspectionImages;
16
20
  }
17
- var filteredRetakes = [];
21
+ var filteredRetakes = {};
18
22
  inspectionImages.forEach(function (image) {
19
23
  if (image.sightId) {
20
- var index = filteredRetakes.findIndex(function (i) { return i.sightId === image.sightId; });
21
- if (index >= 0) {
22
- if (image.createdAt &&
23
- filteredRetakes[index].createdAt &&
24
- image.createdAt > filteredRetakes[index].createdAt) {
25
- filteredRetakes[index] = image;
26
- }
27
- return;
24
+ var existingImage = filteredRetakes[image.sightId];
25
+ if (!existingImage ||
26
+ (image.createdAt && existingImage.createdAt && image.createdAt > existingImage.createdAt)) {
27
+ filteredRetakes[image.sightId] = image;
28
28
  }
29
29
  }
30
- filteredRetakes.push(image);
30
+ else {
31
+ filteredRetakes[image.id] = image;
32
+ }
31
33
  });
32
- return filteredRetakes;
34
+ return Object.values(filteredRetakes);
33
35
  }
34
36
  exports.getInspectionImages = getInspectionImages;
@@ -0,0 +1,5 @@
1
+ import { VehicleType, VehicleModel } from '@monkvision/types';
2
+ /**
3
+ * Returns the vehicle model corresponding to the given vehicle type.
4
+ */
5
+ export declare function getVehicleModel(vehicleType: VehicleType): VehicleModel;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getVehicleModel = void 0;
4
+ var sights_1 = require("@monkvision/sights");
5
+ var types_1 = require("@monkvision/types");
6
+ /**
7
+ * Returns the vehicle model corresponding to the given vehicle type.
8
+ */
9
+ function getVehicleModel(vehicleType) {
10
+ var _a;
11
+ var ajustedVehicletype = vehicleType === types_1.VehicleType.SUV ? types_1.VehicleType.CUV : vehicleType;
12
+ var detail = (_a = Object.entries(sights_1.vehicles)
13
+ .filter(function (_a) {
14
+ var type = _a[0];
15
+ return type !== types_1.VehicleModel.AUDIA7;
16
+ })
17
+ .find(function (_a) {
18
+ var details = _a[1];
19
+ return details.type === ajustedVehicletype;
20
+ })) === null || _a === void 0 ? void 0 : _a[1];
21
+ if (detail === undefined) {
22
+ throw new Error("No vehicle model found for vehicle type ".concat(ajustedVehicletype));
23
+ }
24
+ return detail.id;
25
+ }
26
+ exports.getVehicleModel = getVehicleModel;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monkvision/common",
3
- "version": "4.5.6",
3
+ "version": "4.6.0",
4
4
  "license": "BSD-3-Clause-Clear",
5
5
  "packageManager": "yarn@3.2.4",
6
6
  "description": "MonkJs common logic package",
@@ -28,10 +28,10 @@
28
28
  "lint:fix": "yarn run prettier:fix && yarn run eslint:fix"
29
29
  },
30
30
  "dependencies": {
31
- "@monkvision/analytics": "4.5.6",
32
- "@monkvision/monitoring": "4.5.6",
33
- "@monkvision/sights": "4.5.6",
34
- "@monkvision/types": "4.5.6",
31
+ "@monkvision/analytics": "4.6.0",
32
+ "@monkvision/monitoring": "4.6.0",
33
+ "@monkvision/sights": "4.6.0",
34
+ "@monkvision/types": "4.6.0",
35
35
  "i18next": "^23.4.5",
36
36
  "jsonwebtoken": "^9.0.2",
37
37
  "jwt-decode": "^4.0.0",
@@ -47,13 +47,13 @@
47
47
  "react-router-dom": "^6.22.3"
48
48
  },
49
49
  "devDependencies": {
50
- "@monkvision/eslint-config-base": "4.5.6",
51
- "@monkvision/eslint-config-typescript": "4.5.6",
52
- "@monkvision/eslint-config-typescript-react": "4.5.6",
53
- "@monkvision/jest-config": "4.5.6",
54
- "@monkvision/prettier-config": "4.5.6",
55
- "@monkvision/test-utils": "4.5.6",
56
- "@monkvision/typescript-config": "4.5.6",
50
+ "@monkvision/eslint-config-base": "4.6.0",
51
+ "@monkvision/eslint-config-typescript": "4.6.0",
52
+ "@monkvision/eslint-config-typescript-react": "4.6.0",
53
+ "@monkvision/jest-config": "4.6.0",
54
+ "@monkvision/prettier-config": "4.6.0",
55
+ "@monkvision/test-utils": "4.6.0",
56
+ "@monkvision/typescript-config": "4.6.0",
57
57
  "@testing-library/react": "^12.1.5",
58
58
  "@testing-library/react-hooks": "^8.0.1",
59
59
  "@types/jest": "^29.2.2",
@@ -96,5 +96,5 @@
96
96
  "url": "https://github.com/monkvision/monkjs/issues"
97
97
  },
98
98
  "homepage": "https://github.com/monkvision/monkjs",
99
- "gitHead": "c12e283e4abf1f810fdbc924a2d199652b92db30"
99
+ "gitHead": "68caf5a157e344b2187519616c9fe35eecafc65b"
100
100
  }