@pol-studios/hooks 1.0.9 → 1.0.11

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.
@@ -0,0 +1,77 @@
1
+ // src/version/useVersionCheck.ts
2
+ import { useState, useEffect, useRef, useCallback } from "react";
3
+ var DEFAULT_POLLING_INTERVAL = 18e4;
4
+ function useVersionCheck(options = {}) {
5
+ const {
6
+ pollingInterval = DEFAULT_POLLING_INTERVAL,
7
+ enabled = typeof window !== "undefined" && window.location.hostname !== "localhost"
8
+ } = options;
9
+ const [hasUpdate, setHasUpdate] = useState(false);
10
+ const [error, setError] = useState(false);
11
+ const initialDeploymentId = useRef(null);
12
+ const dismissedDeploymentId = useRef(null);
13
+ const latestDeploymentId = useRef(null);
14
+ const getDeploymentId = useCallback(async () => {
15
+ if (typeof window === "undefined") return null;
16
+ try {
17
+ const response = await fetch(window.location.origin, {
18
+ method: "HEAD",
19
+ cache: "no-store"
20
+ });
21
+ const deploymentUrl = response.headers.get("x-vercel-deployment-url");
22
+ if (deploymentUrl) {
23
+ setError(false);
24
+ return deploymentUrl;
25
+ }
26
+ const deploymentId = response.headers.get("x-vercel-id") || null;
27
+ if (deploymentId) {
28
+ setError(false);
29
+ }
30
+ return deploymentId;
31
+ } catch {
32
+ setError(true);
33
+ return null;
34
+ }
35
+ }, []);
36
+ const checkForUpdate = useCallback(async () => {
37
+ const currentDeploymentId = await getDeploymentId();
38
+ if (!currentDeploymentId) {
39
+ return;
40
+ }
41
+ latestDeploymentId.current = currentDeploymentId;
42
+ if (initialDeploymentId.current === null) {
43
+ initialDeploymentId.current = currentDeploymentId;
44
+ return;
45
+ }
46
+ if (currentDeploymentId !== initialDeploymentId.current && currentDeploymentId !== dismissedDeploymentId.current) {
47
+ setHasUpdate(true);
48
+ }
49
+ }, [getDeploymentId]);
50
+ const refresh = useCallback(() => {
51
+ window.location.reload();
52
+ }, []);
53
+ const dismiss = useCallback(() => {
54
+ if (latestDeploymentId.current) {
55
+ dismissedDeploymentId.current = latestDeploymentId.current;
56
+ }
57
+ setHasUpdate(false);
58
+ }, []);
59
+ useEffect(() => {
60
+ if (!enabled) return;
61
+ checkForUpdate();
62
+ const intervalId = setInterval(checkForUpdate, pollingInterval);
63
+ return () => {
64
+ clearInterval(intervalId);
65
+ };
66
+ }, [enabled, pollingInterval, checkForUpdate]);
67
+ return {
68
+ hasUpdate,
69
+ refresh,
70
+ dismiss,
71
+ error
72
+ };
73
+ }
74
+
75
+ export {
76
+ useVersionCheck
77
+ };
package/dist/index.d.ts CHANGED
@@ -8,6 +8,7 @@ export { ActionType, Toast, ToastAction, ToastState, ToasterToast, actionTypes,
8
8
  export { useHideOnScroll, useHidingOnScroll, useScrollDirection, useScrollPosition, useScrollRestoration } from './scroll/index.js';
9
9
  export { NetworkStatus, NetworkStatus as OnlineStatus, QueuedMutation, useMutationQueue, useNetworkStatus, useOnline } from './network/index.js';
10
10
  export { useRenderCount, useRenderHookCount, useStateTracker, useTrackedState } from './debug/index.js';
11
+ export { UseVersionCheckOptions, UseVersionCheckReturn, useVersionCheck } from './version/index.js';
11
12
  export { dateReviver, downloadFile, getFile, getFilePost, hasCameraAsync, isDev, isDevEnvironment, isIphone, isPwaLaunched, isUsable, parseWithDate, withComponentMemo } from './_utils/index.js';
12
13
  import 'react';
13
14
  import 'react/jsx-runtime';
package/dist/index.js CHANGED
@@ -16,6 +16,9 @@ import {
16
16
  useStateTracker,
17
17
  useTrackedState
18
18
  } from "./chunk-XIISC67B.js";
19
+ import {
20
+ useVersionCheck
21
+ } from "./chunk-KRFN7UQV.js";
19
22
  import {
20
23
  ChangeTrackingContext,
21
24
  ChangeTrackingProvider,
@@ -163,6 +166,7 @@ export {
163
166
  useThemeDetector,
164
167
  useToast,
165
168
  useTrackedState,
169
+ useVersionCheck,
166
170
  useWindowDimensions,
167
171
  withComponentMemo
168
172
  };
@@ -0,0 +1,39 @@
1
+ interface UseVersionCheckOptions {
2
+ /** Polling interval in milliseconds. Default: 180000 (3 minutes) */
3
+ pollingInterval?: number;
4
+ /** Whether version checking is enabled. Default: true in production */
5
+ enabled?: boolean;
6
+ }
7
+ interface UseVersionCheckReturn {
8
+ /** Whether a new version is available */
9
+ hasUpdate: boolean;
10
+ /** Refresh the page to get the new version */
11
+ refresh: () => void;
12
+ /** Dismiss the update notification (won't show again for this deployment) */
13
+ dismiss: () => void;
14
+ /** Whether an error occurred during version check */
15
+ error: boolean;
16
+ }
17
+ /**
18
+ * Hook to detect when a new version of the app has been deployed on Vercel.
19
+ * Uses the x-vercel-deployment-url header to detect changes.
20
+ *
21
+ * @param options - Configuration options
22
+ * @returns Object with hasUpdate, refresh, dismiss, and error
23
+ *
24
+ * @example
25
+ * ```tsx
26
+ * const { hasUpdate, refresh, dismiss } = useVersionCheck();
27
+ *
28
+ * if (hasUpdate) {
29
+ * return (
30
+ * <Banner onRefresh={refresh} onDismiss={dismiss}>
31
+ * A new version is available!
32
+ * </Banner>
33
+ * );
34
+ * }
35
+ * ```
36
+ */
37
+ declare function useVersionCheck(options?: UseVersionCheckOptions): UseVersionCheckReturn;
38
+
39
+ export { type UseVersionCheckOptions, type UseVersionCheckReturn, useVersionCheck };
@@ -0,0 +1,7 @@
1
+ import {
2
+ useVersionCheck
3
+ } from "../chunk-KRFN7UQV.js";
4
+ import "../chunk-QGM4M3NI.js";
5
+ export {
6
+ useVersionCheck
7
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pol-studios/hooks",
3
- "version": "1.0.9",
3
+ "version": "1.0.11",
4
4
  "description": "React hooks for POL applications",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
@@ -54,6 +54,10 @@
54
54
  "import": "./dist/debug/index.js",
55
55
  "types": "./dist/debug/index.d.ts"
56
56
  },
57
+ "./version": {
58
+ "import": "./dist/version/index.js",
59
+ "types": "./dist/version/index.d.ts"
60
+ },
57
61
  "./utils": {
58
62
  "import": "./dist/_utils/index.js",
59
63
  "types": "./dist/_utils/index.d.ts"
@@ -64,18 +68,17 @@
64
68
  },
65
69
  "peerDependencies": {
66
70
  "react": "^18.0.0 || ^19.0.0",
67
- "react-dom": "^18.0.0 || ^19.0.0"
71
+ "react-dom": "^18.0.0 || ^19.0.0",
72
+ "@tanstack/react-query": "^5.0.0"
68
73
  },
69
74
  "dependencies": {
70
- "@pol-studios/utils": ">=1.0.0",
71
- "@tanstack/react-query": "^5.0.0",
72
75
  "framer-motion": "^11.0.0",
73
- "lodash": "^4.17.21"
76
+ "lodash": "^4.17.21",
77
+ "@pol-studios/utils": "1.0.9"
74
78
  },
75
79
  "devDependencies": {
76
80
  "tsup": "^8.0.0",
77
- "typescript": "^5.0.0",
78
- "@pol-studios/utils": "1.0.8"
81
+ "typescript": "^5.0.0"
79
82
  },
80
83
  "keywords": [
81
84
  "hooks",