Skip to content

Commit d80ef56

Browse files
authored
Sandpack: upgrade dependencies and adds ReactDevtools (#4161)
* upgrade sandpack dependencies * update csb button * remove unnecessary ref * add react dev tools * remove duplicated/unnecessary element * fix: codemirror gutter * fix codemirror gutter * make devtools optional * bump sandpack version * fix: add website theme to the react devtools * fix: react devtools ui tweaks * devtools: custom theme * refactor: reset sandbox * fix sandpack * fix: devtools style * fix: tweaks on mobile version * fix: soft refresh when module is loaded * bump sandpack version * update color * remove demo * remove inspect button * bring back key logic * refactor: icon align * update sandpack * logic to keep the content synced
1 parent 69bd27a commit d80ef56

File tree

10 files changed

+761
-794
lines changed

10 files changed

+761
-794
lines changed

beta/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
"check-all": "npm-run-all prettier lint:fix tsc"
2323
},
2424
"dependencies": {
25-
"@codesandbox/sandpack-react": "^0.1.20",
25+
"@codesandbox/sandpack-react": "0.13.6-experimental.0",
2626
"@docsearch/css": "3.0.0-alpha.41",
2727
"@docsearch/react": "3.0.0-alpha.41",
2828
"@headlessui/react": "^1.3.0",
@@ -34,9 +34,9 @@
3434
"github-slugger": "^1.3.0",
3535
"next": "^12.0.5",
3636
"parse-numeric-range": "^1.2.0",
37-
"react": "18.0.0-alpha-930c9e7ee-20211015",
37+
"react": "experimental",
3838
"react-collapsed": "3.1.0",
39-
"react-dom": "18.0.0-alpha-930c9e7ee-20211015",
39+
"react-dom": "experimental",
4040
"scroll-into-view-if-needed": "^2.2.25"
4141
},
4242
"devDependencies": {

beta/src/components/Icon/IconNewPage.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55
import * as React from 'react';
66

77
export const IconNewPage = React.memo<JSX.IntrinsicElements['svg']>(
8-
function IconNewPage({className}) {
8+
function IconNewPage(props) {
99
return (
1010
<svg
11-
className={className}
1211
width="0.72em"
1312
height="0.72em"
1413
viewBox="0 0 13 13"
15-
xmlns="http://www.w3.org/2000/svg">
14+
xmlns="http://www.w3.org/2000/svg"
15+
{...props}>
1616
<path
1717
d="M4.72038 2.94824V4.28158H1.38704V11.6149H8.72038V8.28158H10.0537V12.2816C10.0537 12.4584 9.98347 12.628 9.85845 12.753C9.73343 12.878 9.56386 12.9482 9.38704 12.9482H0.720378C0.543567 12.9482 0.373997 12.878 0.248973 12.753C0.123949 12.628 0.0537109 12.4584 0.0537109 12.2816V3.61491C0.0537109 3.4381 0.123949 3.26853 0.248973 3.1435C0.373997 3.01848 0.543567 2.94824 0.720378 2.94824H4.72038ZM12.0537 0.948242V6.28158H10.7204V3.22358L5.52504 8.41958L4.58238 7.47691L9.77704 2.28158H6.72038V0.948242H12.0537Z"
1818
fill="currentColor"

beta/src/components/MDX/APIAnatomy.tsx

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ const colors = [
4242

4343
export function APIAnatomy({children}: APIAnatomyProps) {
4444
const [activeStep, setActiveStep] = React.useState<number | null>(null);
45-
const ref = React.useRef<HTMLDivElement>();
4645

4746
const {steps, code} = React.Children.toArray(children).reduce(
4847
(acc: AnatomyContent, child) => {
@@ -60,11 +59,7 @@ export function APIAnatomy({children}: APIAnatomyProps) {
6059
break;
6160
case 'pre':
6261
acc.code = (
63-
<CodeBlock
64-
ref={ref}
65-
{...child.props.children.props}
66-
noMargin={true}
67-
/>
62+
<CodeBlock {...child.props.children.props} noMargin={true} />
6863
);
6964
break;
7065
}

beta/src/components/MDX/CodeBlock/CodeBlock.tsx

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
* Copyright (c) Facebook, Inc. and its affiliates.
33
*/
44

5-
import * as React from 'react';
65
import cn from 'classnames';
76
import {
87
ClasserProvider,
@@ -21,22 +20,19 @@ interface InlineHiglight {
2120
endColumn: number;
2221
}
2322

24-
const CodeBlock = React.forwardRef(function CodeBlock(
25-
{
26-
children,
27-
className = 'language-js',
28-
metastring,
29-
noMargin,
30-
noMarkers,
31-
}: {
32-
children: string;
33-
className?: string;
34-
metastring: string;
35-
noMargin?: boolean;
36-
noMarkers?: boolean;
37-
},
38-
ref?: React.Ref<HTMLDivElement>
39-
) {
23+
const CodeBlock = function CodeBlock({
24+
children,
25+
className = 'language-js',
26+
metastring,
27+
noMargin,
28+
noMarkers,
29+
}: {
30+
children: string;
31+
className?: string;
32+
metastring: string;
33+
noMargin?: boolean;
34+
noMarkers?: boolean;
35+
}) {
4036
const getDecoratedLineInfo = () => {
4137
if (!metastring) {
4238
return [];
@@ -95,7 +91,7 @@ const CodeBlock = React.forwardRef(function CodeBlock(
9591
'sp-cm': styles.codeViewer,
9692
}}>
9793
<SandpackCodeViewer
98-
ref={ref}
94+
key={children.trimEnd()}
9995
showLineNumbers={false}
10096
decorators={decorators}
10197
/>
@@ -104,7 +100,7 @@ const CodeBlock = React.forwardRef(function CodeBlock(
104100
</SandpackProvider>
105101
</div>
106102
);
107-
});
103+
};
108104

109105
export default CodeBlock;
110106

beta/src/components/MDX/Sandpack/CustomPreset.tsx

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,27 @@ import {
1010
useActiveCode,
1111
SandpackCodeEditor,
1212
SandpackThemeProvider,
13+
SandpackReactDevTools,
1314
} from '@codesandbox/sandpack-react';
1415
import scrollIntoView from 'scroll-into-view-if-needed';
1516

17+
import cn from 'classnames';
18+
1619
import {IconChevron} from 'components/Icon/IconChevron';
1720
import {NavigationBar} from './NavigationBar';
1821
import {Preview} from './Preview';
1922
import {CustomTheme} from './Themes';
2023

2124
export function CustomPreset({
2225
isSingleFile,
23-
onReset,
26+
showDevTools,
27+
onDevToolsLoad,
28+
devToolsLoaded,
2429
}: {
2530
isSingleFile: boolean;
26-
onReset: () => void;
31+
showDevTools: boolean;
32+
devToolsLoaded: boolean;
33+
onDevToolsLoad: () => void;
2734
}) {
2835
const lineCountRef = React.useRef<{[key: string]: number}>({});
2936
const containerRef = React.useRef<HTMLDivElement>(null);
@@ -50,11 +57,14 @@ export function CustomPreset({
5057
<div
5158
className="shadow-lg dark:shadow-lg-dark rounded-lg"
5259
ref={containerRef}>
53-
<NavigationBar showDownload={isSingleFile} onReset={onReset} />
60+
<NavigationBar showDownload={isSingleFile} />
5461
<SandpackThemeProvider theme={CustomTheme}>
5562
<div
5663
ref={sandpack.lazyAnchorRef}
57-
className="sp-layout rounded-t-none"
64+
className={cn(
65+
'sp-layout sp-custom-layout',
66+
showDevTools && devToolsLoaded && 'sp-layout-devtools'
67+
)}
5868
style={{
5969
// Prevent it from collapsing below the initial (non-loaded) height.
6070
// There has to be some better way to do this...
@@ -77,6 +87,7 @@ export function CustomPreset({
7787
maxHeight: isExpanded ? '' : 406,
7888
}}
7989
/>
90+
8091
{isExpandable && (
8192
<button
8293
translate="yes"
@@ -104,6 +115,10 @@ export function CustomPreset({
104115
</button>
105116
)}
106117
</div>
118+
119+
{showDevTools && (
120+
<SandpackReactDevTools onLoadModule={onDevToolsLoad} />
121+
)}
107122
</SandpackThemeProvider>
108123
</div>
109124
</>

beta/src/components/MDX/Sandpack/NavigationBar.tsx

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,22 @@
33
*/
44

55
import * as React from 'react';
6-
import {FileTabs, useSandpack} from '@codesandbox/sandpack-react';
6+
import {
7+
FileTabs,
8+
useSandpack,
9+
useSandpackNavigation,
10+
} from '@codesandbox/sandpack-react';
711
import {OpenInCodeSandboxButton} from './OpenInCodeSandboxButton';
812
import {ResetButton} from './ResetButton';
913
import {DownloadButton} from './DownloadButton';
1014
import {FilesDropdown} from './FilesDropdown';
1115

12-
export function NavigationBar({
13-
showDownload,
14-
onReset,
15-
}: {
16-
showDownload: boolean;
17-
onReset: () => void;
18-
}) {
16+
export function NavigationBar({showDownload}: {showDownload: boolean}) {
1917
const {sandpack} = useSandpack();
2018
const [dropdownActive, setDropdownActive] = React.useState(false);
21-
const {openPaths} = sandpack;
19+
const {openPaths, clients} = sandpack;
20+
const clientId = Object.keys(clients)[0];
21+
const {refresh} = useSandpackNavigation(clientId);
2222

2323
const resizeHandler = React.useCallback(() => {
2424
const width = window.innerWidth || document.documentElement.clientWidth;
@@ -41,6 +41,11 @@ export function NavigationBar({
4141
return;
4242
}, [openPaths.length, resizeHandler]);
4343

44+
const handleReset = () => {
45+
sandpack.resetAllFiles();
46+
refresh();
47+
};
48+
4449
return (
4550
<div className="bg-wash dark:bg-card-dark flex justify-between items-center relative z-10 border-b border-border dark:border-border-dark rounded-t-lg rounded-b-none">
4651
<div className="px-4 lg:px-6">
@@ -50,8 +55,8 @@ export function NavigationBar({
5055
className="px-3 flex items-center justify-end flex-grow text-right"
5156
translate="yes">
5257
{showDownload && <DownloadButton />}
53-
<ResetButton onReset={onReset} />
54-
<OpenInCodeSandboxButton className="ml-2 md:ml-4" />
58+
<ResetButton onReset={handleReset} />
59+
<OpenInCodeSandboxButton />
5560
</div>
5661
</div>
5762
);

beta/src/components/MDX/Sandpack/OpenInCodeSandboxButton.tsx

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,20 @@
33
*/
44

55
import * as React from 'react';
6-
import {useCodeSandboxLink} from '@codesandbox/sandpack-react';
7-
import cn from 'classnames';
6+
import {UnstyledOpenInCodeSandboxButton} from '@codesandbox/sandpack-react';
87
import {IconNewPage} from '../../Icon/IconNewPage';
98

10-
export const OpenInCodeSandboxButton = ({className}: {className?: string}) => {
11-
const url = useCodeSandboxLink();
12-
9+
export const OpenInCodeSandboxButton = () => {
1310
return (
14-
<a
15-
className={cn(
16-
'text-sm text-primary dark:text-primary-dark inline-flex items-center hover:text-link duration-100 ease-in transition mx-1',
17-
className
18-
)}
19-
href={url}
20-
rel="noreferrer noopener"
21-
target="_blank"
11+
<UnstyledOpenInCodeSandboxButton
12+
className="text-sm text-primary dark:text-primary-dark inline-flex items-center hover:text-link duration-100 ease-in transition mx-1 ml-3 md:ml-1"
2213
title="Open in CodeSandbox">
23-
<span className="hidden md:inline">
24-
<IconNewPage className="inline mb-0.5 text-base" /> Fork
25-
</span>
26-
<span className="inline md:hidden">
27-
<IconNewPage className="inline mb-0.5 text-base" /> Fork
28-
</span>
29-
</a>
14+
<IconNewPage
15+
className="inline mb-0.5 ml-1 mr-1 relative top-px"
16+
width=".8em"
17+
height=".8em"
18+
/>
19+
<span className="hidden md:block">Fork</span>
20+
</UnstyledOpenInCodeSandboxButton>
3021
);
3122
};

beta/src/components/MDX/Sandpack/index.tsx

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ type SandpackProps = {
1515
children: React.ReactChildren;
1616
autorun?: boolean;
1717
setup?: SandpackSetup;
18+
showDevTools?: boolean;
1819
};
1920

2021
const sandboxStyle = `
@@ -64,8 +65,8 @@ ul {
6465
`.trim();
6566

6667
function Sandpack(props: SandpackProps) {
67-
let {children, setup, autorun = true} = props;
68-
let [resetKey, setResetKey] = React.useState(0);
68+
let {children, setup, autorun = true, showDevTools = false} = props;
69+
const [devToolsLoaded, setDevToolsLoaded] = React.useState(false);
6970
let codeSnippets = React.Children.toArray(children) as React.ReactElement[];
7071
let isSingleFile = true;
7172

@@ -121,29 +122,17 @@ function Sandpack(props: SandpackProps) {
121122
hidden: true,
122123
};
123124

124-
let key = String(resetKey);
125-
if (process.env.NODE_ENV !== 'production') {
126-
// Remount on any source change in development.
127-
key +=
128-
'-' +
129-
JSON.stringify({
130-
...props,
131-
children: files,
132-
});
133-
}
134-
135125
return (
136-
<div className="my-8" translate="no">
126+
<div className="sandpack-container my-8" translate="no">
137127
<SandpackProvider
138-
key={key}
139128
template="react"
140129
customSetup={{...setup, files: files}}
141130
autorun={autorun}>
142131
<CustomPreset
143132
isSingleFile={isSingleFile}
144-
onReset={() => {
145-
setResetKey((k) => k + 1);
146-
}}
133+
showDevTools={showDevTools}
134+
onDevToolsLoad={() => setDevToolsLoaded(true)}
135+
devToolsLoaded={devToolsLoaded}
147136
/>
148137
</SandpackProvider>
149138
</div>

0 commit comments

Comments
 (0)