From 20a899337343e35a8d8e0b4e00c42e7190625747 Mon Sep 17 00:00:00 2001 From: Danilo Woznica Date: Wed, 25 May 2022 14:24:24 +0100 Subject: [PATCH] feat(react/client): BREAKING CHANGES (#375) --- .eslintignore | 4 +- .github/workflows/checks.yml | 144 +- .github/workflows/release-canary.yml | 3 +- .github/workflows/release.yml | 5 +- .gitignore | 4 - .nvmrc | 2 +- README.md | 11 +- cypress/integration/CodeMirror.spec.js | 6 +- cypress/integration/Sandpack.spec.js | 30 +- cypress/integration/Templates.spec.js | 29 + cypress/snapshots.js | 43 +- examples/cra/.gitignore | 23 + examples/cra/package.json | 40 + examples/cra/public/favicon.ico | Bin 0 -> 3870 bytes examples/cra/public/index.html | 43 + examples/cra/public/logo192.png | Bin 0 -> 5347 bytes examples/cra/public/logo512.png | Bin 0 -> 9664 bytes examples/cra/public/manifest.json | 25 + examples/cra/src/App.tsx | 15 + examples/cra/src/index.tsx | 10 + examples/cra/tsconfig.json | 26 + examples/gatsby/.gitignore | 3 + examples/gatsby/gatsby-config.js | 7 + examples/gatsby/gatsby-ssr.js | 13 + examples/gatsby/package.json | 24 + examples/gatsby/src/pages/index.js | 16 + examples/nextjs/next-env.d.ts | 5 + examples/nextjs/package.json | 22 + examples/nextjs/pages/_document.tsx | 22 + examples/nextjs/pages/index.tsx | 15 + examples/nextjs/tsconfig.json | 20 + package.json | 9 +- .../docusaurus/src/theme/CodeBlock/index.jsx | 61 +- .../docusaurus/src/theme/CodeBlock/style.css | 4 +- sandpack-client/package.json | 3 +- sandpack-client/src/client.ts | 12 +- sandpack-client/src/iframe-protocol.ts | 2 +- sandpack-client/src/types.ts | 2 +- sandpack-client/src/utils.test.ts | 100 + sandpack-client/src/utils.ts | 62 +- sandpack-client/tsconfig.json | 2 +- sandpack-react/.storybook/preview.js | 2 - sandpack-react/README.md | 1 - sandpack-react/package.json | 14 +- sandpack-react/src/Issues.stories.tsx | 11 +- sandpack-react/src/Playground.stories.tsx | 19 +- sandpack-react/src/common/ErrorOverlay.tsx | 32 +- sandpack-react/src/common/Layout.tsx | 85 +- sandpack-react/src/common/Loading.tsx | 103 + sandpack-react/src/common/LoadingOverlay.tsx | 65 +- .../OpenInCodeSandboxButton.tsx | 18 +- .../UnstyledOpenInCodeSandboxButton.tsx | 7 +- sandpack-react/src/common/RunButton.tsx | 35 +- sandpack-react/src/common/Stack.tsx | 29 +- .../CodeEditor/CodeEditor.stories.tsx | 40 +- .../src/components/CodeEditor/CodeMirror.tsx | 104 +- .../useSyntaxHighlight.test.tsx.snap | 1859 ++ .../src/components/CodeEditor/index.tsx | 33 +- .../components/CodeEditor/languages-mocks.ts | 93 + .../src/components/CodeEditor/styles.ts | 59 + .../components/CodeEditor/useGeneratedId.ts | 10 +- .../CodeEditor/useSyntaxHighlight.test.tsx | 31 + .../CodeEditor/useSyntaxHighlight.ts | 44 + .../src/components/CodeEditor/utils.ts | 105 +- .../CodeViewer/CodeViewer.stories.tsx | 8 +- .../src/components/CodeViewer/index.tsx | 37 +- .../src/components/FileExplorer/Directory.tsx | 12 +- .../src/components/FileExplorer/File.tsx | 73 +- .../FileExplorer/FileExplorer.stories.tsx | 45 +- .../components/FileExplorer/ModuleList.tsx | 12 +- .../src/components/FileExplorer/index.tsx | 18 +- .../components/FileTabs/FileTabs.stories.tsx | 30 +- .../src/components/FileTabs/FileTabs.test.tsx | 16 +- .../src/components/FileTabs/index.tsx | 82 +- .../Navigator/Navigator.stories.tsx | 4 +- .../src/components/Navigator/index.tsx | 73 +- .../components/Preview/Preview.stories.tsx | 24 +- .../src/components/Preview/RefreshButton.tsx | 16 +- .../src/components/Preview/index.tsx | 122 +- .../ReactDevTools/ReactDevTool.stories.tsx | 6 +- .../src/components/ReactDevTools/index.tsx | 22 +- .../TranspiledCodeView.stories.tsx | 10 +- .../src/components/TranspiledCode/index.tsx | 39 +- sandpack-react/src/components/index.ts | 1 + .../src/contexts/sandpackContext.tsx | 265 +- sandpack-react/src/contexts/themeContext.tsx | 59 +- sandpack-react/src/hooks/useActiveCode.ts | 4 +- .../src/hooks/useLoadingOverlayState.ts | 6 + sandpack-react/src/hooks/useSandpack.ts | 9 +- sandpack-react/src/hooks/useTranspiledCode.ts | 4 +- sandpack-react/src/icons/index.tsx | 61 +- sandpack-react/src/index.ts | 16 +- .../src/presets/CustomSandpack.stories.tsx | 49 +- .../src/presets/Sandpack.stories.tsx | 10 +- sandpack-react/src/presets/Sandpack.test.tsx | 136 + sandpack-react/src/presets/Sandpack.tsx | 160 +- sandpack-react/src/presets/SandpackRunner.tsx | 65 - sandpack-react/src/presets/index.ts | 1 - .../styles/__snapshots__/styles.test.ts.snap | 231 + sandpack-react/src/styles/index.css | 495 - sandpack-react/src/styles/index.ts | 117 + sandpack-react/src/styles/shared.ts | 82 + sandpack-react/src/styles/styles.test.ts | 97 + .../src/templates/Templates.stories.tsx | 8 +- sandpack-react/src/templates/angular.ts | 71 +- sandpack-react/src/templates/index.tsx | 19 +- .../src/templates/react-typescript.ts | 45 +- sandpack-react/src/templates/react.ts | 20 +- sandpack-react/src/templates/solid.ts | 9 +- sandpack-react/src/templates/svelte.ts | 11 +- .../src/templates/vanilla-typescript.ts | 9 +- sandpack-react/src/templates/vanilla.ts | 9 +- sandpack-react/src/templates/vue.ts | 9 +- sandpack-react/src/templates/vue3.ts | 9 +- .../src/themes/ExternalThemes.stories.tsx | 11 + sandpack-react/src/themes/index.ts | 406 +- sandpack-react/src/types.ts | 631 +- sandpack-react/src/utils/classNames.ts | 4 + sandpack-react/src/utils/domUtils.ts | 27 - .../src/utils/sandpackUtils.test.ts | 376 +- sandpack-react/src/utils/sandpackUtils.ts | 176 +- sandpack-react/src/utils/stringUtils.ts | 9 - sandpack-react/tsconfig.json | 7 +- sandpack-themes/README.md | 17 + sandpack-themes/build.js | 39 + sandpack-themes/package.json | 32 + sandpack-themes/src/aquaBlue.ts | 37 + sandpack-themes/src/githubLight.ts | 39 + sandpack-themes/src/index.ts | 5 + sandpack-themes/src/monokaiPro.ts | 36 + sandpack-themes/src/nightOwl.ts | 33 + sandpack-themes/src/sandpackDark.ts | 36 + sandpack-themes/src/types.ts | 59 + sandpack-themes/tsconfig.json | 18 + scripts/sizebot/createCurrentSizes.js | 14 +- website/docs/.gitignore | 5 + .../docs/docs/advanced-usage/components.md | 7 +- website/docs/docs/advanced-usage/hooks.md | 32 +- website/docs/docs/advanced-usage/provider.md | 1 - website/docs/docs/faq.md | 16 +- .../docs/getting-started/custom-content.md | 13 +- .../docs/docs/getting-started/custom-ui.md | 96 +- website/docs/docs/getting-started/install.md | 1 - website/docs/docs/getting-started/ssr.md | 73 + website/docs/docs/getting-started/themes.md | 59 + website/docs/docs/guides/_category_.json | 2 +- .../docs/guides/integrate-monaco-editor.md | 2 +- website/docs/docs/releases/_category_.json | 4 + website/docs/docs/releases/v1.md | 237 + website/docs/docusaurus.config.js | 29 +- website/docs/package.json | 15 +- website/docs/src/CustomSandpack.tsx | 5 +- website/docs/src/NestedSandpack.tsx | 6 +- website/docs/src/examples/Decorators.js | 6 +- website/docs/src/scss/_code.scss | 10 +- website/docs/src/scss/_menu.scss | 12 +- website/docs/src/scss/sandpack-theme.js | 34 - website/docs/static/img/v1-ts.mp4 | Bin 0 -> 195786 bytes .../AdvancedUsage/ExampleIllustration.tsx | 7 +- .../landing/components/Features/Features.tsx | 1 + website/landing/components/Hero/Hero.tsx | 6 +- .../Hero/HeroDesktop/HeroDesktop.tsx | 3 +- website/landing/components/Intro/Examples.tsx | 4 +- .../components/Intro/SandpackExample.tsx | 4 +- .../components/Intro/Sections/Custom.tsx | 32 +- .../components/Intro/Sections/Editor.tsx | 3 +- .../components/Intro/Sections/Layout.tsx | 13 +- .../Intro/Sections/LayoutContext.tsx | 5 +- .../components/Intro/Sections/Template.tsx | 39 +- .../components/Intro/Sections/Theme.tsx | 18 +- .../components/Intro/Sections/common.tsx | 4 +- .../components/common/ClipboardProvider.tsx | 4 +- .../landing/components/common/CodeBlock.tsx | 24 +- .../landing/components/common/Resources.tsx | 2 +- .../components/common/SandpackPreview.tsx | 12 +- website/landing/components/common/Section.tsx | 3 - website/landing/package.json | 9 +- website/landing/pages/_app.tsx | 9 +- website/landing/pages/_document.tsx | 5 + website/landing/styles/typography.ts | 1 - website/theme/components/picker/index.js | 56 +- website/theme/lib/codeExamples.js | 33 - website/theme/lib/generateTheme.js | 24 +- website/theme/lib/themeGallery.js | 224 - website/theme/package.json | 9 +- website/theme/pages/_app.js | 1 - website/theme/pages/index.js | 126 +- website/theme/public/codesandbox-logo.svg | 28 +- website/theme/styles/globals.scss | 2 +- yarn.lock | 14220 ++++++++++------ 190 files changed, 16002 insertions(+), 8008 deletions(-) create mode 100644 cypress/integration/Templates.spec.js create mode 100644 examples/cra/.gitignore create mode 100644 examples/cra/package.json create mode 100644 examples/cra/public/favicon.ico create mode 100644 examples/cra/public/index.html create mode 100644 examples/cra/public/logo192.png create mode 100644 examples/cra/public/logo512.png create mode 100644 examples/cra/public/manifest.json create mode 100644 examples/cra/src/App.tsx create mode 100644 examples/cra/src/index.tsx create mode 100644 examples/cra/tsconfig.json create mode 100644 examples/gatsby/.gitignore create mode 100644 examples/gatsby/gatsby-config.js create mode 100644 examples/gatsby/gatsby-ssr.js create mode 100644 examples/gatsby/package.json create mode 100644 examples/gatsby/src/pages/index.js create mode 100644 examples/nextjs/next-env.d.ts create mode 100644 examples/nextjs/package.json create mode 100644 examples/nextjs/pages/_document.tsx create mode 100644 examples/nextjs/pages/index.tsx create mode 100644 examples/nextjs/tsconfig.json create mode 100644 sandpack-client/src/utils.test.ts create mode 100644 sandpack-react/src/common/Loading.tsx create mode 100644 sandpack-react/src/components/CodeEditor/__snapshots__/useSyntaxHighlight.test.tsx.snap create mode 100644 sandpack-react/src/components/CodeEditor/languages-mocks.ts create mode 100644 sandpack-react/src/components/CodeEditor/styles.ts create mode 100644 sandpack-react/src/components/CodeEditor/useSyntaxHighlight.test.tsx create mode 100644 sandpack-react/src/components/CodeEditor/useSyntaxHighlight.ts create mode 100644 sandpack-react/src/presets/Sandpack.test.tsx delete mode 100644 sandpack-react/src/presets/SandpackRunner.tsx create mode 100644 sandpack-react/src/styles/__snapshots__/styles.test.ts.snap delete mode 100644 sandpack-react/src/styles/index.css create mode 100644 sandpack-react/src/styles/index.ts create mode 100644 sandpack-react/src/styles/shared.ts create mode 100644 sandpack-react/src/styles/styles.test.ts create mode 100644 sandpack-react/src/themes/ExternalThemes.stories.tsx create mode 100644 sandpack-react/src/utils/classNames.ts delete mode 100644 sandpack-react/src/utils/domUtils.ts create mode 100644 sandpack-themes/README.md create mode 100644 sandpack-themes/build.js create mode 100644 sandpack-themes/package.json create mode 100644 sandpack-themes/src/aquaBlue.ts create mode 100644 sandpack-themes/src/githubLight.ts create mode 100644 sandpack-themes/src/index.ts create mode 100644 sandpack-themes/src/monokaiPro.ts create mode 100644 sandpack-themes/src/nightOwl.ts create mode 100644 sandpack-themes/src/sandpackDark.ts create mode 100644 sandpack-themes/src/types.ts create mode 100644 sandpack-themes/tsconfig.json create mode 100644 website/docs/docs/getting-started/ssr.md create mode 100644 website/docs/docs/getting-started/themes.md create mode 100644 website/docs/docs/releases/_category_.json create mode 100644 website/docs/docs/releases/v1.md delete mode 100644 website/docs/src/scss/sandpack-theme.js create mode 100644 website/docs/static/img/v1-ts.mp4 delete mode 100644 website/theme/lib/codeExamples.js delete mode 100644 website/theme/lib/themeGallery.js diff --git a/.eslintignore b/.eslintignore index 621e5a5f9..4bce95fdf 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,4 +1,6 @@ dist/ esm/ sandpack/ -file-resolver-protocol.ts \ No newline at end of file +file-resolver-protocol.ts +examples/ +cypress/ \ No newline at end of file diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 1d12d4c90..41fb1edc5 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -1,9 +1,9 @@ name: CI -on: [pull_request, push] +on: [pull_request] jobs: install: - name: Install + name: Install & build runs-on: ubuntu-latest timeout-minutes: 10 steps: @@ -15,63 +15,43 @@ jobs: with: node-version-file: .nvmrc - - name: Setup | Cache - uses: c-hive/gha-yarn-cache@v2 - - - name: Setup | Install dependencies - run: yarn install --frozen-lockfile - - name: Setup | Cache node_modules uses: actions/cache@v3 - id: cache-node-modules with: path: | node_modules packages/*/node_modules key: modules-${{ hashFiles('yarn.lock') }} - - build: - name: Build - runs-on: ubuntu-18.04 - timeout-minutes: 10 - needs: install - steps: - - name: Setup | Checkout - uses: actions/checkout@v1 - - - name: Setup | Node.js - uses: actions/setup-node@v2 - with: - node-version-file: .nvmrc - - - name: Setup | Cache - uses: c-hive/gha-yarn-cache@v2 - name: Setup | Install dependencies run: yarn install --frozen-lockfile - name: Build run: yarn run build - - - name: Cache react build - uses: actions/cache@v3 + + - name: Cache | react build + uses: actions/upload-artifact@v2 with: path: sandpack-react/dist - key: sandpack-react-${{ github.run_id }} - restore-keys: sandpack-react- - - - name: Cache client build - uses: actions/cache@v3 + name: sandpack-react-${{ github.sha }} + + - name: Cache | client build + uses: actions/upload-artifact@v2 with: path: sandpack-client/dist - key: sandpack-client-${{ github.run_id }} - restore-keys: sandpack-client- - + name: sandpack-client-${{ github.sha }} + + - name: Cache | theme build + uses: actions/upload-artifact@v2 + with: + path: sandpack-themes/dist + name: sandpack-themes-${{ github.sha }} + sizebot: name: Sizebot runs-on: ubuntu-latest timeout-minutes: 10 - needs: [install, build] + needs: install steps: - name: Setup | Checkout uses: actions/checkout@v1 @@ -80,7 +60,7 @@ jobs: uses: actions/setup-node@v2 with: node-version-file: .nvmrc - + - name: Setup | Cache node_modules uses: actions/cache@v3 with: @@ -88,29 +68,35 @@ jobs: node_modules packages/*/node_modules key: modules-${{ hashFiles('yarn.lock') }} - + - name: Setup | Restore react build - uses: actions/cache@v3 + uses: actions/download-artifact@v2 with: + name: sandpack-react-${{ github.sha }} path: sandpack-react/dist - key: sandpack-react-${{ github.run_id }} - + - name: Setup | Restore client build - uses: actions/cache@v3 + uses: actions/download-artifact@v2 with: + name: sandpack-client-${{ github.sha }} path: sandpack-client/dist - key: sandpack-client-${{ github.run_id }} + + - name: Setup | Restore themes build + uses: actions/download-artifact@v2 + with: + name: sandpack-themes-${{ github.sha }} + path: sandpack-themes/dist - name: Bot script run: node scripts/sizebot/index.js env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - + chromatic-deployment: name: Chromatic deployment runs-on: ubuntu-latest timeout-minutes: 10 - needs: [install, build] + needs: install steps: - name: Setup | Checkout uses: actions/checkout@v1 @@ -119,7 +105,7 @@ jobs: uses: actions/setup-node@v2 with: node-version-file: .nvmrc - + - name: Setup | Cache node_modules uses: actions/cache@v3 with: @@ -127,18 +113,24 @@ jobs: node_modules packages/*/node_modules key: modules-${{ hashFiles('yarn.lock') }} - + - name: Setup | Restore react build - uses: actions/cache@v3 + uses: actions/download-artifact@v2 with: + name: sandpack-react-${{ github.sha }} path: sandpack-react/dist - key: sandpack-react-${{ github.run_id }} - + - name: Setup | Restore client build - uses: actions/cache@v3 + uses: actions/download-artifact@v2 with: + name: sandpack-client-${{ github.sha }} path: sandpack-client/dist - key: sandpack-client-${{ github.run_id }} + + - name: Setup | Restore theme build + uses: actions/download-artifact@v2 + with: + name: sandpack-themes-${{ github.sha }} + path: sandpack-themes/dist - name: Publish to Chromatic uses: chromaui/action@v1 @@ -151,7 +143,7 @@ jobs: name: Integration tests runs-on: ubuntu-latest timeout-minutes: 10 - needs: [install, build] + needs: install steps: - name: Setup | Checkout uses: actions/checkout@v1 @@ -160,7 +152,7 @@ jobs: uses: actions/setup-node@v2 with: node-version-file: .nvmrc - + - name: Setup | Cache node_modules uses: actions/cache@v3 with: @@ -168,18 +160,24 @@ jobs: node_modules packages/*/node_modules key: modules-${{ hashFiles('yarn.lock') }} - + - name: Setup | Restore react build - uses: actions/cache@v3 + uses: actions/download-artifact@v2 with: + name: sandpack-react-${{ github.sha }} path: sandpack-react/dist - key: sandpack-react-${{ github.run_id }} - + - name: Setup | Restore client build - uses: actions/cache@v3 + uses: actions/download-artifact@v2 with: + name: sandpack-client-${{ github.sha }} path: sandpack-client/dist - key: sandpack-client-${{ github.run_id }} + + - name: Setup | Restore theme build + uses: actions/download-artifact@v2 + with: + name: sandpack-themes-${{ github.sha }} + path: sandpack-themes/dist - name: Cypress run uses: cypress-io/github-action@v2 @@ -191,7 +189,7 @@ jobs: name: Unit tests runs-on: ubuntu-latest timeout-minutes: 10 - needs: [install, build] + needs: install steps: - name: Setup | Checkout uses: actions/checkout@v1 @@ -200,7 +198,7 @@ jobs: uses: actions/setup-node@v2 with: node-version-file: .nvmrc - + - name: Setup | Cache node_modules uses: actions/cache@v3 with: @@ -208,18 +206,18 @@ jobs: node_modules packages/*/node_modules key: modules-${{ hashFiles('yarn.lock') }} - + - name: Setup | Restore react build - uses: actions/cache@v3 + uses: actions/download-artifact@v2 with: + name: sandpack-react-${{ github.sha }} path: sandpack-react/dist - key: sandpack-react-${{ github.run_id }} - + - name: Setup | Restore client build - uses: actions/cache@v3 + uses: actions/download-artifact@v2 with: + name: sandpack-client-${{ github.sha }} path: sandpack-client/dist - key: sandpack-client-${{ github.run_id }} - name: Test | Jest run: yarn run test @@ -228,7 +226,6 @@ jobs: name: Lint runs-on: ubuntu-latest timeout-minutes: 10 - needs: install steps: - name: Setup | Checkout uses: actions/checkout@v1 @@ -237,7 +234,7 @@ jobs: uses: actions/setup-node@v2 with: node-version-file: .nvmrc - + - name: Setup | Cache node_modules uses: actions/cache@v3 with: @@ -253,7 +250,6 @@ jobs: name: Format runs-on: ubuntu-18.04 timeout-minutes: 10 - needs: install steps: - name: Setup | Checkout uses: actions/checkout@v1 @@ -262,7 +258,7 @@ jobs: uses: actions/setup-node@v2 with: node-version-file: .nvmrc - + - name: Setup | Cache node_modules uses: actions/cache@v3 with: diff --git a/.github/workflows/release-canary.yml b/.github/workflows/release-canary.yml index 1632a4517..78f6ff9f3 100644 --- a/.github/workflows/release-canary.yml +++ b/.github/workflows/release-canary.yml @@ -60,7 +60,7 @@ jobs: - name: Setup | Node.js uses: actions/setup-node@v2 with: - node-version: "14.16.1" + node-version: "14.17.0" - name: Setup | Authenticate with Registry run: echo //registry.npmjs.org/:_authToken=${NPM_TOKEN} > .npmrc @@ -87,6 +87,7 @@ jobs: run: | yarn workspace @codesandbox/sandpack-client build:publish yarn workspace @codesandbox/sandpack-react build:publish + yarn workspace @codesandbox/sandpack-themes build:publish - name: Prepare | Lerna Version run: lerna version --conventional-commits --conventional-prerelease --yes diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8824d5690..abe3a8ab9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -59,7 +59,7 @@ jobs: - name: Setup | Node.js uses: actions/setup-node@v2 with: - node-version: "14.16.1" + node-version: "14.17.0" - name: Setup | Authenticate with Registry run: echo //registry.npmjs.org/:_authToken=${NPM_TOKEN} > .npmrc @@ -83,12 +83,13 @@ jobs: path: bundler - name: Prepare | Lerna Version - run: yarn lerna version --yes --no-private + run: yarn lerna version major --yes --no-private - name: Prepare | Build run: | yarn workspace @codesandbox/sandpack-client build:publish yarn workspace @codesandbox/sandpack-react build:publish + yarn workspace @codesandbox/sandpack-themes build:publish - name: Sizebot | Generate run: node scripts/sizebot/createCurrentSizes.js diff --git a/.gitignore b/.gitignore index 6ca1c676e..b3564f6b6 100644 --- a/.gitignore +++ b/.gitignore @@ -107,9 +107,5 @@ dist # Mac .DS_Store -# Autogenerate docs -website/docs/docs/api/client -website/docs/docs/api/react - cypress/videos cypress/screenshots \ No newline at end of file diff --git a/.nvmrc b/.nvmrc index ca3f1e5c8..c9d82507f 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v14 \ No newline at end of file +v14.17.0 \ No newline at end of file diff --git a/README.md b/README.md index 2cf14ed54..9c3282718 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Component toolkit for live running code editing experiences +Component toolkit for live running code editing experiences # Sandpack @@ -19,7 +19,6 @@ React components that give you the power of editable sandboxes that run in the b ```jsx import { Sandpack } from "@codesandbox/sandpack-react"; -import "@codesandbox/sandpack-react/dist/index.css"; ; ``` @@ -34,7 +33,7 @@ Start with the [Sandpack introduction](https://sandpack.codesandbox.io/docs) pag The documentation is divided into following sections: -- [Getting Started](https://sandpack.codesandbox.io/docs/getting-started/install) -- [Advanced Guides](https://sandpack.codesandbox.io/docs/advanced-usage/provider) -- [API reference](https://sandpack.codesandbox.io/docs/api/client) -- [Releases](https://sandpack.codesandbox.io/docs/releases) +- [Getting Started](https://sandpack.codesandbox.io/docs/getting-started/install) +- [Advanced Guides](https://sandpack.codesandbox.io/docs/advanced-usage/provider) +- [API reference](https://sandpack.codesandbox.io/docs/api/client) +- [Releases](https://sandpack.codesandbox.io/docs/releases) diff --git a/cypress/integration/CodeMirror.spec.js b/cypress/integration/CodeMirror.spec.js index e5dd02c43..a88085c5a 100644 --- a/cypress/integration/CodeMirror.spec.js +++ b/cypress/integration/CodeMirror.spec.js @@ -1,7 +1,7 @@ -describe("CodeMirror", () => { - const languages = ["html", "javascript", "jsx", "css", "less", "vue"]; +import * as mocks from "../../sandpack-react/src/components/CodeEditor/languages-mocks"; - languages.forEach((lang, index) => { +describe("CodeMirror", () => { + Object.keys(mocks).forEach((lang, index) => { it(`Should render a "${lang}" component with a proper syntax-highlight`, () => { cy.viewport(600, 1000).visit( `/iframe.html?id=components-codemirror--${lang}` diff --git a/cypress/integration/Sandpack.spec.js b/cypress/integration/Sandpack.spec.js index c51a7ae1f..eb6fed9f9 100644 --- a/cypress/integration/Sandpack.spec.js +++ b/cypress/integration/Sandpack.spec.js @@ -1,37 +1,11 @@ -const getIframeDocument = () => { - return cy.get(".sp-preview-iframe").its("0.contentDocument").should("exist"); -}; - -const getIframeBody = () => { - return getIframeDocument() - .its("body") - .should("not.be.undefined") - .then(cy.wrap); -}; - const accessPage = (wait) => { // eslint-disable-next-line cypress/no-unnecessary-waiting cy.viewport(600, 1000) - .visit(`/iframe.html?id=presets-template--react`) - .wait(wait ? 2000 : 0); // warm-up sandbox + .visit(`/iframe.html?id=bug-reports-issues--file-tab`) + .wait(wait ? 10000 : 0); // warm-up sandbox }; describe("Sandpack", () => { - // TODO: To be fixed - // it(`Should render a React template and be able to interact with`, () => { - // accessPage(true); - // getIframeBody().find("h1").should("have.text", "Hello World"); - - // cy.get(".cm-content").type("{command}A").type("{backspace}"); - // cy.get(".cm-content").type(`export default function App() { - // return

Hello Sandpack

`); - - // getIframeBody() - // .wait(200) - // .find("p.target") - // .should("have.text", "Hello Sandpack"); - // }); - it(`Should be able to navigate between files`, () => { accessPage(); diff --git a/cypress/integration/Templates.spec.js b/cypress/integration/Templates.spec.js new file mode 100644 index 000000000..409a5eb15 --- /dev/null +++ b/cypress/integration/Templates.spec.js @@ -0,0 +1,29 @@ +import { SANDBOX_TEMPLATES } from "../../sandpack-react/src/templates"; + +const accessPage = (template) => { + const timeout = template === "solid" ? 20000 : 10000; + // eslint-disable-next-line cypress/no-unnecessary-waiting + cy.viewport(600, 1000) + .visit(`/iframe.html?id=presets-template--${template}`) + .wait(timeout); // warm-up sandbox +}; +const getIframeDocument = () => { + return cy.get(".sp-preview-iframe").its("0.contentDocument"); +}; + +const getIframeBody = () => { + return getIframeDocument() + .its("body") + .should("not.be.undefined") + .then(cy.wrap); +}; + +describe("Templates", () => { + Object.keys(SANDBOX_TEMPLATES).forEach((template) => { + it(`Should run the ${template} template`, () => { + accessPage(template); + + getIframeBody().find("h1").should("have.text", "Hello World"); + }); + }); +}); diff --git a/cypress/snapshots.js b/cypress/snapshots.js index c88711751..378705040 100644 --- a/cypress/snapshots.js +++ b/cypress/snapshots.js @@ -1,34 +1,31 @@ module.exports = { - "__version": "9.1.1", - "CodeMirror": { - "Should render a \"html\" component with a proper syntax-highlight": { - "1": "
\n

\n
<!DOCTYPE html>
\n
<html\n lang=\"en\">
\n
<head>
\n
<meta charset=\"UTF-8\">
\n
<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">
\n
<meta http-equiv=\"X-UA-Compatible\" content=\"ie=edge\">
\n
<title>HTML 5\n Boilerplate</title>
\n
<link rel=\"stylesheet\" href=\"style.css\">
\n
</head>
\n
<body>
\n
<script src=\"index.js\"></script>
\n
</body>
\n
</html>
\n

\n
" + __version: "9.1.1", + CodeMirror: { + 'Should render a "html" component with a proper syntax-highlight': { + 1: '
\n

\n
<!DOCTYPE html>
\n
<html lang="en">
\n
<head>
\n
<meta charset="UTF-8">
\n
<meta name="viewport" content="width=device-width,\n initial-scale=1.0">\n
\n
<meta http-equiv="X-UA-Compatible" content="ie=edge">
\n
<title>HTML 5 Boilerplate</title>
\n
<link rel="stylesheet" href="style.css">
\n
</head>
\n
<body>
\n
<script src="index.js"></script>
\n
</body>
\n
</html>
\n

\n
', }, - "Should render a \"javascript\" component with a proper syntax-highlight": { - "1": "
\n

\n
function foo(params) {
\n
return params
\n
}
\n

\n
const baz\n = (foo) => {
\n
return foo
\n
}
\n

\n
const array = [];
\n
const object = {};
\n
const regex = new Regex(//);
\n

\n
const expr = 'Papayas';
\n
switch (expr)\n {
\n
case 'Oranges':
\n
console.log('Oranges\n are $0.59 a pound.');
\n
break;\n
\n
case 'Mangoes':
\n
case 'Papayas':
\n
console.log('Mangoes\n and papayas are $2.79 a pound.');
\n
// expected output: \"Mangoes and\n papayas are $2.79 a pound.\"
\n
break;\n
\n
default:
\n
console.log(`Sorry, we\n are out of ${expr}.`);\n
\n
}
\n

\n
" + 'Should render a "js" component with a proper syntax-highlight': { + 1: '
\n

\n
function Greeting({ name }) {
\n
return <h1>Hello, {name}!</h1>;
\n
}
\n

\n
export default function App() {
\n
return (
\n
<div>
\n
<Greeting name="Divyesh" />
\n
<Greeting name="Sarah" />
\n
<Greeting name="Taylor" />
\n
</div>
\n
);
\n
}
\n

\n
', }, - "Should render a \"jsx\" component with a proper syntax-highlight": { - "1": "
\n

\n
function Greeting({ name }) {\n
\n
return <h1>Hello, {name}!</h1>;
\n
}
\n

\n
export default function App()\n {
\n
return (
\n
<div>
\n
<Greeting name=\"Divyesh\" />
\n
<Greeting name=\"Sarah\" />
\n
<Greeting name=\"Taylor\" />
\n
</div>
\n
);\n
\n
}
\n

\n
" + 'Should render a "jsx" component with a proper syntax-highlight': { + 1: '
\n

\n
function Greeting({ name }) {
\n
return <h1>Hello, {name}!</h1>;
\n
}
\n

\n
export default function App() {
\n
return (
\n
<div>
\n
<Greeting name="Divyesh" />
\n
<Greeting name="Sarah" />
\n
<Greeting name="Taylor" />
\n
</div>
\n
);
\n
}
\n

\n
', }, - "Should render a \"css\" component with a proper syntax-highlight": { - "1": "
\n

\n
body {\n
\n
background-color: lightblue;
\n
}
\n

\n
h1 {\n
\n
color:\n white;
\n
text-align: center;
\n
}
\n

\n
p {\n
\n
font-family: verdana;
\n
font-size: 20px;
\n
}
\n

\n
" + 'Should render a "css" component with a proper syntax-highlight': { + 1: '
\n

\n
body {
\n
background-color: lightblue;
\n
}
\n

\n
h1 {
\n
color: white;
\n
text-align: center;
\n
}
\n

\n
p {
\n
font-family: verdana;
\n
font-size: 20px;
\n
}
\n

\n
', }, - "Should render a \"less\" component with a proper syntax-highlight": { - "1": "
\n

\n
@width:\n 10px;
\n
@height:\n @width + 10px;
\n

\n
#header {
\n
width:\n @width;
\n
height:\n @height;
\n
}
\n

\n
" + 'Should render a "less" component with a proper syntax-highlight': { + 1: '
\n

\n
@width: 10px;
\n
@height: @width + 10px;
\n

\n
#header {\n
\n
width: @width;
\n
height: @height;
\n
}
\n

\n
', }, - "Should render a \"vue\" component with a proper syntax-highlight": { - "1": "
\n

\n
<template>
\n
<div\n class=\"column is-12\">
\n
<label class=\"label\" for=\"email\">Email</label>
\n
<p\n :class=\"{ 'control': true\n }\">
\n
<input v-validate=\"'required|email'\" :class=\"{'input': true, 'is-danger': errors.has('email') }\"\n name=\"email\" type=\"text\" placeholder=\"Email\">
\n
<span v-show=\"errors.has('email')\" class=\"help is-danger\">{{ errors.first('email') }}</span>
\n
</p>
\n
</div>
\n
</template>
\n

\n
<script>
\n
export default {
\n
name:\n 'basic-example'
\n
};\n
\n
</script>
\n

\n
" + 'Should render a "vue" component with a proper syntax-highlight': { + 1: '
\n

\n
<template>
\n
<div class="column is-12">
\n
<label class="label" for="email">Email</label>
\n
<p :class="{\n \'control\': true }">\n
\n
<input v-validate="\'required|email\'" :class="{\'input\': true, \'is-danger\': errors.has(\'email\')\n }" name="email" type="text" placeholder="Email">
\n
<span v-show="errors.has(\'email\')" class="help is-danger">{{ errors.first(\'email\') }}</span>
\n
</p>
\n
</div>
\n
</template>
\n

\n
<script>
\n
export default {
\n
name: \'basic-example\'
\n
};
\n
</script>
\n

\n
', }, "should render a decoration component properly": { - "1": "
\n
const people = [{
\n
id:\n 0,
\n
name:\n 'Creola Katherine Johnson',\n
\n
profession: 'mathematician',
\n
},\n {
\n
id:\n 1,
\n
name:\n 'Mario José Molina-Pasquel Henríquez',
\n
profession: 'chemist',
\n
}];
\n

\n
export default function List()\n {
\n
const [text,\n setText] = useState(\"\")
\n
const listItems = people.map(person =>
\n
<li>{person}</li>
\n
);\n
\n
return <ul>{listItems}</ul>;
\n
}
\n
" + 1: '
\n
const\n people = [{
\n
id: 0,
\n
name: \'Creola Katherine Johnson\',
\n
profession: \'mathematician\',
\n
}, {
\n
id: 1,
\n
name: \'Mario José Molina-Pasquel Henríquez\',
\n
profession: \'chemist\',
\n
}];
\n

\n
export default function List() {
\n
const [text, setText] = useState("")
\n
const listItems = people.map(person =>
\n
<li>{person}</li>
\n
);
\n
return <ul>{listItems}</ul>;
\n
}
\n
', }, - "should load the autocomplete CodeMirror extension": { - "1": "
\n
class name {
\n
constructor(params) {
\n
\n
}
\n
}
\n
" - } }, - "CodeViewer": { + CodeViewer: { "should not be able to cut the content": { - "1": "
\n
import \"./styles.css\";
\n

\n
document.getElementById(\"app\").innerHTML = `
\n
<h1>Hello\n Vanilla!</h1>
\n
<div>
\n
We use the same configuration as Parcel\n to bundle this sandbox, you can find more
\n
info about Parcel
\n
<a href=\"https://parceljs.org\"\n target=\"_blank\" rel=\"noopener noreferrer\">here</a>.
\n
</div>
\n
`;
\n

\n
" - } - } -} + 1: '
\n
import "./styles.css";
\n

\n
document.getElementById("app").innerHTML = `
\n
<h1>Hello\n World</h1>
\n
<div>
\n
We use the same\n configuration as Parcel to bundle this sandbox, you can find more\n
\n
info about Parcel \n
\n
<a\n href="https://parceljs.org" target="_blank" rel="noopener\n noreferrer">here</a>.
\n
</div>
\n
`;
\n

\n
', + }, + }, +}; diff --git a/examples/cra/.gitignore b/examples/cra/.gitignore new file mode 100644 index 000000000..4d29575de --- /dev/null +++ b/examples/cra/.gitignore @@ -0,0 +1,23 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# production +/build + +# misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* diff --git a/examples/cra/package.json b/examples/cra/package.json new file mode 100644 index 000000000..974792f61 --- /dev/null +++ b/examples/cra/package.json @@ -0,0 +1,40 @@ +{ + "name": "cra", + "version": "0.1.0", + "private": true, + "dependencies": { + "@codesandbox/sandpack-react": "*", + "@codesandbox/sandpack-themes": "*", + "@types/react": "^18.0.9", + "@types/react-dom": "^18.0.4", + "react": "^18.1.0", + "react-dom": "^18.1.0", + "react-scripts": "5.0.1", + "typescript": "^4.6.4" + }, + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build", + "serve": "react-scripts serve", + "test": "react-scripts test", + "eject": "react-scripts eject" + }, + "eslintConfig": { + "extends": [ + "react-app", + "react-app/jest" + ] + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + } +} diff --git a/examples/cra/public/favicon.ico b/examples/cra/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..a11777cc471a4344702741ab1c8a588998b1311a GIT binary patch literal 3870 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 baj7?x%VD!5Cxk2YbYLNVeiXvvpMCWYo=by@ literal 0 HcmV?d00001 diff --git a/examples/cra/public/index.html b/examples/cra/public/index.html new file mode 100644 index 000000000..aa069f27c --- /dev/null +++ b/examples/cra/public/index.html @@ -0,0 +1,43 @@ + + + + + + + + + + + + + React App + + + +
+ + + diff --git a/examples/cra/public/logo192.png b/examples/cra/public/logo192.png new file mode 100644 index 0000000000000000000000000000000000000000..fc44b0a3796c0e0a64c3d858ca038bd4570465d9 GIT binary patch literal 5347 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 b{|{}U^kRn2wo}j7|0ATu<;8xA7zX}7|B6mN literal 0 HcmV?d00001 diff --git a/examples/cra/public/manifest.json b/examples/cra/public/manifest.json new file mode 100644 index 000000000..080d6c77a --- /dev/null +++ b/examples/cra/public/manifest.json @@ -0,0 +1,25 @@ +{ + "short_name": "React App", + "name": "Create React App Sample", + "icons": [ + { + "src": "favicon.ico", + "sizes": "64x64 32x32 24x24 16x16", + "type": "image/x-icon" + }, + { + "src": "logo192.png", + "type": "image/png", + "sizes": "192x192" + }, + { + "src": "logo512.png", + "type": "image/png", + "sizes": "512x512" + } + ], + "start_url": ".", + "display": "standalone", + "theme_color": "#000000", + "background_color": "#ffffff" +} diff --git a/examples/cra/src/App.tsx b/examples/cra/src/App.tsx new file mode 100644 index 000000000..100cfdd5e --- /dev/null +++ b/examples/cra/src/App.tsx @@ -0,0 +1,15 @@ +import { Sandpack } from "@codesandbox/sandpack-react"; +import { githubLight, sandpackDark } from "@codesandbox/sandpack-themes"; + +const Home = () => { + return ( +
+ + + + +
+ ); +}; + +export default Home; diff --git a/examples/cra/src/index.tsx b/examples/cra/src/index.tsx new file mode 100644 index 000000000..b1ef1c04d --- /dev/null +++ b/examples/cra/src/index.tsx @@ -0,0 +1,10 @@ +import React from "react"; +import ReactDOM from "react-dom"; +import App from "./App"; + +ReactDOM.render( + + + , + document.getElementById("root") +); diff --git a/examples/cra/tsconfig.json b/examples/cra/tsconfig.json new file mode 100644 index 000000000..a273b0cfc --- /dev/null +++ b/examples/cra/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], + "allowJs": true, + "skipLibCheck": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noFallthroughCasesInSwitch": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx" + }, + "include": [ + "src" + ] +} diff --git a/examples/gatsby/.gitignore b/examples/gatsby/.gitignore new file mode 100644 index 000000000..557f97c6f --- /dev/null +++ b/examples/gatsby/.gitignore @@ -0,0 +1,3 @@ +node_modules/ +.cache/ +public diff --git a/examples/gatsby/gatsby-config.js b/examples/gatsby/gatsby-config.js new file mode 100644 index 000000000..dbec6c9f8 --- /dev/null +++ b/examples/gatsby/gatsby-config.js @@ -0,0 +1,7 @@ +module.exports = { + siteMetadata: { + siteUrl: "https://www.yourdomain.tld", + title: "gatsby", + }, + plugins: [], +}; diff --git a/examples/gatsby/gatsby-ssr.js b/examples/gatsby/gatsby-ssr.js new file mode 100644 index 000000000..c5a9a35c8 --- /dev/null +++ b/examples/gatsby/gatsby-ssr.js @@ -0,0 +1,13 @@ +import * as React from "react"; +import { getSandpackCssText } from "@codesandbox/sandpack-react"; + +export const onRenderBody = ({ setHeadComponents }) => { + setHeadComponents([ +
-

Hello {name}!

+

Hello {name}

`, }, "/index.js": { diff --git a/sandpack-react/src/templates/vanilla-typescript.ts b/sandpack-react/src/templates/vanilla-typescript.ts index fc2829a37..0e95ac3a6 100644 --- a/sandpack-react/src/templates/vanilla-typescript.ts +++ b/sandpack-react/src/templates/vanilla-typescript.ts @@ -1,6 +1,7 @@ -import type { SandboxTemplate } from "../types"; - -export const VANILLA_TYPESCRIPT_TEMPLATE: SandboxTemplate = { +/** + * @category Template + */ +export const VANILLA_TYPESCRIPT_TEMPLATE = { files: { "tsconfig.json": { code: `{ @@ -24,7 +25,7 @@ export const VANILLA_TYPESCRIPT_TEMPLATE: SandboxTemplate = { code: `import "./styles.css"; document.getElementById("app").innerHTML = \` -

Hello Vanilla!

+

Hello World

We use the same configuration as Parcel to bundle this sandbox, you can find more info about Parcel diff --git a/sandpack-react/src/templates/vanilla.ts b/sandpack-react/src/templates/vanilla.ts index 872c3f98a..ebce0dfa0 100644 --- a/sandpack-react/src/templates/vanilla.ts +++ b/sandpack-react/src/templates/vanilla.ts @@ -1,12 +1,13 @@ -import type { SandboxTemplate } from "../types"; - -export const VANILLA_TEMPLATE: SandboxTemplate = { +/** + * @category Template + */ +export const VANILLA_TEMPLATE = { files: { "/src/index.js": { code: `import "./styles.css"; document.getElementById("app").innerHTML = \` -

Hello Vanilla!

+

Hello World

We use the same configuration as Parcel to bundle this sandbox, you can find more info about Parcel diff --git a/sandpack-react/src/templates/vue.ts b/sandpack-react/src/templates/vue.ts index 18dcf3359..8e2d53f78 100644 --- a/sandpack-react/src/templates/vue.ts +++ b/sandpack-react/src/templates/vue.ts @@ -1,11 +1,12 @@ -import type { SandboxTemplate } from "../types"; - -export const VUE_TEMPLATE: SandboxTemplate = { +/** + * @category Template + */ +export const VUE_TEMPLATE = { files: { "/src/App.vue": { code: ` diff --git a/sandpack-react/src/templates/vue3.ts b/sandpack-react/src/templates/vue3.ts index a014f7026..9bf48836c 100644 --- a/sandpack-react/src/templates/vue3.ts +++ b/sandpack-react/src/templates/vue3.ts @@ -1,6 +1,7 @@ -import type { SandboxTemplate } from "../types"; - -export const VUE_TEMPLATE_3: SandboxTemplate = { +/** + * @category Template + */ +export const VUE_TEMPLATE_3 = { files: { "/src/App.vue": { code: `