Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions sandpack-client/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ export interface ClientOptions {
isFile: (path: string) => Promise<boolean>;
readFile: (path: string) => Promise<string>;
};

reactDevTools?: boolean;
}

export interface SandboxInfo {
Expand Down Expand Up @@ -271,6 +273,7 @@ export class SandpackClient {
version: 3,
isInitializationCompile,
modules,
reactDevTools: this.options.reactDevTools,
externalResources: this.options.externalResources || [],
hasFileResolver: Boolean(this.options.fileResolver),
disableDependencyPreprocessing:
Expand Down
4 changes: 4 additions & 0 deletions sandpack-client/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ export type SandpackMessage = BaseSandpackMessage &
showLoadingScreen: boolean;
skipEval: boolean;
clearConsoleDisabled?: boolean;
reactDevTools?: boolean;
}
| {
type: "refresh";
Expand All @@ -184,4 +185,7 @@ export type SandpackMessage = BaseSandpackMessage &
| {
type: "get-transpiler-context";
}
| {
type: "activate-react-devtools";
}
);
3 changes: 2 additions & 1 deletion sandpack-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@
"@codesandbox/sandpack-client": "^0.9.13",
"@react-hook/intersection-observer": "^3.1.1",
"codesandbox-import-util-types": "^2.2.3",
"codesandbox-import-utils": "^2.2.3"
"codesandbox-import-utils": "^2.2.3",
"react-devtools-inline": "4.4.0"
},
"devDependencies": {
"@babel/core": "^7.12.3",
Expand Down
4 changes: 3 additions & 1 deletion sandpack-react/src/common/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type { SandpackThemeProp } from "../types";

export interface SandpackLayoutProps {
theme?: SandpackThemeProp;
style?: React.CSSProperties;
}

/**
Expand All @@ -15,13 +16,14 @@ export interface SandpackLayoutProps {
export const SandpackLayout: React.FC<SandpackLayoutProps> = ({
children,
theme,
...props
}) => {
const { sandpack } = useSandpack();
const c = useClasser("sp");

return (
<SandpackThemeProvider theme={theme}>
<div ref={sandpack.lazyAnchorRef} className={c("layout")}>
<div ref={sandpack.lazyAnchorRef} className={c("layout")} {...props}>
{children}
</div>
</SandpackThemeProvider>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { SandpackPreview } from "..";
import { SandpackProvider, SandpackLayout, SandpackThemeProvider } from "../..";

import { SandpackReactDevTools } from "./";

export default {
title: "components/ReactDevTools",
};

export const ReactDevTool: React.FC = () => (
<SandpackProvider
customSetup={{
files: {
"/App.js": `
const Container = ({children}) => <div>{children}</div>
const Button = () => <p>Button</p>

export default function App() {
return (
<Container>
<div>
<Button />
<Button />
<h1>Hello World</h1>
<Button />
</div>
</Container>
)
}
`,
},
}}
template="react"
>
<SandpackThemeProvider>
<SandpackLayout>
<SandpackPreview />
<SandpackReactDevTools style={{ width: "50%" }} />
</SandpackLayout>
</SandpackThemeProvider>
</SandpackProvider>
);
60 changes: 60 additions & 0 deletions sandpack-react/src/components/ReactDevTools/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { useClasser } from "@code-hike/classer";
import type { CSSProperties } from "react";
import React, { useEffect, useRef, useState } from "react";

import { useSandpackTheme } from "../..";
import { useSandpack } from "../../hooks/useSandpack";
import { isDarkColor } from "../../utils/stringUtils";

export const SandpackReactDevTools = ({
clientId,
...props
}: {
clientId?: string;
style?: CSSProperties;
}): JSX.Element | null => {
const { listen, sandpack } = useSandpack();
const { theme } = useSandpackTheme();
const c = useClasser("sp");
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const reactDevtools = useRef<any>();

const [ReactDevTools, setDevTools] = useState<React.FunctionComponent<{
browserTheme: "dark" | "light";
}> | null>(null);

useEffect(() => {
import("react-devtools-inline/frontend").then((module) => {
reactDevtools.current = module;
});
}, []);

useEffect(() => {
const unsubscribe = listen((msg) => {
if (msg.type === "activate-react-devtools") {
const client = clientId
? sandpack.clients[clientId]
: Object.values(sandpack.clients)[0];
const contentWindow = client?.iframe?.contentWindow;

setDevTools(reactDevtools.current.initialize(contentWindow));
}
});

return unsubscribe;
}, [clientId, listen, sandpack.clients]);

useEffect(() => {
sandpack.registerReactDevTools();
}, []);

if (!ReactDevTools) return null;

const isDarkTheme = isDarkColor(theme.palette.defaultBackground);

return (
<div className={c("devtools")} {...props}>
<ReactDevTools browserTheme={isDarkTheme ? "dark" : "light"} />
</div>
);
};
1 change: 1 addition & 0 deletions sandpack-react/src/components/ReactDevTools/types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
declare module "react-devtools-inline/frontend";
1 change: 1 addition & 0 deletions sandpack-react/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export * from "./FileTabs";
export * from "./Navigator";
export * from "./Preview";
export * from "./TranspiledCode";
export * from "./ReactDevTools";
12 changes: 12 additions & 0 deletions sandpack-react/src/contexts/sandpackContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export interface SandpackProviderState {
editorState: EditorState;
renderHiddenIframe: boolean;
initMode: SandpackInitMode;
reactDevTools: boolean;
}

export interface SandpackProviderProps {
Expand Down Expand Up @@ -129,6 +130,7 @@ class SandpackProvider extends React.PureComponent<
editorState: "pristine",
renderHiddenIframe: false,
initMode: this.props.initMode || "lazy",
reactDevTools: false,
};

/**
Expand Down Expand Up @@ -181,6 +183,13 @@ class SandpackProvider extends React.PureComponent<
}
};

/**
* @hidden
*/
registerReactDevTools = (): void => {
this.setState({ reactDevTools: true });
};

/**
* @hidden
*/
Expand Down Expand Up @@ -376,6 +385,7 @@ class SandpackProvider extends React.PureComponent<
showOpenInCodeSandbox: !this.openInCSBRegistered.current,
showErrorScreen: !this.errorScreenRegistered.current,
showLoadingScreen: !this.loadingScreenRegistered.current,
reactDevTools: this.state.reactDevTools,
}
);

