1
1
import type { ColorScheme } from "@mantine/core" ;
2
2
import {
3
- MantineProvider ,
3
+ Box ,
4
4
ColorSchemeProvider ,
5
5
createEmotionCache ,
6
+ MantineProvider ,
7
+ Title ,
8
+ useEmotionCache ,
6
9
} from "@mantine/core" ;
10
+ import { useIsomorphicEffect } from "@mantine/hooks" ;
11
+ import { StylesPlaceholder } from "@mantine/remix" ;
7
12
import type { MetaFunction } from "@remix-run/node" ;
8
13
import {
9
14
Links ,
@@ -12,8 +17,11 @@ import {
12
17
Outlet ,
13
18
Scripts ,
14
19
ScrollRestoration ,
20
+ useCatch ,
15
21
} from "@remix-run/react" ;
16
- import { useState } from "react" ;
22
+ import { useContext , useRef , useState } from "react" ;
23
+
24
+ import { ClientStyleContext } from "./clientStyleContext" ;
17
25
18
26
export const meta : MetaFunction = ( ) => ( {
19
27
charset : "utf-8" ,
@@ -23,18 +31,86 @@ export const meta: MetaFunction = () => ({
23
31
24
32
createEmotionCache ( { key : "mantine" } ) ;
25
33
34
+ export function CatchBoundary ( ) {
35
+ const caught = useCatch ( ) ;
36
+
37
+ return (
38
+ < Document title = { `${ caught . status } ${ caught . statusText } ` } >
39
+ < Box p = "lg" >
40
+ < Title color = "red" >
41
+ [CatchBoundary]: { caught . status } { caught . statusText }
42
+ </ Title >
43
+ </ Box >
44
+ </ Document >
45
+ ) ;
46
+ }
47
+
48
+ export function ErrorBoundary ( { error } : { error : Error } ) {
49
+ return (
50
+ < Document title = "Error!" >
51
+ < Box p = "lg" >
52
+ < Title color = "red" >
53
+ [ErrorBoundary]: There was an error: { error . message }
54
+ </ Title >
55
+ </ Box >
56
+ </ Document >
57
+ ) ;
58
+ }
59
+
26
60
export default function App ( ) {
61
+ return (
62
+ < Document >
63
+ < Outlet />
64
+ </ Document >
65
+ ) ;
66
+ }
67
+
68
+ function Document ( {
69
+ title,
70
+ children,
71
+ } : {
72
+ title ?: string ;
73
+ children : React . ReactNode ;
74
+ } ) {
75
+ const clientStyleData = useContext ( ClientStyleContext ) ;
76
+ const cache = useEmotionCache ( ) ;
77
+ const reinjectStylesRef = useRef ( true ) ;
78
+
79
+ // Only executed on client
80
+ // When a top level ErrorBoundary or CatchBoundary are rendered,
81
+ // the document head gets removed, so we have to create the style tags
82
+ useIsomorphicEffect ( ( ) => {
83
+ if ( ! reinjectStylesRef . current ) {
84
+ return ;
85
+ }
86
+
87
+ // re-link sheet container
88
+ cache . sheet . container = document . head ;
89
+
90
+ // re-inject tags
91
+ const tags = cache . sheet . tags ;
92
+ cache . sheet . flush ( ) ;
93
+ tags . forEach ( ( tag ) => {
94
+ ( cache . sheet as any ) . _insertTag ( tag ) ;
95
+ } ) ;
96
+
97
+ // reset cache to re-apply global styles
98
+ clientStyleData ?. reset ( ) ;
99
+
100
+ // ensure we only do this once per mount
101
+ reinjectStylesRef . current = false ;
102
+ } , [ ] ) ;
103
+
27
104
return (
28
105
< html lang = "en" >
29
106
< head >
107
+ < StylesPlaceholder />
108
+ { title ? < title > { title } </ title > : null }
30
109
< Meta />
31
110
< Links />
32
111
</ head >
33
112
< body >
34
- < MantineTheme >
35
- < Outlet />
36
- </ MantineTheme >
37
-
113
+ < MantineTheme > { children } </ MantineTheme >
38
114
< ScrollRestoration />
39
115
< Scripts />
40
116
< LiveReload />
0 commit comments