File tree Expand file tree Collapse file tree 6 files changed +765
-9
lines changed
Expand file tree Collapse file tree 6 files changed +765
-9
lines changed Load Diff Large diffs are not rendered by default.
Original file line number Diff line number Diff line change 1+ import { config } from 'eslint-config'
2+
3+ export default config ( )
Original file line number Diff line number Diff line change 1+ import { useEffect } from 'react'
2+ import type { Router } from 'next/router'
3+
4+ /**
5+ * Don't let a user navigate or close the page if changes aren't saved
6+ * @param unsaved Are there unsaved changes?
7+ * @param nextRouter If using NextJS, the next router (prevents NextJS navigation)
8+ */
9+ export function useUnsaved ( unsaved ?: boolean , nextRouter ?: Router ) : void {
10+ useEffect ( ( ) => {
11+ if ( unsaved ) {
12+ /**
13+ * If the tab is closed with unsaved changes
14+ */
15+ function preventUnsavedClose ( e : Event ) : void {
16+ e . preventDefault ( )
17+ }
18+
19+ /**
20+ * If a Next.JS SPA nav is started with unsaved changes
21+ * @param url The new URL (to check if simply changing page props rather than a page)
22+ * @throws {Error } To prevent page navigation
23+ */
24+ function preventUnsavedNav ( url : string ) : void {
25+ const urlSplit = url . split ( '?' ) [ 0 ] ! . split ( '/' )
26+ if ( nextRouter ?. pathname . split ( '/' ) . every ( ( subroute , i ) => ( subroute . startsWith ( '[' ) && subroute . endsWith ( ']' ) ) || subroute === urlSplit [ i ] ) ) return
27+
28+ if ( ! confirm ( 'Changes you made may not be saved.' ) ) throw new Error ( 'Navigation Canceled' )
29+ }
30+
31+ nextRouter ?. events . on ( 'routeChangeStart' , preventUnsavedNav )
32+ window . addEventListener ( 'beforeunload' , preventUnsavedClose )
33+ return ( ) => {
34+ nextRouter ?. events . off ( 'routeChangeStart' , preventUnsavedNav )
35+ window . removeEventListener ( 'beforeunload' , preventUnsavedClose )
36+ }
37+ }
38+ } , [ unsaved ] )
39+ }
Original file line number Diff line number Diff line change @@ -11,3 +11,7 @@ export {
1111export {
1212 useDebouncedState
1313} from './hooks/use-debounced-state'
14+
15+ export {
16+ useUnsaved
17+ } from './hooks/use-unsaved'
Original file line number Diff line number Diff line change 11{
22 "name" : " react-exo-hooks" ,
33 "module" : " index.ts" ,
4- "type" : " module" ,
54 "devDependencies" : {
6- "@types/bun" : " latest"
5+ "@types/bun" : " latest" ,
6+ "@types/next" : " ^9.0.0" ,
7+ "eslint" : " ^9.30.1" ,
8+ "eslint-config" : " github:exoRift/eslint-config" ,
9+ "eslint-plugin-jsdoc" : " ^51.3.4"
710 },
811 "peerDependencies" : {
12+ "react" : " ^19.1.0" ,
913 "typescript" : " ^5"
1014 },
11- "dependencies" : {
12- "react" : " ^19.1.0"
13- }
15+ "type" : " module"
1416}
Original file line number Diff line number Diff line change 11{
22 "compilerOptions" : {
33 // Environment setup & latest features
4- "lib" : [" ESNext" ],
4+ "lib" : [" ESNext" , " DOM " ],
55 "target" : " ESNext" ,
66 "module" : " Preserve" ,
77 "moduleDetection" : " force" ,
You can’t perform that action at this time.
0 commit comments