Expand Down Expand Up @@ -673,6 +683,7 @@ class SandpackProvider extends React.PureComponent<
status: sandpackStatus,
editorState,
initMode,
clients: this.clients,
closeFile: this.closeFile,
deleteFile: this.deleteFile,
dispatch: this.dispatchMessage,
Expand All @@ -690,6 +701,7 @@ class SandpackProvider extends React.PureComponent<
unregisterBundler: this.unregisterBundler,
updateCurrentFile: this.updateCurrentFile,
updateFile: this.updateFile,
registerReactDevTools: this.registerReactDevTools,
};
};

Expand Down
8 changes: 7 additions & 1 deletion sandpack-react/src/styles/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
--sp-colors-accent: #64d2ff;
--sp-colors-bg-error: #ffcdca;
--sp-colors-fg-error: #811e18;
--sp-layout-height: 300px;

--sp-font-size: 14px;
--sp-font-body: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
Expand Down Expand Up @@ -106,7 +107,7 @@
flex-shrink: 1;
flex-basis: 0;
min-width: 350px;
height: 300px;
height: var(--sp-layout-height);
}

@media print {
Expand Down Expand Up @@ -510,3 +511,8 @@
animation: sp-fade-in 0.15s ease-in;
color: var(--sp-colors-fg-error);
}

