@trackunit/react-core-hooks 1.12.69 → 1.14.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/index.cjs.js +94 -0
- package/index.esm.js +96 -3
- package/package.json +4 -4
- package/src/geolocation/useGeolocation.d.ts +23 -0
- package/src/index.d.ts +1 -0
package/index.cjs.js
CHANGED
|
@@ -230,6 +230,99 @@ const useFilterBarContext = () => {
|
|
|
230
230
|
return context;
|
|
231
231
|
};
|
|
232
232
|
|
|
233
|
+
const useStandaloneGeolocation = ({ enabled, requestOnMount, }) => {
|
|
234
|
+
const [position, setPosition] = react.useState(null);
|
|
235
|
+
const queryGeolocationPermission = react.useCallback(async () => {
|
|
236
|
+
if (!enabled || typeof navigator === "undefined") {
|
|
237
|
+
return null;
|
|
238
|
+
}
|
|
239
|
+
try {
|
|
240
|
+
const status = await navigator.permissions.query({ name: "geolocation" });
|
|
241
|
+
return status.state;
|
|
242
|
+
}
|
|
243
|
+
catch {
|
|
244
|
+
return null;
|
|
245
|
+
}
|
|
246
|
+
}, [enabled]);
|
|
247
|
+
const getCurrentPosition = react.useCallback(async () => {
|
|
248
|
+
if (!enabled || typeof navigator === "undefined") {
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
return await new Promise(resolve => {
|
|
252
|
+
try {
|
|
253
|
+
navigator.geolocation.getCurrentPosition(currentPosition => {
|
|
254
|
+
resolve([currentPosition.coords.longitude, currentPosition.coords.latitude]);
|
|
255
|
+
}, () => {
|
|
256
|
+
resolve(null);
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
catch {
|
|
260
|
+
resolve(null);
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
}, [enabled]);
|
|
264
|
+
const getPosition = react.useCallback(async (options) => {
|
|
265
|
+
const prompt = options?.prompt !== false;
|
|
266
|
+
if (!prompt) {
|
|
267
|
+
const permissionState = await queryGeolocationPermission();
|
|
268
|
+
if (permissionState !== "granted") {
|
|
269
|
+
return null;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
const currentPosition = await getCurrentPosition();
|
|
273
|
+
if (currentPosition !== null) {
|
|
274
|
+
setPosition(currentPosition);
|
|
275
|
+
}
|
|
276
|
+
return currentPosition;
|
|
277
|
+
}, [getCurrentPosition, queryGeolocationPermission]);
|
|
278
|
+
react.useEffect(() => {
|
|
279
|
+
if (!enabled || requestOnMount !== true) {
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
void queryGeolocationPermission()
|
|
283
|
+
.then(permissionState => {
|
|
284
|
+
if (permissionState !== "granted") {
|
|
285
|
+
return null;
|
|
286
|
+
}
|
|
287
|
+
return getCurrentPosition();
|
|
288
|
+
})
|
|
289
|
+
.then(currentPosition => {
|
|
290
|
+
if (currentPosition !== null) {
|
|
291
|
+
setPosition(currentPosition);
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
}, [enabled, getCurrentPosition, queryGeolocationPermission, requestOnMount]);
|
|
295
|
+
return react.useMemo(() => ({
|
|
296
|
+
position,
|
|
297
|
+
getPosition,
|
|
298
|
+
}), [getPosition, position]);
|
|
299
|
+
};
|
|
300
|
+
/**
|
|
301
|
+
* Hook providing geolocation capabilities.
|
|
302
|
+
*
|
|
303
|
+
* In the host, geolocation is resolved directly via the browser API.
|
|
304
|
+
* In Iris Apps, requests are proxied to the host via the iframe bridge,
|
|
305
|
+
* so permission is only requested once at the host level.
|
|
306
|
+
*
|
|
307
|
+
* @example
|
|
308
|
+
* ```ts
|
|
309
|
+
* const { position, getPosition } = useGeolocation();
|
|
310
|
+
*
|
|
311
|
+
* // User-initiated request (e.g. "My Location" button)
|
|
312
|
+
* onClick: () => {
|
|
313
|
+
* void getPosition().then(pos => { if (pos) fitBounds(pos); });
|
|
314
|
+
* }
|
|
315
|
+
* ```
|
|
316
|
+
*/
|
|
317
|
+
const useGeolocation = (options) => {
|
|
318
|
+
const context = react.useContext(reactCoreContextsApi.GeolocationContext);
|
|
319
|
+
const standaloneGeolocation = useStandaloneGeolocation({
|
|
320
|
+
enabled: context === null,
|
|
321
|
+
requestOnMount: options?.requestOnMount,
|
|
322
|
+
});
|
|
323
|
+
return context ?? standaloneGeolocation;
|
|
324
|
+
};
|
|
325
|
+
|
|
233
326
|
/**
|
|
234
327
|
* This is a hook to use the TokenContext.
|
|
235
328
|
*
|
|
@@ -1109,6 +1202,7 @@ exports.useExportDataContext = useExportDataContext;
|
|
|
1109
1202
|
exports.useFeatureBranchQueryString = useFeatureBranchQueryString;
|
|
1110
1203
|
exports.useFeatureFlags = useFeatureFlags;
|
|
1111
1204
|
exports.useFilterBarContext = useFilterBarContext;
|
|
1205
|
+
exports.useGeolocation = useGeolocation;
|
|
1112
1206
|
exports.useHasAccessTo = useHasAccessTo;
|
|
1113
1207
|
exports.useImageUploader = useImageUploader;
|
|
1114
1208
|
exports.useIrisAppId = useIrisAppId;
|
package/index.esm.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { AnalyticsContext, AssetSortingContext, ConfirmationDialogContext, EnvironmentContext, ErrorHandlingContext, ExportDataContext, FeatureFlagContext, FilterBarContext, TokenContext, ModalDialogContext, NavigationContext, OemBrandingContext, UserSubscriptionContext, TimeRangeContext, ToastContext, CurrentUserContext, CurrentUserPreferenceContext, WidgetConfigContext } from '@trackunit/react-core-contexts-api';
|
|
2
|
-
import { useContext, useMemo, useState, useCallback,
|
|
1
|
+
import { AnalyticsContext, AssetSortingContext, ConfirmationDialogContext, EnvironmentContext, ErrorHandlingContext, ExportDataContext, FeatureFlagContext, FilterBarContext, GeolocationContext, TokenContext, ModalDialogContext, NavigationContext, OemBrandingContext, UserSubscriptionContext, TimeRangeContext, ToastContext, CurrentUserContext, CurrentUserPreferenceContext, WidgetConfigContext } from '@trackunit/react-core-contexts-api';
|
|
2
|
+
import { useContext, useMemo, useState, useCallback, useEffect, useReducer, useRef } from 'react';
|
|
3
3
|
import { isEqual } from 'es-toolkit';
|
|
4
4
|
import { AssetRuntime, CustomerRuntime, EventRuntime, ParamsRuntime, SiteRuntime, WidgetConfigRuntime } from '@trackunit/iris-app-runtime-core';
|
|
5
5
|
|
|
@@ -228,6 +228,99 @@ const useFilterBarContext = () => {
|
|
|
228
228
|
return context;
|
|
229
229
|
};
|
|
230
230
|
|
|
231
|
+
const useStandaloneGeolocation = ({ enabled, requestOnMount, }) => {
|
|
232
|
+
const [position, setPosition] = useState(null);
|
|
233
|
+
const queryGeolocationPermission = useCallback(async () => {
|
|
234
|
+
if (!enabled || typeof navigator === "undefined") {
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
try {
|
|
238
|
+
const status = await navigator.permissions.query({ name: "geolocation" });
|
|
239
|
+
return status.state;
|
|
240
|
+
}
|
|
241
|
+
catch {
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
244
|
+
}, [enabled]);
|
|
245
|
+
const getCurrentPosition = useCallback(async () => {
|
|
246
|
+
if (!enabled || typeof navigator === "undefined") {
|
|
247
|
+
return null;
|
|
248
|
+
}
|
|
249
|
+
return await new Promise(resolve => {
|
|
250
|
+
try {
|
|
251
|
+
navigator.geolocation.getCurrentPosition(currentPosition => {
|
|
252
|
+
resolve([currentPosition.coords.longitude, currentPosition.coords.latitude]);
|
|
253
|
+
}, () => {
|
|
254
|
+
resolve(null);
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
catch {
|
|
258
|
+
resolve(null);
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
}, [enabled]);
|
|
262
|
+
const getPosition = useCallback(async (options) => {
|
|
263
|
+
const prompt = options?.prompt !== false;
|
|
264
|
+
if (!prompt) {
|
|
265
|
+
const permissionState = await queryGeolocationPermission();
|
|
266
|
+
if (permissionState !== "granted") {
|
|
267
|
+
return null;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
const currentPosition = await getCurrentPosition();
|
|
271
|
+
if (currentPosition !== null) {
|
|
272
|
+
setPosition(currentPosition);
|
|
273
|
+
}
|
|
274
|
+
return currentPosition;
|
|
275
|
+
}, [getCurrentPosition, queryGeolocationPermission]);
|
|
276
|
+
useEffect(() => {
|
|
277
|
+
if (!enabled || requestOnMount !== true) {
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
void queryGeolocationPermission()
|
|
281
|
+
.then(permissionState => {
|
|
282
|
+
if (permissionState !== "granted") {
|
|
283
|
+
return null;
|
|
284
|
+
}
|
|
285
|
+
return getCurrentPosition();
|
|
286
|
+
})
|
|
287
|
+
.then(currentPosition => {
|
|
288
|
+
if (currentPosition !== null) {
|
|
289
|
+
setPosition(currentPosition);
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
}, [enabled, getCurrentPosition, queryGeolocationPermission, requestOnMount]);
|
|
293
|
+
return useMemo(() => ({
|
|
294
|
+
position,
|
|
295
|
+
getPosition,
|
|
296
|
+
}), [getPosition, position]);
|
|
297
|
+
};
|
|
298
|
+
/**
|
|
299
|
+
* Hook providing geolocation capabilities.
|
|
300
|
+
*
|
|
301
|
+
* In the host, geolocation is resolved directly via the browser API.
|
|
302
|
+
* In Iris Apps, requests are proxied to the host via the iframe bridge,
|
|
303
|
+
* so permission is only requested once at the host level.
|
|
304
|
+
*
|
|
305
|
+
* @example
|
|
306
|
+
* ```ts
|
|
307
|
+
* const { position, getPosition } = useGeolocation();
|
|
308
|
+
*
|
|
309
|
+
* // User-initiated request (e.g. "My Location" button)
|
|
310
|
+
* onClick: () => {
|
|
311
|
+
* void getPosition().then(pos => { if (pos) fitBounds(pos); });
|
|
312
|
+
* }
|
|
313
|
+
* ```
|
|
314
|
+
*/
|
|
315
|
+
const useGeolocation = (options) => {
|
|
316
|
+
const context = useContext(GeolocationContext);
|
|
317
|
+
const standaloneGeolocation = useStandaloneGeolocation({
|
|
318
|
+
enabled: context === null,
|
|
319
|
+
requestOnMount: options?.requestOnMount,
|
|
320
|
+
});
|
|
321
|
+
return context ?? standaloneGeolocation;
|
|
322
|
+
};
|
|
323
|
+
|
|
231
324
|
/**
|
|
232
325
|
* This is a hook to use the TokenContext.
|
|
233
326
|
*
|
|
@@ -1087,4 +1180,4 @@ const useWidgetConfig = () => {
|
|
|
1087
1180
|
return result;
|
|
1088
1181
|
};
|
|
1089
1182
|
|
|
1090
|
-
export { fetchAssetBlobUrl, useAnalytics, useAssetRuntime, useAssetSorting, useConfirmationDialog, useCurrentUser, useCurrentUserFavoriteAdvancedSensors, useCurrentUserFavoriteInsights, useCurrentUserLanguage, useCurrentUserSystemOfMeasurement, useCurrentUserTimeZonePreference, useCustomerRuntime, useEnvironment, useErrorHandler, useErrorHandlerOrNull, useEventRuntime, useExportDataContext, useFeatureBranchQueryString, useFeatureFlags, useFilterBarContext, useHasAccessTo, useImageUploader, useIrisAppId, useIrisAppImage, useIrisAppName, useModalDialogContext, useNavigateInHost, useOemBrandingContext, useSiteRuntime, useTimeRange, useToast, useToken, useUserPermission, useUserSubscription, useWidgetConfig, useWidgetConfigAsync };
|
|
1183
|
+
export { fetchAssetBlobUrl, useAnalytics, useAssetRuntime, useAssetSorting, useConfirmationDialog, useCurrentUser, useCurrentUserFavoriteAdvancedSensors, useCurrentUserFavoriteInsights, useCurrentUserLanguage, useCurrentUserSystemOfMeasurement, useCurrentUserTimeZonePreference, useCustomerRuntime, useEnvironment, useErrorHandler, useErrorHandlerOrNull, useEventRuntime, useExportDataContext, useFeatureBranchQueryString, useFeatureFlags, useFilterBarContext, useGeolocation, useHasAccessTo, useImageUploader, useIrisAppId, useIrisAppImage, useIrisAppName, useModalDialogContext, useNavigateInHost, useOemBrandingContext, useSiteRuntime, useTimeRange, useToast, useToken, useUserPermission, useUserSubscription, useWidgetConfig, useWidgetConfigAsync };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trackunit/react-core-hooks",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.14.0",
|
|
4
4
|
"repository": "https://github.com/Trackunit/manager",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6
6
|
"engines": {
|
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"react": "19.0.0",
|
|
11
11
|
"es-toolkit": "^1.39.10",
|
|
12
|
-
"@trackunit/iris-app-runtime-core": "1.
|
|
13
|
-
"@trackunit/iris-app-runtime-core-api": "1.
|
|
14
|
-
"@trackunit/react-core-contexts-api": "1.
|
|
12
|
+
"@trackunit/iris-app-runtime-core": "1.14.0",
|
|
13
|
+
"@trackunit/iris-app-runtime-core-api": "1.13.0",
|
|
14
|
+
"@trackunit/react-core-contexts-api": "1.14.0"
|
|
15
15
|
},
|
|
16
16
|
"module": "./index.esm.js",
|
|
17
17
|
"main": "./index.cjs.js",
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type GeolocationContextValue } from "@trackunit/react-core-contexts-api";
|
|
2
|
+
type UseGeolocationOptions = Readonly<{
|
|
3
|
+
requestOnMount?: boolean;
|
|
4
|
+
}>;
|
|
5
|
+
/**
|
|
6
|
+
* Hook providing geolocation capabilities.
|
|
7
|
+
*
|
|
8
|
+
* In the host, geolocation is resolved directly via the browser API.
|
|
9
|
+
* In Iris Apps, requests are proxied to the host via the iframe bridge,
|
|
10
|
+
* so permission is only requested once at the host level.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* const { position, getPosition } = useGeolocation();
|
|
15
|
+
*
|
|
16
|
+
* // User-initiated request (e.g. "My Location" button)
|
|
17
|
+
* onClick: () => {
|
|
18
|
+
* void getPosition().then(pos => { if (pos) fitBounds(pos); });
|
|
19
|
+
* }
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export declare const useGeolocation: (options?: UseGeolocationOptions) => GeolocationContextValue;
|
|
23
|
+
export {};
|
package/src/index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export * from "./exportData/useExportDataContext";
|
|
|
7
7
|
export * from "./featureFlags/useFeatureFlags";
|
|
8
8
|
export * from "./fetchAssetBlobUrl";
|
|
9
9
|
export * from "./filterBar/useFilterBarContext";
|
|
10
|
+
export * from "./geolocation/useGeolocation";
|
|
10
11
|
export * from "./images/useImageUploader";
|
|
11
12
|
export * from "./images/useIrisAppImage";
|
|
12
13
|
export * from "./modalDialog/useModalDialogContext";
|