-
-
Notifications
You must be signed in to change notification settings - Fork 63
/
Copy pathEmbedded.js
147 lines (134 loc) · 3.92 KB
/
Embedded.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
import React, { useEffect } from 'react';
import queryString from 'query-string';
import { useLocation, useParams } from 'react-router-dom';
import Preview from './Preview';
import Query from './Query';
import Result from './Result';
import MarkupEditor from './MarkupEditor';
import useParentMessaging from '../hooks/useParentMessaging';
import usePlayground from '../hooks/usePlayground';
import Loader from './Loader';
const SUPPORTED_PANES = {
markup: true,
preview: true,
query: true,
result: true,
};
const styles = {
offscreen: {
position: 'absolute',
left: -300,
width: 100,
},
};
// TODO: we should support readonly mode
function Embedded(props) {
const params = useParams();
const [state, dispatch] = usePlayground({
gistId: props.gistId || params.gistId,
gistVersion: props.gistVersion || params.gistVersion,
});
const { markup, query, result, status } = state;
const isLoading = status === 'loading';
// props.height because it describes better, params.maxheight because oembed
const height = props.height || params.maxheight || params.height;
const location = useLocation();
const searchParams = queryString.parse(location.search);
const panes = props.panes
? props.panes
: searchParams.panes
? searchParams.panes
.split(',')
.map((x) => x.trim())
.filter((x) => SUPPORTED_PANES[x])
: ['query', 'preview'];
// TODO: we should add tabs to handle > 2 panes
const areaCount = panes.length;
// Yes, it looks like we could compose this like `grid-cols-${n}`, but that way it isn't detectable by purgeCss
const columnClass =
areaCount === 4
? 'grid-cols-4'
: areaCount === 3
? 'grid-cols-3'
: areaCount === 2
? 'grid-cols-2'
: 'grid-cols-1';
useEffect(() => {
if (window === top) {
return;
}
document.body.classList.add('embedded');
return () => document.body.classList.remove('embedded');
}, []);
useParentMessaging(dispatch);
return (
<div
className="relative w-full h-screen"
style={height ? { height } : undefined}
>
<Loader loading={isLoading} />
<div
className={[
`h-full overflow-hidden grid grid-flow-col gap-4 p-4 bg-white shadow rounded fade`,
columnClass,
isLoading ? 'opacity-0' : 'opacity-100',
].join(' ')}
>
{/*the sandbox must always be rendered!*/}
{!panes.includes('preview') && (
<div style={styles.offscreen}>
<Preview
markup={markup}
elements={result?.elements}
accessibleRoles={result?.accessibleRoles}
dispatch={dispatch}
/>
</div>
)}
{panes.map((area, idx) => {
switch (area) {
case 'preview':
return (
<Preview
key={`${area}-${idx}`}
markup={markup}
elements={result?.elements}
accessibleRoles={result?.accessibleRoles}
dispatch={dispatch}
/>
);
case 'markup':
return (
<MarkupEditor
key={`${area}-${idx}`}
markup={markup}
dispatch={dispatch}
/>
);
case 'query':
return (
<Query
key={`${area}-${idx}`}
query={query}
result={result}
dispatch={dispatch}
variant="minimal"
/>
);
case 'result':
return (
<Result
key={`${area}-${idx}`}
result={result}
dispatch={dispatch}
/>
);
default:
return null;
}
})}
</div>
</div>
);
}
export default Embedded;