.sp-devtools {
height: var(--sp-layout-height);
width: 100%;
}
3 changes: 3 additions & 0 deletions sandpack-react/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type {
BundlerState,
ListenerFunction,
SandpackBundlerFiles,
SandpackClient,
SandpackError,
SandpackMessage,
UnsubscribeFunction,
Expand Down Expand Up @@ -34,6 +35,7 @@ export interface SandpackState {
environment?: SandboxEnvironment;
status: SandpackStatus;
initMode: SandpackInitMode;
clients: Record<string, SandpackClient>;

runSandpack: () => void;
registerBundler: (iframe: HTMLIFrameElement, clientId: string) => void;
Expand All @@ -46,6 +48,7 @@ export interface SandpackState {
setActiveFile: (path: string) => void;
resetFile: (path: string) => void;
resetAllFiles: () => void;
registerReactDevTools: () => void;

// Element refs
// Different components inside the SandpackProvider might register certain elements of interest for sandpack
Expand Down
38 changes: 36 additions & 2 deletions website/docs/docs/advanced-usage/components.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
sidebar_position: 2
---

import { SandpackProvider, SandpackCodeEditor, SandpackCodeViewer, SandpackTranspiledCode, SandpackPreview } from "@codesandbox/sandpack-react"
import { Sandpack, SandpackProvider, SandpackCodeEditor, SandpackCodeViewer, SandpackTranspiledCode, SandpackPreview } from "@codesandbox/sandpack-react"
import { SandpackLayout } from "../../src/CustomSandpack"

# Components
Expand Down Expand Up @@ -173,7 +173,41 @@ For situations when you strictly want to show some code and run it in the browse
</SandpackLayout>
</SandpackProvider>

## UnstyledOpenInCodeSandboxButton & OpenInCodeSandboxButton
## ReactDevTools

Sandpack also provides a component that adds React DevTools, allowing you to inspect the React component hierarchies in the iframe. This is useful for `props` debugging and understanding the component tree. Our `SandpackReactDevTools` component has the same functionality as the React DevTools browser extensions, but it only shows what is in your Sandpack instance.

<!-- prettier-ignore -->
<div className="nestedSandpack">
<Sandpack
theme="sandpack-dark"
customSetup={{
dependencies: { "@codesandbox/sandpack-react": "latest" },
}}
files={{
"/App.js": `import {
SandpackProvider,
SandpackLayout,
SandpackPreview,
SandpackReactDevTools,
} from "@codesandbox/sandpack-react";
import "@codesandbox/sandpack-react/dist/index.css";\n
export default function CustomSandpack() {
return (
<SandpackProvider template="react">
<SandpackLayout>
<SandpackPreview />
<SandpackReactDevTools style={{ width: "50%" }} />
</SandpackLayout>
</SandpackProvider>
)
}`
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like you forgot the "```" ticks for formatting here.

}}
template="react"
/>
</div>

## OpenInCodeSandboxButton

You can build a custom button that creates a new sandbox from the sandpack files. It will include any edits made in the Sandpack editor, so it is a great way to persist your changes. The created sandbox will open on [CodeSandbox](https://codesandbox.io) in a new tab.

Expand Down
Binary file added website/docs/static/img/docs/react-devtools.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 8 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -8649,7 +8649,7 @@ es6-shim@^0.35.5:
resolved "https://registry.yarnpkg.com/es6-shim/-/es6-shim-0.35.6.tgz#d10578301a83af2de58b9eadb7c2c9945f7388a0"
integrity sha512-EmTr31wppcaIAgblChZiuN/l9Y7DPyw8Xtbg7fIVngn6zMW+IEBJDJngeKC3x6wr0V/vcA2wqeFnaw1bFJbDdA==

es6-symbol@^3.1.1, es6-symbol@~3.1.3:
es6-symbol@^3, es6-symbol@^3.1.1, es6-symbol@~3.1.3:
version "3.1.3"
resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18"
integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==
Expand Down Expand Up @@ -15769,6 +15769,13 @@ react-dev-utils@^11.0.4:
strip-ansi "6.0.0"
text-table "0.2.0"

[email protected]:
version "4.4.0"
resolved "https://registry.yarnpkg.com/react-devtools-inline/-/react-devtools-inline-4.4.0.tgz#e032a6eb17a9977b682306f84b46e683adf4bf68"
integrity sha512-ES0GolSrKO8wsKbsEkVeiR/ZAaHQTY4zDh1UW8DImVmm8oaGLl3ijJDvSGe+qDRKPZdPRnDtWWnSvvrgxXdThQ==
dependencies:
es6-symbol "^3"

react-docgen-typescript@^2.0.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/react-docgen-typescript/-/react-docgen-typescript-2.1.1.tgz#c9f9ccb1fa67e0f4caf3b12f2a07512a201c2dcf"
Expand Down