+ (
+ showConsoleButton?: boolean,
+ editorHeight: CSSProperties["height"] = `var(--${THEME_PREFIX}-layout-height)`
+ ) =>
(ratio = 2): string | number | undefined => {
if (showConsoleButton) {
const height =
typeof editorHeight === "number" ? `${editorHeight}px` : editorHeight;
- return `calc(${
- height ?? `var(--${THEME_PREFIX}-layout-height)`
- } / ${ratio})`;
+ return `calc(${height} / ${ratio})`;
}
return editorHeight;
diff --git a/sandpack-react/src/styles/__snapshots__/styles.test.ts.snap b/sandpack-react/src/styles/__snapshots__/styles.test.ts.snap
index 03182c043..aabb5cd78 100644
--- a/sandpack-react/src/styles/__snapshots__/styles.test.ts.snap
+++ b/sandpack-react/src/styles/__snapshots__/styles.test.ts.snap
@@ -26,6 +26,7 @@ Object {
"size": "14px",
},
"layout": Object {
+ "headerHeight": "40px",
"height": "300px",
},
"space": Object {
diff --git a/sandpack-react/src/styles/index.ts b/sandpack-react/src/styles/index.ts
index d17fbb91a..f11e7a1dd 100644
--- a/sandpack-react/src/styles/index.ts
+++ b/sandpack-react/src/styles/index.ts
@@ -21,7 +21,7 @@ const defaultVariables = {
return { ...acc, [index + 1]: `${(index + 1) * 4}px` };
}, {}),
border: { radius: "4px" },
- layout: { height: "300px" },
+ layout: { height: "300px", headerHeight: "40px" },
transitions: { default: "150ms ease" },
zIndices: {
base: "1",
diff --git a/sandpack-react/src/styles/shared.ts b/sandpack-react/src/styles/shared.ts
index 29b247d36..c58822c4a 100644
--- a/sandpack-react/src/styles/shared.ts
+++ b/sandpack-react/src/styles/shared.ts
@@ -15,7 +15,6 @@ export const buttonClassName = css({
backgroundColor: "transparent",
transition: "color $default, background $default",
cursor: "pointer",
-
color: "$colors$clickable",
"&:disabled": { color: "$colors$disabled" },
@@ -37,14 +36,17 @@ export const buttonClassName = css({
},
});
-export const actionButtonClassName = css({
+export const roundedButtonClassName = css({
backgroundColor: "$colors$surface2",
borderRadius: "99999px",
- transition: "background $transitions$default, color $transitions$default",
- "&:hover": {
+ '&[data-active="true"]': {
+ color: "$colors$surface1",
+ background: "$colors$accent",
+ },
+
+ "&:hover:not(:disabled,[data-active='true'])": {
backgroundColor: "$colors$surface3",
- color: "$colors$hover",
},
});
diff --git a/sandpack-react/src/templates/Templates.stories.tsx b/sandpack-react/src/templates/Templates.stories.tsx
index 3792da0b1..d2487a6b1 100644
--- a/sandpack-react/src/templates/Templates.stories.tsx
+++ b/sandpack-react/src/templates/Templates.stories.tsx
@@ -10,9 +10,6 @@ const stories = storiesOf("presets/Template", module);
Object.keys(SANDBOX_TEMPLATES).forEach((template) =>
stories.add(template, () => (
-
+
))
);
diff --git a/sandpack-react/src/templates/angular.ts b/sandpack-react/src/templates/angular.ts
index d92f2df7c..06bb8716a 100644
--- a/sandpack-react/src/templates/angular.ts
+++ b/sandpack-react/src/templates/angular.ts
@@ -1,5 +1,5 @@
/**
- * @category Template
+ * @hidden
*/
export const ANGULAR_TEMPLATE = {
files: {
diff --git a/sandpack-react/src/templates/index.tsx b/sandpack-react/src/templates/index.tsx
index a9fd8dff4..526de8c34 100644
--- a/sandpack-react/src/templates/index.tsx
+++ b/sandpack-react/src/templates/index.tsx
@@ -3,6 +3,7 @@ import { REACT_TEMPLATE } from "./react";
import { REACT_TYPESCRIPT_TEMPLATE } from "./react-typescript";
import { SOLID_TEMPLATE } from "./solid";
import { SVELTE_TEMPLATE } from "./svelte";
+import { TEST_TYPESCRIPT_TEMPLATE } from "./tests-ts";
import { VANILLA_TEMPLATE } from "./vanilla";
import { VANILLA_TYPESCRIPT_TEMPLATE } from "./vanilla-typescript";
import { VUE_TEMPLATE } from "./vue";
@@ -12,6 +13,7 @@ export { REACT_TEMPLATE } from "./react";
export { REACT_TYPESCRIPT_TEMPLATE } from "./react-typescript";
export { SOLID_TEMPLATE } from "./solid";
export { SVELTE_TEMPLATE } from "./svelte";
+export { TEST_TYPESCRIPT_TEMPLATE } from "./tests-ts";
export { VANILLA_TEMPLATE } from "./vanilla";
export { VANILLA_TYPESCRIPT_TEMPLATE } from "./vanilla-typescript";
export { VUE_TEMPLATE } from "./vue";
@@ -30,4 +32,5 @@ export const SANDBOX_TEMPLATES = {
angular: ANGULAR_TEMPLATE,
svelte: SVELTE_TEMPLATE,
solid: SOLID_TEMPLATE,
+ "test-ts": TEST_TYPESCRIPT_TEMPLATE,
};
diff --git a/sandpack-react/src/templates/react-typescript.ts b/sandpack-react/src/templates/react-typescript.ts
index d87b2df50..40403bad2 100644
--- a/sandpack-react/src/templates/react-typescript.ts
+++ b/sandpack-react/src/templates/react-typescript.ts
@@ -1,5 +1,5 @@
/**
- * @category Template
+ * @hidden
*/
export const REACT_TYPESCRIPT_TEMPLATE = {
files: {
diff --git a/sandpack-react/src/templates/react.ts b/sandpack-react/src/templates/react.ts
index 590b0bf89..c4d762d62 100644
--- a/sandpack-react/src/templates/react.ts
+++ b/sandpack-react/src/templates/react.ts
@@ -1,5 +1,5 @@
/**
- * @category Template
+ * @hidden
*/
export const REACT_TEMPLATE = {
files: {
diff --git a/sandpack-react/src/templates/solid.ts b/sandpack-react/src/templates/solid.ts
index 7bbfdb9e8..45419dda7 100644
--- a/sandpack-react/src/templates/solid.ts
+++ b/sandpack-react/src/templates/solid.ts
@@ -1,5 +1,5 @@
/**
- * @category Template
+ * @hidden
*/
export const SOLID_TEMPLATE = {
files: {
diff --git a/sandpack-react/src/templates/svelte.ts b/sandpack-react/src/templates/svelte.ts
index f5b76cd2a..945a61e19 100644
--- a/sandpack-react/src/templates/svelte.ts
+++ b/sandpack-react/src/templates/svelte.ts
@@ -1,5 +1,5 @@
/**
- * @category Template
+ * @hidden
*/
export const SVELTE_TEMPLATE = {
environment: "svelte",
diff --git a/sandpack-react/src/templates/tests-ts.ts b/sandpack-react/src/templates/tests-ts.ts
new file mode 100644
index 000000000..cb1257a5a
--- /dev/null
+++ b/sandpack-react/src/templates/tests-ts.ts
@@ -0,0 +1,40 @@
+/**
+ * @hidden
+ */
+export const TEST_TYPESCRIPT_TEMPLATE = {
+ files: {
+ "tsconfig.json": {
+ code: `{
+ "include": [
+ "./**/*"
+ ],
+ "compilerOptions": {
+ "strict": true,
+ "esModuleInterop": true,
+ "lib": [ "dom", "es2015" ],
+ "jsx": "react-jsx"
+ }
+}`,
+ },
+ "/add.ts": {
+ code: `export const add = (a: number, b: number): number => a + b;`,
+ },
+ "/add.test.ts": {
+ code: `import { add } from './add';
+
+describe('add', () => {
+ test('Commutative Law of Addition', () => {
+ expect(add(1, 2)).toBe(add(2, 1));
+ });
+});`,
+ },
+ },
+ dependencies: {},
+ devDependencies: {
+ typescript: "^4.0.0",
+ },
+ entry: "/add.ts",
+ main: "/add.test.ts",
+ environment: "parcel",
+ mode: "tests",
+};
diff --git a/sandpack-react/src/templates/vanilla-typescript.ts b/sandpack-react/src/templates/vanilla-typescript.ts
index 0e95ac3a6..81a8916f8 100644
--- a/sandpack-react/src/templates/vanilla-typescript.ts
+++ b/sandpack-react/src/templates/vanilla-typescript.ts
@@ -1,5 +1,5 @@
/**
- * @category Template
+ * @hidden
*/
export const VANILLA_TYPESCRIPT_TEMPLATE = {
files: {
diff --git a/sandpack-react/src/templates/vanilla.ts b/sandpack-react/src/templates/vanilla.ts
index ebce0dfa0..3dc0ebcfd 100644
--- a/sandpack-react/src/templates/vanilla.ts
+++ b/sandpack-react/src/templates/vanilla.ts
@@ -1,5 +1,5 @@
/**
- * @category Template
+ * @hidden
*/
export const VANILLA_TEMPLATE = {
files: {
diff --git a/sandpack-react/src/templates/vue.ts b/sandpack-react/src/templates/vue.ts
index 8e2d53f78..ec8bc7955 100644
--- a/sandpack-react/src/templates/vue.ts
+++ b/sandpack-react/src/templates/vue.ts
@@ -1,5 +1,5 @@
/**
- * @category Template
+ * @hidden
*/
export const VUE_TEMPLATE = {
files: {
diff --git a/sandpack-react/src/templates/vue3.ts b/sandpack-react/src/templates/vue3.ts
index 9bf48836c..5533f7e35 100644
--- a/sandpack-react/src/templates/vue3.ts
+++ b/sandpack-react/src/templates/vue3.ts
@@ -1,5 +1,5 @@
/**
- * @category Template
+ * @hidden
*/
export const VUE_TEMPLATE_3 = {
files: {
diff --git a/sandpack-react/src/types.ts b/sandpack-react/src/types.ts
index a8a998671..e63aa1e03 100644
--- a/sandpack-react/src/types.ts
+++ b/sandpack-react/src/types.ts
@@ -235,6 +235,7 @@ export type SandpackPredefinedTemplate =
| "angular"
| "react"
| "react-ts"
+ | "test-ts"
| "vanilla"
| "vanilla-ts"
| "vue"
diff --git a/website/docs/docs/advanced-usage/components.md b/website/docs/docs/advanced-usage/components.md
index 52680a596..2ac17b631 100644
--- a/website/docs/docs/advanced-usage/components.md
+++ b/website/docs/docs/advanced-usage/components.md
@@ -2,7 +2,8 @@
sidebar_position: 2
---
-import { SandpackProvider, SandpackCodeEditor, SandpackCodeViewer, SandpackTranspiledCode, SandpackPreview, SandpackThemeProvider } from "@codesandbox/sandpack-react"
+import { Sandpack as DefaultSandpack, SandpackProvider, SandpackCodeEditor, SandpackCodeViewer, SandpackTranspiledCode, SandpackPreview, SandpackThemeProvider, SandpackTests } from "@codesandbox/sandpack-react"
+import { sandpackDark } from "@codesandbox/sandpack-themes";
import { Sandpack, SandpackLayout } from "../../src/CustomSandpack"
import SandpackDecorators from "../../src/examples/Decorators"
@@ -40,7 +41,7 @@ const CustomSandpack = () => (
);
```
-
+
@@ -61,7 +62,7 @@ You can easily swap the two components inside the `SandpackLayout` to get a diff
```
-
+
@@ -100,7 +101,7 @@ There's nothing stopping you from rendering multiple previews in the same `Provi
```
-
+
@@ -131,7 +132,7 @@ The `` component also allows you to add additional buttons to
```
-
+
```
-
+
{
This is especially useful to get the cursor's current position, add custom decorators, set the selection in a specific position, etc.
-## Code Viewer
+## Tests
-For situations when you strictly want to show some code and run it in the browser, you can use the `SandpackCodeViewer` component. It looks similar to the code editor, but it renders a read-only version of `codemirror`, so users will not be able to edit the code.
+The `SandpackTests` component renders a thin wrapper around [`Jest`](https://jestjs.io/) to run tests directly in the browser. This means you can run tests but additional configuration may not possible given the browser environment.
+
+:::info
+Any test files ending with `.test.js(x)`, `.spec.js(x)`, `.test.ts(x)` and `.spec.ts(x)` will automatically be run with Jest and the results shown in the `SandpackTests` component.
+:::
+
+### Usage
+
+There are two ways to run tests and check out the output:
+
+#### Sandpack Preset
+
+Using `test-ts` template preset, which contains an example test.
```jsx
-import {
- SandpackProvider,
- SandpackLayout,
- SandpackCodeEditor,
- SandpackCodeViewer,
- SandpackPreview
-} from "@codesandbox/sandpack-react";
+
+```
-const CustomSandpack = () => (
-
-
-
-
-
-
-)
+
+
+#### SandpackTests component
+
+Standalone and configurable component to run tests, which you can combine with `test-ts` template or supply custom files. For more details about its usage and implementation, check out the [API reference](/api/react/#sandpacktests).
+
+**Options**
+
+- `verbose`: Display individual test results with the test suite hierarchy.
+- `watchMode`: Watch files for changes and rerun all tests. Note if changing a test file then the current file will run on it's own.
+- `onComplete`: A callback that is invoked with the completed specs.
+
+```jsx
+
+
+
+
+
+
```
-
+
-
-
+
+
-### CodeMirror decorations
+### Extending expect
-This API provides a way to draw or style a piece of code in the editor content. You can implement it in the following ways:
+:::note
+Although not all configuration is supported, [extending expect](https://jestjs.io/docs/expect#expectextendmatchers) with custom / third party matchers is still possible.
+:::
-- Entire line: add `className` or elements attributes to an entire line;
-- Range: add `className` or elements attributes to a piece of content, given a `line`, `startColumn` and `endColumn`;
+Add the matchers either as a dependency or as a file and then import the matchers into your tests and invoke `expect.extend` with your matchers.
+
+```jsx
+const extendedTest = `
+import * as matchers from 'jest-extended';
+import { add } from './add';
+
+expect.extend(matchers);
+
+describe('jest-extended matchers are supported', () => {
+ test('adding two positive integers yields a positive integer', () => {
+ expect(add(1, 2)).toBePositive();
+ });
+});
+`;
+
+
+
+
+
+
+;
+```
+
+
+ {
+ test('adding two positive integers yields a positive integer', () => {
+ expect(add(1, 2)).toBePositive();
+ });
+});
+`,
+ }}
+>
+
+
+
+
+
-
## Console
@@ -345,7 +418,7 @@ This API provides a way to draw or style a piece of code in the editor content.
Sandpack runs the console directly into the iframe. As a result, all console messages pass through the Sandpack protocol, where you can attach a listener to these messages in your own component or use the proper Sandpack React hook to consume them.
-#### Usage
+### Usage
There are three ways to print the logs:
- [``](/api/react/interfaces/SandpackOptions#showconsole): shows a panel right after the `SandpackPreview`;
@@ -375,7 +448,7 @@ document.getElementById("app").innerHTML = \`
options={{ showConsole: true, showConsoleButton: true }}
/>
-#### Limitation
+### Limitation
Considering that `SandpackConsole` is meant to be a light version of a browser console, there are a few limitations in its implementation in order to keep it modular and light:
- It needs to have a Sandpack client running (iframe) to execute the logs.
@@ -384,6 +457,44 @@ Considering that `SandpackConsole` is meant to be a light version of a browser c
However, if you need to support more advanced cases, [`useSandpackConsole`](/api/react/#usesandpackconsole) hook is compatible with [console-feed](https://www.npmjs.com/package/console-feed), which provides a closer browser-console experience without any of the limitations mentioned above.
+## Code Viewer
+
+For situations when you strictly want to show some code and run it in the browser, you can use the `SandpackCodeViewer` component. It looks similar to the code editor, but it renders a read-only version of `codemirror`, so users will not be able to edit the code.
+
+```jsx
+import {
+ SandpackProvider,
+ SandpackLayout,
+ SandpackCodeEditor,
+ SandpackCodeViewer,
+ SandpackPreview
+} from "@codesandbox/sandpack-react";
+
+const CustomSandpack = () => (
+
+
+
+
+
+
+)
+```
+
+
+
+
+
+
+
+
+### CodeMirror decorations
+
+This API provides a way to draw or style a piece of code in the editor content. You can implement it in the following ways:
+
+- Entire line: add `className` or elements attributes to an entire line;
+- Range: add `className` or elements attributes to a piece of content, given a `line`, `startColumn` and `endColumn`;
+
+
## ReactDevTools
@@ -474,7 +585,7 @@ const CustomSandpack = () => (
);
```
-
+
diff --git a/website/docs/docs/advanced-usage/hooks.md b/website/docs/docs/advanced-usage/hooks.md
index 1b14b0e88..cdefd1299 100644
--- a/website/docs/docs/advanced-usage/hooks.md
+++ b/website/docs/docs/advanced-usage/hooks.md
@@ -193,6 +193,24 @@ const { logs, reset } = useSandpackConsole();
[Check the API reference for more details](/api/react/#usesandpackconsole)
+## useSandpackClient
+
+It registers a new sandpack client and returns its instance, listeners, and dispatch function. Using it when creating a custom component to interact directly with the client is recommended. For other cases, use `useSandpack` instead.
+
+[Check the API reference for more details](/api/react/#usesandpackclient)
+
+## useSandpackTheme
+
+It exposes the `theme` object configured on `SandpackContext` and contains an `id` to ensure uniqueness for custom themes. This `theme` object is responsible for distributing all the style configurations for the component thee.
+
+[Check the API reference for more details](/api/react/#usesandpacktheme)
+
+## useTranspiledCode
+
+It returns the transpile module from the bundler, the same one evaluated inside it.
+
+[Check the API reference for more details](/api/react/#usetranspiledcode)
+
:::success Congrats!
You can now build your own sandpack-aware components on top of the sandpack custom hooks. The final piece of the puzzle is to understand the `sandpack-client`, the framework agnostic library that we use to manage the access to the bundler.
-:::
\ No newline at end of file
+:::
diff --git a/website/docs/docs/intro.md b/website/docs/docs/intro.md
index d227c8dc1..ed90ada54 100644
--- a/website/docs/docs/intro.md
+++ b/website/docs/docs/intro.md
@@ -25,14 +25,16 @@ deeper into our ecosystem.
+
+
-
-
+
+
### Live coding environment in minutes
```js sandpack
diff --git a/yarn.lock b/yarn.lock
index e442b7e19..ecebd34f7 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -9975,6 +9975,11 @@ clean-css@^5.1.5, clean-css@^5.2.2, clean-css@^5.3.0:
dependencies:
source-map "~0.6.0"
+clean-set@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/clean-set/-/clean-set-1.1.2.tgz#76d8bf238c3e27827bfa73073ecdfdc767187070"
+ integrity sha512-cA8uCj0qSoG9e0kevyOWXwPaELRPVg5Pxp6WskLMwerx257Zfnh8Nl0JBH59d7wQzij2CK7qEfJQK3RjuKKIug==
+
clean-stack@^2.0.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b"