From a4afdc7153a4d14da34d8de5d906a829fb52360f Mon Sep 17 00:00:00 2001 From: naporin0624 Date: Fri, 9 Feb 2024 17:10:47 +0900 Subject: [PATCH 01/79] chore(docs): fix glob pattern jest --- docs/snippets/common/portable-stories-jest-snapshot-test.js.mdx | 2 +- docs/snippets/common/portable-stories-jest-snapshot-test.ts.mdx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/snippets/common/portable-stories-jest-snapshot-test.js.mdx b/docs/snippets/common/portable-stories-jest-snapshot-test.js.mdx index 8a6f022a9492..4078691b055d 100644 --- a/docs/snippets/common/portable-stories-jest-snapshot-test.js.mdx +++ b/docs/snippets/common/portable-stories-jest-snapshot-test.js.mdx @@ -25,7 +25,7 @@ const compose = (entry) => { function getAllStoryFiles() { // Place the glob you want to match your stories files const storyFiles = glob.sync( - path.join(__dirname, 'stories/**/*.(stories|story).@(js|jsx|mjs|ts|tsx)'), + path.join(__dirname, 'stories/**/*.{stories,story}.{js,jsx,mjs,ts,tsx}'), ); return storyFiles.map((filePath) => { diff --git a/docs/snippets/common/portable-stories-jest-snapshot-test.ts.mdx b/docs/snippets/common/portable-stories-jest-snapshot-test.ts.mdx index 45bcd3d4f7f1..07bb7a277c60 100644 --- a/docs/snippets/common/portable-stories-jest-snapshot-test.ts.mdx +++ b/docs/snippets/common/portable-stories-jest-snapshot-test.ts.mdx @@ -33,7 +33,7 @@ const compose = (entry: StoryFile): ReturnType> function getAllStoryFiles() { // Place the glob you want to match your stories files const storyFiles = glob.sync( - path.join(__dirname, 'stories/**/*.(stories|story).@(js|jsx|mjs|ts|tsx)'), + path.join(__dirname, 'stories/**/*.{stories,story}.{js,jsx,mjs,ts,tsx}'), ); return storyFiles.map((filePath) => { From 11a848414e651bf44bce6abbf3c15d793cf6179b Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Fri, 9 Feb 2024 23:06:36 +0100 Subject: [PATCH 02/79] consolidate generate-sandboxes workflows into a single workflow and composite action --- .../generate-sandboxes-composite-action.yml | 58 ++++++++++++++++++ .github/workflows/generate-sandboxes-main.yml | 60 ------------------- .github/workflows/generate-sandboxes.yml | 34 +++++++++++ 3 files changed, 92 insertions(+), 60 deletions(-) create mode 100644 .github/actions/generate-sandboxes-composite-action.yml delete mode 100644 .github/workflows/generate-sandboxes-main.yml create mode 100644 .github/workflows/generate-sandboxes.yml diff --git a/.github/actions/generate-sandboxes-composite-action.yml b/.github/actions/generate-sandboxes-composite-action.yml new file mode 100644 index 000000000000..d47166c73ec4 --- /dev/null +++ b/.github/actions/generate-sandboxes-composite-action.yml @@ -0,0 +1,58 @@ +name: Generate and push sandboxes action +description: This is a composite action that generates sandboxes and pushes them to the storybookjs/sandboxes repository + +inputs: + destination-branch: + description: The destination branch to generate sandboxes to in the storybookjs/sandboxes repository + required: true + +defaults: + run: + shell: bash + working-directory: ./code + +runs: + using: "composite" + steps: + - uses: actions/setup-node@v3 + with: + node-version-file: ".nvmrc" + + - name: Setup git user + run: | + git config --global user.name "storybook-bot" + git config --global user.email "32066757+storybook-bot@users.noreply.github.com" + + - name: Install dependencies + working-directory: ./scripts + env: + YARN_ENABLE_IMMUTABLE_INSTALLS: false + run: node --experimental-modules ./check-dependencies.js + + - name: Compile Storybook libraries + run: yarn task --task compile --start-from=auto --no-link + + - name: Publish to local registry + run: yarn local-registry --publish + + - name: Run local registry + run: yarn local-registry --open & + + - name: Wait for registry + run: yarn wait-on tcp:127.0.0.1:6001 + + - name: Generate + env: + CLEANUP_SANDBOX_NODE_MODULES: true + run: yarn generate-sandboxes --local-registry + + - name: Publish + run: yarn publish-sandboxes --remote=https://storybook-bot:${{ secrets.PAT_STORYBOOK_BOT}}@github.com/storybookjs/sandboxes.git --push --branch=${{ inputs.destination-branch }} + + - name: The job has failed + if: ${{ failure() || cancelled() }} + env: + DISCORD_WEBHOOK: ${{ secrets.DISCORD_MONITORING_URL }} + uses: Ilshidur/action-discord@master + with: + args: "The generation of sandboxes in the **${{ inputs.destination-branch }}** branch has failed. [View Run](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})" diff --git a/.github/workflows/generate-sandboxes-main.yml b/.github/workflows/generate-sandboxes-main.yml deleted file mode 100644 index cc17376c57de..000000000000 --- a/.github/workflows/generate-sandboxes-main.yml +++ /dev/null @@ -1,60 +0,0 @@ -name: Generate and push sandboxes (main) - -on: - schedule: - - cron: '2 2 */1 * *' - workflow_dispatch: - # To test fixes on push rather than wait for the scheduling, do the following: - # 1. Uncomment the lines below and add your branch. - # push: - # branches: - # - - # 2. change the "ref" value to in the actions/checkout step below. - # 3. πŸ‘‰ DON'T FORGET TO UNDO THE VALUES BACK TO `main` BEFORE YOU MERGE YOUR CHANGES! - -jobs: - generate: - runs-on: ubuntu-latest - env: - YARN_ENABLE_IMMUTABLE_INSTALLS: false - CLEANUP_SANDBOX_NODE_MODULES: true - steps: - - uses: actions/checkout@v3 - with: - ref: main - - uses: actions/setup-node@v3 - with: - node-version-file: '.nvmrc' - - name: Setup git user - run: | - git config --global user.name "Storybook Bot" - git config --global user.email "bot@storybook.js.org" - - name: Install dependencies - run: | - cd ./scripts - node --experimental-modules ./check-dependencies.js - cd .. - - name: Compile Storybook libraries - run: yarn task --task compile --start-from=auto --no-link - - name: Publishing to local registry - run: yarn local-registry --publish - working-directory: ./code - - name: Running local registry - run: yarn local-registry --open & - working-directory: ./code - - name: Wait for registry - run: yarn wait-on tcp:127.0.0.1:6001 - working-directory: ./code - - name: Generate - run: yarn generate-sandboxes --local-registry - working-directory: ./code - - name: Publish - run: yarn publish-sandboxes --remote=https://storybook-bot:${{ secrets.PAT_STORYBOOK_BOT}}@github.com/storybookjs/sandboxes.git --push --branch=main - working-directory: ./code - - name: The job has failed - if: ${{ failure() || cancelled() }} - env: - DISCORD_WEBHOOK: ${{ secrets.DISCORD_MONITORING_URL }} - uses: Ilshidur/action-discord@master - with: - args: 'The generation of sandboxes in the **main** branch has failed. [View Run](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})' diff --git a/.github/workflows/generate-sandboxes.yml b/.github/workflows/generate-sandboxes.yml new file mode 100644 index 000000000000..dd80cefcb790 --- /dev/null +++ b/.github/workflows/generate-sandboxes.yml @@ -0,0 +1,34 @@ +name: Generate and push sandboxes + +on: + schedule: + - cron: "2 2 */1 * *" + workflow_dispatch: + # To test fixes on push rather than wait for the scheduling, do the following: + # 1. Uncomment the lines below and add your branch. + # push: + # branches: + # - + # 2. Change the "ref" value to in the actions/checkout step below. + # 3. Comment out the whole "generate-main" job starting at line 26 + # 3. πŸ‘‰ DON'T FORGET TO UNDO STEP 2 AND 3 BEFORE YOU MERGE YOUR CHANGES! + +jobs: + generate-next: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: next + - uses: .github/actions/generate-sandboxes-composite-action.yml + with: + destination-branch: next + generate-main: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: main + - uses: .github/actions/generate-sandboxes-composite-action.yml + with: + destination-branch: main From 81abd2ac5f5f5c0f6b2a1d65b1972650cf86949e Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Fri, 9 Feb 2024 23:08:06 +0100 Subject: [PATCH 03/79] temporarily test this branch as for sandbox generation --- .github/workflows/generate-sandboxes.yml | 26 ++++++++++++------------ 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/generate-sandboxes.yml b/.github/workflows/generate-sandboxes.yml index dd80cefcb790..af353f6b19aa 100644 --- a/.github/workflows/generate-sandboxes.yml +++ b/.github/workflows/generate-sandboxes.yml @@ -6,9 +6,9 @@ on: workflow_dispatch: # To test fixes on push rather than wait for the scheduling, do the following: # 1. Uncomment the lines below and add your branch. - # push: - # branches: - # - + push: + branches: + - jeppe/25922-ci-generation-of-sandboxes-fail-sometimes-on-prereleases # 2. Change the "ref" value to in the actions/checkout step below. # 3. Comment out the whole "generate-main" job starting at line 26 # 3. πŸ‘‰ DON'T FORGET TO UNDO STEP 2 AND 3 BEFORE YOU MERGE YOUR CHANGES! @@ -19,16 +19,16 @@ jobs: steps: - uses: actions/checkout@v4 with: - ref: next + ref: jeppe/25922-ci-generation-of-sandboxes-fail-sometimes-on-prereleases - uses: .github/actions/generate-sandboxes-composite-action.yml with: destination-branch: next - generate-main: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - ref: main - - uses: .github/actions/generate-sandboxes-composite-action.yml - with: - destination-branch: main + # generate-main: + # runs-on: ubuntu-latest + # steps: + # - uses: actions/checkout@v4 + # with: + # ref: main + # - uses: .github/actions/generate-sandboxes-composite-action.yml + # with: + # destination-branch: main From 658f715228ae08b5f7187e13ed94e40392c6447c Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Fri, 9 Feb 2024 23:09:11 +0100 Subject: [PATCH 04/79] correct syntax for local composite actions --- .github/workflows/generate-sandboxes.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/generate-sandboxes.yml b/.github/workflows/generate-sandboxes.yml index af353f6b19aa..a138a7ebe4ef 100644 --- a/.github/workflows/generate-sandboxes.yml +++ b/.github/workflows/generate-sandboxes.yml @@ -20,7 +20,7 @@ jobs: - uses: actions/checkout@v4 with: ref: jeppe/25922-ci-generation-of-sandboxes-fail-sometimes-on-prereleases - - uses: .github/actions/generate-sandboxes-composite-action.yml + - uses: ./.github/actions/generate-sandboxes-composite-action.yml with: destination-branch: next # generate-main: @@ -29,6 +29,6 @@ jobs: # - uses: actions/checkout@v4 # with: # ref: main - # - uses: .github/actions/generate-sandboxes-composite-action.yml + # - uses: ./.github/actions/generate-sandboxes-composite-action.yml # with: # destination-branch: main From a38557413a09dcdc0dafee7c1cf6c6f61a07c68b Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Fri, 9 Feb 2024 23:12:07 +0100 Subject: [PATCH 05/79] correcterer composite action syntax --- .github/workflows/generate-sandboxes.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/generate-sandboxes.yml b/.github/workflows/generate-sandboxes.yml index a138a7ebe4ef..0f6b5e992e7d 100644 --- a/.github/workflows/generate-sandboxes.yml +++ b/.github/workflows/generate-sandboxes.yml @@ -20,7 +20,7 @@ jobs: - uses: actions/checkout@v4 with: ref: jeppe/25922-ci-generation-of-sandboxes-fail-sometimes-on-prereleases - - uses: ./.github/actions/generate-sandboxes-composite-action.yml + - uses: ./.github/actions/generate-sandboxes-composite-action with: destination-branch: next # generate-main: @@ -29,6 +29,6 @@ jobs: # - uses: actions/checkout@v4 # with: # ref: main - # - uses: ./.github/actions/generate-sandboxes-composite-action.yml + # - uses: ./.github/actions/generate-sandboxes-composite-action # with: # destination-branch: main From 871e1b17f78721e05d67bde518c3e63879d48e09 Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Fri, 9 Feb 2024 23:16:08 +0100 Subject: [PATCH 06/79] correctest composite action syntax --- .../action.yml} | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) rename .github/actions/{generate-sandboxes-composite-action.yml => generate-sandboxes-composite-action/action.yml} (88%) diff --git a/.github/actions/generate-sandboxes-composite-action.yml b/.github/actions/generate-sandboxes-composite-action/action.yml similarity index 88% rename from .github/actions/generate-sandboxes-composite-action.yml rename to .github/actions/generate-sandboxes-composite-action/action.yml index d47166c73ec4..e2d84a2c283d 100644 --- a/.github/actions/generate-sandboxes-composite-action.yml +++ b/.github/actions/generate-sandboxes-composite-action/action.yml @@ -6,11 +6,6 @@ inputs: description: The destination branch to generate sandboxes to in the storybookjs/sandboxes repository required: true -defaults: - run: - shell: bash - working-directory: ./code - runs: using: "composite" steps: @@ -19,34 +14,42 @@ runs: node-version-file: ".nvmrc" - name: Setup git user + shell: bash run: | git config --global user.name "storybook-bot" git config --global user.email "32066757+storybook-bot@users.noreply.github.com" - name: Install dependencies + shell: bash working-directory: ./scripts env: - YARN_ENABLE_IMMUTABLE_INSTALLS: false + YARN_ENABLE_IMMUTABLE_INSTALLS: "false" run: node --experimental-modules ./check-dependencies.js - name: Compile Storybook libraries + shell: bash run: yarn task --task compile --start-from=auto --no-link - name: Publish to local registry + shell: bash run: yarn local-registry --publish - name: Run local registry + shell: bash run: yarn local-registry --open & - name: Wait for registry + shell: bash run: yarn wait-on tcp:127.0.0.1:6001 - name: Generate + shell: bash env: - CLEANUP_SANDBOX_NODE_MODULES: true + CLEANUP_SANDBOX_NODE_MODULES: "true" run: yarn generate-sandboxes --local-registry - name: Publish + shell: bash run: yarn publish-sandboxes --remote=https://storybook-bot:${{ secrets.PAT_STORYBOOK_BOT}}@github.com/storybookjs/sandboxes.git --push --branch=${{ inputs.destination-branch }} - name: The job has failed From bb0d0d0f7ea919118d275c0c10833ced6297db96 Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Fri, 9 Feb 2024 23:20:38 +0100 Subject: [PATCH 07/79] move secrets to workflow --- .../generate-sandboxes-composite-action/action.yml | 10 ++++++++-- .github/workflows/generate-sandboxes.yml | 7 +++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/.github/actions/generate-sandboxes-composite-action/action.yml b/.github/actions/generate-sandboxes-composite-action/action.yml index e2d84a2c283d..a4f0112731e7 100644 --- a/.github/actions/generate-sandboxes-composite-action/action.yml +++ b/.github/actions/generate-sandboxes-composite-action/action.yml @@ -5,6 +5,12 @@ inputs: destination-branch: description: The destination branch to generate sandboxes to in the storybookjs/sandboxes repository required: true + token: + description: The personal access token to use when authenticating with the destination repository + required: true + discord-url: + description: The Discord URL to use when reporting failures + required: true runs: using: "composite" @@ -50,12 +56,12 @@ runs: - name: Publish shell: bash - run: yarn publish-sandboxes --remote=https://storybook-bot:${{ secrets.PAT_STORYBOOK_BOT}}@github.com/storybookjs/sandboxes.git --push --branch=${{ inputs.destination-branch }} + run: yarn publish-sandboxes --remote=https://storybook-bot:${{ inputs.token }}@github.com/storybookjs/sandboxes.git --push --branch=${{ inputs.destination-branch }} - name: The job has failed if: ${{ failure() || cancelled() }} env: - DISCORD_WEBHOOK: ${{ secrets.DISCORD_MONITORING_URL }} + DISCORD_WEBHOOK: ${{ inputs.discord-url }} uses: Ilshidur/action-discord@master with: args: "The generation of sandboxes in the **${{ inputs.destination-branch }}** branch has failed. [View Run](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})" diff --git a/.github/workflows/generate-sandboxes.yml b/.github/workflows/generate-sandboxes.yml index 0f6b5e992e7d..942ad7527d42 100644 --- a/.github/workflows/generate-sandboxes.yml +++ b/.github/workflows/generate-sandboxes.yml @@ -15,6 +15,7 @@ on: jobs: generate-next: + name: Generate to next runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -23,7 +24,11 @@ jobs: - uses: ./.github/actions/generate-sandboxes-composite-action with: destination-branch: next + token: ${{ secrets.PAT_STORYBOOK_BOT }} + discord-url: ${{ secrets.DISCORD_MONITORING_URL }} + # generate-main: + # name: Generate to main # runs-on: ubuntu-latest # steps: # - uses: actions/checkout@v4 @@ -32,3 +37,5 @@ jobs: # - uses: ./.github/actions/generate-sandboxes-composite-action # with: # destination-branch: main + # token: ${{ secrets.PAT_STORYBOOK_BOT }} + # discord-url: ${{ secrets.DISCORD_MONITORING_URL }} From 02f624193347e4920a01fc9a2da5135efa979131 Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Fri, 9 Feb 2024 23:27:25 +0100 Subject: [PATCH 08/79] use regular workflow instead of composite action --- .../action.yml | 67 ------------------- .github/workflows/generate-sandboxes-next.yml | 60 ----------------- .github/workflows/generate-sandboxes.yml | 63 ++++++++++++----- 3 files changed, 46 insertions(+), 144 deletions(-) delete mode 100644 .github/actions/generate-sandboxes-composite-action/action.yml delete mode 100644 .github/workflows/generate-sandboxes-next.yml diff --git a/.github/actions/generate-sandboxes-composite-action/action.yml b/.github/actions/generate-sandboxes-composite-action/action.yml deleted file mode 100644 index a4f0112731e7..000000000000 --- a/.github/actions/generate-sandboxes-composite-action/action.yml +++ /dev/null @@ -1,67 +0,0 @@ -name: Generate and push sandboxes action -description: This is a composite action that generates sandboxes and pushes them to the storybookjs/sandboxes repository - -inputs: - destination-branch: - description: The destination branch to generate sandboxes to in the storybookjs/sandboxes repository - required: true - token: - description: The personal access token to use when authenticating with the destination repository - required: true - discord-url: - description: The Discord URL to use when reporting failures - required: true - -runs: - using: "composite" - steps: - - uses: actions/setup-node@v3 - with: - node-version-file: ".nvmrc" - - - name: Setup git user - shell: bash - run: | - git config --global user.name "storybook-bot" - git config --global user.email "32066757+storybook-bot@users.noreply.github.com" - - - name: Install dependencies - shell: bash - working-directory: ./scripts - env: - YARN_ENABLE_IMMUTABLE_INSTALLS: "false" - run: node --experimental-modules ./check-dependencies.js - - - name: Compile Storybook libraries - shell: bash - run: yarn task --task compile --start-from=auto --no-link - - - name: Publish to local registry - shell: bash - run: yarn local-registry --publish - - - name: Run local registry - shell: bash - run: yarn local-registry --open & - - - name: Wait for registry - shell: bash - run: yarn wait-on tcp:127.0.0.1:6001 - - - name: Generate - shell: bash - env: - CLEANUP_SANDBOX_NODE_MODULES: "true" - run: yarn generate-sandboxes --local-registry - - - name: Publish - shell: bash - run: yarn publish-sandboxes --remote=https://storybook-bot:${{ inputs.token }}@github.com/storybookjs/sandboxes.git --push --branch=${{ inputs.destination-branch }} - - - name: The job has failed - if: ${{ failure() || cancelled() }} - env: - DISCORD_WEBHOOK: ${{ inputs.discord-url }} - uses: Ilshidur/action-discord@master - with: - args: "The generation of sandboxes in the **${{ inputs.destination-branch }}** branch has failed. [View Run](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})" diff --git a/.github/workflows/generate-sandboxes-next.yml b/.github/workflows/generate-sandboxes-next.yml deleted file mode 100644 index 2c0b592d024f..000000000000 --- a/.github/workflows/generate-sandboxes-next.yml +++ /dev/null @@ -1,60 +0,0 @@ -name: Generate and push sandboxes (next) - -on: - schedule: - - cron: '2 2 */1 * *' - workflow_dispatch: - # To test fixes on push rather than wait for the scheduling, do the following: - # 1. Uncomment the lines below and add your branch. - # push: - # branches: - # - - # 2. change the "ref" value to in the actions/checkout step below. - # 3. πŸ‘‰ DON'T FORGET TO UNDO THE VALUES BACK TO `next` BEFORE YOU MERGE YOUR CHANGES! - -jobs: - generate: - runs-on: ubuntu-latest - env: - YARN_ENABLE_IMMUTABLE_INSTALLS: false - CLEANUP_SANDBOX_NODE_MODULES: true - steps: - - uses: actions/checkout@v3 - with: - ref: next - - uses: actions/setup-node@v3 - with: - node-version-file: '.nvmrc' - - name: Setup git user - run: | - git config --global user.name "Storybook Bot" - git config --global user.email "bot@storybook.js.org" - - name: Install dependencies - run: | - cd ./scripts - node --experimental-modules ./check-dependencies.js - cd .. - - name: Compile Storybook libraries - run: yarn task --task compile --start-from=auto --no-link - - name: Publishing to local registry - run: yarn local-registry --publish - working-directory: ./code - - name: Running local registry - run: yarn local-registry --open & - working-directory: ./code - - name: Wait for registry - run: yarn wait-on tcp:127.0.0.1:6001 - working-directory: ./code - - name: Generate - run: yarn generate-sandboxes --local-registry --debug - working-directory: ./code - - name: Publish - run: yarn publish-sandboxes --remote=https://storybook-bot:${{ secrets.PAT_STORYBOOK_BOT}}@github.com/storybookjs/sandboxes.git --push --branch=next - working-directory: ./code - - name: The job has failed - if: ${{ failure() || cancelled() }} - env: - DISCORD_WEBHOOK: ${{ secrets.DISCORD_MONITORING_URL }} - uses: Ilshidur/action-discord@master - with: - args: 'The generation of sandboxes in the **next** branch has failed. [View Run](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})' diff --git a/.github/workflows/generate-sandboxes.yml b/.github/workflows/generate-sandboxes.yml index 942ad7527d42..8c1af15b40ad 100644 --- a/.github/workflows/generate-sandboxes.yml +++ b/.github/workflows/generate-sandboxes.yml @@ -13,6 +13,14 @@ on: # 3. Comment out the whole "generate-main" job starting at line 26 # 3. πŸ‘‰ DON'T FORGET TO UNDO STEP 2 AND 3 BEFORE YOU MERGE YOUR CHANGES! +env: + YARN_ENABLE_IMMUTABLE_INSTALLS: "false" + CLEANUP_SANDBOX_NODE_MODULES: "true" + +defaults: + run: + working-directory: ./code + jobs: generate-next: name: Generate to next @@ -21,21 +29,42 @@ jobs: - uses: actions/checkout@v4 with: ref: jeppe/25922-ci-generation-of-sandboxes-fail-sometimes-on-prereleases - - uses: ./.github/actions/generate-sandboxes-composite-action + + - uses: actions/setup-node@v4 + with: + node-version-file: ".nvmrc" + + - name: Setup git user + run: | + git config --global user.name "storybook-bot" + git config --global user.email "32066757+storybook-bot@users.noreply.github.com" + + - name: Install dependencies + working-directory: ./scripts + run: node --experimental-modules ./check-dependencies.js + + - name: Compile Storybook libraries + run: yarn task --task compile --start-from=auto --no-link + + - name: Publish to local registry + run: yarn local-registry --publish + + - name: Run local registry + run: yarn local-registry --open & + + - name: Wait for registry + run: yarn wait-on tcp:127.0.0.1:6001 + + - name: Generate + run: yarn generate-sandboxes --local-registry + + - name: Publish + run: yarn publish-sandboxes --remote=https://storybook-bot:${{ secrets.PAT_STORYBOOK_BOT }}@github.com/storybookjs/sandboxes.git --push --branch=next + + - name: The job has failed + if: ${{ failure() || cancelled() }} + env: + DISCORD_WEBHOOK: ${{ secrets.DISCORD_MONITORING_URL }} + uses: Ilshidur/action-discord@master with: - destination-branch: next - token: ${{ secrets.PAT_STORYBOOK_BOT }} - discord-url: ${{ secrets.DISCORD_MONITORING_URL }} - - # generate-main: - # name: Generate to main - # runs-on: ubuntu-latest - # steps: - # - uses: actions/checkout@v4 - # with: - # ref: main - # - uses: ./.github/actions/generate-sandboxes-composite-action - # with: - # destination-branch: main - # token: ${{ secrets.PAT_STORYBOOK_BOT }} - # discord-url: ${{ secrets.DISCORD_MONITORING_URL }} + args: "The generation of sandboxes on the **next** branch has failed. [View Run](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})" From f1846015d018d27302942cc94a988db56c8f8ba1 Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Sat, 10 Feb 2024 00:09:13 +0100 Subject: [PATCH 09/79] Continue with publishing even if some sandboxes fail --- .github/workflows/generate-sandboxes.yml | 17 +++++-- scripts/sandbox/generate.ts | 57 +++++++++++++++++------- 2 files changed, 55 insertions(+), 19 deletions(-) diff --git a/.github/workflows/generate-sandboxes.yml b/.github/workflows/generate-sandboxes.yml index 8c1af15b40ad..643361e63143 100644 --- a/.github/workflows/generate-sandboxes.yml +++ b/.github/workflows/generate-sandboxes.yml @@ -1,4 +1,4 @@ -name: Generate and push sandboxes +name: Generate and publish sandboxes on: schedule: @@ -56,15 +56,24 @@ jobs: run: yarn wait-on tcp:127.0.0.1:6001 - name: Generate + id: generate run: yarn generate-sandboxes --local-registry - name: Publish + # publish sandboxes even if the generation fails, as some sandboxes might have been generated successfully + if: !cancelled() run: yarn publish-sandboxes --remote=https://storybook-bot:${{ secrets.PAT_STORYBOOK_BOT }}@github.com/storybookjs/sandboxes.git --push --branch=next - - name: The job has failed - if: ${{ failure() || cancelled() }} + - name: Report failure to Discord + if: failure() env: DISCORD_WEBHOOK: ${{ secrets.DISCORD_MONITORING_URL }} uses: Ilshidur/action-discord@master with: - args: "The generation of sandboxes on the **next** branch has failed. [View Run](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})" + args: | + The generation of some or all sandboxes on the **next** branch has failed. + [View Job](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}/job/${{ github.job }}) + + ${{ steps.generate.outputs.failed-before-script-templates && format('The following templates failed to execute the before script:\n- {0}', steps.generate.outputs.failed-before-script-templates) || '' }} + + ${{ steps.generate.outputs.failed-before-script-templates && format('The following templates failed to initialize Storybook:\n- {0}', steps.generate.outputs.failed-init-templates) || '' }} diff --git a/scripts/sandbox/generate.ts b/scripts/sandbox/generate.ts index 27f17f8c7ad0..969247d6ba1d 100755 --- a/scripts/sandbox/generate.ts +++ b/scripts/sandbox/generate.ts @@ -27,6 +27,7 @@ import { REPROS_DIRECTORY, LOCAL_REGISTRY_URL, } from '../utils/constants'; +import { setOutput } from '@actions/core'; const sbInit = async ( cwd: string, @@ -148,7 +149,10 @@ const runGenerators = async ( const limit = pLimit(1); - await Promise.all( + const failedBeforeScriptTemplates: string[] = []; + const failedInitTemplates: string[] = []; + + await Promise.allSettled( generators.map(({ dirName, name, script, expected, env }) => limit(async () => { let flags: string[] = []; @@ -173,19 +177,26 @@ const runGenerators = async ( // Some tools refuse to run inside an existing directory and replace the contents, // where as others are very picky about what directories can be called. So we need to // handle different modes of operation. - if (script.includes('{{beforeDir}}')) { - const scriptWithBeforeDir = script.replaceAll('{{beforeDir}}', BEFORE_DIR_NAME); - await runCommand( - scriptWithBeforeDir, - { - cwd: createBaseDir, - timeout: SCRIPT_TIMEOUT, - }, - debug - ); - } else { - await ensureDir(createBeforeDir); - await runCommand(script, { cwd: createBeforeDir, timeout: SCRIPT_TIMEOUT }, debug); + try { + if (script.includes('{{beforeDir}}')) { + const scriptWithBeforeDir = script.replaceAll('{{beforeDir}}', BEFORE_DIR_NAME); + await runCommand( + scriptWithBeforeDir, + { + cwd: createBaseDir, + timeout: SCRIPT_TIMEOUT, + }, + debug + ); + } else { + await ensureDir(createBeforeDir); + await runCommand(script, { cwd: createBeforeDir, timeout: SCRIPT_TIMEOUT }, debug); + } + } catch (error) { + console.error(`❌ Failed to execute before-script for template: ${name}`); + console.error(error); + failedBeforeScriptTemplates.push(name); + return; } await localizeYarnConfigFiles(createBaseDir, createBeforeDir); @@ -196,7 +207,14 @@ const runGenerators = async ( // Make sure there are no git projects in the folder await remove(join(beforeDir, '.git')); - await addStorybook({ baseDir, localRegistry, flags, debug, env }); + try { + await addStorybook({ baseDir, localRegistry, flags, debug, env }); + } catch (error) { + console.error(`❌ Failed to add Storybook to template: ${name}`); + console.error(error); + failedInitTemplates.push(name); + return; + } await addDocumentation(baseDir, { name, dirName }); @@ -218,6 +236,15 @@ const runGenerators = async ( }) ) ); + + if (process.env.GITHUB_ACTIONS === 'true') { + if (failedBeforeScriptTemplates.length > 0) { + setOutput('failed-before-script-templates', failedBeforeScriptTemplates.join('\n- ')); + } + if (failedInitTemplates.length > 0) { + setOutput('failed-init-templates', failedInitTemplates.join('\n- ')); + } + } }; export const options = createOptions({ From 86c58958146617d044748cdd97f0a4dcb190da7c Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Sat, 10 Feb 2024 00:20:35 +0100 Subject: [PATCH 10/79] =?UTF-8?q?Yet=20Another=20Maddening=20Language?= =?UTF-8?q?=E2=84=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/generate-sandboxes.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/generate-sandboxes.yml b/.github/workflows/generate-sandboxes.yml index 643361e63143..339e6eb9d0c8 100644 --- a/.github/workflows/generate-sandboxes.yml +++ b/.github/workflows/generate-sandboxes.yml @@ -61,7 +61,7 @@ jobs: - name: Publish # publish sandboxes even if the generation fails, as some sandboxes might have been generated successfully - if: !cancelled() + if: ${{ !cancelled() }} run: yarn publish-sandboxes --remote=https://storybook-bot:${{ secrets.PAT_STORYBOOK_BOT }}@github.com/storybookjs/sandboxes.git --push --branch=next - name: Report failure to Discord From 11222151b69819c9d7e1cdd049b61f24cfccb3f3 Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Sat, 10 Feb 2024 00:23:02 +0100 Subject: [PATCH 11/79] randomly cause generation failures --- scripts/sandbox/generate.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/scripts/sandbox/generate.ts b/scripts/sandbox/generate.ts index 969247d6ba1d..ee0b952175a6 100755 --- a/scripts/sandbox/generate.ts +++ b/scripts/sandbox/generate.ts @@ -81,6 +81,9 @@ const addStorybook = async ({ const tmpDir = directory(); try { + if (Math.random() < 0.2) { + throw new Error('Blip Bloop random error in addStorybook'); + } await copy(beforeDir, tmpDir); const packageManager = JsPackageManagerFactory.getPackageManager({ force: 'yarn1' }, tmpDir); @@ -178,6 +181,9 @@ const runGenerators = async ( // where as others are very picky about what directories can be called. So we need to // handle different modes of operation. try { + if (Math.random() < 0.2) { + throw new Error('Blip Bloop random error when executing before-script'); + } if (script.includes('{{beforeDir}}')) { const scriptWithBeforeDir = script.replaceAll('{{beforeDir}}', BEFORE_DIR_NAME); await runCommand( From 78f122caed653f9e3a38b732a779d1eefba1696c Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Mon, 12 Feb 2024 12:22:01 +0100 Subject: [PATCH 12/79] simplify error handling, rethrow errors --- .github/workflows/generate-sandboxes.yml | 6 +- scripts/sandbox/generate.ts | 218 ++++++++++++++--------- 2 files changed, 136 insertions(+), 88 deletions(-) diff --git a/.github/workflows/generate-sandboxes.yml b/.github/workflows/generate-sandboxes.yml index 339e6eb9d0c8..a7d1ded22573 100644 --- a/.github/workflows/generate-sandboxes.yml +++ b/.github/workflows/generate-sandboxes.yml @@ -72,8 +72,4 @@ jobs: with: args: | The generation of some or all sandboxes on the **next** branch has failed. - [View Job](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}/job/${{ github.job }}) - - ${{ steps.generate.outputs.failed-before-script-templates && format('The following templates failed to execute the before script:\n- {0}', steps.generate.outputs.failed-before-script-templates) || '' }} - - ${{ steps.generate.outputs.failed-before-script-templates && format('The following templates failed to initialize Storybook:\n- {0}', steps.generate.outputs.failed-init-templates) || '' }} + [See the job summary for details](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}/job/${{ github.job }}) diff --git a/scripts/sandbox/generate.ts b/scripts/sandbox/generate.ts index ee0b952175a6..510b34b9a2b6 100755 --- a/scripts/sandbox/generate.ts +++ b/scripts/sandbox/generate.ts @@ -27,7 +27,14 @@ import { REPROS_DIRECTORY, LOCAL_REGISTRY_URL, } from '../utils/constants'; -import { setOutput } from '@actions/core'; +import * as ghActions from '@actions/core'; + +const isCI = process.env.GITHUB_ACTIONS === 'true'; + +const logError = isCI ? ghActions.error : console.error; + +class BeforeScriptExecutionError extends Error {} +class StorybookInitError extends Error {} const sbInit = async ( cwd: string, @@ -152,105 +159,150 @@ const runGenerators = async ( const limit = pLimit(1); - const failedBeforeScriptTemplates: string[] = []; - const failedInitTemplates: string[] = []; - - await Promise.allSettled( + const generationResults = await Promise.allSettled( generators.map(({ dirName, name, script, expected, env }) => limit(async () => { - let flags: string[] = []; - if (expected.renderer === '@storybook/html') flags = ['--type html']; - else if (expected.renderer === '@storybook/server') flags = ['--type server']; - - const time = process.hrtime(); - console.log(`🧬 Generating ${name}`); + try { + if (isCI) { + ghActions.startGroup(`Generating sandbox for ${name}`); + } - const baseDir = join(REPROS_DIRECTORY, dirName); - const beforeDir = join(baseDir, BEFORE_DIR_NAME); - await emptyDir(baseDir); + let flags: string[] = []; + if (expected.renderer === '@storybook/html') flags = ['--type html']; + else if (expected.renderer === '@storybook/server') flags = ['--type server']; - // We do the creation inside a temp dir to avoid yarn container problems - const createBaseDir = directory(); - if (!script.includes('pnp')) { - await setupYarn({ cwd: createBaseDir }); - } + const time = process.hrtime(); + console.log(`🧬 Generating ${name}`); - const createBeforeDir = join(createBaseDir, BEFORE_DIR_NAME); + const baseDir = join(REPROS_DIRECTORY, dirName); + const beforeDir = join(baseDir, BEFORE_DIR_NAME); + await emptyDir(baseDir); - // Some tools refuse to run inside an existing directory and replace the contents, - // where as others are very picky about what directories can be called. So we need to - // handle different modes of operation. - try { - if (Math.random() < 0.2) { - throw new Error('Blip Bloop random error when executing before-script'); + // We do the creation inside a temp dir to avoid yarn container problems + const createBaseDir = directory(); + if (!script.includes('pnp')) { + await setupYarn({ cwd: createBaseDir }); } - if (script.includes('{{beforeDir}}')) { - const scriptWithBeforeDir = script.replaceAll('{{beforeDir}}', BEFORE_DIR_NAME); - await runCommand( - scriptWithBeforeDir, - { - cwd: createBaseDir, - timeout: SCRIPT_TIMEOUT, - }, - debug - ); - } else { - await ensureDir(createBeforeDir); - await runCommand(script, { cwd: createBeforeDir, timeout: SCRIPT_TIMEOUT }, debug); - } - } catch (error) { - console.error(`❌ Failed to execute before-script for template: ${name}`); - console.error(error); - failedBeforeScriptTemplates.push(name); - return; - } - await localizeYarnConfigFiles(createBaseDir, createBeforeDir); - - // Now move the created before dir into it's final location and add storybook - await move(createBeforeDir, beforeDir); + const createBeforeDir = join(createBaseDir, BEFORE_DIR_NAME); + + // Some tools refuse to run inside an existing directory and replace the contents, + // where as others are very picky about what directories can be called. So we need to + // handle different modes of operation. + try { + if (Math.random() < 0.4) { + throw new Error('Blip Bloop random error when executing before-script'); + } + if (script.includes('{{beforeDir}}')) { + const scriptWithBeforeDir = script.replaceAll('{{beforeDir}}', BEFORE_DIR_NAME); + await runCommand( + scriptWithBeforeDir, + { + cwd: createBaseDir, + timeout: SCRIPT_TIMEOUT, + }, + debug + ); + } else { + await ensureDir(createBeforeDir); + await runCommand(script, { cwd: createBeforeDir, timeout: SCRIPT_TIMEOUT }, debug); + } + } catch (error) { + const message = `❌ Failed to execute before-script for template: ${name}`; + logError(message); + logError(error); + logError((error as any).stack); + throw new BeforeScriptExecutionError(message, { cause: error }); + } - // Make sure there are no git projects in the folder - await remove(join(beforeDir, '.git')); + await localizeYarnConfigFiles(createBaseDir, createBeforeDir); + + // Now move the created before dir into it's final location and add storybook + await move(createBeforeDir, beforeDir); + + // Make sure there are no git projects in the folder + await remove(join(beforeDir, '.git')); + + try { + if (Math.random() < 0.4) { + throw new Error('Blip Bloop random error when init storybook'); + } + await addStorybook({ baseDir, localRegistry, flags, debug, env }); + } catch (error) { + const message = `❌ Failed to initialize Storybook in template: ${name}`; + logError(message); + logError(error); + logError((error as any).stack); + throw new StorybookInitError(message, { + cause: error, + }); + } + if (Math.random() < 0.4) { + throw new Error('Blip Bloop random error anywhere'); + } + await addDocumentation(baseDir, { name, dirName }); + + // Remove node_modules to save space and avoid GH actions failing + // They're not uploaded to the git sandboxes repo anyway + if (process.env.CLEANUP_SANDBOX_NODE_MODULES) { + console.log(`πŸ—‘οΈ Removing ${join(beforeDir, 'node_modules')}`); + await remove(join(beforeDir, 'node_modules')); + console.log(`πŸ—‘οΈ Removing ${join(baseDir, AFTER_DIR_NAME, 'node_modules')}`); + await remove(join(baseDir, AFTER_DIR_NAME, 'node_modules')); + } - try { - await addStorybook({ baseDir, localRegistry, flags, debug, env }); + console.log( + `βœ… Created ${dirName} in ./${relative( + process.cwd(), + baseDir + )} successfully in ${prettyTime(process.hrtime(time))}` + ); } catch (error) { - console.error(`❌ Failed to add Storybook to template: ${name}`); - console.error(error); - failedInitTemplates.push(name); - return; - } - - await addDocumentation(baseDir, { name, dirName }); - - // Remove node_modules to save space and avoid GH actions failing - // They're not uploaded to the git sandboxes repo anyway - if (process.env.CLEANUP_SANDBOX_NODE_MODULES) { - console.log(`πŸ—‘οΈ Removing ${join(beforeDir, 'node_modules')}`); - await remove(join(beforeDir, 'node_modules')); - console.log(`πŸ—‘οΈ Removing ${join(baseDir, AFTER_DIR_NAME, 'node_modules')}`); - await remove(join(baseDir, AFTER_DIR_NAME, 'node_modules')); + throw error; + } finally { + if (isCI) { + ghActions.endGroup(); + } } - - console.log( - `βœ… Created ${dirName} in ./${relative( - process.cwd(), - baseDir - )} successfully in ${prettyTime(process.hrtime(time))}` - ); }) ) ); - if (process.env.GITHUB_ACTIONS === 'true') { - if (failedBeforeScriptTemplates.length > 0) { - setOutput('failed-before-script-templates', failedBeforeScriptTemplates.join('\n- ')); - } - if (failedInitTemplates.length > 0) { - setOutput('failed-init-templates', failedInitTemplates.join('\n- ')); - } + ghActions.summary.addHeading('Sandbox generation summary'); + + if (!generationResults.some((result) => result.status === 'rejected')) { + await ghActions.summary.addRaw('βœ… Success!').write(); + return; + } + + if (isCI) { + await ghActions.summary + .addRaw('Some sandboxes failed, see the action log for details') + .addTable([ + [ + { data: 'Template', header: true }, + { data: 'Result', header: true }, + ], + ...generationResults.map((result, index) => { + const template = generators[index].name; + if (result.status === 'fulfilled') { + return [template, '🟒 Pass']; + } + const generationError = (result as PromiseRejectedResult).reason as Error; + const errorCause = generationError.cause; + if (errorCause instanceof BeforeScriptExecutionError) { + return [template, 'πŸ”΄ Failed to execute before script']; + } else if (errorCause instanceof StorybookInitError) { + return [template, 'πŸ”΄ Failed to initialize Storybook']; + } else { + return [template, 'πŸ”΄ Failed with unknown error']; + } + }), + ]) + .write(); } + + throw new Error(`Some sandboxes failed to generate`); }; export const options = createOptions({ From b7eb43338b28f7f24fd7190d92c70de41c04ce3b Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Mon, 12 Feb 2024 13:02:17 +0100 Subject: [PATCH 13/79] fix error logging and summary generation --- .github/workflows/generate-sandboxes.yml | 2 +- scripts/sandbox/generate.ts | 45 +++++++++++++----------- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/.github/workflows/generate-sandboxes.yml b/.github/workflows/generate-sandboxes.yml index a7d1ded22573..b3a875bcfb00 100644 --- a/.github/workflows/generate-sandboxes.yml +++ b/.github/workflows/generate-sandboxes.yml @@ -72,4 +72,4 @@ jobs: with: args: | The generation of some or all sandboxes on the **next** branch has failed. - [See the job summary for details](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}/job/${{ github.job }}) + [See the job summary for details](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) diff --git a/scripts/sandbox/generate.ts b/scripts/sandbox/generate.ts index 510b34b9a2b6..85a296f71f30 100755 --- a/scripts/sandbox/generate.ts +++ b/scripts/sandbox/generate.ts @@ -28,11 +28,10 @@ import { LOCAL_REGISTRY_URL, } from '../utils/constants'; import * as ghActions from '@actions/core'; +import dedent from 'ts-dedent'; const isCI = process.env.GITHUB_ACTIONS === 'true'; -const logError = isCI ? ghActions.error : console.error; - class BeforeScriptExecutionError extends Error {} class StorybookInitError extends Error {} @@ -164,7 +163,7 @@ const runGenerators = async ( limit(async () => { try { if (isCI) { - ghActions.startGroup(`Generating sandbox for ${name}`); + ghActions.startGroup(`${name} (${dirName})`); } let flags: string[] = []; @@ -208,10 +207,12 @@ const runGenerators = async ( await runCommand(script, { cwd: createBeforeDir, timeout: SCRIPT_TIMEOUT }, debug); } } catch (error) { - const message = `❌ Failed to execute before-script for template: ${name}`; - logError(message); - logError(error); - logError((error as any).stack); + const message = `❌ Failed to execute before-script for template: ${name} (${dirName})`; + if (isCI) { + ghActions.error(dedent`${message} + ${(error as any).stack}`); + } + console.error(error); throw new BeforeScriptExecutionError(message, { cause: error }); } @@ -229,10 +230,12 @@ const runGenerators = async ( } await addStorybook({ baseDir, localRegistry, flags, debug, env }); } catch (error) { - const message = `❌ Failed to initialize Storybook in template: ${name}`; - logError(message); - logError(error); - logError((error as any).stack); + const message = `❌ Failed to initialize Storybook in template: ${name} (${dirName})`; + if (isCI) { + ghActions.error(dedent`${message} + ${(error as any).stack}`); + } + console.error(error); throw new StorybookInitError(message, { cause: error, }); @@ -277,25 +280,25 @@ const runGenerators = async ( if (isCI) { await ghActions.summary - .addRaw('Some sandboxes failed, see the action log for details') + .addRaw('Some sandboxes failed, see the job log for detailed errors') .addTable([ [ - { data: 'Template', header: true }, + { data: 'Name', header: true }, + { data: 'Key', header: true }, { data: 'Result', header: true }, ], ...generationResults.map((result, index) => { - const template = generators[index].name; + const { name, dirName } = generators[index]; if (result.status === 'fulfilled') { - return [template, '🟒 Pass']; + return [name, dirName, '🟒 Pass']; } const generationError = (result as PromiseRejectedResult).reason as Error; - const errorCause = generationError.cause; - if (errorCause instanceof BeforeScriptExecutionError) { - return [template, 'πŸ”΄ Failed to execute before script']; - } else if (errorCause instanceof StorybookInitError) { - return [template, 'πŸ”΄ Failed to initialize Storybook']; + if (generationError instanceof BeforeScriptExecutionError) { + return [name, dirName, 'πŸ”΄ Failed to execute before script']; + } else if (generationError instanceof StorybookInitError) { + return [name, dirName, 'πŸ”΄ Failed to initialize Storybook']; } else { - return [template, 'πŸ”΄ Failed with unknown error']; + return [name, dirName, 'πŸ”΄ Failed with unknown error']; } }), ]) From c9e9d6242536edb2b7359671455dcc1af46e94f7 Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Mon, 12 Feb 2024 13:23:09 +0100 Subject: [PATCH 14/79] fix double error logging --- scripts/sandbox/generate.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/scripts/sandbox/generate.ts b/scripts/sandbox/generate.ts index 85a296f71f30..a3c88eb4eb5c 100755 --- a/scripts/sandbox/generate.ts +++ b/scripts/sandbox/generate.ts @@ -189,7 +189,7 @@ const runGenerators = async ( // where as others are very picky about what directories can be called. So we need to // handle different modes of operation. try { - if (Math.random() < 0.4) { + if (Math.random() < 0.2) { throw new Error('Blip Bloop random error when executing before-script'); } if (script.includes('{{beforeDir}}')) { @@ -211,8 +211,10 @@ const runGenerators = async ( if (isCI) { ghActions.error(dedent`${message} ${(error as any).stack}`); + } else { + console.error(message); + console.error(error); } - console.error(error); throw new BeforeScriptExecutionError(message, { cause: error }); } @@ -225,7 +227,7 @@ const runGenerators = async ( await remove(join(beforeDir, '.git')); try { - if (Math.random() < 0.4) { + if (Math.random() < 0.2) { throw new Error('Blip Bloop random error when init storybook'); } await addStorybook({ baseDir, localRegistry, flags, debug, env }); @@ -234,8 +236,10 @@ const runGenerators = async ( if (isCI) { ghActions.error(dedent`${message} ${(error as any).stack}`); + } else { + console.error(message); + console.error(error); } - console.error(error); throw new StorybookInitError(message, { cause: error, }); @@ -366,7 +370,7 @@ if (esMain(import.meta.url)) { .action((optionValues) => { generate(optionValues) .catch((e) => { - console.trace(e); + console.error(e); process.exit(1); }) .then(() => { From 57cbc5ece4f192a09e0a20591cbfc268db0b11b8 Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Mon, 12 Feb 2024 14:25:01 +0100 Subject: [PATCH 15/79] support partial publishing to sandboxes repo --- .github/workflows/generate-sandboxes.yml | 2 +- scripts/sandbox/generate.ts | 6 +++--- scripts/sandbox/publish.ts | 27 +++++++++++++++--------- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/.github/workflows/generate-sandboxes.yml b/.github/workflows/generate-sandboxes.yml index b3a875bcfb00..774cd297c571 100644 --- a/.github/workflows/generate-sandboxes.yml +++ b/.github/workflows/generate-sandboxes.yml @@ -62,7 +62,7 @@ jobs: - name: Publish # publish sandboxes even if the generation fails, as some sandboxes might have been generated successfully if: ${{ !cancelled() }} - run: yarn publish-sandboxes --remote=https://storybook-bot:${{ secrets.PAT_STORYBOOK_BOT }}@github.com/storybookjs/sandboxes.git --push --branch=next + run: yarn publish-sandboxes --remote=https://storybook-bot:${{ secrets.PAT_STORYBOOK_BOT }}@github.com/storybookjs/sandboxes.git --push --branch=jeppe/experiment-partial-generation - name: Report failure to Discord if: failure() diff --git a/scripts/sandbox/generate.ts b/scripts/sandbox/generate.ts index a3c88eb4eb5c..dd77b4ee8574 100755 --- a/scripts/sandbox/generate.ts +++ b/scripts/sandbox/generate.ts @@ -189,7 +189,7 @@ const runGenerators = async ( // where as others are very picky about what directories can be called. So we need to // handle different modes of operation. try { - if (Math.random() < 0.2) { + if (Math.random() < 0.6) { throw new Error('Blip Bloop random error when executing before-script'); } if (script.includes('{{beforeDir}}')) { @@ -227,7 +227,7 @@ const runGenerators = async ( await remove(join(beforeDir, '.git')); try { - if (Math.random() < 0.2) { + if (Math.random() < 0.6) { throw new Error('Blip Bloop random error when init storybook'); } await addStorybook({ baseDir, localRegistry, flags, debug, env }); @@ -244,7 +244,7 @@ const runGenerators = async ( cause: error, }); } - if (Math.random() < 0.4) { + if (Math.random() < 0.6) { throw new Error('Blip Bloop random error anywhere'); } await addDocumentation(baseDir, { name, dirName }); diff --git a/scripts/sandbox/publish.ts b/scripts/sandbox/publish.ts index e4307690efdd..99323c3a2420 100755 --- a/scripts/sandbox/publish.ts +++ b/scripts/sandbox/publish.ts @@ -1,14 +1,15 @@ import program from 'commander'; -import { join } from 'path'; +import { join, relative } from 'path'; import { existsSync } from 'fs'; import * as tempy from 'tempy'; -import { copy, emptyDir, readdir, remove, stat, writeFile } from 'fs-extra'; +import { copy, emptyDir, remove, writeFile } from 'fs-extra'; import { execaCommand } from 'execa'; import { getTemplatesData, renderTemplate } from './utils/template'; // eslint-disable-next-line import/no-cycle import { commitAllToGit } from './utils/git'; import { REPROS_DIRECTORY } from '../utils/constants'; +import { glob } from 'glob'; export const logger = console; @@ -31,15 +32,21 @@ const publish = async (options: PublishOptions & { tmpFolder: string }) => { // otherwise old files will stick around and result inconsistent states logger.log(`πŸ—‘ Delete existing template dirs from clone`); - const files = await Promise.all( - ( - await readdir(REPROS_DIRECTORY) - ).map(async (f) => ({ path: f, stats: await stat(join(REPROS_DIRECTORY, f)) })) - ); + + // empty all existing directories for sandboxes that have a successful after-storybook directory await Promise.all( - files - .filter(({ stats, path }) => stats.isDirectory && !path.startsWith('.')) - .map(async ({ path }) => emptyDir(join(tmpFolder, path))) + // find all successfully generated after-storybook directories + // eg. /home/repros/react-vite/default-ts/after-storybook + (await glob(join(REPROS_DIRECTORY, '**', 'after-storybook'))).map((dir) => { + // get their path relative to the source 'repros' directory + // eg. ./react-vite/default-ts/after-storybook + const pathRelativeToSource = relative(REPROS_DIRECTORY, dir); + // get the actual path to the corresponding sandbox directory in the clone + // eg. /home/sandboxes-clone/react-vite/default-ts + const sandboxDirectoryToEmpty = join(tmpFolder, pathRelativeToSource, '..'); + console.log({ pathRelativeToSource, sandboxDirectoryToEmpty }); + return emptyDir(sandboxDirectoryToEmpty); + }) ); logger.log(`🚚 Moving template files into the repository`); From 1e8eaa4583a1727599e8c7bb5153c309ac101937 Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Tue, 13 Feb 2024 09:49:09 +0100 Subject: [PATCH 16/79] publish based on the presence of a README.md --- scripts/sandbox/publish.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/scripts/sandbox/publish.ts b/scripts/sandbox/publish.ts index 99323c3a2420..fc5d6b6db5a6 100755 --- a/scripts/sandbox/publish.ts +++ b/scripts/sandbox/publish.ts @@ -1,5 +1,5 @@ import program from 'commander'; -import { join, relative } from 'path'; +import { dirname, join, relative } from 'path'; import { existsSync } from 'fs'; import * as tempy from 'tempy'; import { copy, emptyDir, remove, writeFile } from 'fs-extra'; @@ -35,16 +35,16 @@ const publish = async (options: PublishOptions & { tmpFolder: string }) => { // empty all existing directories for sandboxes that have a successful after-storybook directory await Promise.all( - // find all successfully generated after-storybook directories - // eg. /home/repros/react-vite/default-ts/after-storybook - (await glob(join(REPROS_DIRECTORY, '**', 'after-storybook'))).map((dir) => { - // get their path relative to the source 'repros' directory + // find all successfully generated after-storybook/README.md files + // eg. /home/repros/react-vite/default-ts/after-storybook/README.md + // README.md being the last fil generated, thus representing a successful generation + (await glob(join(REPROS_DIRECTORY, '**', 'after-storybook/README.md'))).map((readmePath) => { + // get the after-storybook path relative to the source 'repros' directory // eg. ./react-vite/default-ts/after-storybook - const pathRelativeToSource = relative(REPROS_DIRECTORY, dir); + const pathRelativeToSource = relative(REPROS_DIRECTORY, dirname(readmePath)); // get the actual path to the corresponding sandbox directory in the clone // eg. /home/sandboxes-clone/react-vite/default-ts const sandboxDirectoryToEmpty = join(tmpFolder, pathRelativeToSource, '..'); - console.log({ pathRelativeToSource, sandboxDirectoryToEmpty }); return emptyDir(sandboxDirectoryToEmpty); }) ); From fce6818d61b1e21d9235625e19def339c2ae04fa Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Tue, 13 Feb 2024 09:49:36 +0100 Subject: [PATCH 17/79] lower fake error threshold --- scripts/sandbox/generate.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/sandbox/generate.ts b/scripts/sandbox/generate.ts index dd77b4ee8574..91a4fd2fccd5 100755 --- a/scripts/sandbox/generate.ts +++ b/scripts/sandbox/generate.ts @@ -189,7 +189,7 @@ const runGenerators = async ( // where as others are very picky about what directories can be called. So we need to // handle different modes of operation. try { - if (Math.random() < 0.6) { + if (Math.random() < 0.2) { throw new Error('Blip Bloop random error when executing before-script'); } if (script.includes('{{beforeDir}}')) { @@ -227,7 +227,7 @@ const runGenerators = async ( await remove(join(beforeDir, '.git')); try { - if (Math.random() < 0.6) { + if (Math.random() < 0.2) { throw new Error('Blip Bloop random error when init storybook'); } await addStorybook({ baseDir, localRegistry, flags, debug, env }); @@ -244,7 +244,7 @@ const runGenerators = async ( cause: error, }); } - if (Math.random() < 0.6) { + if (Math.random() < 0.2) { throw new Error('Blip Bloop random error anywhere'); } await addDocumentation(baseDir, { name, dirName }); From 6b1be49c6b807939b6a940c0cf00b6ab7b7d6461 Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Tue, 13 Feb 2024 09:50:19 +0100 Subject: [PATCH 18/79] remove fake errors --- scripts/sandbox/generate.ts | 9 --------- 1 file changed, 9 deletions(-) diff --git a/scripts/sandbox/generate.ts b/scripts/sandbox/generate.ts index 91a4fd2fccd5..a28bbd6963f2 100755 --- a/scripts/sandbox/generate.ts +++ b/scripts/sandbox/generate.ts @@ -189,9 +189,6 @@ const runGenerators = async ( // where as others are very picky about what directories can be called. So we need to // handle different modes of operation. try { - if (Math.random() < 0.2) { - throw new Error('Blip Bloop random error when executing before-script'); - } if (script.includes('{{beforeDir}}')) { const scriptWithBeforeDir = script.replaceAll('{{beforeDir}}', BEFORE_DIR_NAME); await runCommand( @@ -227,9 +224,6 @@ const runGenerators = async ( await remove(join(beforeDir, '.git')); try { - if (Math.random() < 0.2) { - throw new Error('Blip Bloop random error when init storybook'); - } await addStorybook({ baseDir, localRegistry, flags, debug, env }); } catch (error) { const message = `❌ Failed to initialize Storybook in template: ${name} (${dirName})`; @@ -244,9 +238,6 @@ const runGenerators = async ( cause: error, }); } - if (Math.random() < 0.2) { - throw new Error('Blip Bloop random error anywhere'); - } await addDocumentation(baseDir, { name, dirName }); // Remove node_modules to save space and avoid GH actions failing From cea38444efa47fe291fe9cfddb1b255790951f05 Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Tue, 13 Feb 2024 12:31:57 +0100 Subject: [PATCH 19/79] =?UTF-8?q?actually=20remove=20fake=20errors=20?= =?UTF-8?q?=F0=9F=A4=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/sandbox/generate.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/scripts/sandbox/generate.ts b/scripts/sandbox/generate.ts index a28bbd6963f2..c313117987b5 100755 --- a/scripts/sandbox/generate.ts +++ b/scripts/sandbox/generate.ts @@ -87,9 +87,6 @@ const addStorybook = async ({ const tmpDir = directory(); try { - if (Math.random() < 0.2) { - throw new Error('Blip Bloop random error in addStorybook'); - } await copy(beforeDir, tmpDir); const packageManager = JsPackageManagerFactory.getPackageManager({ force: 'yarn1' }, tmpDir); From 1c3713eb6c54a5f66a0b55b1220b2edbfec57b5d Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Tue, 13 Feb 2024 21:28:14 +0100 Subject: [PATCH 20/79] always cleanup node_modules, don't collapse sandbox logs --- scripts/sandbox/generate.ts | 42 ++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/scripts/sandbox/generate.ts b/scripts/sandbox/generate.ts index c313117987b5..4e8f4bae1f4f 100755 --- a/scripts/sandbox/generate.ts +++ b/scripts/sandbox/generate.ts @@ -158,20 +158,15 @@ const runGenerators = async ( const generationResults = await Promise.allSettled( generators.map(({ dirName, name, script, expected, env }) => limit(async () => { + const baseDir = join(REPROS_DIRECTORY, dirName); + const beforeDir = join(baseDir, BEFORE_DIR_NAME); try { - if (isCI) { - ghActions.startGroup(`${name} (${dirName})`); - } - let flags: string[] = []; if (expected.renderer === '@storybook/html') flags = ['--type html']; else if (expected.renderer === '@storybook/server') flags = ['--type server']; const time = process.hrtime(); - console.log(`🧬 Generating ${name}`); - - const baseDir = join(REPROS_DIRECTORY, dirName); - const beforeDir = join(baseDir, BEFORE_DIR_NAME); + console.log(`🧬 Generating ${name} (${{ dirName }})`); await emptyDir(baseDir); // We do the creation inside a temp dir to avoid yarn container problems @@ -237,17 +232,8 @@ const runGenerators = async ( } await addDocumentation(baseDir, { name, dirName }); - // Remove node_modules to save space and avoid GH actions failing - // They're not uploaded to the git sandboxes repo anyway - if (process.env.CLEANUP_SANDBOX_NODE_MODULES) { - console.log(`πŸ—‘οΈ Removing ${join(beforeDir, 'node_modules')}`); - await remove(join(beforeDir, 'node_modules')); - console.log(`πŸ—‘οΈ Removing ${join(baseDir, AFTER_DIR_NAME, 'node_modules')}`); - await remove(join(baseDir, AFTER_DIR_NAME, 'node_modules')); - } - console.log( - `βœ… Created ${dirName} in ./${relative( + `βœ… Generated ${name} (${dirName}) in ./${relative( process.cwd(), baseDir )} successfully in ${prettyTime(process.hrtime(time))}` @@ -255,8 +241,13 @@ const runGenerators = async ( } catch (error) { throw error; } finally { - if (isCI) { - ghActions.endGroup(); + // Remove node_modules to save space and avoid GH actions failing + // They're not uploaded to the git sandboxes repo anyway + if (process.env.CLEANUP_SANDBOX_NODE_MODULES) { + console.log(`πŸ—‘οΈ Removing ${join(beforeDir, 'node_modules')}`); + await remove(join(beforeDir, 'node_modules')); + console.log(`πŸ—‘οΈ Removing ${join(baseDir, AFTER_DIR_NAME, 'node_modules')}`); + await remove(join(baseDir, AFTER_DIR_NAME, 'node_modules')); } } }) @@ -281,17 +272,20 @@ const runGenerators = async ( ], ...generationResults.map((result, index) => { const { name, dirName } = generators[index]; + const row = [name, `\`${dirName}\``]; if (result.status === 'fulfilled') { - return [name, dirName, '🟒 Pass']; + row.push('🟒 Pass'); + return row; } const generationError = (result as PromiseRejectedResult).reason as Error; if (generationError instanceof BeforeScriptExecutionError) { - return [name, dirName, 'πŸ”΄ Failed to execute before script']; + row.push('πŸ”΄ Failed to execute before script'); } else if (generationError instanceof StorybookInitError) { - return [name, dirName, 'πŸ”΄ Failed to initialize Storybook']; + row.push('πŸ”΄ Failed to initialize Storybook'); } else { - return [name, dirName, 'πŸ”΄ Failed with unknown error']; + row.push('πŸ”΄ Failed with unknown error'); } + return row; }), ]) .write(); From 01962f352935bba1cd3fc7ce52873a7edc6caa6f Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Tue, 13 Feb 2024 21:28:39 +0100 Subject: [PATCH 21/79] remove test variables from generate workflow, add job for main --- .github/workflows/generate-sandboxes.yml | 66 +++++++++++++++++++++--- 1 file changed, 59 insertions(+), 7 deletions(-) diff --git a/.github/workflows/generate-sandboxes.yml b/.github/workflows/generate-sandboxes.yml index 774cd297c571..88dc9e21bb41 100644 --- a/.github/workflows/generate-sandboxes.yml +++ b/.github/workflows/generate-sandboxes.yml @@ -6,12 +6,12 @@ on: workflow_dispatch: # To test fixes on push rather than wait for the scheduling, do the following: # 1. Uncomment the lines below and add your branch. - push: - branches: - - jeppe/25922-ci-generation-of-sandboxes-fail-sometimes-on-prereleases + # push: + # branches: + # - # 2. Change the "ref" value to in the actions/checkout step below. - # 3. Comment out the whole "generate-main" job starting at line 26 - # 3. πŸ‘‰ DON'T FORGET TO UNDO STEP 2 AND 3 BEFORE YOU MERGE YOUR CHANGES! + # 3. Comment out the whole "generate-main" job starting at line 77 + # 4. πŸ‘‰ DON'T FORGET TO UNDO THE STEPS BEFORE YOU MERGE YOUR CHANGES! env: YARN_ENABLE_IMMUTABLE_INSTALLS: "false" @@ -28,7 +28,7 @@ jobs: steps: - uses: actions/checkout@v4 with: - ref: jeppe/25922-ci-generation-of-sandboxes-fail-sometimes-on-prereleases + ref: next - uses: actions/setup-node@v4 with: @@ -62,7 +62,7 @@ jobs: - name: Publish # publish sandboxes even if the generation fails, as some sandboxes might have been generated successfully if: ${{ !cancelled() }} - run: yarn publish-sandboxes --remote=https://storybook-bot:${{ secrets.PAT_STORYBOOK_BOT }}@github.com/storybookjs/sandboxes.git --push --branch=jeppe/experiment-partial-generation + run: yarn publish-sandboxes --remote=https://storybook-bot:${{ secrets.PAT_STORYBOOK_BOT }}@github.com/storybookjs/sandboxes.git --push --branch=next - name: Report failure to Discord if: failure() @@ -73,3 +73,55 @@ jobs: args: | The generation of some or all sandboxes on the **next** branch has failed. [See the job summary for details](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) + + generate-main: + name: Generate to main + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: main + + - uses: actions/setup-node@v4 + with: + node-version-file: ".nvmrc" + + - name: Setup git user + run: | + git config --global user.name "storybook-bot" + git config --global user.email "32066757+storybook-bot@users.noreply.github.com" + + - name: Install dependencies + working-directory: ./scripts + run: node --experimental-modules ./check-dependencies.js + + - name: Compile Storybook libraries + run: yarn task --task compile --start-from=auto --no-link + + - name: Publish to local registry + run: yarn local-registry --publish + + - name: Run local registry + run: yarn local-registry --open & + + - name: Wait for registry + run: yarn wait-on tcp:127.0.0.1:6001 + + - name: Generate + id: generate + run: yarn generate-sandboxes --local-registry + + - name: Publish + # publish sandboxes even if the generation fails, as some sandboxes might have been generated successfully + if: ${{ !cancelled() }} + run: yarn publish-sandboxes --remote=https://storybook-bot:${{ secrets.PAT_STORYBOOK_BOT }}@github.com/storybookjs/sandboxes.git --push --branch=main + + - name: Report failure to Discord + if: failure() + env: + DISCORD_WEBHOOK: ${{ secrets.DISCORD_MONITORING_URL }} + uses: Ilshidur/action-discord@master + with: + args: | + The generation of some or all sandboxes on the **main** branch has failed. + [See the job summary for details](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) From 43deb5f2ab9c3553daf6fccd0a4bc5ffdc76b6b5 Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Tue, 13 Feb 2024 21:37:01 +0100 Subject: [PATCH 22/79] only write summary in CI --- scripts/sandbox/generate.ts | 65 ++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 29 deletions(-) diff --git a/scripts/sandbox/generate.ts b/scripts/sandbox/generate.ts index 4e8f4bae1f4f..410d49373d93 100755 --- a/scripts/sandbox/generate.ts +++ b/scripts/sandbox/generate.ts @@ -254,42 +254,49 @@ const runGenerators = async ( ) ); + const hasGenerationErrors = generationResults.some((result) => result.status === 'rejected'); + + if (!isCI) { + if (hasGenerationErrors) { + throw new Error(`Some sandboxes failed to generate`); + } + return; + } + ghActions.summary.addHeading('Sandbox generation summary'); - if (!generationResults.some((result) => result.status === 'rejected')) { + if (!hasGenerationErrors) { await ghActions.summary.addRaw('βœ… Success!').write(); return; } - if (isCI) { - await ghActions.summary - .addRaw('Some sandboxes failed, see the job log for detailed errors') - .addTable([ - [ - { data: 'Name', header: true }, - { data: 'Key', header: true }, - { data: 'Result', header: true }, - ], - ...generationResults.map((result, index) => { - const { name, dirName } = generators[index]; - const row = [name, `\`${dirName}\``]; - if (result.status === 'fulfilled') { - row.push('🟒 Pass'); - return row; - } - const generationError = (result as PromiseRejectedResult).reason as Error; - if (generationError instanceof BeforeScriptExecutionError) { - row.push('πŸ”΄ Failed to execute before script'); - } else if (generationError instanceof StorybookInitError) { - row.push('πŸ”΄ Failed to initialize Storybook'); - } else { - row.push('πŸ”΄ Failed with unknown error'); - } + await ghActions.summary + .addRaw('Some sandboxes failed, see the job log for detailed errors') + .addTable([ + [ + { data: 'Name', header: true }, + { data: 'Key', header: true }, + { data: 'Result', header: true }, + ], + ...generationResults.map((result, index) => { + const { name, dirName } = generators[index]; + const row = [name, `\`${dirName}\``]; + if (result.status === 'fulfilled') { + row.push('🟒 Pass'); return row; - }), - ]) - .write(); - } + } + const generationError = (result as PromiseRejectedResult).reason as Error; + if (generationError instanceof BeforeScriptExecutionError) { + row.push('πŸ”΄ Failed to execute before script'); + } else if (generationError instanceof StorybookInitError) { + row.push('πŸ”΄ Failed to initialize Storybook'); + } else { + row.push('πŸ”΄ Failed with unknown error'); + } + return row; + }), + ]) + .write(); throw new Error(`Some sandboxes failed to generate`); }; From d8e40ace46938dc5f22813c15d4d7266d78d6261 Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Tue, 13 Feb 2024 21:45:08 +0100 Subject: [PATCH 23/79] typo --- scripts/sandbox/publish.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/sandbox/publish.ts b/scripts/sandbox/publish.ts index fc5d6b6db5a6..334e8a9177eb 100755 --- a/scripts/sandbox/publish.ts +++ b/scripts/sandbox/publish.ts @@ -37,7 +37,7 @@ const publish = async (options: PublishOptions & { tmpFolder: string }) => { await Promise.all( // find all successfully generated after-storybook/README.md files // eg. /home/repros/react-vite/default-ts/after-storybook/README.md - // README.md being the last fil generated, thus representing a successful generation + // README.md being the last file generated, thus representing a successful generation (await glob(join(REPROS_DIRECTORY, '**', 'after-storybook/README.md'))).map((readmePath) => { // get the after-storybook path relative to the source 'repros' directory // eg. ./react-vite/default-ts/after-storybook From 249276b860be1354d523f940076a3ae609f113be Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Fri, 23 Feb 2024 13:25:04 +0100 Subject: [PATCH 24/79] support new way of mounting components in svelte 5 --- code/renderers/svelte/package.json | 11 +- .../svelte/src/createSvelte5Props.svelte.js | 12 ++ code/renderers/svelte/src/render.ts | 161 ++++++++++++------ .../svelte/templates/PreviewRender.svelte | 36 ++-- code/yarn.lock | 91 ++++++++-- 5 files changed, 227 insertions(+), 84 deletions(-) create mode 100644 code/renderers/svelte/src/createSvelte5Props.svelte.js diff --git a/code/renderers/svelte/package.json b/code/renderers/svelte/package.json index d7efba34d699..03a0f1da6664 100644 --- a/code/renderers/svelte/package.json +++ b/code/renderers/svelte/package.json @@ -32,7 +32,8 @@ "./package.json": "./package.json", "./templates/HOC.svelte": "./templates/HOC.svelte", "./templates/PreviewRender.svelte": "./templates/PreviewRender.svelte", - "./templates/SlotDecorator.svelte": "./templates/SlotDecorator.svelte" + "./templates/SlotDecorator.svelte": "./templates/SlotDecorator.svelte", + "./internal/createSvelte5Props": "./src/createSvelte5Props.svelte.js" }, "main": "dist/index.js", "module": "dist/index.mjs", @@ -62,14 +63,14 @@ "type-fest": "~2.19" }, "devDependencies": { - "@sveltejs/vite-plugin-svelte": "^3.0.1", + "@sveltejs/vite-plugin-svelte": "^3.0.2", "expect-type": "^0.15.0", - "svelte": "^5.0.0-next.28", - "svelte-check": "^3.6.1", + "svelte": "^5.0.0-next.65", + "svelte-check": "^3.6.4", "typescript": "^5.3.2" }, "peerDependencies": { - "svelte": "^4.0.0 || ^5.0.0-next.16" + "svelte": "^4.0.0 || ^5.0.0-next.65" }, "engines": { "node": ">=18.0.0" diff --git a/code/renderers/svelte/src/createSvelte5Props.svelte.js b/code/renderers/svelte/src/createSvelte5Props.svelte.js new file mode 100644 index 000000000000..bef729413204 --- /dev/null +++ b/code/renderers/svelte/src/createSvelte5Props.svelte.js @@ -0,0 +1,12 @@ +/** + * Turns an object into reactive props in Svelte 5. + * Needs to be in a separate .svelte.js file to ensure Svelte + * compiles it. + * @template TProps + * @param {TProps} data - The data to create Svelte 5 props from. + * @returns {TProps} - The created Svelte 5 props. + */ +export const createSvelte5Props = (data) => { + const props = $state(data); + return props; +}; diff --git a/code/renderers/svelte/src/render.ts b/code/renderers/svelte/src/render.ts index 514b3128ed21..c9925d56e0ca 100644 --- a/code/renderers/svelte/src/render.ts +++ b/code/renderers/svelte/src/render.ts @@ -1,50 +1,30 @@ import type { RenderContext, ArgsStoryFn } from '@storybook/types'; import { RESET_STORY_ARGS } from '@storybook/core-events'; -// ! DO NOT change this PreviewRender import to a relative path, it will break it. -// ! A relative import will be compiled at build time, and Svelte will be unable to -// ! render the component together with the user's Svelte components -// ! importing from @storybook/svelte will make sure that it is compiled at runtime -// ! with the same bundle as the user's Svelte components +// ! DO NOT change these PreviewRender and createSvelte5Props imports to relative paths, it will break them. +// ! Relative imports will be compiled at build time by tsup, but we need Svelte to compile them +// ! when compiling the rest of the Svelte files. // eslint-disable-next-line import/no-extraneous-dependencies import PreviewRender from '@storybook/svelte/templates/PreviewRender.svelte'; +// @ts-expect-error Don't know why TS doesn't pick up the types export here +import { createSvelte5Props } from '@storybook/svelte/internal/createSvelte5Props'; + import { addons } from '@storybook/preview-api'; import * as svelte from 'svelte'; +import { VERSION as SVELTE_VERSION } from 'svelte/compiler'; import type { SvelteRenderer } from './types'; -const componentsByDomElement = new Map< - SvelteRenderer['canvasElement'], - any // ReturnType depends on the version of Svelte v4 or v5 ->(); - -function teardown(canvasElement: SvelteRenderer['canvasElement']) { - if (!componentsByDomElement.has(canvasElement)) { - return; - } - - componentsByDomElement.get(canvasElement)!.$destroy(); - - canvasElement.innerHTML = ''; - componentsByDomElement.delete(canvasElement); -} +const IS_SVELTE_V4 = Number(SVELTE_VERSION[0]) >= 4; -/** - * Mount the PreviewRender component to the provided canvasElement - * Either using the Svelte v4 or v5 API - */ -function createRoot(target: HTMLElement, props: any) { - if ((svelte as any).createRoot) { - // Svelte v5 - return (svelte as any).createRoot(PreviewRender, { - target, - props, - }); +export function renderToCanvas( + renderContext: RenderContext, + canvasElement: SvelteRenderer['canvasElement'] +) { + if (IS_SVELTE_V4) { + return renderToCanvasV4(renderContext, canvasElement); + } else { + return renderToCanvasV5(renderContext, canvasElement); } - // Svelte v4 - return new (PreviewRender as any)({ - target, - props, - }); } /** @@ -55,16 +35,21 @@ function createRoot(target: HTMLElement, props: any) { * * We listen for the RESET_STORY_ARGS event and store the storyId to be reset * We then use this in the renderToCanvas function to force remount the story + * + * This is only necessary in Svelte v4 */ const storyIdsToRemountFromResetArgsEvent = new Set(); -addons.getChannel().on(RESET_STORY_ARGS, ({ storyId }) => { - storyIdsToRemountFromResetArgsEvent.add(storyId); -}); +if (IS_SVELTE_V4) { + addons.getChannel().on(RESET_STORY_ARGS, ({ storyId }) => { + storyIdsToRemountFromResetArgsEvent.add(storyId); + }); +} +const componentsByDomElementV4 = new Map(); -export function renderToCanvas( +function renderToCanvasV4( { storyFn, - kind, + title, name, showMain, showError, @@ -73,43 +58,117 @@ export function renderToCanvas( }: RenderContext, canvasElement: SvelteRenderer['canvasElement'] ) { - const existingComponent = componentsByDomElement.get(canvasElement); + function unmount(canvasElementToUnmount: SvelteRenderer['canvasElement']) { + if (!componentsByDomElementV4.has(canvasElementToUnmount)) { + return; + } + componentsByDomElementV4.get(canvasElementToUnmount)!.$destroy(); + componentsByDomElementV4.delete(canvasElementToUnmount); + canvasElementToUnmount.innerHTML = ''; + } + const existingComponent = componentsByDomElementV4.get(canvasElement); let remount = forceRemount; - if (storyIdsToRemountFromResetArgsEvent.has(storyContext.id)) { remount = true; storyIdsToRemountFromResetArgsEvent.delete(storyContext.id); } if (remount) { - teardown(canvasElement); + unmount(canvasElement); } if (!existingComponent || remount) { - const createdComponent = createRoot(canvasElement, { + const mountedComponent = new PreviewRender({ + target: canvasElement, + props: { + storyFn, + storyContext, + name, + title, + showError, + }, + }); + componentsByDomElementV4.set(canvasElement, mountedComponent); + } else { + existingComponent.$set({ + storyFn, + storyContext, + name, + title, + showError, + }); + } + + showMain(); + + // unmount the component when the story changes + return () => { + unmount(canvasElement); + }; +} + +const componentsByDomElementV5 = new Map< + SvelteRenderer['canvasElement'], + { mountedComponent: ReturnType<(typeof svelte)['mount']>; props: RenderContext } +>(); + +function renderToCanvasV5( + { + storyFn, + title, + name, + showMain, + showError, + storyContext, + forceRemount, + }: RenderContext, + canvasElement: SvelteRenderer['canvasElement'] +) { + function unmount(canvasElementToUnmount: SvelteRenderer['canvasElement']) { + const { mountedComponent } = componentsByDomElementV5.get(canvasElementToUnmount) ?? {}; + if (!mountedComponent) { + return; + } + svelte.unmount(mountedComponent); + componentsByDomElementV5.delete(canvasElementToUnmount); + } + + const existingComponent = componentsByDomElementV5.get(canvasElement); + + if (forceRemount) { + unmount(canvasElement); + } + + if (!existingComponent || forceRemount) { + const props = createSvelte5Props({ storyFn, storyContext, name, - kind, + title, showError, }); - componentsByDomElement.set(canvasElement, createdComponent); + const mountedComponent = svelte.mount(PreviewRender, { + target: canvasElement, + props, + }); + componentsByDomElementV5.set(canvasElement, { mountedComponent, props }); } else { - existingComponent.$set({ + // We need to mutate the existing props for Svelte reactivity to work, we can't just re-assign them + Object.assign(existingComponent.props, { storyFn, storyContext, name, - kind, + title, showError, }); } showMain(); - // teardown the component when the story changes + // unmount the component when the story changes return () => { - teardown(canvasElement); + unmount(canvasElement); }; } diff --git a/code/renderers/svelte/templates/PreviewRender.svelte b/code/renderers/svelte/templates/PreviewRender.svelte index 581aa4d78e05..b2900a0ddb24 100644 --- a/code/renderers/svelte/templates/PreviewRender.svelte +++ b/code/renderers/svelte/templates/PreviewRender.svelte @@ -3,7 +3,7 @@ import { dedent } from 'ts-dedent'; export let name; - export let kind; + export let title; export let storyFn; export let showError; export let storyContext; @@ -17,22 +17,22 @@ on, } = storyFn(); - let firstTime = true; - - // the first time we don't want to call storyFn two times so we just return the values - // we already have from the previous call. If storyFn changes this function will run - // again but this time firstTime will be false - function getStoryFnValue(storyFn){ - if(firstTime){ - firstTime = false; - return { - Component, - props, - on, - } - } - return storyFn(); - } + let firstTime = true; + + // the first time we don't want to call storyFn two times so we just return the values + // we already have from the previous call. If storyFn changes this function will run + // again but this time firstTime will be false + function getStoryFnValue(storyFn) { + if (firstTime) { + firstTime = false; + return { + Component, + props, + on, + }; + } + return storyFn(); + } // reactive, re-render on storyFn change $: ({ Component, props = {}, on } = getStoryFnValue(storyFn)); @@ -45,7 +45,7 @@ if (!Component) { showError({ - title: `Expecting a Svelte component from the story: "${name}" of "${kind}".`, + title: `Expecting a Svelte component from the story: "${name}" of "${title}".`, description: dedent` Did you forget to return the Svelte component configuration from the story? Use "() => ({ Component: YourComponent, props: {} })" diff --git a/code/yarn.lock b/code/yarn.lock index 07c7d2bd6b0e..5d66006d503e 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -6676,16 +6676,16 @@ __metadata: "@storybook/global": "npm:^5.0.0" "@storybook/preview-api": "workspace:*" "@storybook/types": "workspace:*" - "@sveltejs/vite-plugin-svelte": "npm:^3.0.1" + "@sveltejs/vite-plugin-svelte": "npm:^3.0.2" expect-type: "npm:^0.15.0" - svelte: "npm:^5.0.0-next.28" - svelte-check: "npm:^3.6.1" + svelte: "npm:^5.0.0-next.65" + svelte-check: "npm:^3.6.4" sveltedoc-parser: "npm:^4.2.1" ts-dedent: "npm:^2.0.0" type-fest: "npm:~2.19" typescript: "npm:^5.3.2" peerDependencies: - svelte: ^4.0.0 || ^5.0.0-next.16 + svelte: ^4.0.0 || ^5.0.0-next.65 languageName: unknown linkType: soft @@ -6919,7 +6919,7 @@ __metadata: languageName: node linkType: hard -"@sveltejs/vite-plugin-svelte-inspector@npm:^2.0.0-next.0 || ^2.0.0": +"@sveltejs/vite-plugin-svelte-inspector@npm:^2.0.0, @sveltejs/vite-plugin-svelte-inspector@npm:^2.0.0-next.0 || ^2.0.0": version: 2.0.0 resolution: "@sveltejs/vite-plugin-svelte-inspector@npm:2.0.0" dependencies: @@ -6950,6 +6950,24 @@ __metadata: languageName: node linkType: hard +"@sveltejs/vite-plugin-svelte@npm:^3.0.2": + version: 3.0.2 + resolution: "@sveltejs/vite-plugin-svelte@npm:3.0.2" + dependencies: + "@sveltejs/vite-plugin-svelte-inspector": "npm:^2.0.0" + debug: "npm:^4.3.4" + deepmerge: "npm:^4.3.1" + kleur: "npm:^4.1.5" + magic-string: "npm:^0.30.5" + svelte-hmr: "npm:^0.15.3" + vitefu: "npm:^0.2.5" + peerDependencies: + svelte: ^4.0.0 || ^5.0.0-next.0 + vite: ^5.0.0 + checksum: 7150877f61b65a51d55916fccacb7851859b0aab9c7e4f591c98b6775a7e55f5410cc854add4c427f99978f115a92ac75f116a813b67814cc7801daac1b78439 + languageName: node + linkType: hard + "@swc/helpers@npm:0.5.2": version: 0.5.2 resolution: "@swc/helpers@npm:0.5.2" @@ -7432,6 +7450,13 @@ __metadata: languageName: node linkType: hard +"@types/estree@npm:^1.0.5": + version: 1.0.5 + resolution: "@types/estree@npm:1.0.5" + checksum: b3b0e334288ddb407c7b3357ca67dbee75ee22db242ca7c56fe27db4e1a31989cb8af48a84dd401deb787fe10cc6b2ab1ee82dc4783be87ededbe3d53c79c70d + languageName: node + linkType: hard + "@types/express-serve-static-core@npm:*, @types/express-serve-static-core@npm:^4.17.33": version: 4.17.37 resolution: "@types/express-serve-static-core@npm:4.17.37" @@ -9266,6 +9291,15 @@ __metadata: languageName: node linkType: hard +"acorn-typescript@npm:^1.4.13": + version: 1.4.13 + resolution: "acorn-typescript@npm:1.4.13" + peerDependencies: + acorn: ">=8.9.0" + checksum: f2f17cf03379d63beeb007f0feea02cebbd9af261f6b5619ea7345b177bd7a5f99752927cbf652baa3fc97962ae4561592093ab0a1c3e00ca4f354ba23c557ae + languageName: node + linkType: hard + "acorn-walk@npm:^7.2.0": version: 7.2.0 resolution: "acorn-walk@npm:7.2.0" @@ -9305,6 +9339,15 @@ __metadata: languageName: node linkType: hard +"acorn@npm:^8.11.3": + version: 8.11.3 + resolution: "acorn@npm:8.11.3" + bin: + acorn: bin/acorn + checksum: 3ff155f8812e4a746fee8ecff1f227d527c4c45655bb1fad6347c3cb58e46190598217551b1500f18542d2bbe5c87120cb6927f5a074a59166fbdd9468f0a299 + languageName: node + linkType: hard + "address@npm:^1.0.1": version: 1.2.2 resolution: "address@npm:1.2.2" @@ -17871,7 +17914,7 @@ __metadata: languageName: node linkType: hard -"is-reference@npm:^3.0.0, is-reference@npm:^3.0.1": +"is-reference@npm:^3.0.0, is-reference@npm:^3.0.1, is-reference@npm:^3.0.2": version: 3.0.2 resolution: "is-reference@npm:3.0.2" dependencies: @@ -27088,9 +27131,9 @@ __metadata: languageName: node linkType: hard -"svelte-check@npm:^3.6.1": - version: 3.6.2 - resolution: "svelte-check@npm:3.6.2" +"svelte-check@npm:^3.6.4": + version: 3.6.4 + resolution: "svelte-check@npm:3.6.4" dependencies: "@jridgewell/trace-mapping": "npm:^0.3.17" chokidar: "npm:^3.4.1" @@ -27104,7 +27147,7 @@ __metadata: svelte: ^3.55.0 || ^4.0.0-next.0 || ^4.0.0 || ^5.0.0-next.0 bin: svelte-check: bin/svelte-check - checksum: 3f389df29268d4df9b561d0b206566e827af84923c70150b2dadfd407bcbdaccbfd561bd8b93884597de62477d62826ff1a5108854641078b692130441a49a55 + checksum: acbcc04c8c6ab7baee7ccf36ca134dcabe49fae103aa92661e7f80e01216623363fb794fec9a3f794f7003d55629373567ff485925dc33272f48cea63e7b2452 languageName: node linkType: hard @@ -27233,6 +27276,27 @@ __metadata: languageName: node linkType: hard +"svelte@npm:^5.0.0-next.65": + version: 5.0.0-next.65 + resolution: "svelte@npm:5.0.0-next.65" + dependencies: + "@ampproject/remapping": "npm:^2.2.1" + "@jridgewell/sourcemap-codec": "npm:^1.4.15" + "@types/estree": "npm:^1.0.5" + acorn: "npm:^8.11.3" + acorn-typescript: "npm:^1.4.13" + aria-query: "npm:^5.3.0" + axobject-query: "npm:^4.0.0" + esm-env: "npm:^1.0.0" + esrap: "npm:^1.2.1" + is-reference: "npm:^3.0.2" + locate-character: "npm:^3.0.0" + magic-string: "npm:^0.30.5" + zimmerframe: "npm:^1.1.2" + checksum: 6a686847f887d2871eabce4888916cba6aec5bae924a76fd01f4098db1c0053d4e5d6434070d0a048eac75eaddd4fd40e3fae625a0253464f7baa6b0f147f209 + languageName: node + linkType: hard + "sveltedoc-parser@npm:^4.2.1": version: 4.3.1 resolution: "sveltedoc-parser@npm:4.3.1" @@ -30261,6 +30325,13 @@ __metadata: languageName: node linkType: hard +"zimmerframe@npm:^1.1.2": + version: 1.1.2 + resolution: "zimmerframe@npm:1.1.2" + checksum: 8f693609c31cbb4449db223acd61661bc93b73e615f9db6fb8c86d4ceea84ca54cbbeebcf53cf74c22a1f923b92abd18e97988a5e175c76b6ab17238e5593a9d + languageName: node + linkType: hard + "zod@npm:^3.22.2": version: 3.22.4 resolution: "zod@npm:3.22.4" From f37524b8e07bf104dc758ac484a932fc38e80b89 Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Mon, 26 Feb 2024 08:51:54 +0100 Subject: [PATCH 25/79] move and cleanup Svelte components --- code/frameworks/svelte-webpack5/src/typings.d.ts | 5 ++--- code/renderers/svelte/package.json | 5 ++--- .../{templates => src/components}/PreviewRender.svelte | 0 .../{templates => src/components}/SlotDecorator.svelte | 0 code/renderers/svelte/src/decorators.ts | 3 +-- code/renderers/svelte/src/render.ts | 3 +-- code/renderers/svelte/templates/HOC.svelte | 7 ------- 7 files changed, 6 insertions(+), 17 deletions(-) rename code/renderers/svelte/{templates => src/components}/PreviewRender.svelte (100%) rename code/renderers/svelte/{templates => src/components}/SlotDecorator.svelte (100%) delete mode 100644 code/renderers/svelte/templates/HOC.svelte diff --git a/code/frameworks/svelte-webpack5/src/typings.d.ts b/code/frameworks/svelte-webpack5/src/typings.d.ts index 48e7ba6228fd..153f6ec1f9ce 100644 --- a/code/frameworks/svelte-webpack5/src/typings.d.ts +++ b/code/frameworks/svelte-webpack5/src/typings.d.ts @@ -1,3 +1,2 @@ -declare module '@storybook/svelte/templates/SlotDecorator.svelte'; -declare module '@storybook/svelte/templates/PreviewRender.svelte'; -declare module '@storybook/svelte/templates/HOC.svelte'; +declare module '@storybook/svelte/internal/SlotDecorator.svelte'; +declare module '@storybook/svelte/internal/PreviewRender.svelte'; diff --git a/code/renderers/svelte/package.json b/code/renderers/svelte/package.json index 03a0f1da6664..6fdccc844d86 100644 --- a/code/renderers/svelte/package.json +++ b/code/renderers/svelte/package.json @@ -30,9 +30,8 @@ "./dist/entry-preview.mjs": "./dist/entry-preview.mjs", "./dist/entry-preview-docs.mjs": "./dist/entry-preview-docs.mjs", "./package.json": "./package.json", - "./templates/HOC.svelte": "./templates/HOC.svelte", - "./templates/PreviewRender.svelte": "./templates/PreviewRender.svelte", - "./templates/SlotDecorator.svelte": "./templates/SlotDecorator.svelte", + "./internal/PreviewRender.svelte": "./src/components/PreviewRender.svelte", + "./internal/SlotDecorator.svelte": "./src/components/SlotDecorator.svelte", "./internal/createSvelte5Props": "./src/createSvelte5Props.svelte.js" }, "main": "dist/index.js", diff --git a/code/renderers/svelte/templates/PreviewRender.svelte b/code/renderers/svelte/src/components/PreviewRender.svelte similarity index 100% rename from code/renderers/svelte/templates/PreviewRender.svelte rename to code/renderers/svelte/src/components/PreviewRender.svelte diff --git a/code/renderers/svelte/templates/SlotDecorator.svelte b/code/renderers/svelte/src/components/SlotDecorator.svelte similarity index 100% rename from code/renderers/svelte/templates/SlotDecorator.svelte rename to code/renderers/svelte/src/components/SlotDecorator.svelte diff --git a/code/renderers/svelte/src/decorators.ts b/code/renderers/svelte/src/decorators.ts index 07fb1753b56d..58ca0f7ea229 100644 --- a/code/renderers/svelte/src/decorators.ts +++ b/code/renderers/svelte/src/decorators.ts @@ -5,8 +5,7 @@ import { sanitizeStoryContextUpdate } from '@storybook/preview-api'; // ! render the component together with the user's Svelte components // ! importing from @storybook/svelte will make sure that it is compiled at runtime // ! with the same bundle as the user's Svelte components -// eslint-disable-next-line import/no-extraneous-dependencies -import SlotDecorator from '@storybook/svelte/templates/SlotDecorator.svelte'; +import SlotDecorator from '@storybook/svelte/internal/SlotDecorator.svelte'; import type { SvelteRenderer } from './types'; /** diff --git a/code/renderers/svelte/src/render.ts b/code/renderers/svelte/src/render.ts index c9925d56e0ca..c828fe831834 100644 --- a/code/renderers/svelte/src/render.ts +++ b/code/renderers/svelte/src/render.ts @@ -3,8 +3,7 @@ import { RESET_STORY_ARGS } from '@storybook/core-events'; // ! DO NOT change these PreviewRender and createSvelte5Props imports to relative paths, it will break them. // ! Relative imports will be compiled at build time by tsup, but we need Svelte to compile them // ! when compiling the rest of the Svelte files. -// eslint-disable-next-line import/no-extraneous-dependencies -import PreviewRender from '@storybook/svelte/templates/PreviewRender.svelte'; +import PreviewRender from '@storybook/svelte/internal/PreviewRender.svelte'; // @ts-expect-error Don't know why TS doesn't pick up the types export here import { createSvelte5Props } from '@storybook/svelte/internal/createSvelte5Props'; diff --git a/code/renderers/svelte/templates/HOC.svelte b/code/renderers/svelte/templates/HOC.svelte deleted file mode 100644 index 0b6c3618701e..000000000000 --- a/code/renderers/svelte/templates/HOC.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - \ No newline at end of file From 1b17dfee562a85be19013071f1d7703b945d9b2a Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Mon, 26 Feb 2024 09:10:06 +0100 Subject: [PATCH 26/79] comment improvements --- .../svelte/src/createSvelte5Props.svelte.js | 1 + code/renderers/svelte/src/decorators.ts | 12 +++++++----- code/renderers/svelte/src/render.ts | 8 +++++--- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/code/renderers/svelte/src/createSvelte5Props.svelte.js b/code/renderers/svelte/src/createSvelte5Props.svelte.js index bef729413204..bbefc19bbf43 100644 --- a/code/renderers/svelte/src/createSvelte5Props.svelte.js +++ b/code/renderers/svelte/src/createSvelte5Props.svelte.js @@ -2,6 +2,7 @@ * Turns an object into reactive props in Svelte 5. * Needs to be in a separate .svelte.js file to ensure Svelte * compiles it. + * As proposed in https://github.com/sveltejs/svelte/issues/9827#issuecomment-1845589616 * @template TProps * @param {TProps} data - The data to create Svelte 5 props from. * @returns {TProps} - The created Svelte 5 props. diff --git a/code/renderers/svelte/src/decorators.ts b/code/renderers/svelte/src/decorators.ts index 58ca0f7ea229..657fa91ff28e 100644 --- a/code/renderers/svelte/src/decorators.ts +++ b/code/renderers/svelte/src/decorators.ts @@ -1,10 +1,12 @@ import type { DecoratorFunction, StoryContext, LegacyStoryFn } from '@storybook/types'; import { sanitizeStoryContextUpdate } from '@storybook/preview-api'; -// ! DO NOT change this SlotDecorator import to a relative path, it will break it. -// ! A relative import will be compiled at build time, and Svelte will be unable to -// ! render the component together with the user's Svelte components -// ! importing from @storybook/svelte will make sure that it is compiled at runtime -// ! with the same bundle as the user's Svelte components +/* +! DO NOT change this SlotDecorator import to a relative path, it will break it. +! A relative import will be compiled at build time, and Svelte will be unable to +! render the component together with the user's Svelte components +! importing from @storybook/svelte will make sure that it is compiled at runtime +! with the same bundle as the user's Svelte components +*/ import SlotDecorator from '@storybook/svelte/internal/SlotDecorator.svelte'; import type { SvelteRenderer } from './types'; diff --git a/code/renderers/svelte/src/render.ts b/code/renderers/svelte/src/render.ts index c828fe831834..f8875a13e815 100644 --- a/code/renderers/svelte/src/render.ts +++ b/code/renderers/svelte/src/render.ts @@ -1,8 +1,10 @@ import type { RenderContext, ArgsStoryFn } from '@storybook/types'; import { RESET_STORY_ARGS } from '@storybook/core-events'; -// ! DO NOT change these PreviewRender and createSvelte5Props imports to relative paths, it will break them. -// ! Relative imports will be compiled at build time by tsup, but we need Svelte to compile them -// ! when compiling the rest of the Svelte files. +/* +! DO NOT change these PreviewRender and createSvelte5Props imports to relative paths, it will break them. +! Relative imports will be compiled at build time by tsup, but we need Svelte to compile them +! when compiling the rest of the Svelte files. +*/ import PreviewRender from '@storybook/svelte/internal/PreviewRender.svelte'; // @ts-expect-error Don't know why TS doesn't pick up the types export here import { createSvelte5Props } from '@storybook/svelte/internal/createSvelte5Props'; From a3bfcbb2511b4f8e226ce4099f8f0f61649878b1 Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Mon, 26 Feb 2024 14:47:52 +0100 Subject: [PATCH 27/79] =?UTF-8?q?Fix=20Svelte=20version=20check.=20?= =?UTF-8?q?=F0=9F=A4=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/renderers/svelte/src/render.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/renderers/svelte/src/render.ts b/code/renderers/svelte/src/render.ts index f8875a13e815..3b22469af003 100644 --- a/code/renderers/svelte/src/render.ts +++ b/code/renderers/svelte/src/render.ts @@ -15,7 +15,7 @@ import { VERSION as SVELTE_VERSION } from 'svelte/compiler'; import type { SvelteRenderer } from './types'; -const IS_SVELTE_V4 = Number(SVELTE_VERSION[0]) >= 4; +const IS_SVELTE_V4 = Number(SVELTE_VERSION[0]) <= 4; export function renderToCanvas( renderContext: RenderContext, From 80cb9ec4ea11e7874a808a71e92bcc3069d703fb Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Mon, 26 Feb 2024 14:48:58 +0100 Subject: [PATCH 28/79] fix internal unbundled file references --- code/renderers/svelte/package.json | 9 ++++---- .../svelte/scripts/copy-unbundled-to-dist.ts | 23 +++++++++++++++++++ 2 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 code/renderers/svelte/scripts/copy-unbundled-to-dist.ts diff --git a/code/renderers/svelte/package.json b/code/renderers/svelte/package.json index 6fdccc844d86..c26cf76409f3 100644 --- a/code/renderers/svelte/package.json +++ b/code/renderers/svelte/package.json @@ -30,16 +30,15 @@ "./dist/entry-preview.mjs": "./dist/entry-preview.mjs", "./dist/entry-preview-docs.mjs": "./dist/entry-preview-docs.mjs", "./package.json": "./package.json", - "./internal/PreviewRender.svelte": "./src/components/PreviewRender.svelte", - "./internal/SlotDecorator.svelte": "./src/components/SlotDecorator.svelte", - "./internal/createSvelte5Props": "./src/createSvelte5Props.svelte.js" + "./internal/PreviewRender.svelte": "./dist/components/PreviewRender.svelte", + "./internal/SlotDecorator.svelte": "./dist/components/SlotDecorator.svelte", + "./internal/createSvelte5Props": "./dist/createSvelte5Props.svelte.js" }, "main": "dist/index.js", "module": "dist/index.mjs", "types": "dist/index.d.ts", "files": [ "dist/**/*", - "templates/**/*", "template/cli/**/*", "README.md", "*.js", @@ -64,6 +63,7 @@ "devDependencies": { "@sveltejs/vite-plugin-svelte": "^3.0.2", "expect-type": "^0.15.0", + "fs-extra": "^11.1.0", "svelte": "^5.0.0-next.65", "svelte-check": "^3.6.4", "typescript": "^5.3.2" @@ -78,6 +78,7 @@ "access": "public" }, "bundler": { + "post": "./scripts/copy-unbundled-to-dist.ts", "entries": [ "./src/index.ts", "./src/preset.ts", diff --git a/code/renderers/svelte/scripts/copy-unbundled-to-dist.ts b/code/renderers/svelte/scripts/copy-unbundled-to-dist.ts new file mode 100644 index 000000000000..a82964679960 --- /dev/null +++ b/code/renderers/svelte/scripts/copy-unbundled-to-dist.ts @@ -0,0 +1,23 @@ +import { copy } from 'fs-extra'; +import { join } from 'path'; + +const src = join(__dirname, '..', 'src'); +const dist = join(__dirname, '..', 'dist'); + +// relative to src directory +const PATHS_TO_COPY = ['createSvelte5Props.svelte.js', 'components']; + +const run = async () => { + console.log('Copying unbundled files to dist...'); + await Promise.all( + PATHS_TO_COPY.map((pathToCopy) => + copy(join(src, pathToCopy), join(dist, pathToCopy), { overwrite: true }) + ) + ); + console.log('Done!'); +}; + +run().catch((e) => { + console.error(e); + process.exitCode = 1; +}); From 2d5f1f55f46cc6b0e6d307db77f2760cf6c13dc5 Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Mon, 26 Feb 2024 14:49:31 +0100 Subject: [PATCH 29/79] pin Svelte 5 version to next.65 --- code/frameworks/svelte-vite/package.json | 4 +- code/frameworks/svelte-webpack5/package.json | 2 +- code/frameworks/sveltekit/package.json | 2 +- code/package.json | 2 +- code/presets/svelte-webpack/package.json | 2 +- code/yarn.lock | 49 +++----------------- 6 files changed, 13 insertions(+), 48 deletions(-) diff --git a/code/frameworks/svelte-vite/package.json b/code/frameworks/svelte-vite/package.json index 78d2347568ed..dc6da57aad4b 100644 --- a/code/frameworks/svelte-vite/package.json +++ b/code/frameworks/svelte-vite/package.json @@ -58,13 +58,13 @@ "devDependencies": { "@sveltejs/vite-plugin-svelte": "^3.0.1", "@types/node": "^18.0.0", - "svelte": "^5.0.0-next.28", + "svelte": "^5.0.0-next.65", "typescript": "^5.3.2", "vite": "^4.0.0" }, "peerDependencies": { "@sveltejs/vite-plugin-svelte": "^2.0.0 || ^3.0.0", - "svelte": "^4.0.0 || ^5.0.0-next.16", + "svelte": "^4.0.0 || ^5.0.0-next.65", "vite": "^4.0.0 || ^5.0.0" }, "engines": { diff --git a/code/frameworks/svelte-webpack5/package.json b/code/frameworks/svelte-webpack5/package.json index eebe0738192b..a6e32e26c4f1 100644 --- a/code/frameworks/svelte-webpack5/package.json +++ b/code/frameworks/svelte-webpack5/package.json @@ -58,7 +58,7 @@ "typescript": "^5.3.2" }, "peerDependencies": { - "svelte": "^4.0.0 || ^5.0.0-next.16", + "svelte": "^4.0.0 || ^5.0.0-next.65", "svelte-loader": "*" }, "engines": { diff --git a/code/frameworks/sveltekit/package.json b/code/frameworks/sveltekit/package.json index 4c451ff5e4d7..44c0db39e4a9 100644 --- a/code/frameworks/sveltekit/package.json +++ b/code/frameworks/sveltekit/package.json @@ -64,7 +64,7 @@ "vite": "^4.0.0" }, "peerDependencies": { - "svelte": "^4.0.0 || ^5.0.0-next.16", + "svelte": "^4.0.0 || ^5.0.0-next.65", "vite": "^4.0.0 || ^5.0.0" }, "engines": { diff --git a/code/package.json b/code/package.json index 1d6e075439ea..4a7377133993 100644 --- a/code/package.json +++ b/code/package.json @@ -212,7 +212,7 @@ "react-dom": "^18.2.0", "semver": "^7.3.7", "serve-static": "^1.14.1", - "svelte": "^5.0.0-next.28", + "svelte": "^5.0.0-next.65", "trash": "^7.0.0", "ts-dedent": "^2.0.0", "ts-node": "^10.9.1", diff --git a/code/presets/svelte-webpack/package.json b/code/presets/svelte-webpack/package.json index 008078d8721c..dcb985c2737e 100644 --- a/code/presets/svelte-webpack/package.json +++ b/code/presets/svelte-webpack/package.json @@ -75,7 +75,7 @@ "typescript": "^5.3.2" }, "peerDependencies": { - "svelte": "^4.0.0 || ^5.0.0-next.16", + "svelte": "^4.0.0 || ^5.0.0-next.65", "svelte-loader": "*" }, "engines": { diff --git a/code/yarn.lock b/code/yarn.lock index 5d66006d503e..ba606272fc36 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -6230,7 +6230,7 @@ __metadata: ts-dedent: "npm:^2.0.0" typescript: "npm:^5.3.2" peerDependencies: - svelte: ^4.0.0 || ^5.0.0-next.16 + svelte: ^4.0.0 || ^5.0.0-next.65 svelte-loader: "*" languageName: unknown linkType: soft @@ -6536,7 +6536,7 @@ __metadata: react-dom: "npm:^18.2.0" semver: "npm:^7.3.7" serve-static: "npm:^1.14.1" - svelte: "npm:^5.0.0-next.28" + svelte: "npm:^5.0.0-next.65" trash: "npm:^7.0.0" ts-dedent: "npm:^2.0.0" ts-node: "npm:^10.9.1" @@ -6636,7 +6636,7 @@ __metadata: "@sveltejs/vite-plugin-svelte": "npm:^3.0.1" "@types/node": "npm:^18.0.0" magic-string: "npm:^0.30.0" - svelte: "npm:^5.0.0-next.28" + svelte: "npm:^5.0.0-next.65" svelte-preprocess: "npm:^5.1.1" sveltedoc-parser: "npm:^4.2.1" ts-dedent: "npm:^2.2.0" @@ -6644,7 +6644,7 @@ __metadata: vite: "npm:^4.0.0" peerDependencies: "@sveltejs/vite-plugin-svelte": ^2.0.0 || ^3.0.0 - svelte: ^4.0.0 || ^5.0.0-next.16 + svelte: ^4.0.0 || ^5.0.0-next.65 vite: ^4.0.0 || ^5.0.0 languageName: unknown linkType: soft @@ -6661,7 +6661,7 @@ __metadata: svelte-loader: "npm:^3.1.9" typescript: "npm:^5.3.2" peerDependencies: - svelte: ^4.0.0 || ^5.0.0-next.16 + svelte: ^4.0.0 || ^5.0.0-next.65 svelte-loader: "*" languageName: unknown linkType: soft @@ -6678,6 +6678,7 @@ __metadata: "@storybook/types": "workspace:*" "@sveltejs/vite-plugin-svelte": "npm:^3.0.2" expect-type: "npm:^0.15.0" + fs-extra: "npm:^11.1.0" svelte: "npm:^5.0.0-next.65" svelte-check: "npm:^3.6.4" sveltedoc-parser: "npm:^4.2.1" @@ -6701,7 +6702,7 @@ __metadata: typescript: "npm:^5.3.2" vite: "npm:^4.0.0" peerDependencies: - svelte: ^4.0.0 || ^5.0.0-next.16 + svelte: ^4.0.0 || ^5.0.0-next.65 vite: ^4.0.0 || ^5.0.0 languageName: unknown linkType: soft @@ -9282,15 +9283,6 @@ __metadata: languageName: node linkType: hard -"acorn-typescript@npm:^1.4.11": - version: 1.4.12 - resolution: "acorn-typescript@npm:1.4.12" - peerDependencies: - acorn: ">=8.9.0" - checksum: a3b33ed0dc321e3364da507a3decec96423736384068c88fea5ea57aeae864ea115a6c4a20b3ace71b75f4901b0657bec82d83aab30a8ad0dfc4bfc0d8337546 - languageName: node - linkType: hard - "acorn-typescript@npm:^1.4.13": version: 1.4.13 resolution: "acorn-typescript@npm:1.4.13" @@ -27256,26 +27248,6 @@ __metadata: languageName: node linkType: hard -"svelte@npm:^5.0.0-next.28": - version: 5.0.0-next.28 - resolution: "svelte@npm:5.0.0-next.28" - dependencies: - "@ampproject/remapping": "npm:^2.2.1" - "@jridgewell/sourcemap-codec": "npm:^1.4.15" - acorn: "npm:^8.10.0" - acorn-typescript: "npm:^1.4.11" - aria-query: "npm:^5.3.0" - axobject-query: "npm:^4.0.0" - esm-env: "npm:^1.0.0" - esrap: "npm:^1.2.1" - is-reference: "npm:^3.0.1" - locate-character: "npm:^3.0.0" - magic-string: "npm:^0.30.4" - zimmerframe: "npm:^1.1.0" - checksum: d309cd3d1a9fe16c67a626af867288b02f6e7c49311c851aeb0f36feb5ab9603ca5594338fb933dbbada41b26faea6dcef52ed6ab3e86f54626545e53059eb28 - languageName: node - linkType: hard - "svelte@npm:^5.0.0-next.65": version: 5.0.0-next.65 resolution: "svelte@npm:5.0.0-next.65" @@ -30318,13 +30290,6 @@ __metadata: languageName: node linkType: hard -"zimmerframe@npm:^1.1.0": - version: 1.1.0 - resolution: "zimmerframe@npm:1.1.0" - checksum: dffe3f555bb000176ed9c7577e0fb0c3eddeceb6df9bb3ff870995bac3a51b40fab5443bd3dc47ce91c1f8ecf07282742efb80771ae6a088edc0340bb217f93d - languageName: node - linkType: hard - "zimmerframe@npm:^1.1.2": version: 1.1.2 resolution: "zimmerframe@npm:1.1.2" From b9247ec4e34dadc798c6a99e2485cd8e049f3e57 Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Mon, 26 Feb 2024 14:58:35 +0100 Subject: [PATCH 30/79] add Svelte prerelease sandbox back to CI --- .circleci/config.yml | 10 +++++----- code/lib/cli/src/sandbox-templates.ts | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index b212c825ddc2..0d3340694846 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -706,22 +706,22 @@ workflows: requires: - build - create-sandboxes: - parallelism: 34 + parallelism: 35 requires: - build # - smoke-test-sandboxes: # disabled for now # requires: # - create-sandboxes - build-sandboxes: - parallelism: 34 + parallelism: 35 requires: - create-sandboxes - chromatic-sandboxes: - parallelism: 31 + parallelism: 32 requires: - build-sandboxes - e2e-production: - parallelism: 29 + parallelism: 30 requires: - build-sandboxes - e2e-dev: @@ -729,7 +729,7 @@ workflows: requires: - create-sandboxes - test-runner-production: - parallelism: 29 + parallelism: 30 requires: - build-sandboxes diff --git a/code/lib/cli/src/sandbox-templates.ts b/code/lib/cli/src/sandbox-templates.ts index e1395b81156f..182e49798148 100644 --- a/code/lib/cli/src/sandbox-templates.ts +++ b/code/lib/cli/src/sandbox-templates.ts @@ -626,6 +626,7 @@ export const daily: TemplateKey[] = [ 'vue-cli/default-js', 'lit-vite/default-js', 'svelte-kit/skeleton-js', + 'svelte-kit/prerelease-ts', 'svelte-vite/default-js', 'nextjs/13-ts', 'nextjs/default-js', From 982be2deac6c8b3295126737de40f1f88e014a7c Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Mon, 26 Feb 2024 16:20:34 +0100 Subject: [PATCH 31/79] bring back fix for resetting story args in Svelte 5 --- code/renderers/svelte/src/render.ts | 21 ++++++++++-------- .../svelte/template/stories/args.stories.js | 22 +++++++++++-------- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/code/renderers/svelte/src/render.ts b/code/renderers/svelte/src/render.ts index 3b22469af003..28552379bf90 100644 --- a/code/renderers/svelte/src/render.ts +++ b/code/renderers/svelte/src/render.ts @@ -36,15 +36,12 @@ export function renderToCanvas( * * We listen for the RESET_STORY_ARGS event and store the storyId to be reset * We then use this in the renderToCanvas function to force remount the story - * - * This is only necessary in Svelte v4 */ const storyIdsToRemountFromResetArgsEvent = new Set(); -if (IS_SVELTE_V4) { - addons.getChannel().on(RESET_STORY_ARGS, ({ storyId }) => { - storyIdsToRemountFromResetArgsEvent.add(storyId); - }); -} +addons.getChannel().on(RESET_STORY_ARGS, ({ storyId }) => { + storyIdsToRemountFromResetArgsEvent.add(storyId); +}); + const componentsByDomElementV4 = new Map(); function renderToCanvasV4( @@ -137,11 +134,17 @@ function renderToCanvasV5( const existingComponent = componentsByDomElementV5.get(canvasElement); - if (forceRemount) { + let remount = forceRemount; + if (storyIdsToRemountFromResetArgsEvent.has(storyContext.id)) { + remount = true; + storyIdsToRemountFromResetArgsEvent.delete(storyContext.id); + } + + if (remount) { unmount(canvasElement); } - if (!existingComponent || forceRemount) { + if (!existingComponent || remount) { const props = createSvelte5Props({ storyFn, storyContext, diff --git a/code/renderers/svelte/template/stories/args.stories.js b/code/renderers/svelte/template/stories/args.stories.js index 7ecee85a982c..493b5519e6e2 100644 --- a/code/renderers/svelte/template/stories/args.stories.js +++ b/code/renderers/svelte/template/stories/args.stories.js @@ -14,14 +14,16 @@ export default { }; export const RemountOnResetStoryArgs = { - play: async ({ canvasElement, id }) => { + play: async ({ canvasElement, id, step }) => { const canvas = await within(canvasElement); const channel = addons.getChannel(); - // Just to ensure the story is always in a clean state from the beginning, not really part of the test - await channel.emit(RESET_STORY_ARGS, { storyId: id }); - await new Promise((resolve) => { - channel.once(STORY_RENDERED, resolve); + await step('Reset story args', async () => { + // Just to ensure the story is always in a clean state from the beginning, not really part of the test + await channel.emit(RESET_STORY_ARGS, { storyId: id }); + await new Promise((resolve) => { + channel.once(STORY_RENDERED, resolve); + }); }); const button = await canvas.getByRole('button'); await expect(button).toHaveTextContent('You clicked: 0'); @@ -29,16 +31,18 @@ export const RemountOnResetStoryArgs = { await userEvent.click(button); await expect(button).toHaveTextContent('You clicked: 1'); - await channel.emit(UPDATE_STORY_ARGS, { storyId: id, updatedArgs: { text: 'Changed' } }); - await new Promise((resolve) => { - channel.once(STORY_RENDERED, resolve); + await step("Update story args with { text: 'Changed' }", async () => { + await channel.emit(UPDATE_STORY_ARGS, { storyId: id, updatedArgs: { text: 'Changed' } }); + await new Promise((resolve) => { + channel.once(STORY_RENDERED, resolve); + }); }); await expect(button).toHaveTextContent('Changed: 1'); // expect that all state and args are reset after RESET_STORY_ARGS because Svelte needs to remount the component // most other renderers would have 'You clicked: 1' here because they don't remount the component // if this doesn't fully remount it would be 'undefined: 1' because undefined args are used as is in Svelte, and the state is kept - await channel.emit(RESET_STORY_ARGS, { storyId: id }); + await step('Reset story args', () => channel.emit(RESET_STORY_ARGS, { storyId: id })); await waitFor(async () => expect(await within(canvasElement).getByRole('button')).toHaveTextContent('You clicked: 0') ); From d3f533f6fb8d00eb661a9583f55edd2e897dba2b Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Mon, 26 Feb 2024 23:37:23 +0100 Subject: [PATCH 32/79] Don't expose 'count' state in Button example component as a prop --- .../svelte/template/stories/views/ButtonJavaScript.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/renderers/svelte/template/stories/views/ButtonJavaScript.svelte b/code/renderers/svelte/template/stories/views/ButtonJavaScript.svelte index 23af7eaac0f0..800ee79de0f4 100644 --- a/code/renderers/svelte/template/stories/views/ButtonJavaScript.svelte +++ b/code/renderers/svelte/template/stories/views/ButtonJavaScript.svelte @@ -15,7 +15,7 @@ /** * Displays the count */ - export let count = 0; + let count = 0; /** * Button text From e29d22b08707a10682234b3f950034eed4f7178f Mon Sep 17 00:00:00 2001 From: James Garbutt <43081j@users.noreply.github.com> Date: Thu, 29 Feb 2024 13:17:36 +0000 Subject: [PATCH 33/79] chore: upgrade esbuild to 0.20.1 --- code/builders/builder-manager/package.json | 2 +- code/lib/core-common/package.json | 2 +- code/package.json | 2 +- code/yarn.lock | 200 +++++++++++---------- scripts/package.json | 2 +- scripts/yarn.lock | 196 ++++++++++---------- 6 files changed, 212 insertions(+), 192 deletions(-) diff --git a/code/builders/builder-manager/package.json b/code/builders/builder-manager/package.json index 03f53e5dd368..2733705ef1cd 100644 --- a/code/builders/builder-manager/package.json +++ b/code/builders/builder-manager/package.json @@ -52,7 +52,7 @@ "@yarnpkg/esbuild-plugin-pnp": "^3.0.0-rc.10", "browser-assert": "^1.2.1", "ejs": "^3.1.8", - "esbuild": "^0.18.0", + "esbuild": "^0.20.1", "esbuild-plugin-alias": "^0.2.1", "express": "^4.17.3", "fs-extra": "^11.1.0", diff --git a/code/lib/core-common/package.json b/code/lib/core-common/package.json index c40b6c3569d8..9f74856a0af9 100644 --- a/code/lib/core-common/package.json +++ b/code/lib/core-common/package.json @@ -52,7 +52,7 @@ "@yarnpkg/libzip": "2.3.0", "chalk": "^4.1.0", "cross-spawn": "^7.0.3", - "esbuild": "^0.18.0", + "esbuild": "^0.20.1", "esbuild-register": "^3.5.0", "execa": "^5.0.0", "file-system-cache": "2.3.0", diff --git a/code/package.json b/code/package.json index 071cf4a60003..a9cb89380c79 100644 --- a/code/package.json +++ b/code/package.json @@ -80,7 +80,7 @@ "@storybook/theming": "workspace:*", "@types/node": "^18.0.0", "@vitest/expect@1.1.3": "patch:@vitest/expect@npm%3A1.1.3#~/.yarn/patches/@vitest-expect-npm-1.1.3-2062bf533f.patch", - "esbuild": "^0.18.0", + "esbuild": "^0.20.1", "playwright": "1.36.0", "playwright-core": "1.36.0", "serialize-javascript": "^3.1.0", diff --git a/code/yarn.lock b/code/yarn.lock index c0338dabe0c4..01c18ce7fef5 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -2583,156 +2583,163 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-arm64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/android-arm64@npm:0.18.20" +"@esbuild/aix-ppc64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/aix-ppc64@npm:0.20.1" + conditions: os=aix & cpu=ppc64 + languageName: node + linkType: hard + +"@esbuild/android-arm64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/android-arm64@npm:0.20.1" conditions: os=android & cpu=arm64 languageName: node linkType: hard -"@esbuild/android-arm@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/android-arm@npm:0.18.20" +"@esbuild/android-arm@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/android-arm@npm:0.20.1" conditions: os=android & cpu=arm languageName: node linkType: hard -"@esbuild/android-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/android-x64@npm:0.18.20" +"@esbuild/android-x64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/android-x64@npm:0.20.1" conditions: os=android & cpu=x64 languageName: node linkType: hard -"@esbuild/darwin-arm64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/darwin-arm64@npm:0.18.20" +"@esbuild/darwin-arm64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/darwin-arm64@npm:0.20.1" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@esbuild/darwin-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/darwin-x64@npm:0.18.20" +"@esbuild/darwin-x64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/darwin-x64@npm:0.20.1" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@esbuild/freebsd-arm64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/freebsd-arm64@npm:0.18.20" +"@esbuild/freebsd-arm64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/freebsd-arm64@npm:0.20.1" conditions: os=freebsd & cpu=arm64 languageName: node linkType: hard -"@esbuild/freebsd-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/freebsd-x64@npm:0.18.20" +"@esbuild/freebsd-x64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/freebsd-x64@npm:0.20.1" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"@esbuild/linux-arm64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-arm64@npm:0.18.20" +"@esbuild/linux-arm64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/linux-arm64@npm:0.20.1" conditions: os=linux & cpu=arm64 languageName: node linkType: hard -"@esbuild/linux-arm@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-arm@npm:0.18.20" +"@esbuild/linux-arm@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/linux-arm@npm:0.20.1" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@esbuild/linux-ia32@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-ia32@npm:0.18.20" +"@esbuild/linux-ia32@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/linux-ia32@npm:0.20.1" conditions: os=linux & cpu=ia32 languageName: node linkType: hard -"@esbuild/linux-loong64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-loong64@npm:0.18.20" +"@esbuild/linux-loong64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/linux-loong64@npm:0.20.1" conditions: os=linux & cpu=loong64 languageName: node linkType: hard -"@esbuild/linux-mips64el@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-mips64el@npm:0.18.20" +"@esbuild/linux-mips64el@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/linux-mips64el@npm:0.20.1" conditions: os=linux & cpu=mips64el languageName: node linkType: hard -"@esbuild/linux-ppc64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-ppc64@npm:0.18.20" +"@esbuild/linux-ppc64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/linux-ppc64@npm:0.20.1" conditions: os=linux & cpu=ppc64 languageName: node linkType: hard -"@esbuild/linux-riscv64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-riscv64@npm:0.18.20" +"@esbuild/linux-riscv64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/linux-riscv64@npm:0.20.1" conditions: os=linux & cpu=riscv64 languageName: node linkType: hard -"@esbuild/linux-s390x@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-s390x@npm:0.18.20" +"@esbuild/linux-s390x@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/linux-s390x@npm:0.20.1" conditions: os=linux & cpu=s390x languageName: node linkType: hard -"@esbuild/linux-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-x64@npm:0.18.20" +"@esbuild/linux-x64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/linux-x64@npm:0.20.1" conditions: os=linux & cpu=x64 languageName: node linkType: hard -"@esbuild/netbsd-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/netbsd-x64@npm:0.18.20" +"@esbuild/netbsd-x64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/netbsd-x64@npm:0.20.1" conditions: os=netbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/openbsd-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/openbsd-x64@npm:0.18.20" +"@esbuild/openbsd-x64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/openbsd-x64@npm:0.20.1" conditions: os=openbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/sunos-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/sunos-x64@npm:0.18.20" +"@esbuild/sunos-x64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/sunos-x64@npm:0.20.1" conditions: os=sunos & cpu=x64 languageName: node linkType: hard -"@esbuild/win32-arm64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/win32-arm64@npm:0.18.20" +"@esbuild/win32-arm64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/win32-arm64@npm:0.20.1" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@esbuild/win32-ia32@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/win32-ia32@npm:0.18.20" +"@esbuild/win32-ia32@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/win32-ia32@npm:0.20.1" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@esbuild/win32-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/win32-x64@npm:0.18.20" +"@esbuild/win32-x64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/win32-x64@npm:0.20.1" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -5470,7 +5477,7 @@ __metadata: "@yarnpkg/esbuild-plugin-pnp": "npm:^3.0.0-rc.10" browser-assert: "npm:^1.2.1" ejs: "npm:^3.1.8" - esbuild: "npm:^0.18.0" + esbuild: "npm:^0.20.1" esbuild-plugin-alias: "npm:^0.2.1" express: "npm:^4.17.3" fs-extra: "npm:^11.1.0" @@ -5737,7 +5744,7 @@ __metadata: "@yarnpkg/libzip": "npm:2.3.0" chalk: "npm:^4.1.0" cross-spawn: "npm:^7.0.3" - esbuild: "npm:^0.18.0" + esbuild: "npm:^0.20.1" esbuild-register: "npm:^3.5.0" execa: "npm:^5.0.0" file-system-cache: "npm:2.3.0" @@ -14211,33 +14218,36 @@ __metadata: languageName: node linkType: hard -"esbuild@npm:^0.18.0": - version: 0.18.20 - resolution: "esbuild@npm:0.18.20" - dependencies: - "@esbuild/android-arm": "npm:0.18.20" - "@esbuild/android-arm64": "npm:0.18.20" - "@esbuild/android-x64": "npm:0.18.20" - "@esbuild/darwin-arm64": "npm:0.18.20" - "@esbuild/darwin-x64": "npm:0.18.20" - "@esbuild/freebsd-arm64": "npm:0.18.20" - "@esbuild/freebsd-x64": "npm:0.18.20" - "@esbuild/linux-arm": "npm:0.18.20" - "@esbuild/linux-arm64": "npm:0.18.20" - "@esbuild/linux-ia32": "npm:0.18.20" - "@esbuild/linux-loong64": "npm:0.18.20" - "@esbuild/linux-mips64el": "npm:0.18.20" - "@esbuild/linux-ppc64": "npm:0.18.20" - "@esbuild/linux-riscv64": "npm:0.18.20" - "@esbuild/linux-s390x": "npm:0.18.20" - "@esbuild/linux-x64": "npm:0.18.20" - "@esbuild/netbsd-x64": "npm:0.18.20" - "@esbuild/openbsd-x64": "npm:0.18.20" - "@esbuild/sunos-x64": "npm:0.18.20" - "@esbuild/win32-arm64": "npm:0.18.20" - "@esbuild/win32-ia32": "npm:0.18.20" - "@esbuild/win32-x64": "npm:0.18.20" +"esbuild@npm:^0.20.1": + version: 0.20.1 + resolution: "esbuild@npm:0.20.1" + dependencies: + "@esbuild/aix-ppc64": "npm:0.20.1" + "@esbuild/android-arm": "npm:0.20.1" + "@esbuild/android-arm64": "npm:0.20.1" + "@esbuild/android-x64": "npm:0.20.1" + "@esbuild/darwin-arm64": "npm:0.20.1" + "@esbuild/darwin-x64": "npm:0.20.1" + "@esbuild/freebsd-arm64": "npm:0.20.1" + "@esbuild/freebsd-x64": "npm:0.20.1" + "@esbuild/linux-arm": "npm:0.20.1" + "@esbuild/linux-arm64": "npm:0.20.1" + "@esbuild/linux-ia32": "npm:0.20.1" + "@esbuild/linux-loong64": "npm:0.20.1" + "@esbuild/linux-mips64el": "npm:0.20.1" + "@esbuild/linux-ppc64": "npm:0.20.1" + "@esbuild/linux-riscv64": "npm:0.20.1" + "@esbuild/linux-s390x": "npm:0.20.1" + "@esbuild/linux-x64": "npm:0.20.1" + "@esbuild/netbsd-x64": "npm:0.20.1" + "@esbuild/openbsd-x64": "npm:0.20.1" + "@esbuild/sunos-x64": "npm:0.20.1" + "@esbuild/win32-arm64": "npm:0.20.1" + "@esbuild/win32-ia32": "npm:0.20.1" + "@esbuild/win32-x64": "npm:0.20.1" dependenciesMeta: + "@esbuild/aix-ppc64": + optional: true "@esbuild/android-arm": optional: true "@esbuild/android-arm64": @@ -14284,7 +14294,7 @@ __metadata: optional: true bin: esbuild: bin/esbuild - checksum: 473b1d92842f50a303cf948a11ebd5f69581cd254d599dd9d62f9989858e0533f64e83b723b5e1398a5b488c0f5fd088795b4235f65ecaf4f007d4b79f04bc88 + checksum: 7e0303cb80defd55f3f7b85108081afc9c2f3852dda13bf70975a89210f20cd658fc02540d34247401806cb069c4ec489f7cf0df833e040ee361826484926c3a languageName: node linkType: hard diff --git a/scripts/package.json b/scripts/package.json index 52d2013ec288..34ae8e6f6a23 100644 --- a/scripts/package.json +++ b/scripts/package.json @@ -55,7 +55,7 @@ }, "resolutions": { "@testing-library/jest-dom": "^5.11.9", - "esbuild": "^0.18.0", + "esbuild": "^0.20.1", "serialize-javascript": "^3.1.0", "type-fest": "~2.19" }, diff --git a/scripts/yarn.lock b/scripts/yarn.lock index fd8ab47be372..85371e960f38 100644 --- a/scripts/yarn.lock +++ b/scripts/yarn.lock @@ -1490,156 +1490,163 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-arm64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/android-arm64@npm:0.18.20" +"@esbuild/aix-ppc64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/aix-ppc64@npm:0.20.1" + conditions: os=aix & cpu=ppc64 + languageName: node + linkType: hard + +"@esbuild/android-arm64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/android-arm64@npm:0.20.1" conditions: os=android & cpu=arm64 languageName: node linkType: hard -"@esbuild/android-arm@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/android-arm@npm:0.18.20" +"@esbuild/android-arm@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/android-arm@npm:0.20.1" conditions: os=android & cpu=arm languageName: node linkType: hard -"@esbuild/android-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/android-x64@npm:0.18.20" +"@esbuild/android-x64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/android-x64@npm:0.20.1" conditions: os=android & cpu=x64 languageName: node linkType: hard -"@esbuild/darwin-arm64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/darwin-arm64@npm:0.18.20" +"@esbuild/darwin-arm64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/darwin-arm64@npm:0.20.1" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@esbuild/darwin-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/darwin-x64@npm:0.18.20" +"@esbuild/darwin-x64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/darwin-x64@npm:0.20.1" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@esbuild/freebsd-arm64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/freebsd-arm64@npm:0.18.20" +"@esbuild/freebsd-arm64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/freebsd-arm64@npm:0.20.1" conditions: os=freebsd & cpu=arm64 languageName: node linkType: hard -"@esbuild/freebsd-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/freebsd-x64@npm:0.18.20" +"@esbuild/freebsd-x64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/freebsd-x64@npm:0.20.1" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"@esbuild/linux-arm64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-arm64@npm:0.18.20" +"@esbuild/linux-arm64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/linux-arm64@npm:0.20.1" conditions: os=linux & cpu=arm64 languageName: node linkType: hard -"@esbuild/linux-arm@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-arm@npm:0.18.20" +"@esbuild/linux-arm@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/linux-arm@npm:0.20.1" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@esbuild/linux-ia32@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-ia32@npm:0.18.20" +"@esbuild/linux-ia32@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/linux-ia32@npm:0.20.1" conditions: os=linux & cpu=ia32 languageName: node linkType: hard -"@esbuild/linux-loong64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-loong64@npm:0.18.20" +"@esbuild/linux-loong64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/linux-loong64@npm:0.20.1" conditions: os=linux & cpu=loong64 languageName: node linkType: hard -"@esbuild/linux-mips64el@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-mips64el@npm:0.18.20" +"@esbuild/linux-mips64el@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/linux-mips64el@npm:0.20.1" conditions: os=linux & cpu=mips64el languageName: node linkType: hard -"@esbuild/linux-ppc64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-ppc64@npm:0.18.20" +"@esbuild/linux-ppc64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/linux-ppc64@npm:0.20.1" conditions: os=linux & cpu=ppc64 languageName: node linkType: hard -"@esbuild/linux-riscv64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-riscv64@npm:0.18.20" +"@esbuild/linux-riscv64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/linux-riscv64@npm:0.20.1" conditions: os=linux & cpu=riscv64 languageName: node linkType: hard -"@esbuild/linux-s390x@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-s390x@npm:0.18.20" +"@esbuild/linux-s390x@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/linux-s390x@npm:0.20.1" conditions: os=linux & cpu=s390x languageName: node linkType: hard -"@esbuild/linux-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-x64@npm:0.18.20" +"@esbuild/linux-x64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/linux-x64@npm:0.20.1" conditions: os=linux & cpu=x64 languageName: node linkType: hard -"@esbuild/netbsd-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/netbsd-x64@npm:0.18.20" +"@esbuild/netbsd-x64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/netbsd-x64@npm:0.20.1" conditions: os=netbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/openbsd-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/openbsd-x64@npm:0.18.20" +"@esbuild/openbsd-x64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/openbsd-x64@npm:0.20.1" conditions: os=openbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/sunos-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/sunos-x64@npm:0.18.20" +"@esbuild/sunos-x64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/sunos-x64@npm:0.20.1" conditions: os=sunos & cpu=x64 languageName: node linkType: hard -"@esbuild/win32-arm64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/win32-arm64@npm:0.18.20" +"@esbuild/win32-arm64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/win32-arm64@npm:0.20.1" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@esbuild/win32-ia32@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/win32-ia32@npm:0.18.20" +"@esbuild/win32-ia32@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/win32-ia32@npm:0.20.1" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@esbuild/win32-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/win32-x64@npm:0.18.20" +"@esbuild/win32-x64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/win32-x64@npm:0.20.1" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -6567,33 +6574,36 @@ __metadata: languageName: node linkType: hard -"esbuild@npm:^0.18.0": - version: 0.18.20 - resolution: "esbuild@npm:0.18.20" - dependencies: - "@esbuild/android-arm": "npm:0.18.20" - "@esbuild/android-arm64": "npm:0.18.20" - "@esbuild/android-x64": "npm:0.18.20" - "@esbuild/darwin-arm64": "npm:0.18.20" - "@esbuild/darwin-x64": "npm:0.18.20" - "@esbuild/freebsd-arm64": "npm:0.18.20" - "@esbuild/freebsd-x64": "npm:0.18.20" - "@esbuild/linux-arm": "npm:0.18.20" - "@esbuild/linux-arm64": "npm:0.18.20" - "@esbuild/linux-ia32": "npm:0.18.20" - "@esbuild/linux-loong64": "npm:0.18.20" - "@esbuild/linux-mips64el": "npm:0.18.20" - "@esbuild/linux-ppc64": "npm:0.18.20" - "@esbuild/linux-riscv64": "npm:0.18.20" - "@esbuild/linux-s390x": "npm:0.18.20" - "@esbuild/linux-x64": "npm:0.18.20" - "@esbuild/netbsd-x64": "npm:0.18.20" - "@esbuild/openbsd-x64": "npm:0.18.20" - "@esbuild/sunos-x64": "npm:0.18.20" - "@esbuild/win32-arm64": "npm:0.18.20" - "@esbuild/win32-ia32": "npm:0.18.20" - "@esbuild/win32-x64": "npm:0.18.20" +"esbuild@npm:^0.20.1": + version: 0.20.1 + resolution: "esbuild@npm:0.20.1" + dependencies: + "@esbuild/aix-ppc64": "npm:0.20.1" + "@esbuild/android-arm": "npm:0.20.1" + "@esbuild/android-arm64": "npm:0.20.1" + "@esbuild/android-x64": "npm:0.20.1" + "@esbuild/darwin-arm64": "npm:0.20.1" + "@esbuild/darwin-x64": "npm:0.20.1" + "@esbuild/freebsd-arm64": "npm:0.20.1" + "@esbuild/freebsd-x64": "npm:0.20.1" + "@esbuild/linux-arm": "npm:0.20.1" + "@esbuild/linux-arm64": "npm:0.20.1" + "@esbuild/linux-ia32": "npm:0.20.1" + "@esbuild/linux-loong64": "npm:0.20.1" + "@esbuild/linux-mips64el": "npm:0.20.1" + "@esbuild/linux-ppc64": "npm:0.20.1" + "@esbuild/linux-riscv64": "npm:0.20.1" + "@esbuild/linux-s390x": "npm:0.20.1" + "@esbuild/linux-x64": "npm:0.20.1" + "@esbuild/netbsd-x64": "npm:0.20.1" + "@esbuild/openbsd-x64": "npm:0.20.1" + "@esbuild/sunos-x64": "npm:0.20.1" + "@esbuild/win32-arm64": "npm:0.20.1" + "@esbuild/win32-ia32": "npm:0.20.1" + "@esbuild/win32-x64": "npm:0.20.1" dependenciesMeta: + "@esbuild/aix-ppc64": + optional: true "@esbuild/android-arm": optional: true "@esbuild/android-arm64": @@ -6640,7 +6650,7 @@ __metadata: optional: true bin: esbuild: bin/esbuild - checksum: 473b1d92842f50a303cf948a11ebd5f69581cd254d599dd9d62f9989858e0533f64e83b723b5e1398a5b488c0f5fd088795b4235f65ecaf4f007d4b79f04bc88 + checksum: 7e0303cb80defd55f3f7b85108081afc9c2f3852dda13bf70975a89210f20cd658fc02540d34247401806cb069c4ec489f7cf0df833e040ee361826484926c3a languageName: node linkType: hard From 7bcbb3c0f4f5cdb0d69d5b03064b5cfb8e08bdb0 Mon Sep 17 00:00:00 2001 From: Vanessa Yuen <6842965+vanessayuenn@users.noreply.github.com> Date: Thu, 29 Feb 2024 15:32:43 +0100 Subject: [PATCH 34/79] only use contributors' github handles in release notes --- scripts/release/utils/get-github-info.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/release/utils/get-github-info.ts b/scripts/release/utils/get-github-info.ts index bdfe995a9001..0247e8319e04 100644 --- a/scripts/release/utils/get-github-info.ts +++ b/scripts/release/utils/get-github-info.ts @@ -73,7 +73,7 @@ function makeQuery(repos: ReposWithCommitsAndPRsToFetch) { nodes { name } - } + } mergeCommit { commitUrl oid @@ -255,7 +255,7 @@ export async function getPullInfoFromCommit(request: { pull: associatedPullRequest ? `[#${associatedPullRequest.number}](${associatedPullRequest.url})` : null, - user: user ? `[@${user.login}](${user.url})` : null, + user: user ? `@${user.login}` : null, }, }; } @@ -294,7 +294,7 @@ export async function getPullInfoFromPullRequest(request: { links: { commit: commit ? `[\`${commit.oid}\`](${commit.commitUrl})` : null, pull: `[#${request.pull}](https://github.com/${request.repo}/pull/${request.pull})`, - user: user ? `[@${user.login}](${user.url})` : null, + user: user ? `@${user.login}` : null, }, }; } From 4d24ee07b96b178c78ffa3e1501fddc98349f7ff Mon Sep 17 00:00:00 2001 From: Valentin Palkovic Date: Thu, 29 Feb 2024 16:25:56 +0100 Subject: [PATCH 35/79] Resolve vite config from project root instead of cwd --- .../cli/src/automigrate/fixes/vite-config-file.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/code/lib/cli/src/automigrate/fixes/vite-config-file.ts b/code/lib/cli/src/automigrate/fixes/vite-config-file.ts index 6325b71ad062..c74c7f378373 100644 --- a/code/lib/cli/src/automigrate/fixes/vite-config-file.ts +++ b/code/lib/cli/src/automigrate/fixes/vite-config-file.ts @@ -4,6 +4,7 @@ import findUp from 'find-up'; import { getFrameworkPackageName } from '../helpers/mainConfigFile'; import { frameworkToRenderer } from '../../helpers'; import { frameworkPackages } from '@storybook/core-common'; +import path from 'path'; interface ViteConfigFileRunOptions { plugins: string[]; @@ -15,13 +16,11 @@ export const viteConfigFile = { versionRange: ['<8.0.0-beta.3', '>=8.0.0-beta.3'], - async check({ mainConfig, packageManager }) { - let isViteConfigFileFound = !!(await findUp([ - 'vite.config.js', - 'vite.config.mjs', - 'vite.config.cjs', - 'vite.config.ts', - ])); + async check({ mainConfig, packageManager, mainConfigPath }) { + let isViteConfigFileFound = !!(await findUp( + ['vite.config.js', 'vite.config.mjs', 'vite.config.cjs', 'vite.config.ts'], + { cwd: mainConfigPath ? path.join(mainConfigPath, '..') : process.cwd() } + )); const rendererToVitePluginMap: Record = { preact: '@preact/preset-vite', From ea40ff899fb300dff73de8e108ee6108c4bb1200 Mon Sep 17 00:00:00 2001 From: Valentin Palkovic Date: Fri, 1 Mar 2024 09:51:32 +0100 Subject: [PATCH 36/79] Handle TypeScript path aliases in react-docgen loader --- code/frameworks/react-vite/package.json | 5 +- .../src/plugins/react-docgen.test.ts | 52 +++++++++++++++++++ .../react-vite/src/plugins/react-docgen.ts | 52 +++++++++++++++---- code/frameworks/react-vite/src/preset.ts | 2 +- code/presets/react-webpack/package.json | 2 + .../src/loaders/react-docgen-loader.test.ts | 52 +++++++++++++++++++ .../src/loaders/react-docgen-loader.ts | 52 +++++++++++++++---- code/yarn.lock | 7 ++- 8 files changed, 201 insertions(+), 23 deletions(-) create mode 100644 code/frameworks/react-vite/src/plugins/react-docgen.test.ts create mode 100644 code/presets/react-webpack/src/loaders/react-docgen-loader.test.ts diff --git a/code/frameworks/react-vite/package.json b/code/frameworks/react-vite/package.json index b16bfeeaecb1..a413f6b4786e 100644 --- a/code/frameworks/react-vite/package.json +++ b/code/frameworks/react-vite/package.json @@ -50,10 +50,13 @@ "@joshwooding/vite-plugin-react-docgen-typescript": "0.3.0", "@rollup/pluginutils": "^5.0.2", "@storybook/builder-vite": "workspace:*", + "@storybook/node-logger": "workspace:*", "@storybook/react": "workspace:*", + "find-up": "^5.0.0", "magic-string": "^0.30.0", "react-docgen": "^7.0.0", - "resolve": "^1.22.8" + "resolve": "^1.22.8", + "tsconfig-paths": "^4.2.0" }, "devDependencies": { "@types/node": "^18.0.0", diff --git a/code/frameworks/react-vite/src/plugins/react-docgen.test.ts b/code/frameworks/react-vite/src/plugins/react-docgen.test.ts new file mode 100644 index 000000000000..1fed686198b9 --- /dev/null +++ b/code/frameworks/react-vite/src/plugins/react-docgen.test.ts @@ -0,0 +1,52 @@ +import { getReactDocgenImporter } from './react-docgen'; +import { describe, it, expect, vi } from 'vitest'; + +const reactDocgenMock = vi.hoisted(() => { + return { + makeFsImporter: vi.fn().mockImplementation((fn) => fn), + }; +}); + +const reactDocgenResolverMock = vi.hoisted(() => { + return { + defaultLookupModule: vi.fn(), + }; +}); + +vi.mock('./docgen-resolver', async (importOriginal) => { + const actual = await importOriginal(); + return { + ...actual, + defaultLookupModule: reactDocgenResolverMock.defaultLookupModule, + }; +}); + +vi.mock('react-docgen', async (importOriginal) => { + const actual = await importOriginal(); + return { + ...actual, + makeFsImporter: reactDocgenMock.makeFsImporter, + }; +}); + +describe('getReactDocgenImporter function', () => { + it('should not map the request if a tsconfig path mapping is not available', () => { + const filename = './src/components/Button.tsx'; + const basedir = '/src'; + const imported = getReactDocgenImporter(undefined); + reactDocgenResolverMock.defaultLookupModule.mockImplementation((filen: string) => filen); + const result = (imported as any)(filename, basedir); + expect(result).toBe(filename); + }); + + it('should map the request', () => { + const mappedFile = './mapped-file.tsx'; + const matchPath = vi.fn().mockReturnValue(mappedFile); + const filename = './src/components/Button.tsx'; + const basedir = '/src'; + const imported = getReactDocgenImporter(matchPath); + reactDocgenResolverMock.defaultLookupModule.mockImplementation((filen: string) => filen); + const result = (imported as any)(filename, basedir); + expect(result).toBe(mappedFile); + }); +}); diff --git a/code/frameworks/react-vite/src/plugins/react-docgen.ts b/code/frameworks/react-vite/src/plugins/react-docgen.ts index 9d2242ce2654..c59861e4ff43 100644 --- a/code/frameworks/react-vite/src/plugins/react-docgen.ts +++ b/code/frameworks/react-vite/src/plugins/react-docgen.ts @@ -10,12 +10,15 @@ import { } from 'react-docgen'; import MagicString from 'magic-string'; import type { PluginOption } from 'vite'; +import * as TsconfigPaths from 'tsconfig-paths'; +import findUp from 'find-up'; import actualNameHandler from './docgen-handlers/actualNameHandler'; import { RESOLVE_EXTENSIONS, ReactDocgenResolveError, defaultLookupModule, } from './docgen-resolver'; +import { logger } from '@storybook/node-logger'; type DocObj = Documentation & { actualName: string }; @@ -29,13 +32,27 @@ type Options = { exclude?: string | RegExp | (string | RegExp)[]; }; -export function reactDocgen({ +export async function reactDocgen({ include = /\.(mjs|tsx?|jsx?)$/, exclude = [/node_modules\/.*/], -}: Options = {}): PluginOption { +}: Options = {}): Promise { const cwd = process.cwd(); const filter = createFilter(include, exclude); + const tsconfigPath = await findUp('tsconfig.json', { cwd }); + const tsconfig = TsconfigPaths.loadConfig(tsconfigPath); + + let matchPath: TsconfigPaths.MatchPath | undefined; + + if (tsconfig.resultType === 'success') { + logger.info('Using tsconfig paths for react-docgen'); + matchPath = TsconfigPaths.createMatchPath(tsconfig.absoluteBaseUrl, tsconfig.paths, [ + 'browser', + 'module', + 'main', + ]); + } + return { name: 'storybook:react-docgen-plugin', enforce: 'pre', @@ -48,15 +65,7 @@ export function reactDocgen({ const docgenResults = parse(src, { resolver: defaultResolver, handlers, - importer: makeFsImporter((filename, basedir) => { - const result = defaultLookupModule(filename, basedir); - - if (RESOLVE_EXTENSIONS.find((ext) => result.endsWith(ext))) { - return result; - } - - throw new ReactDocgenResolveError(filename); - }), + importer: getReactDocgenImporter(matchPath), filename: id, }) as DocObj[]; const s = new MagicString(src); @@ -83,3 +92,24 @@ export function reactDocgen({ }, }; } + +export function getReactDocgenImporter(matchPath: TsconfigPaths.MatchPath | undefined) { + return makeFsImporter((filename, basedir) => { + const mappedFilenameByPaths = (() => { + if (matchPath) { + const match = matchPath(filename); + return match || filename; + } else { + return filename; + } + })(); + + const result = defaultLookupModule(mappedFilenameByPaths, basedir); + + if (RESOLVE_EXTENSIONS.find((ext) => result.endsWith(ext))) { + return result; + } + + throw new ReactDocgenResolveError(filename); + }); +} diff --git a/code/frameworks/react-vite/src/preset.ts b/code/frameworks/react-vite/src/preset.ts index 35a83a306ce0..cbdde0f61a07 100644 --- a/code/frameworks/react-vite/src/preset.ts +++ b/code/frameworks/react-vite/src/preset.ts @@ -43,7 +43,7 @@ export const viteFinal: StorybookConfig['viteFinal'] = async (config, { presets // Needs to run before the react plugin, so add to the front plugins.unshift( // If react-docgen is specified, use it for everything, otherwise only use it for non-typescript files - reactDocgen({ + await reactDocgen({ include: reactDocgenOption === 'react-docgen' ? /\.(mjs|tsx?|jsx?)$/ : /\.(mjs|jsx?)$/, }) ); diff --git a/code/presets/react-webpack/package.json b/code/presets/react-webpack/package.json index a79480cf13dc..5cec6e7be6af 100644 --- a/code/presets/react-webpack/package.json +++ b/code/presets/react-webpack/package.json @@ -71,11 +71,13 @@ "@storybook/react-docgen-typescript-plugin": "1.0.6--canary.9.0c3f3b7.0", "@types/node": "^18.0.0", "@types/semver": "^7.3.4", + "find-up": "^5.0.0", "fs-extra": "^11.1.0", "magic-string": "^0.30.5", "react-docgen": "^7.0.0", "resolve": "^1.22.8", "semver": "^7.3.7", + "tsconfig-paths": "^4.2.0", "webpack": "5" }, "devDependencies": { diff --git a/code/presets/react-webpack/src/loaders/react-docgen-loader.test.ts b/code/presets/react-webpack/src/loaders/react-docgen-loader.test.ts new file mode 100644 index 000000000000..cb017a7469b7 --- /dev/null +++ b/code/presets/react-webpack/src/loaders/react-docgen-loader.test.ts @@ -0,0 +1,52 @@ +import { getReactDocgenImporter } from './react-docgen-loader'; +import { describe, it, expect, vi } from 'vitest'; + +const reactDocgenMock = vi.hoisted(() => { + return { + makeFsImporter: vi.fn().mockImplementation((fn) => fn), + }; +}); + +const reactDocgenResolverMock = vi.hoisted(() => { + return { + defaultLookupModule: vi.fn(), + }; +}); + +vi.mock('./docgen-resolver', async (importOriginal) => { + const actual = await importOriginal(); + return { + ...actual, + defaultLookupModule: reactDocgenResolverMock.defaultLookupModule, + }; +}); + +vi.mock('react-docgen', async (importOriginal) => { + const actual = await importOriginal(); + return { + ...actual, + makeFsImporter: reactDocgenMock.makeFsImporter, + }; +}); + +describe('getReactDocgenImporter function', () => { + it('should not map the request if a tsconfig path mapping is not available', () => { + const filename = './src/components/Button.tsx'; + const basedir = '/src'; + const imported = getReactDocgenImporter(undefined); + reactDocgenResolverMock.defaultLookupModule.mockImplementation((filen: string) => filen); + const result = (imported as any)(filename, basedir); + expect(result).toBe(filename); + }); + + it('should map the request', () => { + const mappedFile = './mapped-file.tsx'; + const matchPath = vi.fn().mockReturnValue(mappedFile); + const filename = './src/components/Button.tsx'; + const basedir = '/src'; + const imported = getReactDocgenImporter(matchPath); + reactDocgenResolverMock.defaultLookupModule.mockImplementation((filen: string) => filen); + const result = (imported as any)(filename, basedir); + expect(result).toBe(mappedFile); + }); +}); diff --git a/code/presets/react-webpack/src/loaders/react-docgen-loader.ts b/code/presets/react-webpack/src/loaders/react-docgen-loader.ts index 12ab911fd546..15b71f19bfd5 100644 --- a/code/presets/react-webpack/src/loaders/react-docgen-loader.ts +++ b/code/presets/react-webpack/src/loaders/react-docgen-loader.ts @@ -6,6 +6,8 @@ import { ERROR_CODES, utils, } from 'react-docgen'; +import * as TsconfigPaths from 'tsconfig-paths'; +import findUp from 'find-up'; import MagicString from 'magic-string'; import type { LoaderContext } from 'webpack'; import type { Handler, NodePath, babelTypes as t, Documentation } from 'react-docgen'; @@ -62,6 +64,9 @@ const defaultHandlers = Object.values(docgenHandlers).map((handler) => handler); const defaultResolver = new docgenResolver.FindExportedDefinitionsResolver(); const handlers = [...defaultHandlers, actualNameHandler]; +let tsconfigPathsInitialized = false; +let matchPath: TsconfigPaths.MatchPath | undefined; + export default async function reactDocgenLoader( this: LoaderContext<{ debug: boolean }>, source: string @@ -71,20 +76,28 @@ export default async function reactDocgenLoader( const options = this.getOptions() || {}; const { debug = false } = options; + if (!tsconfigPathsInitialized) { + const tsconfigPath = await findUp('tsconfig.json', { cwd: process.cwd() }); + const tsconfig = TsconfigPaths.loadConfig(tsconfigPath); + + if (tsconfig.resultType === 'success') { + logger.info('Using tsconfig paths for react-docgen'); + matchPath = TsconfigPaths.createMatchPath(tsconfig.absoluteBaseUrl, tsconfig.paths, [ + 'browser', + 'module', + 'main', + ]); + } + + tsconfigPathsInitialized = true; + } + try { const docgenResults = parse(source, { filename: this.resourcePath, resolver: defaultResolver, handlers, - importer: makeFsImporter((filename, basedir) => { - const result = defaultLookupModule(filename, basedir); - - if (RESOLVE_EXTENSIONS.find((ext) => result.endsWith(ext))) { - return result; - } - - throw new ReactDocgenResolveError(filename); - }), + importer: getReactDocgenImporter(matchPath), babelOptions: { babelrc: false, configFile: false, @@ -122,3 +135,24 @@ export default async function reactDocgenLoader( } } } + +export function getReactDocgenImporter(matchingPath: TsconfigPaths.MatchPath | undefined) { + return makeFsImporter((filename, basedir) => { + const mappedFilenameByPaths = (() => { + if (matchingPath) { + const match = matchingPath(filename); + return match || filename; + } else { + return filename; + } + })(); + + const result = defaultLookupModule(mappedFilenameByPaths, basedir); + + if (RESOLVE_EXTENSIONS.find((ext) => result.endsWith(ext))) { + return result; + } + + throw new ReactDocgenResolveError(filename); + }); +} diff --git a/code/yarn.lock b/code/yarn.lock index 039c28a0c940..dfbdf6fca037 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -6340,11 +6340,13 @@ __metadata: "@storybook/react-docgen-typescript-plugin": "npm:1.0.6--canary.9.0c3f3b7.0" "@types/node": "npm:^18.0.0" "@types/semver": "npm:^7.3.4" + find-up: "npm:^5.0.0" fs-extra: "npm:^11.1.0" magic-string: "npm:^0.30.5" react-docgen: "npm:^7.0.0" resolve: "npm:^1.22.8" semver: "npm:^7.3.7" + tsconfig-paths: "npm:^4.2.0" typescript: "npm:^5.3.2" webpack: "npm:5" peerDependencies: @@ -6488,11 +6490,14 @@ __metadata: "@joshwooding/vite-plugin-react-docgen-typescript": "npm:0.3.0" "@rollup/pluginutils": "npm:^5.0.2" "@storybook/builder-vite": "workspace:*" + "@storybook/node-logger": "workspace:*" "@storybook/react": "workspace:*" "@types/node": "npm:^18.0.0" + find-up: "npm:^5.0.0" magic-string: "npm:^0.30.0" react-docgen: "npm:^7.0.0" resolve: "npm:^1.22.8" + tsconfig-paths: "npm:^4.2.0" typescript: "npm:^5.3.2" vite: "npm:^4.0.0" peerDependencies: @@ -28381,7 +28386,7 @@ __metadata: languageName: node linkType: hard -"tsconfig-paths@npm:^4.0.0, tsconfig-paths@npm:^4.1.2": +"tsconfig-paths@npm:^4.0.0, tsconfig-paths@npm:^4.1.2, tsconfig-paths@npm:^4.2.0": version: 4.2.0 resolution: "tsconfig-paths@npm:4.2.0" dependencies: From 12495e5027803c1838335b63b1784b4dab520d3e Mon Sep 17 00:00:00 2001 From: Valentin Palkovic Date: Fri, 1 Mar 2024 14:41:56 +0100 Subject: [PATCH 37/79] Setup prompt type for automigration --- code/lib/cli/src/automigrate/fixes/vite-config-file.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/lib/cli/src/automigrate/fixes/vite-config-file.ts b/code/lib/cli/src/automigrate/fixes/vite-config-file.ts index c74c7f378373..6a8dd9ec0e02 100644 --- a/code/lib/cli/src/automigrate/fixes/vite-config-file.ts +++ b/code/lib/cli/src/automigrate/fixes/vite-config-file.ts @@ -16,6 +16,8 @@ export const viteConfigFile = { versionRange: ['<8.0.0-beta.3', '>=8.0.0-beta.3'], + promptType: 'notification', + async check({ mainConfig, packageManager, mainConfigPath }) { let isViteConfigFileFound = !!(await findUp( ['vite.config.js', 'vite.config.mjs', 'vite.config.cjs', 'vite.config.ts'], From 2b48135c376b04ab28fa77c342f535fc242df6b2 Mon Sep 17 00:00:00 2001 From: Michael Shilman Date: Sat, 2 Mar 2024 09:20:07 +0800 Subject: [PATCH 38/79] Controls: Fix type summary --- code/ui/blocks/src/components/ArgsTable/ArgRow.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/code/ui/blocks/src/components/ArgsTable/ArgRow.tsx b/code/ui/blocks/src/components/ArgsTable/ArgRow.tsx index d6e2c73ad905..8f6b6f2c5f99 100644 --- a/code/ui/blocks/src/components/ArgsTable/ArgRow.tsx +++ b/code/ui/blocks/src/components/ArgsTable/ArgRow.tsx @@ -76,12 +76,18 @@ const StyledTd = styled.td<{ expandable: boolean }>(({ theme, expandable }) => ( paddingLeft: expandable ? '40px !important' : '20px !important', })); +const toSummary = (value: any) => { + if (!value) return value; + const val = typeof value === 'string' ? value : value.name; + return { summary: val }; +}; + export const ArgRow: FC = (props) => { const [isHovered, setIsHovered] = useState(false); const { row, updateArgs, compact, expandable, initialExpandedArgs } = props; const { name, description } = row; const table = (row.table || {}) as TableAnnotation; - const type = table.type || row.type; + const type = table.type || toSummary(row.type); const defaultValue = table.defaultValue || row.defaultValue; const required = row.type?.required; const hasDescription = description != null && description !== ''; From 3f766bf200005ac60fee8d3fc7bf017772bf3792 Mon Sep 17 00:00:00 2001 From: 43081j <43081j@users.noreply.github.com> Date: Sat, 2 Mar 2024 12:40:01 +0000 Subject: [PATCH 39/79] chore: upgrade recast This updates recast (patch version) to pull in a recent update which trims down the dependency tree/footprint. --- code/lib/codemod/package.json | 2 +- code/lib/csf-tools/package.json | 2 +- code/yarn.lock | 24 ++++++++++++++++-- scripts/package.json | 2 +- scripts/yarn.lock | 44 +++++++++++---------------------- 5 files changed, 39 insertions(+), 35 deletions(-) diff --git a/code/lib/codemod/package.json b/code/lib/codemod/package.json index 0e4154e0db74..cdb05de5da4d 100644 --- a/code/lib/codemod/package.json +++ b/code/lib/codemod/package.json @@ -67,7 +67,7 @@ "jscodeshift": "^0.15.1", "lodash": "^4.17.21", "prettier": "^3.1.1", - "recast": "^0.23.1", + "recast": "^0.23.5", "tiny-invariant": "^1.3.1" }, "devDependencies": { diff --git a/code/lib/csf-tools/package.json b/code/lib/csf-tools/package.json index 5a32a79f9453..9004d3e3beae 100644 --- a/code/lib/csf-tools/package.json +++ b/code/lib/csf-tools/package.json @@ -49,7 +49,7 @@ "@storybook/csf": "^0.1.2", "@storybook/types": "workspace:*", "fs-extra": "^11.1.0", - "recast": "^0.23.1", + "recast": "^0.23.5", "ts-dedent": "^2.0.0" }, "devDependencies": { diff --git a/code/yarn.lock b/code/yarn.lock index 039c28a0c940..b5e38b978738 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -5671,7 +5671,7 @@ __metadata: mdast-util-mdx-jsx: "npm:^3.0.0" mdast-util-mdxjs-esm: "npm:^2.0.1" prettier: "npm:^3.1.1" - recast: "npm:^0.23.1" + recast: "npm:^0.23.5" remark: "npm:^15.0.1" remark-mdx: "npm:^3.0.0" tiny-invariant: "npm:^1.3.1" @@ -5872,7 +5872,7 @@ __metadata: "@types/js-yaml": "npm:^4.0.5" fs-extra: "npm:^11.1.0" js-yaml: "npm:^4.1.0" - recast: "npm:^0.23.1" + recast: "npm:^0.23.5" ts-dedent: "npm:^2.0.0" typescript: "npm:^5.3.2" languageName: unknown @@ -24989,6 +24989,19 @@ __metadata: languageName: node linkType: hard +"recast@npm:^0.23.5": + version: 0.23.5 + resolution: "recast@npm:0.23.5" + dependencies: + ast-types: "npm:^0.16.1" + esprima: "npm:~4.0.0" + source-map: "npm:~0.6.1" + tiny-invariant: "npm:^1.3.3" + tslib: "npm:^2.0.1" + checksum: 21dc93910d12c71da77072afc3d5d4cdf97783776842efa6fd2cd7c2798d3622ace5d2f05ca5133141ef93de8a0512cbe191fe835f325bd1722f186fe449d11a + languageName: node + linkType: hard + "redent@npm:^3.0.0": version: 3.0.0 resolution: "redent@npm:3.0.0" @@ -28020,6 +28033,13 @@ __metadata: languageName: node linkType: hard +"tiny-invariant@npm:^1.3.3": + version: 1.3.3 + resolution: "tiny-invariant@npm:1.3.3" + checksum: 65af4a07324b591a059b35269cd696aba21bef2107f29b9f5894d83cc143159a204b299553435b03874ebb5b94d019afa8b8eff241c8a4cfee95872c2e1c1c4a + languageName: node + linkType: hard + "tiny-warning@npm:^1.0.2": version: 1.0.3 resolution: "tiny-warning@npm:1.0.3" diff --git a/scripts/package.json b/scripts/package.json index 52d2013ec288..af4682a9ccd9 100644 --- a/scripts/package.json +++ b/scripts/package.json @@ -160,7 +160,7 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "read-pkg-up": "^7.0.1", - "recast": "^0.23.1", + "recast": "^0.23.5", "remark": "^14.0.3", "remark-cli": "^12.0.0", "remark-lint": "^9.1.2", diff --git a/scripts/yarn.lock b/scripts/yarn.lock index fd8ab47be372..c87d27c84be7 100644 --- a/scripts/yarn.lock +++ b/scripts/yarn.lock @@ -2800,7 +2800,7 @@ __metadata: react: "npm:^18.2.0" react-dom: "npm:^18.2.0" read-pkg-up: "npm:^7.0.1" - recast: "npm:^0.23.1" + recast: "npm:^0.23.5" remark: "npm:^14.0.3" remark-cli: "npm:^12.0.0" remark-lint: "npm:^9.1.2" @@ -4490,19 +4490,6 @@ __metadata: languageName: node linkType: hard -"assert@npm:^2.0.0": - version: 2.1.0 - resolution: "assert@npm:2.1.0" - dependencies: - call-bind: "npm:^1.0.2" - is-nan: "npm:^1.3.2" - object-is: "npm:^1.1.5" - object.assign: "npm:^4.1.4" - util: "npm:^0.12.5" - checksum: 7271a5da883c256a1fa690677bf1dd9d6aa882139f2bed1cd15da4f9e7459683e1da8e32a203d6cc6767e5e0f730c77a9532a87b896b4b0af0dd535f668775f0 - languageName: node - linkType: hard - "assertion-error@npm:^1.1.0": version: 1.1.0 resolution: "assertion-error@npm:1.1.0" @@ -8943,16 +8930,6 @@ __metadata: languageName: node linkType: hard -"is-nan@npm:^1.3.2": - version: 1.3.2 - resolution: "is-nan@npm:1.3.2" - dependencies: - call-bind: "npm:^1.0.0" - define-properties: "npm:^1.1.3" - checksum: 8bfb286f85763f9c2e28ea32e9127702fe980ffd15fa5d63ade3be7786559e6e21355d3625dd364c769c033c5aedf0a2ed3d4025d336abf1b9241e3d9eddc5b0 - languageName: node - linkType: hard - "is-natural-number@npm:^4.0.1": version: 4.0.1 resolution: "is-natural-number@npm:4.0.1" @@ -12752,16 +12729,16 @@ __metadata: languageName: node linkType: hard -"recast@npm:^0.23.1": - version: 0.23.4 - resolution: "recast@npm:0.23.4" +"recast@npm:^0.23.5": + version: 0.23.5 + resolution: "recast@npm:0.23.5" dependencies: - assert: "npm:^2.0.0" ast-types: "npm:^0.16.1" esprima: "npm:~4.0.0" source-map: "npm:~0.6.1" + tiny-invariant: "npm:^1.3.3" tslib: "npm:^2.0.1" - checksum: d719633be8029e28f23b8191d4a525c5dbdac721792ab3cb5e9dfcf1694fb93f3c147b186916195a9c7fa0711f1e4990ba457cdcee02faed3899d4a80da1bd1f + checksum: 21dc93910d12c71da77072afc3d5d4cdf97783776842efa6fd2cd7c2798d3622ace5d2f05ca5133141ef93de8a0512cbe191fe835f325bd1722f186fe449d11a languageName: node linkType: hard @@ -14583,6 +14560,13 @@ __metadata: languageName: node linkType: hard +"tiny-invariant@npm:^1.3.3": + version: 1.3.3 + resolution: "tiny-invariant@npm:1.3.3" + checksum: 65af4a07324b591a059b35269cd696aba21bef2107f29b9f5894d83cc143159a204b299553435b03874ebb5b94d019afa8b8eff241c8a4cfee95872c2e1c1c4a + languageName: node + linkType: hard + "tinybench@npm:^2.5.1": version: 2.5.1 resolution: "tinybench@npm:2.5.1" @@ -15437,7 +15421,7 @@ __metadata: languageName: node linkType: hard -"util@npm:^0.12.4, util@npm:^0.12.5": +"util@npm:^0.12.4": version: 0.12.5 resolution: "util@npm:0.12.5" dependencies: From bb8590c9b7d59cfd047be62632eb8e20ca299a9e Mon Sep 17 00:00:00 2001 From: Valentin Palkovic Date: Fri, 1 Mar 2024 14:48:19 +0100 Subject: [PATCH 40/79] Add type-safetyness to Fix type --- code/lib/cli/src/automigrate/types.ts | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/code/lib/cli/src/automigrate/types.ts b/code/lib/cli/src/automigrate/types.ts index 36b4bac18c47..d8cc9f06af3e 100644 --- a/code/lib/cli/src/automigrate/types.ts +++ b/code/lib/cli/src/automigrate/types.ts @@ -27,9 +27,8 @@ export interface RunOptions { */ export type Prompt = 'auto' | 'manual' | 'notification'; -export interface Fix { +type BaseFix = { id: string; - promptType?: Prompt | ((result: ResultType) => Promise | Prompt); /** * The from/to version range of Storybook that this fix applies to. The strings are semver ranges. * The versionRange will only be checked if the automigration is part of an upgrade. @@ -38,8 +37,23 @@ export interface Fix { versionRange: [from: string, to: string]; check: (options: CheckOptions) => Promise; prompt: (result: ResultType) => string; - run?: (options: RunOptions) => Promise; -} +}; + +type PromptType = + | T + | ((result: ResultType) => Promise | Prompt); + +export type Fix = ( + | { + promptType?: PromptType; + run: (options: RunOptions) => Promise; + } + | { + promptType: PromptType; + run?: never; + } +) & + BaseFix; export type FixId = string; From fbbf22d5945301d54bf7500e9a685805dd4367b8 Mon Sep 17 00:00:00 2001 From: Valentin Palkovic Date: Mon, 4 Mar 2024 09:16:41 +0100 Subject: [PATCH 41/79] Add missing isUpgrade parameter to automigrate function --- code/lib/cli/src/automigrate/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/lib/cli/src/automigrate/index.ts b/code/lib/cli/src/automigrate/index.ts index b0864a7071c6..8a84476b5e93 100644 --- a/code/lib/cli/src/automigrate/index.ts +++ b/code/lib/cli/src/automigrate/index.ts @@ -111,6 +111,7 @@ export const automigrate = async ({ renderer: rendererPackage, skipInstall, hideMigrationSummary = false, + isUpgrade, }: AutofixOptions): Promise<{ fixResults: Record; preCheckFailure?: PreCheckFailure; @@ -142,6 +143,7 @@ export const automigrate = async ({ mainConfigPath, storybookVersion, beforeVersion, + isUpgrade, dryRun, yes, }); From 9f0bc7db7e57b830f21311a2b7ea97ff56a476e7 Mon Sep 17 00:00:00 2001 From: Valentin Palkovic Date: Mon, 4 Mar 2024 10:29:57 +0100 Subject: [PATCH 42/79] Add @storybook/addons automigration --- .../src/automigrate/fixes/addon-postcss.ts | 2 +- .../src/automigrate/fixes/addons-api.test.ts | 44 ++++++++++++++++++ .../cli/src/automigrate/fixes/addons-api.ts | 45 +++++++++++++++++++ code/lib/cli/src/automigrate/fixes/index.ts | 2 + 4 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 code/lib/cli/src/automigrate/fixes/addons-api.test.ts create mode 100644 code/lib/cli/src/automigrate/fixes/addons-api.ts diff --git a/code/lib/cli/src/automigrate/fixes/addon-postcss.ts b/code/lib/cli/src/automigrate/fixes/addon-postcss.ts index 7978e545a1c5..f8d134183c0b 100644 --- a/code/lib/cli/src/automigrate/fixes/addon-postcss.ts +++ b/code/lib/cli/src/automigrate/fixes/addon-postcss.ts @@ -29,7 +29,7 @@ export const addonPostCSS: Fix = { return dedent` ${chalk.bold( 'Attention' - )}: We've detected that you're using the following package which are incompatible with Storybook 8 and beyond: + )}: We've detected that you're using the following package which is incompatible with Storybook 8 and beyond: - ${chalk.cyan(`@storybook/addon-postcss`)} diff --git a/code/lib/cli/src/automigrate/fixes/addons-api.test.ts b/code/lib/cli/src/automigrate/fixes/addons-api.test.ts new file mode 100644 index 000000000000..2bae14386d3b --- /dev/null +++ b/code/lib/cli/src/automigrate/fixes/addons-api.test.ts @@ -0,0 +1,44 @@ +import { addonsAPI } from './addons-api'; +import type { StorybookConfig } from '@storybook/types'; +import type { JsPackageManager } from '@storybook/core-common'; +import { expect, describe, it } from 'vitest'; + +const checkAddonsAPI = async ({ + packageManager, + mainConfig = {}, + storybookVersion = '7.0.0', +}: { + packageManager?: Partial; + mainConfig?: Partial; + storybookVersion?: string; +}) => { + return addonsAPI.check({ + packageManager: packageManager as any, + storybookVersion, + mainConfig: mainConfig as any, + }); +}; + +describe('check function', () => { + it('should return { usesAddonsAPI: true } if @storybook/addons is installed', async () => { + await expect( + checkAddonsAPI({ + packageManager: { + getAllDependencies: async () => ({ + '@storybook/addons': '6.0.0', + }), + }, + }) + ).resolves.toEqual({ usesAddonsAPI: true }); + }); + + it('should return null if @storybook/addons is not installed', async () => { + await expect( + checkAddonsAPI({ + packageManager: { + getAllDependencies: async () => ({}), + }, + }) + ).resolves.toBeNull(); + }); +}); diff --git a/code/lib/cli/src/automigrate/fixes/addons-api.ts b/code/lib/cli/src/automigrate/fixes/addons-api.ts new file mode 100644 index 000000000000..f193898aa82f --- /dev/null +++ b/code/lib/cli/src/automigrate/fixes/addons-api.ts @@ -0,0 +1,45 @@ +import chalk from 'chalk'; +import { dedent } from 'ts-dedent'; +import type { Fix } from '../types'; + +interface AddonsAPIRunOptions { + usesAddonsAPI: boolean; +} + +export const addonsAPI: Fix = { + id: 'addons-api', + + versionRange: ['<8', '>=8'], + + promptType: 'notification', + + async check({ packageManager }) { + const allDependencies = await packageManager.getAllDependencies(); + const usesAddonsAPI = !!allDependencies['@storybook/addons']; + + if (!usesAddonsAPI) { + return null; + } + + return { usesAddonsAPI: true }; + }, + + prompt() { + return dedent` + ${chalk.bold( + 'Attention' + )}: We've detected that you're using the following package which is removed in Storybook 8 and beyond: + + - ${chalk.cyan(`@storybook/addons`)} + + This package has been deprecated and replaced with ${chalk.cyan( + `@storybook/preview-api` + )} and ${chalk.cyan(`@storybook/manager-api`)}. + + You can find more information about the new addons API in the migration guide: + ${chalk.yellow( + 'https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#new-addons-api' + )} + `; + }, +}; diff --git a/code/lib/cli/src/automigrate/fixes/index.ts b/code/lib/cli/src/automigrate/fixes/index.ts index 91ba9a27927f..17b3d4942be1 100644 --- a/code/lib/cli/src/automigrate/fixes/index.ts +++ b/code/lib/cli/src/automigrate/fixes/index.ts @@ -23,12 +23,14 @@ import { storyshotsMigration } from './storyshots-migration'; import { removeArgtypesRegex } from './remove-argtypes-regex'; import { webpack5CompilerSetup } from './webpack5-compiler-setup'; import { removeJestTestingLibrary } from './remove-jest-testing-library'; +import { addonsAPI } from './addons-api'; import { mdx1to3 } from './mdx-1-to-3'; import { addonPostCSS } from './addon-postcss'; export * from '../types'; export const allFixes: Fix[] = [ + addonsAPI, newFrameworks, cra5, webpack5, From eb28dad8d0506e1ef73c109ea4eef636f781d936 Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Thu, 29 Feb 2024 11:00:53 +0100 Subject: [PATCH 43/79] Portable stories: Make canvasElement optional in the play function --- MIGRATION.md | 76 +++++++++--- code/lib/preview-api/src/index.ts | 1 + .../store/csf/portable-stories.test.ts | 65 ++++++---- .../src/modules/store/csf/portable-stories.ts | 102 ++++++++++++---- code/lib/types/src/modules/composedStory.ts | 30 ++--- .../portable-stories.test.tsx.snap | 115 ++++++++++++------ .../src/__test__/portable-stories.test.tsx | 15 ++- ...rtable-stories.ts => portable-stories.tsx} | 11 ++ .../portable-stories.test.ts.snap | 106 ++++++++++------ .../composeStories/portable-stories.test.ts | 4 +- code/renderers/vue3/src/portable-stories.ts | 17 ++- 11 files changed, 378 insertions(+), 164 deletions(-) rename code/renderers/react/src/{portable-stories.ts => portable-stories.tsx} (94%) diff --git a/MIGRATION.md b/MIGRATION.md index 202962c2cf7f..c51ddba6347e 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -1,7 +1,9 @@

Migration

- [From version 7.x to 8.0.0](#from-version-7x-to-800) - - [Type change in `composeStories` API](#type-change-in-composestories-api) + - [Portable stories](#portable-stories) + - [Type change in `composeStories` API](#type-change-in-composestories-api) + - [The context in the play function is now optional](#the-context-in-the-play-function-is-now-optional) - [Tab addons are now routed to a query parameter](#tab-addons-are-now-routed-to-a-query-parameter) - [Default keyboard shortcuts changed](#default-keyboard-shortcuts-changed) - [Manager addons are now rendered with React 18](#manager-addons-are-now-rendered-with-react-18) @@ -86,17 +88,17 @@ - [Tab addons cannot manually route, Tool addons can filter their visibility via tabId](#tab-addons-cannot-manually-route-tool-addons-can-filter-their-visibility-via-tabid) - [Removed `config` preset](#removed-config-preset-1) - [From version 7.5.0 to 7.6.0](#from-version-750-to-760) - - [CommonJS with Vite is deprecated](#commonjs-with-vite-is-deprecated) - - [Using implicit actions during rendering is deprecated](#using-implicit-actions-during-rendering-is-deprecated) - - [typescript.skipBabel deprecated](#typescriptskipbabel-deprecated) - - [Primary doc block accepts of prop](#primary-doc-block-accepts-of-prop) - - [Addons no longer need a peer dependency on React](#addons-no-longer-need-a-peer-dependency-on-react) + - [CommonJS with Vite is deprecated](#commonjs-with-vite-is-deprecated) + - [Using implicit actions during rendering is deprecated](#using-implicit-actions-during-rendering-is-deprecated) + - [typescript.skipBabel deprecated](#typescriptskipbabel-deprecated) + - [Primary doc block accepts of prop](#primary-doc-block-accepts-of-prop) + - [Addons no longer need a peer dependency on React](#addons-no-longer-need-a-peer-dependency-on-react) - [From version 7.4.0 to 7.5.0](#from-version-740-to-750) - - [`storyStoreV6` and `storiesOf` is deprecated](#storystorev6-and-storiesof-is-deprecated) - - [`storyIndexers` is replaced with `experimental_indexers`](#storyindexers-is-replaced-with-experimental_indexers) + - [`storyStoreV6` and `storiesOf` is deprecated](#storystorev6-and-storiesof-is-deprecated) + - [`storyIndexers` is replaced with `experimental_indexers`](#storyindexers-is-replaced-with-experimental_indexers) - [From version 7.0.0 to 7.2.0](#from-version-700-to-720) - - [Addon API is more type-strict](#addon-api-is-more-type-strict) - - [Addon-controls hideNoControlsWarning parameter is deprecated](#addon-controls-hidenocontrolswarning-parameter-is-deprecated) + - [Addon API is more type-strict](#addon-api-is-more-type-strict) + - [Addon-controls hideNoControlsWarning parameter is deprecated](#addon-controls-hidenocontrolswarning-parameter-is-deprecated) - [From version 6.5.x to 7.0.0](#from-version-65x-to-700) - [7.0 breaking changes](#70-breaking-changes) - [Dropped support for Node 15 and below](#dropped-support-for-node-15-and-below) @@ -122,7 +124,7 @@ - [Deploying build artifacts](#deploying-build-artifacts) - [Dropped support for file URLs](#dropped-support-for-file-urls) - [Serving with nginx](#serving-with-nginx) - - [Ignore story files from node\_modules](#ignore-story-files-from-node_modules) + - [Ignore story files from node_modules](#ignore-story-files-from-node_modules) - [7.0 Core changes](#70-core-changes) - [7.0 feature flags removed](#70-feature-flags-removed) - [Story context is prepared before for supporting fine grained updates](#story-context-is-prepared-before-for-supporting-fine-grained-updates) @@ -136,7 +138,7 @@ - [Addon-interactions: Interactions debugger is now default](#addon-interactions-interactions-debugger-is-now-default) - [7.0 Vite changes](#70-vite-changes) - [Vite builder uses Vite config automatically](#vite-builder-uses-vite-config-automatically) - - [Vite cache moved to node\_modules/.cache/.vite-storybook](#vite-cache-moved-to-node_modulescachevite-storybook) + - [Vite cache moved to node_modules/.cache/.vite-storybook](#vite-cache-moved-to-node_modulescachevite-storybook) - [7.0 Webpack changes](#70-webpack-changes) - [Webpack4 support discontinued](#webpack4-support-discontinued) - [Babel mode v7 exclusively](#babel-mode-v7-exclusively) @@ -186,7 +188,7 @@ - [Dropped addon-docs manual babel configuration](#dropped-addon-docs-manual-babel-configuration) - [Dropped addon-docs manual configuration](#dropped-addon-docs-manual-configuration) - [Autoplay in docs](#autoplay-in-docs) - - [Removed STORYBOOK\_REACT\_CLASSES global](#removed-storybook_react_classes-global) + - [Removed STORYBOOK_REACT_CLASSES global](#removed-storybook_react_classes-global) - [7.0 Deprecations and default changes](#70-deprecations-and-default-changes) - [storyStoreV7 enabled by default](#storystorev7-enabled-by-default) - [`Story` type deprecated](#story-type-deprecated) @@ -401,7 +403,9 @@ ## From version 7.x to 8.0.0 -### Type change in `composeStories` API +### Portable stories + +#### Type change in `composeStories` API There is a TypeScript type change in the `play` function returned from `composeStories` or `composeStory` in `@storybook/react` or `@storybook/vue3`, where before it was always defined, now it is potentially undefined. This means that you might have to make a small change in your code, such as: @@ -418,6 +422,49 @@ await Primary.play!(...) // if you want a runtime error when the play function d There are plans to make the type of the play function be inferred based on your imported story's play function in a near future, so the types will be 100% accurate. +#### The context in the play function is now optional + +When reusing a story that has a play function, you don't have to pass the context anymore, not even the `canvasElement`. The context is built-in and if you don't pass overrides, it will still be present. It is still possible to pass overrides to the context, if you'd like. + +```tsx +const { Primary } = composeStories(stories); +test("load and render", async () => { + const { container } = render(); + // before: + await Primary.play({ canvasElement: container, ...ArgsOrWhateverElse }); + + // after: + await Primary.play(); +}); +``` + +In order for this to be possible, the portable stories API now adds a wrapper to your stories with a unique id based on your story id, such as: + +```html +
+ +
+``` + +This means that if you take DOM snapshots of your stories, they will be affected and you will have to update them. + +The id calculation is based on different heuristics based on your Meta title and Story name. When using `composeStories`, the id can be inferred automatically. However, when using `composeStory` and your story does not explicitly have a `storyName` property, the story name can't be inferred automatically. As a result, its name will be "Unnamed Story", resulting in a wrapper id like `"#storybook-story-button--unnamed-story"`. If the id matters to you and you want to fix it, you have to specify the `exportsName` property like so: + +```ts +test("snapshots the story with custom id", () => { + const Primary = composeStory( + stories.Primary, + stories.default, + undefined, + // If you do not want the `unnamed-story` id, you have to pass the name of the story as a parameter + "Primary" + ); + + const { baseElement } = render(); + expect(baseElement).toMatchSnapshot(); +}); +``` + ### Tab addons are now routed to a query parameter The URL of a tab used to be: `http://localhost:6006/?path=/my-addon-tab/my-story`. @@ -556,7 +603,6 @@ This means https://github.com/IanVS/vite-plugin-turbosnap is no longer necessary Now that both Vite and Webpack support the `preview-stats.json` file, the flag has been renamed. The old flag will continue to work. - ### Implicit actions can not be used during rendering (for example in the play function) In Storybook 7, we inferred if the component accepts any action props, diff --git a/code/lib/preview-api/src/index.ts b/code/lib/preview-api/src/index.ts index e47cdaa0a0dd..63d45114dc23 100644 --- a/code/lib/preview-api/src/index.ts +++ b/code/lib/preview-api/src/index.ts @@ -56,6 +56,7 @@ export { filterArgTypes, sanitizeStoryContextUpdate, setProjectAnnotations, + getPortableStoryWrapperId, inferControls, userOrAutoTitleFromSpecifier, userOrAutoTitle, diff --git a/code/lib/preview-api/src/modules/store/csf/portable-stories.test.ts b/code/lib/preview-api/src/modules/store/csf/portable-stories.test.ts index af775f27360b..54e82553757f 100644 --- a/code/lib/preview-api/src/modules/store/csf/portable-stories.test.ts +++ b/code/lib/preview-api/src/modules/store/csf/portable-stories.test.ts @@ -1,10 +1,18 @@ // @vitest-environment node import { describe, expect, vi, it } from 'vitest'; -import { composeStory, composeStories } from './portable-stories'; +import type { + ComponentAnnotations as Meta, + StoryAnnotationsOrFn as Story, + Store_CSFExports, +} from '@storybook/types'; + +import { composeStory, composeStories, setProjectAnnotations } from './portable-stories'; + +type StoriesModule = Store_CSFExports & Record; // Most integration tests for this functionality are located under renderers/react describe('composeStory', () => { - const meta = { + const meta: Meta = { title: 'Button', parameters: { firstAddon: true, @@ -15,13 +23,26 @@ describe('composeStory', () => { }, }; - it('should return story with composed args and parameters', () => { - const Story = () => {}; - Story.args = { primary: true }; - Story.parameters = { + it('should return story with composed annotations from story, meta and project', () => { + const decoratorFromProjectAnnotations = vi.fn((StoryFn) => StoryFn()); + const decoratorFromStoryAnnotations = vi.fn((StoryFn) => StoryFn()); + setProjectAnnotations([ + { + parameters: { injected: true }, + globalTypes: { + locale: { defaultValue: 'en' }, + }, + decorators: [decoratorFromProjectAnnotations], + }, + ]); + + const Story: Story = { + render: () => {}, + args: { primary: true }, parameters: { secondAddon: true, }, + decorators: [decoratorFromStoryAnnotations], }; const composedStory = composeStory(Story, meta); @@ -29,28 +50,22 @@ describe('composeStory', () => { expect(composedStory.parameters).toEqual( expect.objectContaining({ ...Story.parameters, ...meta.parameters }) ); + + composedStory(); + + expect(decoratorFromProjectAnnotations).toHaveBeenCalled(); + expect(decoratorFromStoryAnnotations).toHaveBeenCalled(); }); it('should compose with a play function', async () => { const spy = vi.fn(); - const Story = () => {}; + const Story: Story = () => {}; Story.args = { primary: true, }; Story.play = async (context: any) => { spy(context); }; - - const composedStory = composeStory(Story, meta); - await composedStory.play!({ canvasElement: null }); - expect(spy).toHaveBeenCalledWith( - expect.objectContaining({ - args: { - ...Story.args, - ...meta.args, - }, - }) - ); }); it('should throw an error if Story is undefined', () => { @@ -62,7 +77,7 @@ describe('composeStory', () => { describe('Id of the story', () => { it('is exposed correctly when composeStories is used', () => { - const module = { + const module: StoriesModule = { default: { title: 'Example/Button', }, @@ -72,7 +87,7 @@ describe('composeStory', () => { expect(Primary.id).toBe('example-button--csf-3-primary'); }); it('is exposed correctly when composeStory is used and exportsName is passed', () => { - const module = { + const module: StoriesModule = { default: { title: 'Example/Button', }, @@ -83,7 +98,7 @@ describe('composeStory', () => { }); it("is not unique when composeStory is used and exportsName isn't passed", () => { const Primary = composeStory({ render: () => {} }, {}); - expect(Primary.id).toContain('unknown'); + expect(Primary.id).toContain('composedstory--unnamed-story'); }); }); }); @@ -93,7 +108,7 @@ describe('composeStories', () => { const defaultAnnotations = { render: () => '' }; it('should call composeStoryFn with stories', () => { const composeStorySpy = vi.fn((v) => v); - const module = { + const module: StoriesModule = { default: { title: 'Button', }, @@ -118,7 +133,7 @@ describe('composeStories', () => { it('should not call composeStoryFn for non-story exports', () => { const composeStorySpy = vi.fn((v) => v); - const module = { + const module: StoriesModule = { default: { title: 'Button', excludeStories: /Data/, @@ -131,7 +146,7 @@ describe('composeStories', () => { describe('non-story exports', () => { it('should filter non-story exports with excludeStories', () => { - const StoryModuleWithNonStoryExports = { + const StoryModuleWithNonStoryExports: StoriesModule = { default: { title: 'Some/Component', excludeStories: /.*Data/, @@ -149,7 +164,7 @@ describe('composeStories', () => { }); it('should filter non-story exports with includeStories', () => { - const StoryModuleWithNonStoryExports = { + const StoryModuleWithNonStoryExports: StoriesModule = { default: { title: 'Some/Component', includeStories: /.*Story/, diff --git a/code/lib/preview-api/src/modules/store/csf/portable-stories.ts b/code/lib/preview-api/src/modules/store/csf/portable-stories.ts index 91e4cdc365e1..6f24b2933cdf 100644 --- a/code/lib/preview-api/src/modules/store/csf/portable-stories.ts +++ b/code/lib/preview-api/src/modules/store/csf/portable-stories.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/naming-convention */ import { isExportStory } from '@storybook/csf'; import type { Renderer, @@ -12,7 +13,7 @@ import type { Parameters, ComposedStoryFn, StrictArgTypes, - ComposedStoryPlayContext, + PlayFunctionContext, } from '@storybook/types'; import { HooksContext } from '../../../addons'; @@ -22,9 +23,14 @@ import { normalizeStory } from './normalizeStory'; import { normalizeComponentAnnotations } from './normalizeComponentAnnotations'; import { getValuesFromArgTypes } from './getValuesFromArgTypes'; import { normalizeProjectAnnotations } from './normalizeProjectAnnotations'; +import { normalizeArrays } from './normalizeArrays'; let GLOBAL_STORYBOOK_PROJECT_ANNOTATIONS = composeConfigs([]); +export function getPortableStoryWrapperId(storyId: string) { + return `storybook-story-${storyId}`; +} + export function setProjectAnnotations( projectAnnotations: ProjectAnnotations | ProjectAnnotations[] ) { @@ -32,6 +38,46 @@ export function setProjectAnnotations( GLOBAL_STORYBOOK_PROJECT_ANNOTATIONS = composeConfigs(annotations); } +// TODO: we don't have any utility that merges two sets of annotations (e.g. two project annotations) +// this should be elsewhere, probably reused +function mergeAnnotations( + firstAnnotations: ProjectAnnotations, + secondAnnotations: ProjectAnnotations +) { + return { + ...firstAnnotations, + ...secondAnnotations, + args: { + ...firstAnnotations.args, + ...secondAnnotations.args, + }, + argTypes: { + ...firstAnnotations.argTypes, + ...secondAnnotations.argTypes, + }, + parameters: { + ...firstAnnotations.parameters, + ...secondAnnotations.parameters, + }, + decorators: [ + ...normalizeArrays(firstAnnotations.decorators), + ...normalizeArrays(secondAnnotations.decorators), + ], + loaders: [ + ...normalizeArrays(firstAnnotations.loaders), + ...normalizeArrays(secondAnnotations.loaders), + ], + argsEnhancers: [ + ...normalizeArrays(firstAnnotations.argsEnhancers), + ...normalizeArrays(secondAnnotations.argsEnhancers), + ], + argTypesEnhancers: [ + ...normalizeArrays(firstAnnotations.argTypesEnhancers), + ...normalizeArrays(secondAnnotations.argTypesEnhancers), + ], + }; +} + export function composeStory( storyAnnotations: LegacyStoryAnnotationsOrFn, componentAnnotations: ComponentAnnotations, @@ -43,6 +89,12 @@ export function composeStory; + } + // @TODO: Support auto title componentAnnotations.title = componentAnnotations.title ?? 'ComposedStory'; @@ -54,7 +106,7 @@ export function composeStory( storyName, @@ -62,10 +114,9 @@ export function composeStory({ - ...projectAnnotations, - ...defaultConfig, - }); + const normalizedProjectAnnotations = normalizeProjectAnnotations( + mergeAnnotations(projectAnnotations, defaultConfig) + ); const story = prepareStory( normalizedStory, @@ -77,7 +128,10 @@ export function composeStory = { hooks: new HooksContext(), - globals: defaultGlobals, + globals: { + ...defaultGlobals, + ...projectAnnotations.globals, + }, args: { ...story.initialArgs }, viewMode: 'story', loaded: {}, @@ -86,28 +140,35 @@ export function composeStory>) => + story.playFunction!({ + ...context, + ...extraContext, + // if canvasElement is not provided, we default to the root element, which comes from a decorator + // the decorator has to be implemented in the defaultAnnotations of each integrator of portable stories + canvasElement: + extraContext?.canvasElement ?? + globalThis.document?.getElementById(getPortableStoryWrapperId(context.id)), + }) + : undefined; + const composedStory: ComposedStoryFn> = Object.assign( - (extraArgs?: Partial) => { - const finalContext: StoryContext = { - ...context, - args: { ...context.initialArgs, ...extraArgs }, + function storyFn(extraArgs?: Partial) { + context.args = { + ...context.initialArgs, + ...extraArgs, }; - return story.unboundStoryFn(prepareContext(finalContext)); + return story.unboundStoryFn(prepareContext(context)); }, { + id: story.id, storyName, args: story.initialArgs as Partial, parameters: story.parameters as Parameters, argTypes: story.argTypes as StrictArgTypes, - id: story.id, - play: story.playFunction - ? ((async (extraContext: ComposedStoryPlayContext) => - story.playFunction!({ - ...context, - ...extraContext, - })) as unknown as ComposedStoryPlayFn>) - : undefined, + play: playFunction as ComposedStoryPlayFn | undefined, } ); @@ -119,7 +180,6 @@ export function composeStories( globalConfig: ProjectAnnotations, composeStoryFn: ComposeStoryFn ) { - // eslint-disable-next-line @typescript-eslint/naming-convention const { default: meta, __esModule, __namedExportsOrder, ...stories } = storiesImport; const composedStories = Object.entries(stories).reduce((storiesMap, [exportsName, story]) => { if (!isExportStory(exportsName, meta)) { diff --git a/code/lib/types/src/modules/composedStory.ts b/code/lib/types/src/modules/composedStory.ts index 5ce61bc678e8..b7051a699b7f 100644 --- a/code/lib/types/src/modules/composedStory.ts +++ b/code/lib/types/src/modules/composedStory.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import type { Renderer, StoryId, StrictArgTypes } from '@storybook/csf'; +import type { PlayFunction, Renderer, StoryId, StrictArgTypes } from '@storybook/csf'; import type { AnnotatedStoryFn, @@ -9,7 +9,6 @@ import type { Parameters, StoryAnnotations, StoryAnnotationsOrFn, - StoryContext, } from './csf'; import type { ProjectAnnotations } from './story'; @@ -22,23 +21,6 @@ export type Store_CSFExports) // or PrimaryButton() - * PrimaryButton.play({ canvasElement: container }) - */ -export type ComposedStoryPlayContext = Partial< - StoryContext & Pick, 'canvasElement'> ->; - -export type ComposedStoryPlayFn = ( - context: ComposedStoryPlayContext -) => Promise | void; - /** * A story function with partial args, used internally by composeStory */ @@ -48,6 +30,14 @@ export type PartialArgsStoryFn = T extends (...args: infer P) => infer R + ? (...args: { [K in keyof P]?: Partial }) => R + : never; + +export type ComposedStoryPlayFn< + TRenderer extends Renderer = Renderer, + TArgs = Args, +> = MakeAllParametersOptional>>; /** * A story that got recomposed for portable stories, containing all the necessary data to be rendered in external environments */ @@ -55,9 +45,9 @@ export type ComposedStoryFn< TRenderer extends Renderer = Renderer, TArgs = Args, > = PartialArgsStoryFn & { - play: ComposedStoryPlayFn | undefined; args: TArgs; id: StoryId; + play?: ComposedStoryPlayFn; storyName: string; parameters: Parameters; argTypes: StrictArgTypes; diff --git a/code/renderers/react/src/__test__/__snapshots__/portable-stories.test.tsx.snap b/code/renderers/react/src/__test__/__snapshots__/portable-stories.test.tsx.snap index 2b92b1d68424..3f40e5446d0b 100644 --- a/code/renderers/react/src/__test__/__snapshots__/portable-stories.test.tsx.snap +++ b/code/renderers/react/src/__test__/__snapshots__/portable-stories.test.tsx.snap @@ -3,12 +3,17 @@ exports[`Renders CSF2Secondary story 1`] = `
- + +
`; @@ -16,12 +21,17 @@ exports[`Renders CSF2Secondary story 1`] = ` exports[`Renders CSF2StoryWithLocale story 1`] = `
- + +
`; @@ -29,12 +39,17 @@ exports[`Renders CSF2StoryWithLocale story 1`] = ` exports[`Renders CSF2StoryWithParamsAndDecorator story 1`] = `
- + +
`; @@ -42,12 +57,17 @@ exports[`Renders CSF2StoryWithParamsAndDecorator story 1`] = ` exports[`Renders CSF3Button story 1`] = `
- + +
`; @@ -55,18 +75,23 @@ exports[`Renders CSF3Button story 1`] = ` exports[`Renders CSF3ButtonWithRender story 1`] = `
-
-

- I am a custom render function -

- +
+
+

+ I am a custom render function +

+ +
@@ -75,9 +100,14 @@ exports[`Renders CSF3ButtonWithRender story 1`] = ` exports[`Renders CSF3InputFieldFilled story 1`] = `
- +
+ +
`; @@ -85,12 +115,17 @@ exports[`Renders CSF3InputFieldFilled story 1`] = ` exports[`Renders CSF3Primary story 1`] = `
- + +
`; diff --git a/code/renderers/react/src/__test__/portable-stories.test.tsx b/code/renderers/react/src/__test__/portable-stories.test.tsx index afa0b70142e4..f137424fff0b 100644 --- a/code/renderers/react/src/__test__/portable-stories.test.tsx +++ b/code/renderers/react/src/__test__/portable-stories.test.tsx @@ -58,7 +58,7 @@ describe('projectAnnotations', () => { expect(buttonElement).not.toBeNull(); }); - it('renders with custom projectAnnotations via composeStory params', () => { + it('renders with custom globals from projectAnnotations via composeStory params', () => { const WithPortugueseText = composeStory(stories.CSF2StoryWithLocale, stories.default, { globalTypes: { locale: { defaultValue: 'pt' } } as any, }); @@ -94,7 +94,18 @@ describe('CSF3', () => { expect(screen.getByTestId('custom-render')).not.toBeNull(); }); - it('renders with play function', async () => { + it('renders with play function without canvas element', async () => { + const CSF3InputFieldFilled = composeStory(stories.CSF3InputFieldFilled, stories.default); + + render(); + + await CSF3InputFieldFilled.play!(); + + const input = screen.getByTestId('input') as HTMLInputElement; + expect(input.value).toEqual('Hello world!'); + }); + + it('renders with play function with canvas element', async () => { const CSF3InputFieldFilled = composeStory(stories.CSF3InputFieldFilled, stories.default); const { container } = render(); diff --git a/code/renderers/react/src/portable-stories.ts b/code/renderers/react/src/portable-stories.tsx similarity index 94% rename from code/renderers/react/src/portable-stories.ts rename to code/renderers/react/src/portable-stories.tsx index 385e0dc4c804..55ca55c69ff4 100644 --- a/code/renderers/react/src/portable-stories.ts +++ b/code/renderers/react/src/portable-stories.tsx @@ -1,7 +1,9 @@ +import React from 'react'; import { composeStory as originalComposeStory, composeStories as originalComposeStories, setProjectAnnotations as originalSetProjectAnnotations, + getPortableStoryWrapperId, } from '@storybook/preview-api'; import type { Args, @@ -39,6 +41,15 @@ export function setProjectAnnotations( // This will not be necessary once we have auto preset loading const defaultProjectAnnotations: ProjectAnnotations = { render, + decorators: [ + function addStorybookId(StoryFn, { id }) { + return ( +
+ {StoryFn()} +
+ ); + }, + ], }; /** diff --git a/code/renderers/vue3/src/__tests__/composeStories/__snapshots__/portable-stories.test.ts.snap b/code/renderers/vue3/src/__tests__/composeStories/__snapshots__/portable-stories.test.ts.snap index 75eab08758cf..aca5cb96961b 100644 --- a/code/renderers/vue3/src/__tests__/composeStories/__snapshots__/portable-stories.test.ts.snap +++ b/code/renderers/vue3/src/__tests__/composeStories/__snapshots__/portable-stories.test.ts.snap @@ -3,56 +3,51 @@ exports[`Renders CSF2Secondary story 1`] = `
- -
- -`; - -exports[`Renders CSF2StoryWithLocale story 1`] = ` - -
-
-

- locale: undefined -

`; -exports[`Renders CSF3Button story 1`] = ` +exports[`Renders CSF2StoryWithLocale story 1`] = `
- +
+

+ locale: undefined +

+ +
+
`; -exports[`Renders CSF3ButtonWithRender story 1`] = ` +exports[`Renders CSF3Button story 1`] = `
-
-

- I am a custom render function -

+
+
+
+
+ +`; + exports[`Renders CSF3InputFieldFilled story 1`] = `
- +
+ +
`; @@ -77,12 +102,17 @@ exports[`Renders CSF3InputFieldFilled story 1`] = ` exports[`Renders CSF3Primary story 1`] = `
- + +
`; diff --git a/code/renderers/vue3/src/__tests__/composeStories/portable-stories.test.ts b/code/renderers/vue3/src/__tests__/composeStories/portable-stories.test.ts index 4c541e1c4536..97fb295c47bc 100644 --- a/code/renderers/vue3/src/__tests__/composeStories/portable-stories.test.ts +++ b/code/renderers/vue3/src/__tests__/composeStories/portable-stories.test.ts @@ -84,9 +84,9 @@ describe('CSF3', () => { it('renders with play function', async () => { const CSF3InputFieldFilled = composeStory(stories.CSF3InputFieldFilled, stories.default); - const { container } = render(CSF3InputFieldFilled()); + render(CSF3InputFieldFilled()); - await CSF3InputFieldFilled.play!({ canvasElement: container as HTMLElement }); + await CSF3InputFieldFilled.play!(); const input = screen.getByTestId('input') as HTMLInputElement; expect(input.value).toEqual('Hello world!'); diff --git a/code/renderers/vue3/src/portable-stories.ts b/code/renderers/vue3/src/portable-stories.ts index 4e009b25d672..aef26b39a5e7 100644 --- a/code/renderers/vue3/src/portable-stories.ts +++ b/code/renderers/vue3/src/portable-stories.ts @@ -2,6 +2,7 @@ import { composeStory as originalComposeStory, composeStories as originalComposeStories, setProjectAnnotations as originalSetProjectAnnotations, + getPortableStoryWrapperId, } from '@storybook/preview-api'; import type { Args, @@ -11,10 +12,24 @@ import type { StoriesWithPartialProps, } from '@storybook/types'; -import * as defaultProjectAnnotations from './render'; +import * as vueProjectAnnotations from './entry-preview'; import type { Meta } from './public-types'; import type { VueRenderer } from './types'; +const defaultProjectAnnotations: ProjectAnnotations = { + ...vueProjectAnnotations, + decorators: [ + function addStorybookId(story, { id }) { + return { + components: { story }, + template: `
+ +
`, + }; + }, + ], +}; + /** Function that sets the globalConfig of your Storybook. The global config is the preview module of your .storybook folder. * * It should be run a single time, so that your global config (e.g. decorators) is applied to your stories when using `composeStories` or `composeStory`. From 0694772841f956bcf55ec81f8aba71771870f71e Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Fri, 1 Mar 2024 12:23:40 +0100 Subject: [PATCH 44/79] Update code/lib/preview-api/src/modules/store/csf/portable-stories.test.ts Co-authored-by: Jeppe Reinhold --- .../src/modules/store/csf/portable-stories.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/lib/preview-api/src/modules/store/csf/portable-stories.test.ts b/code/lib/preview-api/src/modules/store/csf/portable-stories.test.ts index 54e82553757f..9d3602ecc492 100644 --- a/code/lib/preview-api/src/modules/store/csf/portable-stories.test.ts +++ b/code/lib/preview-api/src/modules/store/csf/portable-stories.test.ts @@ -53,8 +53,8 @@ describe('composeStory', () => { composedStory(); - expect(decoratorFromProjectAnnotations).toHaveBeenCalled(); - expect(decoratorFromStoryAnnotations).toHaveBeenCalled(); + expect(decoratorFromProjectAnnotations).toHaveBeenCalledOnce(); + expect(decoratorFromStoryAnnotations).toHaveBeenCalledOnce(); }); it('should compose with a play function', async () => { From d39b6c93b433750ebdf33f68c855923872d41954 Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Fri, 1 Mar 2024 14:03:12 +0100 Subject: [PATCH 45/79] use composeConfigs function --- .../src/modules/store/csf/portable-stories.ts | 43 +------------------ 1 file changed, 1 insertion(+), 42 deletions(-) diff --git a/code/lib/preview-api/src/modules/store/csf/portable-stories.ts b/code/lib/preview-api/src/modules/store/csf/portable-stories.ts index 6f24b2933cdf..fbe3898fc3d2 100644 --- a/code/lib/preview-api/src/modules/store/csf/portable-stories.ts +++ b/code/lib/preview-api/src/modules/store/csf/portable-stories.ts @@ -23,7 +23,6 @@ import { normalizeStory } from './normalizeStory'; import { normalizeComponentAnnotations } from './normalizeComponentAnnotations'; import { getValuesFromArgTypes } from './getValuesFromArgTypes'; import { normalizeProjectAnnotations } from './normalizeProjectAnnotations'; -import { normalizeArrays } from './normalizeArrays'; let GLOBAL_STORYBOOK_PROJECT_ANNOTATIONS = composeConfigs([]); @@ -38,46 +37,6 @@ export function setProjectAnnotations( GLOBAL_STORYBOOK_PROJECT_ANNOTATIONS = composeConfigs(annotations); } -// TODO: we don't have any utility that merges two sets of annotations (e.g. two project annotations) -// this should be elsewhere, probably reused -function mergeAnnotations( - firstAnnotations: ProjectAnnotations, - secondAnnotations: ProjectAnnotations -) { - return { - ...firstAnnotations, - ...secondAnnotations, - args: { - ...firstAnnotations.args, - ...secondAnnotations.args, - }, - argTypes: { - ...firstAnnotations.argTypes, - ...secondAnnotations.argTypes, - }, - parameters: { - ...firstAnnotations.parameters, - ...secondAnnotations.parameters, - }, - decorators: [ - ...normalizeArrays(firstAnnotations.decorators), - ...normalizeArrays(secondAnnotations.decorators), - ], - loaders: [ - ...normalizeArrays(firstAnnotations.loaders), - ...normalizeArrays(secondAnnotations.loaders), - ], - argsEnhancers: [ - ...normalizeArrays(firstAnnotations.argsEnhancers), - ...normalizeArrays(secondAnnotations.argsEnhancers), - ], - argTypesEnhancers: [ - ...normalizeArrays(firstAnnotations.argTypesEnhancers), - ...normalizeArrays(secondAnnotations.argTypesEnhancers), - ], - }; -} - export function composeStory( storyAnnotations: LegacyStoryAnnotationsOrFn, componentAnnotations: ComponentAnnotations, @@ -115,7 +74,7 @@ export function composeStory( - mergeAnnotations(projectAnnotations, defaultConfig) + composeConfigs([projectAnnotations, defaultConfig]) ); const story = prepareStory( From a2891859107a10b48f5392de7bd0bd30aa7a4cfe Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Fri, 1 Mar 2024 14:09:13 +0100 Subject: [PATCH 46/79] update migration notes --- MIGRATION.md | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/MIGRATION.md b/MIGRATION.md index c51ddba6347e..62aef1593d05 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -3,7 +3,7 @@ - [From version 7.x to 8.0.0](#from-version-7x-to-800) - [Portable stories](#portable-stories) - [Type change in `composeStories` API](#type-change-in-composestories-api) - - [The context in the play function is now optional](#the-context-in-the-play-function-is-now-optional) + - [DOM structure changed in portable stories](#dom-structure-changed-in-portable-stories) - [Tab addons are now routed to a query parameter](#tab-addons-are-now-routed-to-a-query-parameter) - [Default keyboard shortcuts changed](#default-keyboard-shortcuts-changed) - [Manager addons are now rendered with React 18](#manager-addons-are-now-rendered-with-react-18) @@ -422,23 +422,9 @@ await Primary.play!(...) // if you want a runtime error when the play function d There are plans to make the type of the play function be inferred based on your imported story's play function in a near future, so the types will be 100% accurate. -#### The context in the play function is now optional +#### DOM structure changed in portable stories -When reusing a story that has a play function, you don't have to pass the context anymore, not even the `canvasElement`. The context is built-in and if you don't pass overrides, it will still be present. It is still possible to pass overrides to the context, if you'd like. - -```tsx -const { Primary } = composeStories(stories); -test("load and render", async () => { - const { container } = render(); - // before: - await Primary.play({ canvasElement: container, ...ArgsOrWhateverElse }); - - // after: - await Primary.play(); -}); -``` - -In order for this to be possible, the portable stories API now adds a wrapper to your stories with a unique id based on your story id, such as: +The portable stories API now adds a wrapper to your stories with a unique id based on your story id, such as: ```html
From f60fee3fea81fd40888b9c7f494377e56d1cdbf0 Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Fri, 1 Mar 2024 16:35:54 +0100 Subject: [PATCH 47/79] fix compose configs order --- code/lib/preview-api/src/modules/store/csf/portable-stories.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/lib/preview-api/src/modules/store/csf/portable-stories.ts b/code/lib/preview-api/src/modules/store/csf/portable-stories.ts index fbe3898fc3d2..c3dfd53d2877 100644 --- a/code/lib/preview-api/src/modules/store/csf/portable-stories.ts +++ b/code/lib/preview-api/src/modules/store/csf/portable-stories.ts @@ -74,7 +74,7 @@ export function composeStory( - composeConfigs([projectAnnotations, defaultConfig]) + composeConfigs([defaultConfig, projectAnnotations]) ); const story = prepareStory( From 2552e0395840e37f2c988434a497de231b756ded Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Fri, 1 Mar 2024 16:39:28 +0100 Subject: [PATCH 48/79] bring test assertions back --- .../src/modules/store/csf/portable-stories.test.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/code/lib/preview-api/src/modules/store/csf/portable-stories.test.ts b/code/lib/preview-api/src/modules/store/csf/portable-stories.test.ts index 9d3602ecc492..6a6d059834de 100644 --- a/code/lib/preview-api/src/modules/store/csf/portable-stories.test.ts +++ b/code/lib/preview-api/src/modules/store/csf/portable-stories.test.ts @@ -66,6 +66,17 @@ describe('composeStory', () => { Story.play = async (context: any) => { spy(context); }; + + const composedStory = composeStory(Story, meta); + await composedStory.play!({ canvasElement: null }); + expect(spy).toHaveBeenCalledWith( + expect.objectContaining({ + args: { + ...Story.args, + ...meta.args, + }, + }) + ); }); it('should throw an error if Story is undefined', () => { From 40b56a46b42b834c771674d7a3d1140d2f4c4d51 Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Fri, 1 Mar 2024 16:40:11 +0100 Subject: [PATCH 49/79] use jsx in portable stories react decorator --- code/renderers/react/src/portable-stories.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/renderers/react/src/portable-stories.tsx b/code/renderers/react/src/portable-stories.tsx index 55ca55c69ff4..bf91dde7b3e8 100644 --- a/code/renderers/react/src/portable-stories.tsx +++ b/code/renderers/react/src/portable-stories.tsx @@ -45,7 +45,7 @@ const defaultProjectAnnotations: ProjectAnnotations = { function addStorybookId(StoryFn, { id }) { return (
- {StoryFn()} +
); }, From 1dd146fbd045f853d0312e4aa5daab5b8d96daa3 Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Fri, 1 Mar 2024 16:43:08 +0100 Subject: [PATCH 50/79] use play function on snapshot tests --- .../react/src/__test__/portable-stories.test.tsx | 16 ++++++++++++---- .../composeStories/portable-stories.test.ts | 6 ++++-- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/code/renderers/react/src/__test__/portable-stories.test.tsx b/code/renderers/react/src/__test__/portable-stories.test.tsx index f137424fff0b..3c7edd4e8e17 100644 --- a/code/renderers/react/src/__test__/portable-stories.test.tsx +++ b/code/renderers/react/src/__test__/portable-stories.test.tsx @@ -1,5 +1,5 @@ -import { vi, it, expect, afterEach, describe } from 'vitest'; import React from 'react'; +import { vi, it, expect, afterEach, describe } from 'vitest'; import { render, screen, cleanup } from '@testing-library/react'; import { addons } from '@storybook/preview-api'; import type { Meta } from '@storybook/react'; @@ -150,9 +150,17 @@ describe('ComposeStories types', () => { }); // Batch snapshot testing -const testCases = Object.values(composeStories(stories)).map((Story) => [Story.storyName, Story]); +const testCases = Object.values(composeStories(stories)).map( + (Story) => [Story.storyName, Story] as [string, typeof Story] +); it.each(testCases)('Renders %s story', async (_storyName, Story) => { cleanup(); - const tree = await render(); - expect(tree.baseElement).toMatchSnapshot(); + + if (_storyName === 'CSF2WithLocale') { + return; + } + + const { baseElement } = await render(); + await Story.play?.(); + expect(baseElement).toMatchSnapshot(); }); diff --git a/code/renderers/vue3/src/__tests__/composeStories/portable-stories.test.ts b/code/renderers/vue3/src/__tests__/composeStories/portable-stories.test.ts index 97fb295c47bc..e82a6c657a89 100644 --- a/code/renderers/vue3/src/__tests__/composeStories/portable-stories.test.ts +++ b/code/renderers/vue3/src/__tests__/composeStories/portable-stories.test.ts @@ -133,6 +133,8 @@ it.each(testCases)('Renders %s story', async (_storyName, Story) => { await new Promise((resolve) => setTimeout(resolve, 0)); - const tree = await render(Story()); - expect(tree.baseElement).toMatchSnapshot(); + const { baseElement } = await render(Story()); + await Story.play?.(); + + expect(baseElement).toMatchSnapshot(); }); From 69e69d182a754c0ec4d3d326588d9c07b1cfb285 Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Mon, 4 Mar 2024 10:28:54 +0100 Subject: [PATCH 51/79] fix proejct annotation merging logic --- .../store/csf/portable-stories.test.ts | 25 +++++++++++++++++++ .../src/modules/store/csf/portable-stories.ts | 22 ++++++---------- 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/code/lib/preview-api/src/modules/store/csf/portable-stories.test.ts b/code/lib/preview-api/src/modules/store/csf/portable-stories.test.ts index 6a6d059834de..3f2876be4c2c 100644 --- a/code/lib/preview-api/src/modules/store/csf/portable-stories.test.ts +++ b/code/lib/preview-api/src/modules/store/csf/portable-stories.test.ts @@ -79,6 +79,31 @@ describe('composeStory', () => { ); }); + it('should merge parameters with correct precedence in all combinations', async () => { + const storyAnnotations = { render: () => {} }; + const metaAnnotations: Meta = { parameters: { label: 'meta' } }; + const projectAnnotations: Meta = { parameters: { label: 'projectOverrides' } }; + + const storyPrecedence = composeStory( + { ...storyAnnotations, parameters: { label: 'story' } }, + metaAnnotations, + projectAnnotations + ); + expect(storyPrecedence.parameters.label).toEqual('story'); + + const metaPrecedence = composeStory(storyAnnotations, metaAnnotations, projectAnnotations); + expect(metaPrecedence.parameters.label).toEqual('meta'); + + const projectPrecedence = composeStory(storyAnnotations, {}, projectAnnotations); + expect(projectPrecedence.parameters.label).toEqual('projectOverrides'); + + setProjectAnnotations({ parameters: { label: 'setProjectAnnotationsOverrides' } }); + const setProjectAnnotationsPrecedence = composeStory(storyAnnotations, {}, {}); + expect(setProjectAnnotationsPrecedence.parameters.label).toEqual( + 'setProjectAnnotationsOverrides' + ); + }); + it('should throw an error if Story is undefined', () => { expect(() => { // @ts-expect-error (invalid input) diff --git a/code/lib/preview-api/src/modules/store/csf/portable-stories.ts b/code/lib/preview-api/src/modules/store/csf/portable-stories.ts index c3dfd53d2877..65d38e1b9805 100644 --- a/code/lib/preview-api/src/modules/store/csf/portable-stories.ts +++ b/code/lib/preview-api/src/modules/store/csf/portable-stories.ts @@ -24,7 +24,7 @@ import { normalizeComponentAnnotations } from './normalizeComponentAnnotations'; import { getValuesFromArgTypes } from './getValuesFromArgTypes'; import { normalizeProjectAnnotations } from './normalizeProjectAnnotations'; -let GLOBAL_STORYBOOK_PROJECT_ANNOTATIONS = composeConfigs([]); +let globalProjectAnnotations: ProjectAnnotations = {}; export function getPortableStoryWrapperId(storyId: string) { return `storybook-story-${storyId}`; @@ -34,26 +34,20 @@ export function setProjectAnnotations( projectAnnotations: ProjectAnnotations | ProjectAnnotations[] ) { const annotations = Array.isArray(projectAnnotations) ? projectAnnotations : [projectAnnotations]; - GLOBAL_STORYBOOK_PROJECT_ANNOTATIONS = composeConfigs(annotations); + globalProjectAnnotations = composeConfigs(annotations); } export function composeStory( storyAnnotations: LegacyStoryAnnotationsOrFn, componentAnnotations: ComponentAnnotations, - projectAnnotations: ProjectAnnotations = GLOBAL_STORYBOOK_PROJECT_ANNOTATIONS as ProjectAnnotations, - defaultConfig: ProjectAnnotations = {}, + projectAnnotations?: ProjectAnnotations, + defaultConfig?: ProjectAnnotations, exportsName?: string ): ComposedStoryFn> { if (storyAnnotations === undefined) { throw new Error('Expected a story but received undefined.'); } - // users might pass an empty object instead of undefined e.g. composeStory(story, meta, {}, exportsName) - // and likely they expect the default project annotations to be used instead of completely resetting them - if (typeof projectAnnotations === 'object' && Object.keys(projectAnnotations).length === 0) { - projectAnnotations = GLOBAL_STORYBOOK_PROJECT_ANNOTATIONS as ProjectAnnotations; - } - // @TODO: Support auto title componentAnnotations.title = componentAnnotations.title ?? 'ComposedStory'; @@ -74,7 +68,7 @@ export function composeStory( - composeConfigs([defaultConfig, projectAnnotations]) + composeConfigs([defaultConfig ?? {}, globalProjectAnnotations, projectAnnotations ?? {}]) ); const story = prepareStory( @@ -83,13 +77,13 @@ export function composeStory = { hooks: new HooksContext(), globals: { - ...defaultGlobals, - ...projectAnnotations.globals, + ...globalsFromGlobalTypes, + ...normalizedProjectAnnotations.globals, }, args: { ...story.initialArgs }, viewMode: 'story', From 2b6ce98d791aa6f06082d6ed185ff40826bb1674 Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Mon, 4 Mar 2024 11:47:58 +0100 Subject: [PATCH 52/79] Portable stories: Add support for loaders --- .../store/csf/portable-stories.test.ts | 49 ++++++++++++ .../src/modules/store/csf/portable-stories.ts | 5 ++ code/lib/types/src/modules/composedStory.ts | 1 + .../react/src/__test__/Button.stories.tsx | 44 ++++++++++- .../portable-stories.test.tsx.snap | 42 +++++----- .../src/__test__/portable-stories.test.tsx | 29 ++++++- code/renderers/react/src/portable-stories.tsx | 4 +- .../composeStories/Button.stories.ts | 42 +++++++++- .../portable-stories.test.ts.snap | 37 +++++++-- .../composeStories/portable-stories.test.ts | 77 ++++++++++++------- 10 files changed, 262 insertions(+), 68 deletions(-) diff --git a/code/lib/preview-api/src/modules/store/csf/portable-stories.test.ts b/code/lib/preview-api/src/modules/store/csf/portable-stories.test.ts index 3f2876be4c2c..dbca4640b05b 100644 --- a/code/lib/preview-api/src/modules/store/csf/portable-stories.test.ts +++ b/code/lib/preview-api/src/modules/store/csf/portable-stories.test.ts @@ -104,6 +104,55 @@ describe('composeStory', () => { ); }); + it('should call and compose loaders data', async () => { + const loadSpy = vi.fn(); + const args = { story: 'story' }; + const LoaderStory: Story = { + args, + loaders: [ + async (context) => { + loadSpy(); + expect(context.args).toEqual(args); + return { + foo: 'bar', + }; + }, + ], + render: (_args, { loaded }) => { + expect(loaded).toEqual({ foo: 'bar' }); + }, + }; + + const composedStory = composeStory(LoaderStory, {}); + await composedStory.load(); + composedStory(); + expect(loadSpy).toHaveBeenCalled(); + }); + + it('should work with spies set up in loaders', async () => { + const spyFn = vi.fn(); + + const Story: Story = { + args: { + spyFn, + }, + loaders: [ + async () => { + spyFn.mockReturnValue('mockedData'); + }, + ], + render: (args) => { + const data = args.spyFn(); + expect(data).toBe('mockedData'); + }, + }; + + const composedStory = composeStory(Story, {}); + await composedStory.load(); + composedStory(); + expect(spyFn).toHaveBeenCalled(); + }); + it('should throw an error if Story is undefined', () => { expect(() => { // @ts-expect-error (invalid input) diff --git a/code/lib/preview-api/src/modules/store/csf/portable-stories.ts b/code/lib/preview-api/src/modules/store/csf/portable-stories.ts index 65d38e1b9805..0974f0908526 100644 --- a/code/lib/preview-api/src/modules/store/csf/portable-stories.ts +++ b/code/lib/preview-api/src/modules/store/csf/portable-stories.ts @@ -45,6 +45,7 @@ export function composeStory> { if (storyAnnotations === undefined) { + // eslint-disable-next-line local-rules/no-uncategorized-errors throw new Error('Expected a story but received undefined.'); } @@ -118,6 +119,10 @@ export function composeStory { + const loadedContext = await story.applyLoaders(context); + context.loaded = loadedContext.loaded; + }, args: story.initialArgs as Partial, parameters: story.parameters as Parameters, argTypes: story.argTypes as StrictArgTypes, diff --git a/code/lib/types/src/modules/composedStory.ts b/code/lib/types/src/modules/composedStory.ts index b7051a699b7f..b0a7bff6c374 100644 --- a/code/lib/types/src/modules/composedStory.ts +++ b/code/lib/types/src/modules/composedStory.ts @@ -48,6 +48,7 @@ export type ComposedStoryFn< args: TArgs; id: StoryId; play?: ComposedStoryPlayFn; + load: () => Promise; storyName: string; parameters: Parameters; argTypes: StrictArgTypes; diff --git a/code/renderers/react/src/__test__/Button.stories.tsx b/code/renderers/react/src/__test__/Button.stories.tsx index 6882b957b136..277f92ddde1f 100644 --- a/code/renderers/react/src/__test__/Button.stories.tsx +++ b/code/renderers/react/src/__test__/Button.stories.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { within, userEvent } from '@storybook/testing-library'; +import { within, userEvent, fn, expect } from '@storybook/test'; import type { StoryFn as CSF2Story, StoryObj as CSF3Story, Meta } from '..'; import type { ButtonProps } from './Button'; @@ -33,14 +33,21 @@ const getCaptionForLocale = (locale: string) => { return 'μ•ˆλ…•ν•˜μ„Έμš”!'; case 'pt': return 'OlΓ‘!'; - default: + case 'en': return 'Hello!'; + default: + return undefined; } }; export const CSF2StoryWithLocale: CSF2Story = (args, { globals: { locale } }) => { const caption = getCaptionForLocale(locale); - return ; + return ( + <> +

locale: {locale}

+ + + ); }; CSF2StoryWithLocale.storyName = 'WithLocale'; @@ -84,7 +91,36 @@ export const CSF3InputFieldFilled: CSF3Story = { play: async ({ canvasElement, step }) => { const canvas = within(canvasElement); await step('Step label', async () => { - await userEvent.type(canvas.getByTestId('input'), 'Hello world!'); + const inputEl = canvas.getByTestId('input'); + await userEvent.type(inputEl, 'Hello world!'); + await expect(inputEl).toHaveValue('Hello world!'); }); }, }; + +const mockFn = fn(); +export const LoaderStory: CSF3Story<{ mockFn: (val: string) => string }> = { + args: { + mockFn, + }, + loaders: [ + async () => { + mockFn.mockReturnValueOnce('mockFn return value'); + return { + value: 'loaded data', + }; + }, + ], + render: (args, { loaded }) => { + const data = args.mockFn('render'); + return ( +
+
{loaded.value}
+
{String(data)}
+
+ ); + }, + play: async () => { + expect(mockFn).toHaveBeenCalledWith('render'); + }, +}; diff --git a/code/renderers/react/src/__test__/__snapshots__/portable-stories.test.tsx.snap b/code/renderers/react/src/__test__/__snapshots__/portable-stories.test.tsx.snap index 3f40e5446d0b..2779b21001ab 100644 --- a/code/renderers/react/src/__test__/__snapshots__/portable-stories.test.tsx.snap +++ b/code/renderers/react/src/__test__/__snapshots__/portable-stories.test.tsx.snap @@ -18,24 +18,6 @@ exports[`Renders CSF2Secondary story 1`] = ` `; -exports[`Renders CSF2StoryWithLocale story 1`] = ` - -
-
- -
-
- -`; - exports[`Renders CSF2StoryWithParamsAndDecorator story 1`] = `
@@ -129,3 +111,27 @@ exports[`Renders CSF3Primary story 1`] = `
`; + +exports[`Renders LoaderStory story 1`] = ` + +
+
+
+
+ loaded data +
+
+ mockFn return value +
+
+
+
+ +`; diff --git a/code/renderers/react/src/__test__/portable-stories.test.tsx b/code/renderers/react/src/__test__/portable-stories.test.tsx index 3c7edd4e8e17..f8aae6b849f4 100644 --- a/code/renderers/react/src/__test__/portable-stories.test.tsx +++ b/code/renderers/react/src/__test__/portable-stories.test.tsx @@ -10,7 +10,7 @@ import type { Button } from './Button'; import * as stories from './Button.stories'; // example with composeStories, returns an object with all stories composed with args/decorators -const { CSF3Primary } = composeStories(stories); +const { CSF3Primary, LoaderStory } = composeStories(stories); // example with composeStory, returns a single story composed with args/decorators const Secondary = composeStory(stories.CSF2Secondary, stories.default); @@ -44,6 +44,15 @@ describe('renders', () => { const buttonElement = getByText(/foo/i); expect(buttonElement).not.toBeNull(); }); + + it('should call and compose loaders data', async () => { + await LoaderStory.load(); + const { getByTestId } = render(); + expect(getByTestId('spy-data').textContent).toEqual('mockFn return value'); + expect(getByTestId('loaded-data').textContent).toEqual('loaded data'); + // spy assertions happen in the play function and should work + await LoaderStory.play!(); + }); }); describe('projectAnnotations', () => { @@ -52,15 +61,24 @@ describe('projectAnnotations', () => { }); it('renders with default projectAnnotations', () => { + setProjectAnnotations([ + { + parameters: { injected: true }, + globalTypes: { + locale: { defaultValue: 'en' }, + }, + }, + ]); const WithEnglishText = composeStory(stories.CSF2StoryWithLocale, stories.default); const { getByText } = render(); const buttonElement = getByText('Hello!'); expect(buttonElement).not.toBeNull(); + expect(WithEnglishText.parameters?.injected).toBe(true); }); - it('renders with custom globals from projectAnnotations via composeStory params', () => { + it('renders with custom projectAnnotations via composeStory params', () => { const WithPortugueseText = composeStory(stories.CSF2StoryWithLocale, stories.default, { - globalTypes: { locale: { defaultValue: 'pt' } } as any, + globals: { locale: 'pt' }, }); const { getByText } = render(); const buttonElement = getByText('OlΓ‘!'); @@ -156,11 +174,14 @@ const testCases = Object.values(composeStories(stories)).map( it.each(testCases)('Renders %s story', async (_storyName, Story) => { cleanup(); - if (_storyName === 'CSF2WithLocale') { + if (_storyName === 'CSF2StoryWithLocale') { return; } + await Story.load(); + const { baseElement } = await render(); + await Story.play?.(); expect(baseElement).toMatchSnapshot(); }); diff --git a/code/renderers/react/src/portable-stories.tsx b/code/renderers/react/src/portable-stories.tsx index bf91dde7b3e8..3493e0f3b2e5 100644 --- a/code/renderers/react/src/portable-stories.tsx +++ b/code/renderers/react/src/portable-stories.tsx @@ -13,7 +13,7 @@ import type { StoriesWithPartialProps, } from '@storybook/types'; -import { render } from './render'; +import * as reactProjectAnnotations from './entry-preview'; import type { Meta } from './public-types'; import type { ReactRenderer } from './types'; @@ -40,7 +40,7 @@ export function setProjectAnnotations( // This will not be necessary once we have auto preset loading const defaultProjectAnnotations: ProjectAnnotations = { - render, + ...reactProjectAnnotations, decorators: [ function addStorybookId(StoryFn, { id }) { return ( diff --git a/code/renderers/vue3/src/__tests__/composeStories/Button.stories.ts b/code/renderers/vue3/src/__tests__/composeStories/Button.stories.ts index 239416df5c35..0d4623585de0 100644 --- a/code/renderers/vue3/src/__tests__/composeStories/Button.stories.ts +++ b/code/renderers/vue3/src/__tests__/composeStories/Button.stories.ts @@ -1,4 +1,4 @@ -import { userEvent, within } from '@storybook/testing-library'; +import { userEvent, within, expect, fn } from '@storybook/test'; import type { Meta, StoryFn as CSF2Story, StoryObj } from '../..'; import Button from './Button.vue'; @@ -45,8 +45,10 @@ const getCaptionForLocale = (locale: string) => { return 'μ•ˆλ…•ν•˜μ„Έμš”!'; case 'pt': return 'OlΓ‘!'; - default: + case 'en': return 'Hello!'; + default: + return undefined; } }; @@ -58,7 +60,7 @@ export const CSF2StoryWithLocale: CSF2Story = (args, { globals }) => ({ }, template: `

locale: ${globals.locale}

-
`, }); CSF2StoryWithLocale.storyName = 'WithLocale'; @@ -114,7 +116,39 @@ export const CSF3InputFieldFilled: CSF3Story = { play: async ({ canvasElement, step }) => { const canvas = within(canvasElement); await step('Step label', async () => { - await userEvent.type(canvas.getByTestId('input'), 'Hello world!'); + const inputEl = canvas.getByTestId('input'); + await userEvent.type(inputEl, 'Hello world!'); + await expect(inputEl).toHaveValue('Hello world!'); }); }, }; + +const mockFn = fn(); +export const LoaderStory: StoryObj<{ mockFn: (val: string) => string }> = { + args: { + mockFn, + }, + loaders: [ + async () => { + mockFn.mockReturnValueOnce('mockFn return value'); + return { + value: 'loaded data', + }; + }, + ], + render: (args, { loaded }) => ({ + components: { Button }, + setup() { + return { args, data: args.mockFn('render'), loaded: loaded.value }; + }, + template: ` +
+
{{loaded}}
+
{{data}}
+
+ `, + }), + play: async () => { + expect(mockFn).toHaveBeenCalledWith('render'); + }, +}; diff --git a/code/renderers/vue3/src/__tests__/composeStories/__snapshots__/portable-stories.test.ts.snap b/code/renderers/vue3/src/__tests__/composeStories/__snapshots__/portable-stories.test.ts.snap index aca5cb96961b..b6e6feff8f61 100644 --- a/code/renderers/vue3/src/__tests__/composeStories/__snapshots__/portable-stories.test.ts.snap +++ b/code/renderers/vue3/src/__tests__/composeStories/__snapshots__/portable-stories.test.ts.snap @@ -18,22 +18,21 @@ exports[`Renders CSF2Secondary story 1`] = ` `; -exports[`Renders CSF2StoryWithLocale story 1`] = ` +exports[`Renders CSF2StoryWithParamsAndDecorator story 1`] = `
-
-

- locale: undefined -

+
@@ -116,3 +115,27 @@ exports[`Renders CSF3Primary story 1`] = `
`; + +exports[`Renders LoaderStory story 1`] = ` + +
+
+
+
+ loaded data +
+
+ mockFn return value +
+
+
+
+ +`; diff --git a/code/renderers/vue3/src/__tests__/composeStories/portable-stories.test.ts b/code/renderers/vue3/src/__tests__/composeStories/portable-stories.test.ts index e82a6c657a89..36aa7c2e9c56 100644 --- a/code/renderers/vue3/src/__tests__/composeStories/portable-stories.test.ts +++ b/code/renderers/vue3/src/__tests__/composeStories/portable-stories.test.ts @@ -10,39 +10,58 @@ import type Button from './Button.vue'; import { composeStories, composeStory, setProjectAnnotations } from '../../portable-stories'; // example with composeStories, returns an object with all stories composed with args/decorators -const { CSF3Primary } = composeStories(stories); +const { CSF3Primary, LoaderStory } = composeStories(stories); // example with composeStory, returns a single story composed with args/decorators const Secondary = composeStory(stories.CSF2Secondary, stories.default); -it('renders primary button', () => { - render(CSF3Primary({ label: 'Hello world' })); - const buttonElement = screen.getByText(/Hello world/i); - expect(buttonElement).toBeInTheDocument(); -}); +describe('renders', () => { + it('renders primary button', () => { + render(CSF3Primary({ label: 'Hello world' })); + const buttonElement = screen.getByText(/Hello world/i); + expect(buttonElement).toBeInTheDocument(); + }); -it('reuses args from composed story', () => { - render(Secondary()); - const buttonElement = screen.getByRole('button'); - expect(buttonElement.textContent).toEqual(Secondary.args.label); -}); + it('reuses args from composed story', () => { + render(Secondary()); + const buttonElement = screen.getByRole('button'); + expect(buttonElement.textContent).toEqual(Secondary.args.label); + }); -it('myClickEvent handler is called', async () => { - const myClickEventSpy = vi.fn(); - render(Secondary({ onMyClickEvent: myClickEventSpy })); - const buttonElement = screen.getByRole('button'); - buttonElement.click(); - expect(myClickEventSpy).toHaveBeenCalled(); -}); + it('myClickEvent handler is called', async () => { + const myClickEventSpy = vi.fn(); + render(Secondary({ onMyClickEvent: myClickEventSpy })); + const buttonElement = screen.getByRole('button'); + buttonElement.click(); + expect(myClickEventSpy).toHaveBeenCalled(); + }); + + it('reuses args from composeStories', () => { + const { getByText } = render(CSF3Primary()); + const buttonElement = getByText(/foo/i); + expect(buttonElement).toBeInTheDocument(); + }); -it('reuses args from composeStories', () => { - const { getByText } = render(CSF3Primary()); - const buttonElement = getByText(/foo/i); - expect(buttonElement).toBeInTheDocument(); + it('should call and compose loaders data', async () => { + await LoaderStory.load(); + const { getByTestId } = render(LoaderStory()); + expect(getByTestId('spy-data').textContent).toEqual('mockFn return value'); + expect(getByTestId('loaded-data').textContent).toEqual('loaded data'); + // spy assertions happen in the play function and should work + await LoaderStory.play!(); + }); }); describe('projectAnnotations', () => { it('renders with default projectAnnotations', () => { + setProjectAnnotations([ + { + parameters: { injected: true }, + globalTypes: { + locale: { defaultValue: 'en' }, + }, + }, + ]); const WithEnglishText = composeStory(stories.CSF2StoryWithLocale, stories.default); const { getByText } = render(WithEnglishText()); const buttonElement = getByText('Hello!'); @@ -51,7 +70,7 @@ describe('projectAnnotations', () => { it('renders with custom projectAnnotations via composeStory params', () => { const WithPortugueseText = composeStory(stories.CSF2StoryWithLocale, stories.default, { - globalTypes: { locale: { defaultValue: 'pt' } } as any, + globals: { locale: 'pt' }, }); const { getByText } = render(WithPortugueseText()); const buttonElement = getByText('OlÑ!'); @@ -84,9 +103,9 @@ describe('CSF3', () => { it('renders with play function', async () => { const CSF3InputFieldFilled = composeStory(stories.CSF3InputFieldFilled, stories.default); - render(CSF3InputFieldFilled()); + const { container } = render(CSF3InputFieldFilled()); - await CSF3InputFieldFilled.play!(); + await CSF3InputFieldFilled.play!({ canvasElement: container as HTMLElement }); const input = screen.getByTestId('input') as HTMLInputElement; expect(input.value).toEqual('Hello world!'); @@ -127,14 +146,14 @@ describe('ComposeStories types', () => { // Batch snapshot testing const testCases = Object.values(composeStories(stories)).map((Story) => [Story.storyName, Story]); it.each(testCases)('Renders %s story', async (_storyName, Story) => { - if (typeof Story === 'string' || _storyName === 'CSF2StoryWithParamsAndDecorator') { + if (typeof Story === 'string' || _storyName === 'CSF2StoryWithLocale') { return; } + await Story.load(); + const { container, baseElement } = await render(Story()); + await Story.play?.({ canvasElement: container as HTMLElement }); await new Promise((resolve) => setTimeout(resolve, 0)); - const { baseElement } = await render(Story()); - await Story.play?.(); - expect(baseElement).toMatchSnapshot(); }); From 6dae91d30c8d9fc60db1169d2e0be2e225dc9d13 Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Mon, 4 Mar 2024 11:54:37 +0100 Subject: [PATCH 53/79] add migration note regarding project annotation overrides --- MIGRATION.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/MIGRATION.md b/MIGRATION.md index 62aef1593d05..5919ec501c42 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -2,6 +2,7 @@ - [From version 7.x to 8.0.0](#from-version-7x-to-800) - [Portable stories](#portable-stories) + - [Project annotations are now merged instead of overwritten in composeStory](#project-annotations-are-now-merged-instead-of-overwritten-in-composestory) - [Type change in `composeStories` API](#type-change-in-composestories-api) - [DOM structure changed in portable stories](#dom-structure-changed-in-portable-stories) - [Tab addons are now routed to a query parameter](#tab-addons-are-now-routed-to-a-query-parameter) @@ -405,6 +406,21 @@ ### Portable stories +#### Project annotations are now merged instead of overwritten in composeStory + +When passing project annotations overrides via `composeStory` such as: + +```tsx +const projectAnnotationOverrides = { parameters: { foo: "bar" } }; +const Primary = composeStory( + stories.Primary, + stories, + projectAnnotationOverrides +); +``` + +they are now merged with the annotations passed via `setProjectAnnotations` rather than completely overwriting them. This was seen as a bug and it's now fixed. If you have a use case where you really need this, please open an issue to elaborate. + #### Type change in `composeStories` API There is a TypeScript type change in the `play` function returned from `composeStories` or `composeStory` in `@storybook/react` or `@storybook/vue3`, where before it was always defined, now it is potentially undefined. This means that you might have to make a small change in your code, such as: From c9a26c6f25217cc5a595189e8dbbe828937b4437 Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Mon, 4 Mar 2024 13:30:49 +0100 Subject: [PATCH 54/79] fix the bug and add tests to ensure it doesn't fail ever again --- code/lib/cli/src/add.test.ts | 140 +++++++++++++++++++++++++++ code/lib/cli/src/add.ts | 82 +++++++--------- code/lib/cli/src/postinstallAddon.ts | 19 ++++ 3 files changed, 196 insertions(+), 45 deletions(-) create mode 100644 code/lib/cli/src/add.test.ts create mode 100644 code/lib/cli/src/postinstallAddon.ts diff --git a/code/lib/cli/src/add.test.ts b/code/lib/cli/src/add.test.ts new file mode 100644 index 000000000000..2da3bd8e184b --- /dev/null +++ b/code/lib/cli/src/add.test.ts @@ -0,0 +1,140 @@ +import { describe, expect, test, vi } from 'vitest'; +import { add, getVersionSpecifier } from './add'; + +const MockedConfig = vi.hoisted(() => { + return { + appendValueToArray: vi.fn(), + }; +}); +const MockedPackageManager = vi.hoisted(() => { + return { + retrievePackageJson: vi.fn(() => ({})), + latestVersion: vi.fn(() => '1.0.0'), + addDependencies: vi.fn(() => {}), + type: 'npm', + }; +}); +const MockedPostInstall = vi.hoisted(() => { + return { + postinstallAddon: vi.fn(), + }; +}); + +const MockedConsole = { + log: vi.fn(), + warn: vi.fn(), + error: vi.fn(), +} as any as Console; + +vi.mock('@storybook/csf-tools', () => { + return { + readConfig: vi.fn(() => MockedConfig), + writeConfig: vi.fn(), + }; +}); +vi.mock('./postinstallAddon', () => { + return MockedPostInstall; +}); + +vi.mock('@storybook/core-common', () => { + return { + getStorybookInfo: vi.fn(() => ({ mainConfig: {}, configDir: '' })), + serverRequire: vi.fn(() => ({})), + JsPackageManagerFactory: { + getPackageManager: vi.fn(() => MockedPackageManager), + }, + versions: { + '@storybook/addon-onboarding': '8.0.0', + }, + }; +}); + +describe('getVersionSpecifier', (it) => { + test.each([ + ['@storybook/addon-docs', ['@storybook/addon-docs', undefined]], + ['@storybook/addon-docs@7.0.1', ['@storybook/addon-docs', '7.0.1']], + ['@storybook/addon-docs@7.0.1-beta.1', ['@storybook/addon-docs', '7.0.1-beta.1']], + ['@storybook/addon-docs@~7.0.1-beta.1', ['@storybook/addon-docs', '~7.0.1-beta.1']], + ['@storybook/addon-docs@^7.0.1-beta.1', ['@storybook/addon-docs', '^7.0.1-beta.1']], + ['@storybook/addon-docs@next', ['@storybook/addon-docs', 'next']], + ])('%s => %s', (input, expected) => { + const result = getVersionSpecifier(input); + expect(result[0]).toEqual(expected[0]); + expect(result[1]).toEqual(expected[1]); + }); +}); + +describe('add', () => { + const testData = [ + { full: 'aa', expected: 'aa@^1.0.0' }, // resolves to the latest version + { full: 'aa@4', expected: 'aa@^4' }, + { full: 'aa@4.1.0', expected: 'aa@^4.1.0' }, + { full: 'aa@^4', expected: 'aa@^4' }, + { full: 'aa@~4', expected: 'aa@~4' }, + { full: 'aa@4.1.0-alpha.1', expected: 'aa@^4.1.0-alpha.1' }, + { full: 'aa@next', expected: 'aa@next' }, + + { full: '@org/aa', expected: '@org/aa@^1.0.0' }, + { full: '@org/aa@4', expected: '@org/aa@^4' }, + { full: '@org/aa@4.1.0', expected: '@org/aa@^4.1.0' }, + { full: '@org/aa@4.1.0-alpha.1', expected: '@org/aa@^4.1.0-alpha.1' }, + { full: '@org/aa@next', expected: '@org/aa@next' }, + + { full: '@storybook/addon-onboarding@~4', expected: '@storybook/addon-onboarding@~4' }, + { full: '@storybook/addon-onboarding@next', expected: '@storybook/addon-onboarding@next' }, + { full: '@storybook/addon-onboarding', expected: '@storybook/addon-onboarding@^8.0.0' }, // takes it from the versions file + ]; + + test.each(testData)('$full', async ({ full, expected }) => { + const [input] = getVersionSpecifier(full); + + await add(full, { packageManager: 'npm', skipPostinstall: true }, MockedConsole); + + expect(MockedConfig.appendValueToArray).toHaveBeenCalledWith( + expect.arrayContaining(['addons']), + input + ); + + expect(MockedPackageManager.addDependencies).toHaveBeenCalledWith( + { installAsDevDependencies: true }, + [expected] + ); + }); +}); + +describe('add (extra)', () => { + test('not warning when installing the correct version of storybook', async () => { + await add( + '@storybook/addon-onboarding', + { packageManager: 'npm', skipPostinstall: true }, + MockedConsole + ); + + expect(MockedConsole.warn).not.toHaveBeenCalledWith( + `The version of @storybook/addon-onboarding you are installing is not the same as the version of Storybook you are using. This may lead to unexpected behavior.` + ); + }); + test('warning when installing a specific version of storybook', async () => { + await add( + '@storybook/addon-onboarding@2.0.0', + { packageManager: 'npm', skipPostinstall: true }, + MockedConsole + ); + + expect(MockedConsole.warn).toHaveBeenCalledWith( + `The version of @storybook/addon-onboarding you are installing is not the same as the version of Storybook you are using. This may lead to unexpected behavior.` + ); + }); + + test('postInstall', async () => { + await add( + '@storybook/addon-onboarding', + { packageManager: 'npm', skipPostinstall: false }, + MockedConsole + ); + + expect(MockedPostInstall.postinstallAddon).toHaveBeenCalledWith('@storybook/addon-onboarding', { + packageManager: 'npm', + }); + }); +}); diff --git a/code/lib/cli/src/add.ts b/code/lib/cli/src/add.ts index 0321ec966fd7..a19249ddb453 100644 --- a/code/lib/cli/src/add.ts +++ b/code/lib/cli/src/add.ts @@ -1,44 +1,31 @@ import { getStorybookInfo, serverRequire, - getCoercedStorybookVersion, - isCorePackage, JsPackageManagerFactory, + versions, type PackageManagerName, } from '@storybook/core-common'; import { readConfig, writeConfig } from '@storybook/csf-tools'; import { isAbsolute, join } from 'path'; import SemVer from 'semver'; import dedent from 'ts-dedent'; +import { postinstallAddon } from './postinstallAddon'; -const logger = console; - -interface PostinstallOptions { +export interface PostinstallOptions { packageManager: PackageManagerName; } -const postinstallAddon = async (addonName: string, options: PostinstallOptions) => { - try { - const modulePath = require.resolve(`${addonName}/postinstall`, { paths: [process.cwd()] }); - - const postinstall = require(modulePath); - - try { - logger.log(`Running postinstall script for ${addonName}`); - await postinstall(options); - } catch (e) { - logger.error(`Error running postinstall script for ${addonName}`); - logger.error(e); - } - } catch (e) { - // no postinstall script - } -}; - -const getVersionSpecifier = (addon: string) => { - const groups = /^(...*)@(.*)$/.exec(addon); +/** + * Extract the addon name and version specifier from the input string + * @param addon - the input string + * @returns [addonName, versionSpecifier] + * @example + * getVersionSpecifier('@storybook/addon-docs@7.0.1') => ['@storybook/addon-docs', '7.0.1'] + */ +export const getVersionSpecifier = (addon: string) => { + const groups = /^(@{0,1}[^@]+)(?:@(.+))?$/.exec(addon); if (groups) { - return [groups[0], groups[2]] as const; + return [groups[1], groups[2]] as const; } return [addon, undefined] as const; }; @@ -71,9 +58,11 @@ const checkInstalled = (addonName: string, main: any) => { */ export async function add( addon: string, - options: { packageManager: PackageManagerName; skipPostinstall: boolean } + options: { packageManager: PackageManagerName; skipPostinstall: boolean }, + logger = console ) { const { packageManager: pkgMgr } = options; + const [addonName, inputVersion] = getVersionSpecifier(addon); const packageManager = JsPackageManagerFactory.getPackageManager({ force: pkgMgr }); const packageJson = await packageManager.retrievePackageJson(); @@ -85,38 +74,38 @@ export async function add( `); } - if (checkInstalled(addon, requireMain(configDir))) { - throw new Error(dedent` - Addon ${addon} is already installed; we skipped adding it to your ${mainConfig}. - `); - } - - const [addonName, versionSpecifier] = getVersionSpecifier(addon); - if (!mainConfig) { logger.error('Unable to find storybook main.js config'); return; } + + if (checkInstalled(addonName, requireMain(configDir))) { + throw new Error(dedent` + Addon ${addonName} is already installed; we skipped adding it to your ${mainConfig}. + `); + } + const main = await readConfig(mainConfig); logger.log(`Verifying ${addonName}`); - const latestVersion = await packageManager.latestVersion(addonName); - if (!latestVersion) { - logger.error(`Unknown addon ${addonName}`); - } - // add to package.json + const storybookVersion = versions[addonName as keyof typeof versions] as string | undefined; const isStorybookAddon = addonName.startsWith('@storybook/'); - const isAddonFromCore = isCorePackage(addonName); - const storybookVersion = await getCoercedStorybookVersion(packageManager); - const version = versionSpecifier || (isAddonFromCore ? storybookVersion : latestVersion); + const version = + inputVersion || storybookVersion || (await packageManager.latestVersion(addonName)); + + if (storybookVersion && version !== storybookVersion) { + logger.warn( + `The version of ${addonName} you are installing is not the same as the version of Storybook you are using. This may lead to unexpected behavior.` + ); + } - const addonWithVersion = SemVer.valid(version) + const addonWithVersion = isValidVersion(version) ? `${addonName}@^${version}` : `${addonName}@${version}`; + logger.log(`Installing ${addonWithVersion}`); await packageManager.addDependencies({ installAsDevDependencies: true }, [addonWithVersion]); - // add to main.js logger.log(`Adding '${addon}' to main.js addons field.`); main.appendValueToArray(['addons'], addonName); await writeConfig(main); @@ -125,3 +114,6 @@ export async function add( await postinstallAddon(addonName, { packageManager: packageManager.type }); } } +function isValidVersion(version: string) { + return SemVer.valid(version) || version.match(/^\d+$/); +} diff --git a/code/lib/cli/src/postinstallAddon.ts b/code/lib/cli/src/postinstallAddon.ts new file mode 100644 index 000000000000..50719c29e29c --- /dev/null +++ b/code/lib/cli/src/postinstallAddon.ts @@ -0,0 +1,19 @@ +import type { PostinstallOptions } from './add'; + +export const postinstallAddon = async (addonName: string, options: PostinstallOptions) => { + try { + const modulePath = require.resolve(`${addonName}/postinstall`, { paths: [process.cwd()] }); + + const postinstall = require(modulePath); + + try { + console.log(`Running postinstall script for ${addonName}`); + await postinstall(options); + } catch (e) { + console.error(`Error running postinstall script for ${addonName}`); + console.error(e); + } + } catch (e) { + // no postinstall script + } +}; From 8f07e61ef02b3aa752da91576cf016367beaa454 Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Mon, 4 Mar 2024 14:02:07 +0100 Subject: [PATCH 55/79] fixes --- code/lib/cli/src/add.test.ts | 25 ++++++++++++++----------- code/lib/cli/src/add.ts | 21 +++++++++++++++------ 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/code/lib/cli/src/add.test.ts b/code/lib/cli/src/add.test.ts index 2da3bd8e184b..16d86d7c6851 100644 --- a/code/lib/cli/src/add.test.ts +++ b/code/lib/cli/src/add.test.ts @@ -43,8 +43,9 @@ vi.mock('@storybook/core-common', () => { JsPackageManagerFactory: { getPackageManager: vi.fn(() => MockedPackageManager), }, + getCoercedStorybookVersion: vi.fn(() => '8.0.0'), versions: { - '@storybook/addon-onboarding': '8.0.0', + 'storybook/addon-docs': '^8.0.0', }, }; }); @@ -80,9 +81,9 @@ describe('add', () => { { full: '@org/aa@4.1.0-alpha.1', expected: '@org/aa@^4.1.0-alpha.1' }, { full: '@org/aa@next', expected: '@org/aa@next' }, - { full: '@storybook/addon-onboarding@~4', expected: '@storybook/addon-onboarding@~4' }, - { full: '@storybook/addon-onboarding@next', expected: '@storybook/addon-onboarding@next' }, - { full: '@storybook/addon-onboarding', expected: '@storybook/addon-onboarding@^8.0.0' }, // takes it from the versions file + { full: 'storybook/addon-docs@~4', expected: 'storybook/addon-docs@~4' }, + { full: 'storybook/addon-docs@next', expected: 'storybook/addon-docs@next' }, + { full: 'storybook/addon-docs', expected: 'storybook/addon-docs@^8.0.0' }, // takes it from the versions file ]; test.each(testData)('$full', async ({ full, expected }) => { @@ -105,35 +106,37 @@ describe('add', () => { describe('add (extra)', () => { test('not warning when installing the correct version of storybook', async () => { await add( - '@storybook/addon-onboarding', + 'storybook/addon-docs', { packageManager: 'npm', skipPostinstall: true }, MockedConsole ); expect(MockedConsole.warn).not.toHaveBeenCalledWith( - `The version of @storybook/addon-onboarding you are installing is not the same as the version of Storybook you are using. This may lead to unexpected behavior.` + expect.stringContaining(`is not the same as the version of Storybook you are using.`) ); }); - test('warning when installing a specific version of storybook', async () => { + test('warning when installing a core addon mismatching version of storybook', async () => { await add( - '@storybook/addon-onboarding@2.0.0', + 'storybook/addon-docs@2.0.0', { packageManager: 'npm', skipPostinstall: true }, MockedConsole ); expect(MockedConsole.warn).toHaveBeenCalledWith( - `The version of @storybook/addon-onboarding you are installing is not the same as the version of Storybook you are using. This may lead to unexpected behavior.` + expect.stringContaining( + `The version of storybook/addon-docs you are installing is not the same as the version of Storybook you are using. This may lead to unexpected behavior.` + ) ); }); test('postInstall', async () => { await add( - '@storybook/addon-onboarding', + 'storybook/addon-docs', { packageManager: 'npm', skipPostinstall: false }, MockedConsole ); - expect(MockedPostInstall.postinstallAddon).toHaveBeenCalledWith('@storybook/addon-onboarding', { + expect(MockedPostInstall.postinstallAddon).toHaveBeenCalledWith('storybook/addon-docs', { packageManager: 'npm', }); }); diff --git a/code/lib/cli/src/add.ts b/code/lib/cli/src/add.ts index a19249ddb453..a0ddcdbf7cb7 100644 --- a/code/lib/cli/src/add.ts +++ b/code/lib/cli/src/add.ts @@ -2,8 +2,9 @@ import { getStorybookInfo, serverRequire, JsPackageManagerFactory, - versions, + getCoercedStorybookVersion, type PackageManagerName, + versions, } from '@storybook/core-common'; import { readConfig, writeConfig } from '@storybook/csf-tools'; import { isAbsolute, join } from 'path'; @@ -45,6 +46,8 @@ const checkInstalled = (addonName: string, main: any) => { return !!existingAddon; }; +const isCoreAddon = (addonName: string) => !!versions[addonName as keyof typeof versions]; + /** * Install the given addon package and add it to main.js * @@ -88,10 +91,16 @@ export async function add( const main = await readConfig(mainConfig); logger.log(`Verifying ${addonName}`); - const storybookVersion = versions[addonName as keyof typeof versions] as string | undefined; - const isStorybookAddon = addonName.startsWith('@storybook/'); - const version = - inputVersion || storybookVersion || (await packageManager.latestVersion(addonName)); + const storybookVersion = await getCoercedStorybookVersion(packageManager); + + let version = inputVersion; + + if (!version && isCoreAddon(addonName) && storybookVersion) { + version = storybookVersion; + } + if (!version) { + version = await packageManager.latestVersion(addonName); + } if (storybookVersion && version !== storybookVersion) { logger.warn( @@ -110,7 +119,7 @@ export async function add( main.appendValueToArray(['addons'], addonName); await writeConfig(main); - if (!options.skipPostinstall && isStorybookAddon) { + if (!options.skipPostinstall && isCoreAddon(addonName)) { await postinstallAddon(addonName, { packageManager: packageManager.type }); } } From eacdd37e2b02846c98883a4f1b241a6058a718d0 Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Mon, 4 Mar 2024 14:08:49 +0100 Subject: [PATCH 56/79] rename for clarity --- code/lib/cli/src/add.test.ts | 42 ++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/code/lib/cli/src/add.test.ts b/code/lib/cli/src/add.test.ts index 16d86d7c6851..868d0ff7057d 100644 --- a/code/lib/cli/src/add.test.ts +++ b/code/lib/cli/src/add.test.ts @@ -67,33 +67,33 @@ describe('getVersionSpecifier', (it) => { describe('add', () => { const testData = [ - { full: 'aa', expected: 'aa@^1.0.0' }, // resolves to the latest version - { full: 'aa@4', expected: 'aa@^4' }, - { full: 'aa@4.1.0', expected: 'aa@^4.1.0' }, - { full: 'aa@^4', expected: 'aa@^4' }, - { full: 'aa@~4', expected: 'aa@~4' }, - { full: 'aa@4.1.0-alpha.1', expected: 'aa@^4.1.0-alpha.1' }, - { full: 'aa@next', expected: 'aa@next' }, - - { full: '@org/aa', expected: '@org/aa@^1.0.0' }, - { full: '@org/aa@4', expected: '@org/aa@^4' }, - { full: '@org/aa@4.1.0', expected: '@org/aa@^4.1.0' }, - { full: '@org/aa@4.1.0-alpha.1', expected: '@org/aa@^4.1.0-alpha.1' }, - { full: '@org/aa@next', expected: '@org/aa@next' }, - - { full: 'storybook/addon-docs@~4', expected: 'storybook/addon-docs@~4' }, - { full: 'storybook/addon-docs@next', expected: 'storybook/addon-docs@next' }, - { full: 'storybook/addon-docs', expected: 'storybook/addon-docs@^8.0.0' }, // takes it from the versions file + { input: 'aa', expected: 'aa@^1.0.0' }, // resolves to the latest version + { input: 'aa@4', expected: 'aa@^4' }, + { input: 'aa@4.1.0', expected: 'aa@^4.1.0' }, + { input: 'aa@^4', expected: 'aa@^4' }, + { input: 'aa@~4', expected: 'aa@~4' }, + { input: 'aa@4.1.0-alpha.1', expected: 'aa@^4.1.0-alpha.1' }, + { input: 'aa@next', expected: 'aa@next' }, + + { input: '@org/aa', expected: '@org/aa@^1.0.0' }, + { input: '@org/aa@4', expected: '@org/aa@^4' }, + { input: '@org/aa@4.1.0', expected: '@org/aa@^4.1.0' }, + { input: '@org/aa@4.1.0-alpha.1', expected: '@org/aa@^4.1.0-alpha.1' }, + { input: '@org/aa@next', expected: '@org/aa@next' }, + + { input: 'storybook/addon-docs@~4', expected: 'storybook/addon-docs@~4' }, + { input: 'storybook/addon-docs@next', expected: 'storybook/addon-docs@next' }, + { input: 'storybook/addon-docs', expected: 'storybook/addon-docs@^8.0.0' }, // takes it from the versions file ]; - test.each(testData)('$full', async ({ full, expected }) => { - const [input] = getVersionSpecifier(full); + test.each(testData)('$full', async ({ input, expected }) => { + const [packageName] = getVersionSpecifier(input); - await add(full, { packageManager: 'npm', skipPostinstall: true }, MockedConsole); + await add(input, { packageManager: 'npm', skipPostinstall: true }, MockedConsole); expect(MockedConfig.appendValueToArray).toHaveBeenCalledWith( expect.arrayContaining(['addons']), - input + packageName ); expect(MockedPackageManager.addDependencies).toHaveBeenCalledWith( From 2d66683bf127e6d347b7dd555bcd3b0a49958ff8 Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Mon, 4 Mar 2024 14:10:06 +0100 Subject: [PATCH 57/79] cleanup --- code/lib/cli/src/add.test.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/code/lib/cli/src/add.test.ts b/code/lib/cli/src/add.test.ts index 868d0ff7057d..b7bcf5b93ac5 100644 --- a/code/lib/cli/src/add.test.ts +++ b/code/lib/cli/src/add.test.ts @@ -19,7 +19,6 @@ const MockedPostInstall = vi.hoisted(() => { postinstallAddon: vi.fn(), }; }); - const MockedConsole = { log: vi.fn(), warn: vi.fn(), @@ -35,7 +34,6 @@ vi.mock('@storybook/csf-tools', () => { vi.mock('./postinstallAddon', () => { return MockedPostInstall; }); - vi.mock('@storybook/core-common', () => { return { getStorybookInfo: vi.fn(() => ({ mainConfig: {}, configDir: '' })), From be683bf8bc01ba945eb2072ab6bbec0ba3ab0d34 Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Mon, 4 Mar 2024 14:16:52 +0100 Subject: [PATCH 58/79] use hasOwn, which is type-safe, no need for casting --- code/lib/cli/src/add.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/lib/cli/src/add.ts b/code/lib/cli/src/add.ts index a0ddcdbf7cb7..cc56b3f5695d 100644 --- a/code/lib/cli/src/add.ts +++ b/code/lib/cli/src/add.ts @@ -46,7 +46,7 @@ const checkInstalled = (addonName: string, main: any) => { return !!existingAddon; }; -const isCoreAddon = (addonName: string) => !!versions[addonName as keyof typeof versions]; +const isCoreAddon = (addonName: string) => Object.hasOwn(versions, addonName); /** * Install the given addon package and add it to main.js From 320fd3decd4400805634ef20e9f2bd234c1c9ae9 Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Mon, 4 Mar 2024 16:14:12 +0100 Subject: [PATCH 59/79] found a flaw thanks to review from valentin --- code/lib/cli/src/add.test.ts | 31 +++++++++++++++++++++---------- code/lib/cli/src/add.ts | 2 +- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/code/lib/cli/src/add.test.ts b/code/lib/cli/src/add.test.ts index b7bcf5b93ac5..4dc12eb48986 100644 --- a/code/lib/cli/src/add.test.ts +++ b/code/lib/cli/src/add.test.ts @@ -43,7 +43,7 @@ vi.mock('@storybook/core-common', () => { }, getCoercedStorybookVersion: vi.fn(() => '8.0.0'), versions: { - 'storybook/addon-docs': '^8.0.0', + '@storybook/addon-docs': '^8.0.0', }, }; }); @@ -79,12 +79,12 @@ describe('add', () => { { input: '@org/aa@4.1.0-alpha.1', expected: '@org/aa@^4.1.0-alpha.1' }, { input: '@org/aa@next', expected: '@org/aa@next' }, - { input: 'storybook/addon-docs@~4', expected: 'storybook/addon-docs@~4' }, - { input: 'storybook/addon-docs@next', expected: 'storybook/addon-docs@next' }, - { input: 'storybook/addon-docs', expected: 'storybook/addon-docs@^8.0.0' }, // takes it from the versions file + { input: '@storybook/addon-docs@~4', expected: '@storybook/addon-docs@~4' }, + { input: '@storybook/addon-docs@next', expected: '@storybook/addon-docs@next' }, + { input: '@storybook/addon-docs', expected: '@storybook/addon-docs@^8.0.0' }, // takes it from the versions file ]; - test.each(testData)('$full', async ({ input, expected }) => { + test.each(testData)('$input', async ({ input, expected }) => { const [packageName] = getVersionSpecifier(input); await add(input, { packageManager: 'npm', skipPostinstall: true }, MockedConsole); @@ -104,7 +104,18 @@ describe('add', () => { describe('add (extra)', () => { test('not warning when installing the correct version of storybook', async () => { await add( - 'storybook/addon-docs', + '@storybook/addon-docs', + { packageManager: 'npm', skipPostinstall: true }, + MockedConsole + ); + + expect(MockedConsole.warn).not.toHaveBeenCalledWith( + expect.stringContaining(`is not the same as the version of Storybook you are using.`) + ); + }); + test('not warning when installing unrelated package', async () => { + await add( + '@storybook/addon-docs', { packageManager: 'npm', skipPostinstall: true }, MockedConsole ); @@ -115,26 +126,26 @@ describe('add (extra)', () => { }); test('warning when installing a core addon mismatching version of storybook', async () => { await add( - 'storybook/addon-docs@2.0.0', + '@storybook/addon-docs@2.0.0', { packageManager: 'npm', skipPostinstall: true }, MockedConsole ); expect(MockedConsole.warn).toHaveBeenCalledWith( expect.stringContaining( - `The version of storybook/addon-docs you are installing is not the same as the version of Storybook you are using. This may lead to unexpected behavior.` + `The version of @storybook/addon-docs you are installing is not the same as the version of Storybook you are using. This may lead to unexpected behavior.` ) ); }); test('postInstall', async () => { await add( - 'storybook/addon-docs', + '@storybook/addon-docs', { packageManager: 'npm', skipPostinstall: false }, MockedConsole ); - expect(MockedPostInstall.postinstallAddon).toHaveBeenCalledWith('storybook/addon-docs', { + expect(MockedPostInstall.postinstallAddon).toHaveBeenCalledWith('@storybook/addon-docs', { packageManager: 'npm', }); }); diff --git a/code/lib/cli/src/add.ts b/code/lib/cli/src/add.ts index cc56b3f5695d..19a4b552fcc0 100644 --- a/code/lib/cli/src/add.ts +++ b/code/lib/cli/src/add.ts @@ -102,7 +102,7 @@ export async function add( version = await packageManager.latestVersion(addonName); } - if (storybookVersion && version !== storybookVersion) { + if (isCoreAddon(addonName) && version !== storybookVersion) { logger.warn( `The version of ${addonName} you are installing is not the same as the version of Storybook you are using. This may lead to unexpected behavior.` ); From b6b98eb9912727d8de135b96e2ea3d3e85ae96da Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Mon, 4 Mar 2024 16:16:43 +0100 Subject: [PATCH 60/79] change package name for test --- code/lib/cli/src/add.test.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/code/lib/cli/src/add.test.ts b/code/lib/cli/src/add.test.ts index 4dc12eb48986..3025da275e49 100644 --- a/code/lib/cli/src/add.test.ts +++ b/code/lib/cli/src/add.test.ts @@ -114,11 +114,7 @@ describe('add (extra)', () => { ); }); test('not warning when installing unrelated package', async () => { - await add( - '@storybook/addon-docs', - { packageManager: 'npm', skipPostinstall: true }, - MockedConsole - ); + await add('aa', { packageManager: 'npm', skipPostinstall: true }, MockedConsole); expect(MockedConsole.warn).not.toHaveBeenCalledWith( expect.stringContaining(`is not the same as the version of Storybook you are using.`) From 9e01244dac13d8c59ee808ffc8a852030a0d66f9 Mon Sep 17 00:00:00 2001 From: Lars Rickert Date: Mon, 4 Mar 2024 20:01:02 +0100 Subject: [PATCH 61/79] fix(vue-component-meta): prevent reference error when using re-exports --- .../vue3-vite/src/plugins/vue-component-meta.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/code/frameworks/vue3-vite/src/plugins/vue-component-meta.ts b/code/frameworks/vue3-vite/src/plugins/vue-component-meta.ts index bd6a22fe338a..7ec671bddf62 100644 --- a/code/frameworks/vue3-vite/src/plugins/vue-component-meta.ts +++ b/code/frameworks/vue3-vite/src/plugins/vue-component-meta.ts @@ -94,7 +94,13 @@ export async function vueComponentMeta(): Promise { // we can only add the "__docgenInfo" to variables that are actually defined in the current file // so e.g. re-exports like "export { default as MyComponent } from './MyComponent.vue'" must be ignored // to prevent runtime errors - if (new RegExp(`export {.*${name}.*}`).test(src)) { + if ( + new RegExp(`export {.*${name}.*}`).test(src) || + new RegExp(`export \\* from ['"]\\S*${name}['"]`).test(src) || + // when using re-exports, some exports might be resolved via checker.getExportNames + // but are not directly exported inside the current file so we need to ignore them too + !src.includes(name) + ) { return; } From f0a23ca35dcd62bfce1c27bb2997149108528764 Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Mon, 4 Mar 2024 20:19:13 +0100 Subject: [PATCH 62/79] improve the refs detection This should make it possible to have refs share the same origin as each other and as the main storybook. This is useful if you have static-storybooks in static directories --- code/lib/channels/src/postmessage/getEventSourceUrl.ts | 8 ++++++++ code/lib/manager-api/src/lib/events.ts | 10 +++++++--- code/lib/manager-api/src/modules/refs.ts | 8 ++++---- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/code/lib/channels/src/postmessage/getEventSourceUrl.ts b/code/lib/channels/src/postmessage/getEventSourceUrl.ts index da3f4ec4d2f6..33c5729a7a08 100644 --- a/code/lib/channels/src/postmessage/getEventSourceUrl.ts +++ b/code/lib/channels/src/postmessage/getEventSourceUrl.ts @@ -7,6 +7,14 @@ export const getEventSourceUrl = (event: MessageEvent) => { // try to find the originating iframe by matching it's contentWindow // This might not be cross-origin safe const [frame, ...remainder] = frames.filter((element) => { + try { + return ( + element.contentWindow?.location.origin === (event.source as Window).location.origin && + element.contentWindow?.location.pathname === (event.source as Window).location.pathname + ); + } catch (err) { + // continue + } try { return element.contentWindow === event.source; } catch (err) { diff --git a/code/lib/manager-api/src/lib/events.ts b/code/lib/manager-api/src/lib/events.ts index c66c5a9e1403..1892d71ed57a 100644 --- a/code/lib/manager-api/src/lib/events.ts +++ b/code/lib/manager-api/src/lib/events.ts @@ -19,9 +19,13 @@ export const getEventMetadata = (context: Meta, fullAPI: API) => { const { source, refId, type } = context; const [sourceType, sourceLocation] = getSourceType(source!, refId); - const ref = - refId && fullAPI.getRefs()[refId] ? fullAPI.getRefs()[refId] : fullAPI.findRef(sourceLocation!); - + let ref: API_ComposedRef | undefined; + if (refId || sourceType === 'external') { + ref = + refId && fullAPI.getRefs()[refId] + ? fullAPI.getRefs()[refId] + : fullAPI.findRef(sourceLocation!); + } const meta = { source, sourceType, diff --git a/code/lib/manager-api/src/modules/refs.ts b/code/lib/manager-api/src/modules/refs.ts index 906798848e16..bc4b94755a53 100644 --- a/code/lib/manager-api/src/modules/refs.ts +++ b/code/lib/manager-api/src/modules/refs.ts @@ -20,8 +20,6 @@ import type { ModuleFn } from '../lib/types'; const { location, fetch } = global; -const findFilename = /(\/((?:[^\/]+?)\.[^\/]+?)|\/)$/; - export interface SubState { refs: API_Refs; } @@ -75,8 +73,10 @@ export const getSourceType = (source: string, refId?: string) => { const { origin: localOrigin, pathname: localPathname } = location; const { origin: sourceOrigin, pathname: sourcePathname } = new URL(source); - const localFull = `${localOrigin + localPathname}`.replace(findFilename, ''); - const sourceFull = `${sourceOrigin + sourcePathname}`.replace(findFilename, ''); + const localFull = `${localOrigin + localPathname}`.replace('/iframe.html', '').replace(/\/$/, ''); + const sourceFull = `${sourceOrigin + sourcePathname}` + .replace('/iframe.html', '') + .replace(/\/$/, ''); if (localFull === sourceFull) { return ['local', sourceFull]; From dc07edd92d94164690e619b0d5322c9e89ddb15e Mon Sep 17 00:00:00 2001 From: Valentin Palkovic Date: Tue, 5 Mar 2024 09:02:46 +0100 Subject: [PATCH 63/79] Update minimum Node.js version requirement --- code/lib/cli/bin/index.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/lib/cli/bin/index.js b/code/lib/cli/bin/index.js index 7131e95a311d..af7869a6e043 100755 --- a/code/lib/cli/bin/index.js +++ b/code/lib/cli/bin/index.js @@ -1,8 +1,8 @@ #!/usr/bin/env node -const majorNodeVersion = parseInt(process.version.toString().replace('v', '').split('.')[0], 10); -if (majorNodeVersion < 16) { - console.error('To run storybook you need to have node 16 or higher'); +const majorNodeVersion = parseInt(process.versions.node, 10); +if (majorNodeVersion < 18) { + console.error('To run Storybook you need to have Node.js 18 or higher'); process.exit(1); } From 7e6438f7ef201a6e844b48d94eb3a34b500be012 Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Tue, 5 Mar 2024 10:07:38 +0100 Subject: [PATCH 64/79] fix test --- code/lib/manager-api/src/tests/refs.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/lib/manager-api/src/tests/refs.test.ts b/code/lib/manager-api/src/tests/refs.test.ts index afdb0747e39e..791325c27337 100644 --- a/code/lib/manager-api/src/tests/refs.test.ts +++ b/code/lib/manager-api/src/tests/refs.test.ts @@ -25,7 +25,7 @@ vi.mock('@storybook/global', () => { // Add additional variations of global.location mock return values in this array. // NOTE: The order must match the order that global.location is called in the unit tests. const edgecaseLocations = [ - { origin: 'https://storybook.js.org', pathname: '/storybook/index.html' }, + { origin: 'https://storybook.js.org', pathname: '/storybook/iframe.html' }, ]; // global.location value after all edgecaseLocations are returned const lastLocation = { origin: 'https://storybook.js.org', pathname: '/storybook/' }; From b4a274007790b5317f8abe939b104494e6cef6c6 Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Tue, 5 Mar 2024 12:16:13 +0100 Subject: [PATCH 65/79] make composeStory in Vue return a component instead of a function --- .../composeStories/portable-stories.test.ts | 22 +++++++++---------- code/renderers/vue3/src/portable-stories.ts | 11 +++++++++- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/code/renderers/vue3/src/__tests__/composeStories/portable-stories.test.ts b/code/renderers/vue3/src/__tests__/composeStories/portable-stories.test.ts index 36aa7c2e9c56..00257ba3aba0 100644 --- a/code/renderers/vue3/src/__tests__/composeStories/portable-stories.test.ts +++ b/code/renderers/vue3/src/__tests__/composeStories/portable-stories.test.ts @@ -17,34 +17,34 @@ const Secondary = composeStory(stories.CSF2Secondary, stories.default); describe('renders', () => { it('renders primary button', () => { - render(CSF3Primary({ label: 'Hello world' })); + render(CSF3Primary, { props: { label: 'Hello world' } }); const buttonElement = screen.getByText(/Hello world/i); expect(buttonElement).toBeInTheDocument(); }); it('reuses args from composed story', () => { - render(Secondary()); + render(Secondary); const buttonElement = screen.getByRole('button'); expect(buttonElement.textContent).toEqual(Secondary.args.label); }); it('myClickEvent handler is called', async () => { const myClickEventSpy = vi.fn(); - render(Secondary({ onMyClickEvent: myClickEventSpy })); + render(Secondary, { props: { onMyClickEvent: myClickEventSpy } }); const buttonElement = screen.getByRole('button'); buttonElement.click(); expect(myClickEventSpy).toHaveBeenCalled(); }); it('reuses args from composeStories', () => { - const { getByText } = render(CSF3Primary()); + const { getByText } = render(CSF3Primary); const buttonElement = getByText(/foo/i); expect(buttonElement).toBeInTheDocument(); }); it('should call and compose loaders data', async () => { await LoaderStory.load(); - const { getByTestId } = render(LoaderStory()); + const { getByTestId } = render(LoaderStory); expect(getByTestId('spy-data').textContent).toEqual('mockFn return value'); expect(getByTestId('loaded-data').textContent).toEqual('loaded data'); // spy assertions happen in the play function and should work @@ -63,7 +63,7 @@ describe('projectAnnotations', () => { }, ]); const WithEnglishText = composeStory(stories.CSF2StoryWithLocale, stories.default); - const { getByText } = render(WithEnglishText()); + const { getByText } = render(WithEnglishText); const buttonElement = getByText('Hello!'); expect(buttonElement).toBeInTheDocument(); }); @@ -72,7 +72,7 @@ describe('projectAnnotations', () => { const WithPortugueseText = composeStory(stories.CSF2StoryWithLocale, stories.default, { globals: { locale: 'pt' }, }); - const { getByText } = render(WithPortugueseText()); + const { getByText } = render(WithPortugueseText); const buttonElement = getByText('OlÑ!'); expect(buttonElement).toBeInTheDocument(); }); @@ -88,7 +88,7 @@ describe('CSF3', () => { it('renders with inferred globalRender', () => { const Primary = composeStory(stories.CSF3Button, stories.default); - render(Primary({ label: 'Hello world' })); + render(Primary, { props: { label: 'Hello world' } }); const buttonElement = screen.getByText(/Hello world/i); expect(buttonElement).toBeInTheDocument(); }); @@ -96,14 +96,14 @@ describe('CSF3', () => { it('renders with custom render function', () => { const Primary = composeStory(stories.CSF3ButtonWithRender, stories.default); - render(Primary()); + render(Primary); expect(screen.getByTestId('custom-render')).toBeInTheDocument(); }); it('renders with play function', async () => { const CSF3InputFieldFilled = composeStory(stories.CSF3InputFieldFilled, stories.default); - const { container } = render(CSF3InputFieldFilled()); + const { container } = render(CSF3InputFieldFilled); await CSF3InputFieldFilled.play!({ canvasElement: container as HTMLElement }); @@ -122,7 +122,7 @@ it('should pass with decorators that need addons channel', () => { }, ], }); - render(PrimaryWithChannels({ label: 'Hello world' })); + render(PrimaryWithChannels, { props: { label: 'Hello world' } }); const buttonElement = screen.getByText(/Hello world/i); expect(buttonElement).not.toBeNull(); }); diff --git a/code/renderers/vue3/src/portable-stories.ts b/code/renderers/vue3/src/portable-stories.ts index aef26b39a5e7..6321e4957bcd 100644 --- a/code/renderers/vue3/src/portable-stories.ts +++ b/code/renderers/vue3/src/portable-stories.ts @@ -11,6 +11,7 @@ import type { Store_CSFExports, StoriesWithPartialProps, } from '@storybook/types'; +import { h } from 'vue'; import * as vueProjectAnnotations from './entry-preview'; import type { Meta } from './public-types'; @@ -84,13 +85,21 @@ export function composeStory( projectAnnotations?: ProjectAnnotations, exportsName?: string ) { - return originalComposeStory( + const composedStory = originalComposeStory( story as StoryAnnotationsOrFn, componentAnnotations, projectAnnotations, defaultProjectAnnotations, exportsName ); + + // Returning h(composedStory) instead makes it an actual Vue component renderable by @testing-library/vue, Playwright CT, etc. + const renderable = (...args: Parameters) => h(composedStory(...args)); + Object.assign(renderable, composedStory); + + // typing this as newable means TS allows it to be used as a JSX element + // TODO: we should do the same for composeStories as well + return renderable as unknown as typeof composedStory & { new (...args: any[]): any }; } /** From fcd8bf2ce6d12b0eb7684f0c0ab906a9f10a949b Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Tue, 5 Mar 2024 12:19:53 +0100 Subject: [PATCH 66/79] fix testing-react import in migration notes --- MIGRATION.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/MIGRATION.md b/MIGRATION.md index 5919ec501c42..07116d774005 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -89,17 +89,17 @@ - [Tab addons cannot manually route, Tool addons can filter their visibility via tabId](#tab-addons-cannot-manually-route-tool-addons-can-filter-their-visibility-via-tabid) - [Removed `config` preset](#removed-config-preset-1) - [From version 7.5.0 to 7.6.0](#from-version-750-to-760) - - [CommonJS with Vite is deprecated](#commonjs-with-vite-is-deprecated) - - [Using implicit actions during rendering is deprecated](#using-implicit-actions-during-rendering-is-deprecated) - - [typescript.skipBabel deprecated](#typescriptskipbabel-deprecated) - - [Primary doc block accepts of prop](#primary-doc-block-accepts-of-prop) - - [Addons no longer need a peer dependency on React](#addons-no-longer-need-a-peer-dependency-on-react) + - [CommonJS with Vite is deprecated](#commonjs-with-vite-is-deprecated) + - [Using implicit actions during rendering is deprecated](#using-implicit-actions-during-rendering-is-deprecated) + - [typescript.skipBabel deprecated](#typescriptskipbabel-deprecated) + - [Primary doc block accepts of prop](#primary-doc-block-accepts-of-prop) + - [Addons no longer need a peer dependency on React](#addons-no-longer-need-a-peer-dependency-on-react) - [From version 7.4.0 to 7.5.0](#from-version-740-to-750) - - [`storyStoreV6` and `storiesOf` is deprecated](#storystorev6-and-storiesof-is-deprecated) - - [`storyIndexers` is replaced with `experimental_indexers`](#storyindexers-is-replaced-with-experimental_indexers) + - [`storyStoreV6` and `storiesOf` is deprecated](#storystorev6-and-storiesof-is-deprecated) + - [`storyIndexers` is replaced with `experimental_indexers`](#storyindexers-is-replaced-with-experimental_indexers) - [From version 7.0.0 to 7.2.0](#from-version-700-to-720) - - [Addon API is more type-strict](#addon-api-is-more-type-strict) - - [Addon-controls hideNoControlsWarning parameter is deprecated](#addon-controls-hidenocontrolswarning-parameter-is-deprecated) + - [Addon API is more type-strict](#addon-api-is-more-type-strict) + - [Addon-controls hideNoControlsWarning parameter is deprecated](#addon-controls-hidenocontrolswarning-parameter-is-deprecated) - [From version 6.5.x to 7.0.0](#from-version-65x-to-700) - [7.0 breaking changes](#70-breaking-changes) - [Dropped support for Node 15 and below](#dropped-support-for-node-15-and-below) @@ -125,7 +125,7 @@ - [Deploying build artifacts](#deploying-build-artifacts) - [Dropped support for file URLs](#dropped-support-for-file-urls) - [Serving with nginx](#serving-with-nginx) - - [Ignore story files from node_modules](#ignore-story-files-from-node_modules) + - [Ignore story files from node\_modules](#ignore-story-files-from-node_modules) - [7.0 Core changes](#70-core-changes) - [7.0 feature flags removed](#70-feature-flags-removed) - [Story context is prepared before for supporting fine grained updates](#story-context-is-prepared-before-for-supporting-fine-grained-updates) @@ -139,7 +139,7 @@ - [Addon-interactions: Interactions debugger is now default](#addon-interactions-interactions-debugger-is-now-default) - [7.0 Vite changes](#70-vite-changes) - [Vite builder uses Vite config automatically](#vite-builder-uses-vite-config-automatically) - - [Vite cache moved to node_modules/.cache/.vite-storybook](#vite-cache-moved-to-node_modulescachevite-storybook) + - [Vite cache moved to node\_modules/.cache/.vite-storybook](#vite-cache-moved-to-node_modulescachevite-storybook) - [7.0 Webpack changes](#70-webpack-changes) - [Webpack4 support discontinued](#webpack4-support-discontinued) - [Babel mode v7 exclusively](#babel-mode-v7-exclusively) @@ -189,7 +189,7 @@ - [Dropped addon-docs manual babel configuration](#dropped-addon-docs-manual-babel-configuration) - [Dropped addon-docs manual configuration](#dropped-addon-docs-manual-configuration) - [Autoplay in docs](#autoplay-in-docs) - - [Removed STORYBOOK_REACT_CLASSES global](#removed-storybook_react_classes-global) + - [Removed STORYBOOK\_REACT\_CLASSES global](#removed-storybook_react_classes-global) - [7.0 Deprecations and default changes](#70-deprecations-and-default-changes) - [storyStoreV7 enabled by default](#storystorev7-enabled-by-default) - [`Story` type deprecated](#story-type-deprecated) @@ -1061,7 +1061,7 @@ The `hideNoControlsWarning` parameter is now removed. [More info here](#addon-co The `setGlobalConfig` (used for reusing stories in your tests) is now removed in favor of `setProjectAnnotations`. ```ts -import { setProjectAnnotations } from `@storybook/testing-react`. +import { setProjectAnnotations } from `@storybook/react`. ``` #### StorybookViteConfig type from @storybook/builder-vite From e286d2b986fd59fd358fc54c355356228a142d3d Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Tue, 5 Mar 2024 12:31:31 +0100 Subject: [PATCH 67/79] add migration note about new composeStory Vue API --- MIGRATION.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/MIGRATION.md b/MIGRATION.md index 07116d774005..dd4bfee85ee6 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -5,6 +5,7 @@ - [Project annotations are now merged instead of overwritten in composeStory](#project-annotations-are-now-merged-instead-of-overwritten-in-composestory) - [Type change in `composeStories` API](#type-change-in-composestories-api) - [DOM structure changed in portable stories](#dom-structure-changed-in-portable-stories) + - [Composed Vue stories are now components instead of functions](#composed-vue-stories-are-now-components-instead-of-functions) - [Tab addons are now routed to a query parameter](#tab-addons-are-now-routed-to-a-query-parameter) - [Default keyboard shortcuts changed](#default-keyboard-shortcuts-changed) - [Manager addons are now rendered with React 18](#manager-addons-are-now-rendered-with-react-18) @@ -467,6 +468,25 @@ test("snapshots the story with custom id", () => { }); ``` +#### Composed Vue stories are now components instead of functions + +`composeStory` (and `composeStories`) from `@storybook/vue3` now returns Vue components rather than story functions that return components. This means that when rendering these composed stories you just pass the composed story _without_ first calling it. + +Previously when using `composeStory` from `@storybook/testing-vue` you would render composed stories with eg. `render(MyStoryComposedStory({ someProps: true}))`. That is now changed to more [closely match how you would render regular Vue components](https://testing-library.com/docs/vue-testing-library/examples). Here's an example using `@testing-library/vue` and Vitest: + +```diff +import { it } from 'vitest'; +import { render } from '@testing-library/vue'; +import * as stories from './Button.stories'; +import { composeStory } from '@storybook/vue3'; + +it('renders primary button', () => { + const ComposedButton = composeStory(sotries.Primary); +- render(ComposedButton({ label: 'Hello world' })); ++ render(ComposedButton, { props: { label: 'Hello world' } }); +}); +``` + ### Tab addons are now routed to a query parameter The URL of a tab used to be: `http://localhost:6006/?path=/my-addon-tab/my-story`. From 12f5c82b2ef74c094e697c3a771431b17238c5d8 Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Tue, 5 Mar 2024 12:56:04 +0100 Subject: [PATCH 68/79] use `user` directly from GH PR info instead of links.user --- scripts/release/generate-pr-description.ts | 4 +--- scripts/release/utils/get-changes.ts | 9 ++++----- scripts/release/utils/get-github-info.ts | 4 ++-- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/scripts/release/generate-pr-description.ts b/scripts/release/generate-pr-description.ts index 438c13fb4a91..7b4e397dea2c 100644 --- a/scripts/release/generate-pr-description.ts +++ b/scripts/release/generate-pr-description.ts @@ -1,4 +1,3 @@ -/* eslint-disable no-console */ import chalk from 'chalk'; import program from 'commander'; import { z } from 'zod'; @@ -65,7 +64,6 @@ export const mapToChangelist = ({ }): string => { return changes .filter((change) => { - // eslint-disable-next-line no-restricted-syntax for (const titleToIgnore of CHANGE_TITLES_TO_IGNORE) { if (change.title?.match(titleToIgnore)) { return false; @@ -227,7 +225,7 @@ export const generateNonReleaseDescription = ( - Merge this PR - [Follow the run of the publish action](https://github.com/storybookjs/storybook/actions/workflows/publish.yml)` // don't mention contributors in the release PR, to avoid spamming them - .replaceAll('[@', '[@ ') + .replaceAll('@', '') .replaceAll('"', '\\"') .replaceAll('`', '\\`') .replaceAll("'", "\\'") diff --git a/scripts/release/utils/get-changes.ts b/scripts/release/utils/get-changes.ts index 416ea624fb50..8d2811d486db 100644 --- a/scripts/release/utils/get-changes.ts +++ b/scripts/release/utils/get-changes.ts @@ -1,4 +1,3 @@ -/* eslint-disable no-console */ import chalk from 'chalk'; import semver from 'semver'; import type { PullRequestInfo } from './get-github-info'; @@ -206,11 +205,11 @@ export const getChangelogText = ({ return entry.labels?.some((label) => Object.keys(RELEASED_LABELS).includes(label)); }) .map((entry) => { - const { title, links } = entry; - const { pull, commit, user } = links; + const { title, user, links } = entry; + const { pull, commit } = links; return pull - ? `- ${title} - ${pull}, thanks ${user}!` - : `- ⚠️ _Direct commit_ ${title} - ${commit} by ${user}`; + ? `- ${title} - ${pull}, thanks @${user}!` + : `- ⚠️ _Direct commit_ ${title} - ${commit} by @${user}`; }) .sort(); const text = [heading, '', ...formattedEntries].join('\n'); diff --git a/scripts/release/utils/get-github-info.ts b/scripts/release/utils/get-github-info.ts index 0247e8319e04..e124026d7133 100644 --- a/scripts/release/utils/get-github-info.ts +++ b/scripts/release/utils/get-github-info.ts @@ -255,7 +255,7 @@ export async function getPullInfoFromCommit(request: { pull: associatedPullRequest ? `[#${associatedPullRequest.number}](${associatedPullRequest.url})` : null, - user: user ? `@${user.login}` : null, + user: user ? `[@${user.login}](${user.url})` : null, }, }; } @@ -294,7 +294,7 @@ export async function getPullInfoFromPullRequest(request: { links: { commit: commit ? `[\`${commit.oid}\`](${commit.commitUrl})` : null, pull: `[#${request.pull}](https://github.com/${request.repo}/pull/${request.pull})`, - user: user ? `@${user.login}` : null, + user: user ? `[@${user.login}](${user.url})` : null, }, }; } From 788aaac74729a17f9d08eeba02f9d8905a3451a6 Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Tue, 5 Mar 2024 13:34:46 +0100 Subject: [PATCH 69/79] add functionality of emitting an event & and test for websocket-transport --- code/lib/channels/src/index.test.ts | 125 ++++++++++++++++++++++- code/lib/channels/src/index.ts | 2 +- code/lib/channels/src/websocket/index.ts | 14 ++- code/lib/core-events/src/index.ts | 2 + code/ui/manager/src/globals/exports.ts | 1 + 5 files changed, 139 insertions(+), 5 deletions(-) diff --git a/code/lib/channels/src/index.test.ts b/code/lib/channels/src/index.test.ts index 07f6d605af10..04c295d98cff 100644 --- a/code/lib/channels/src/index.test.ts +++ b/code/lib/channels/src/index.test.ts @@ -1,9 +1,43 @@ import { describe, beforeEach, it, expect, vi } from 'vitest'; import type { ChannelTransport, Listener } from '.'; -import { Channel } from '.'; +import { Channel, WebsocketTransport } from '.'; vi.useFakeTimers(); +const MockedWebsocket = vi.hoisted(() => { + const ref = { current: undefined as unknown as InstanceType }; + class MyMockedWebsocket { + onopen: () => void; + + onmessage: (event: { data: string }) => void; + + onerror: (e: any) => void; + + onclose: () => void; + + constructor(url: string) { + this.onopen = vi.fn(); + this.onmessage = vi.fn(); + this.onerror = vi.fn(); + this.onclose = vi.fn(); + + ref.current = this; + } + + send(data: string) { + this.onmessage({ data }); + } + } + return { MyMockedWebsocket, ref }; +}); + +vi.mock('@storybook/global', () => ({ + global: { + ...global, + WebSocket: MockedWebsocket.MyMockedWebsocket, + }, +})); + describe('Channel', () => { let transport: ChannelTransport; let channel: Channel; @@ -232,3 +266,92 @@ describe('Channel', () => { }); }); }); + +describe('WebsocketTransport', () => { + it('should connect', async () => { + const onError = vi.fn(); + const handler = vi.fn(); + + const transport = new WebsocketTransport({ + url: 'ws://localhost:6006', + page: 'preview', + onError, + }); + + transport.setHandler(handler); + MockedWebsocket.ref.current.onopen(); + + expect(handler).toHaveBeenCalledTimes(0); + }); + it('should send message upon disconnect', async () => { + const onError = vi.fn(); + const handler = vi.fn(); + + const transport = new WebsocketTransport({ + url: 'ws://localhost:6006', + page: 'preview', + onError, + }); + + transport.setHandler(handler); + MockedWebsocket.ref.current.onclose(); + + expect(handler.mock.calls).toMatchInlineSnapshot(` + [ + [ + { + "args": [], + "from": "preview", + "type": "channelWSDisconnect", + }, + ], + ] + `); + }); + it('should send message when send', async () => { + const onError = vi.fn(); + const handler = vi.fn(); + + const transport = new WebsocketTransport({ + url: 'ws://localhost:6006', + page: 'preview', + onError, + }); + + transport.setHandler(handler); + MockedWebsocket.ref.current.send('{ "type": "test", "args": [], "from": "preview" }'); + + expect(handler.mock.calls).toMatchInlineSnapshot(` + [ + [ + { + "args": [], + "from": "preview", + "type": "test", + }, + ], + ] + `); + }); + it('should call onError handler', async () => { + const onError = vi.fn(); + const handler = vi.fn(); + + const transport = new WebsocketTransport({ + url: 'ws://localhost:6006', + page: 'preview', + onError, + }); + + transport.setHandler(handler); + MockedWebsocket.ref.current.onerror(new Error('testError')); + + expect(onError.mock.calls).toMatchInlineSnapshot(` + [ + [ + [Error: testError], + ], + ] + `); + }); +}); diff --git a/code/lib/channels/src/index.ts b/code/lib/channels/src/index.ts index 7942d57fa4f3..80a865f31904 100644 --- a/code/lib/channels/src/index.ts +++ b/code/lib/channels/src/index.ts @@ -35,7 +35,7 @@ export function createBrowserChannel({ page, extraTransports = [] }: Options): C const { hostname, port } = window.location; const channelUrl = `${protocol}://${hostname}:${port}/storybook-server-channel`; - transports.push(new WebsocketTransport({ url: channelUrl, onError: () => {} })); + transports.push(new WebsocketTransport({ url: channelUrl, onError: () => {}, page })); } return new Channel({ transports }); diff --git a/code/lib/channels/src/websocket/index.ts b/code/lib/channels/src/websocket/index.ts index a46df1c28610..790f69a8deaa 100644 --- a/code/lib/channels/src/websocket/index.ts +++ b/code/lib/channels/src/websocket/index.ts @@ -5,13 +5,16 @@ import { global } from '@storybook/global'; import { isJSON, parse, stringify } from 'telejson'; import invariant from 'tiny-invariant'; -import type { ChannelTransport, ChannelHandler } from '../types'; +// I tried to use an import statement, but it didn't work +const { CHANNEL_WS_DISCONNECT } = require('@storybook/core-events'); + +import type { ChannelTransport, ChannelHandler, Config } from '../types'; const { WebSocket } = global; type OnError = (message: Event) => void; -interface WebsocketTransportArgs { +interface WebsocketTransportArgs extends Partial { url: string; onError: OnError; } @@ -25,7 +28,8 @@ export class WebsocketTransport implements ChannelTransport { private isReady = false; - constructor({ url, onError }: WebsocketTransportArgs) { + constructor({ url, onError, page }: WebsocketTransportArgs) { + console.log({ WebSocket }); this.socket = new WebSocket(url); this.socket.onopen = () => { this.isReady = true; @@ -41,6 +45,10 @@ export class WebsocketTransport implements ChannelTransport { onError(e); } }; + this.socket.onclose = () => { + invariant(this.handler, 'WebsocketTransport handler should be set'); + this.handler({ type: CHANNEL_WS_DISCONNECT, args: [], from: page || 'preview' }); + }; } setHandler(handler: ChannelHandler) { diff --git a/code/lib/core-events/src/index.ts b/code/lib/core-events/src/index.ts index 6d98e6291200..7542d0aa4e57 100644 --- a/code/lib/core-events/src/index.ts +++ b/code/lib/core-events/src/index.ts @@ -1,5 +1,6 @@ // eslint-disable-next-line @typescript-eslint/naming-convention enum events { + CHANNEL_WS_DISCONNECT = 'channelWSDisconnect', CHANNEL_CREATED = 'channelCreated', // There was an error executing the config, likely an bug in the user's preview.js CONFIG_ERROR = 'configError', @@ -80,6 +81,7 @@ export default events; // Enables: `import * as Events from ...` or `import { CHANNEL_CREATED } as Events from ...` // This is the preferred method export const { + CHANNEL_WS_DISCONNECT, CHANNEL_CREATED, CONFIG_ERROR, CURRENT_STORY_WAS_SET, diff --git a/code/ui/manager/src/globals/exports.ts b/code/ui/manager/src/globals/exports.ts index b8e2d5b14868..079340369fcb 100644 --- a/code/ui/manager/src/globals/exports.ts +++ b/code/ui/manager/src/globals/exports.ts @@ -130,6 +130,7 @@ export default { ], '@storybook/core-events': [ 'CHANNEL_CREATED', + 'CHANNEL_WS_DISCONNECT', 'CONFIG_ERROR', 'CURRENT_STORY_WAS_SET', 'DOCS_PREPARED', From ff54701ed7e9eadd1b8ceda4e6c042285c59c9e9 Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Tue, 5 Mar 2024 14:11:05 +0100 Subject: [PATCH 70/79] fix --- code/lib/channels/src/index.test.ts | 40 ++++++++---------------- code/lib/channels/src/websocket/index.ts | 7 ++--- 2 files changed, 15 insertions(+), 32 deletions(-) diff --git a/code/lib/channels/src/index.test.ts b/code/lib/channels/src/index.test.ts index 04c295d98cff..f99e04f6099c 100644 --- a/code/lib/channels/src/index.test.ts +++ b/code/lib/channels/src/index.test.ts @@ -296,16 +296,12 @@ describe('WebsocketTransport', () => { transport.setHandler(handler); MockedWebsocket.ref.current.onclose(); - expect(handler.mock.calls).toMatchInlineSnapshot(` - [ - [ - { - "args": [], - "from": "preview", - "type": "channelWSDisconnect", - }, - ], - ] + expect(handler.mock.calls[0][0]).toMatchInlineSnapshot(` + { + "args": [], + "from": "preview", + "type": "channelWSDisconnect", + } `); }); it('should send message when send', async () => { @@ -321,16 +317,12 @@ describe('WebsocketTransport', () => { transport.setHandler(handler); MockedWebsocket.ref.current.send('{ "type": "test", "args": [], "from": "preview" }'); - expect(handler.mock.calls).toMatchInlineSnapshot(` - [ - [ - { - "args": [], - "from": "preview", - "type": "test", - }, - ], - ] + expect(handler.mock.calls[0][0]).toMatchInlineSnapshot(` + { + "args": [], + "from": "preview", + "type": "test", + } `); }); it('should call onError handler', async () => { @@ -346,12 +338,6 @@ describe('WebsocketTransport', () => { transport.setHandler(handler); MockedWebsocket.ref.current.onerror(new Error('testError')); - expect(onError.mock.calls).toMatchInlineSnapshot(` - [ - [ - [Error: testError], - ], - ] - `); + expect(onError.mock.calls[0][0]).toMatchInlineSnapshot(`[Error: testError]`); }); }); diff --git a/code/lib/channels/src/websocket/index.ts b/code/lib/channels/src/websocket/index.ts index 790f69a8deaa..0cc73345507d 100644 --- a/code/lib/channels/src/websocket/index.ts +++ b/code/lib/channels/src/websocket/index.ts @@ -5,9 +5,7 @@ import { global } from '@storybook/global'; import { isJSON, parse, stringify } from 'telejson'; import invariant from 'tiny-invariant'; -// I tried to use an import statement, but it didn't work -const { CHANNEL_WS_DISCONNECT } = require('@storybook/core-events'); - +import * as EVENTS from '@storybook/core-events'; import type { ChannelTransport, ChannelHandler, Config } from '../types'; const { WebSocket } = global; @@ -29,7 +27,6 @@ export class WebsocketTransport implements ChannelTransport { private isReady = false; constructor({ url, onError, page }: WebsocketTransportArgs) { - console.log({ WebSocket }); this.socket = new WebSocket(url); this.socket.onopen = () => { this.isReady = true; @@ -47,7 +44,7 @@ export class WebsocketTransport implements ChannelTransport { }; this.socket.onclose = () => { invariant(this.handler, 'WebsocketTransport handler should be set'); - this.handler({ type: CHANNEL_WS_DISCONNECT, args: [], from: page || 'preview' }); + this.handler({ type: EVENTS.CHANNEL_WS_DISCONNECT, args: [], from: page || 'preview' }); }; } From c4956e2a1fe338b25599555f1e2f5bca5a236b5b Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Tue, 5 Mar 2024 14:31:24 +0100 Subject: [PATCH 71/79] broaden version range for vite compatibility --- code/builders/builder-manager/package.json | 2 +- code/lib/core-common/package.json | 2 +- code/package.json | 2 +- code/yarn.lock | 78 ++++------------------ scripts/package.json | 2 +- scripts/yarn.lock | 11 +-- 6 files changed, 18 insertions(+), 79 deletions(-) diff --git a/code/builders/builder-manager/package.json b/code/builders/builder-manager/package.json index 56b28e9c4fbf..98022250a086 100644 --- a/code/builders/builder-manager/package.json +++ b/code/builders/builder-manager/package.json @@ -52,7 +52,7 @@ "@yarnpkg/esbuild-plugin-pnp": "^3.0.0-rc.10", "browser-assert": "^1.2.1", "ejs": "^3.1.8", - "esbuild": "^0.20.1", + "esbuild": "^18.0.0 || ^19.0.0 || ^0.20.0", "esbuild-plugin-alias": "^0.2.1", "express": "^4.17.3", "fs-extra": "^11.1.0", diff --git a/code/lib/core-common/package.json b/code/lib/core-common/package.json index be5bac6b4cf8..c136e06ea40d 100644 --- a/code/lib/core-common/package.json +++ b/code/lib/core-common/package.json @@ -52,7 +52,7 @@ "@yarnpkg/libzip": "2.3.0", "chalk": "^4.1.0", "cross-spawn": "^7.0.3", - "esbuild": "^0.20.1", + "esbuild": "^18.0.0 || ^19.0.0 || ^0.20.0", "esbuild-register": "^3.5.0", "execa": "^5.0.0", "file-system-cache": "2.3.0", diff --git a/code/package.json b/code/package.json index b73a51626082..ee2e28d00986 100644 --- a/code/package.json +++ b/code/package.json @@ -190,7 +190,7 @@ "concurrently": "^5.3.0", "cross-env": "^7.0.3", "danger": "^11.2.6", - "esbuild": "^0.18.0", + "esbuild": "^18.0.0 || ^19.0.0 || ^0.20.0", "esbuild-loader": "^3.0.0", "esbuild-plugin-alias": "^0.2.1", "eslint": "^8.56.0", diff --git a/code/yarn.lock b/code/yarn.lock index d155696ae2d0..a34bb7d5f3b7 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -5477,7 +5477,7 @@ __metadata: "@yarnpkg/esbuild-plugin-pnp": "npm:^3.0.0-rc.10" browser-assert: "npm:^1.2.1" ejs: "npm:^3.1.8" - esbuild: "npm:^0.20.1" + esbuild: "npm:^18.0.0 || ^19.0.0 || ^0.20.0" esbuild-plugin-alias: "npm:^0.2.1" express: "npm:^4.17.3" fs-extra: "npm:^11.1.0" @@ -5744,7 +5744,7 @@ __metadata: "@yarnpkg/libzip": "npm:2.3.0" chalk: "npm:^4.1.0" cross-spawn: "npm:^7.0.3" - esbuild: "npm:^0.20.1" + esbuild: "npm:^18.0.0 || ^19.0.0 || ^0.20.0" esbuild-register: "npm:^3.5.0" execa: "npm:^5.0.0" file-system-cache: "npm:2.3.0" @@ -6682,7 +6682,7 @@ __metadata: concurrently: "npm:^5.3.0" cross-env: "npm:^7.0.3" danger: "npm:^11.2.6" - esbuild: "npm:^0.18.0" + esbuild: "npm:^18.0.0 || ^19.0.0 || ^0.20.0" esbuild-loader: "npm:^3.0.0" esbuild-plugin-alias: "npm:^0.2.1" eslint: "npm:^8.56.0" @@ -7093,7 +7093,7 @@ __metadata: languageName: node linkType: hard -"@sveltejs/vite-plugin-svelte-inspector@npm:^2.0.0, @sveltejs/vite-plugin-svelte-inspector@npm:^2.0.0-next.0 || ^2.0.0": +"@sveltejs/vite-plugin-svelte-inspector@npm:^2.0.0": version: 2.0.0 resolution: "@sveltejs/vite-plugin-svelte-inspector@npm:2.0.0" dependencies: @@ -7106,25 +7106,7 @@ __metadata: languageName: node linkType: hard -"@sveltejs/vite-plugin-svelte@npm:^3.0.1": - version: 3.0.1 - resolution: "@sveltejs/vite-plugin-svelte@npm:3.0.1" - dependencies: - "@sveltejs/vite-plugin-svelte-inspector": "npm:^2.0.0-next.0 || ^2.0.0" - debug: "npm:^4.3.4" - deepmerge: "npm:^4.3.1" - kleur: "npm:^4.1.5" - magic-string: "npm:^0.30.5" - svelte-hmr: "npm:^0.15.3" - vitefu: "npm:^0.2.5" - peerDependencies: - svelte: ^4.0.0 || ^5.0.0-next.0 - vite: ^5.0.0 - checksum: 889d41014d4cc5dfb578cb0a80e64f72c0f8c143e9a299c3a4e2372fd582d982ce118dad5e158e0b747d1df7354a909ed9490b1adcd1bf982b56c82fffd4652c - languageName: node - linkType: hard - -"@sveltejs/vite-plugin-svelte@npm:^3.0.2": +"@sveltejs/vite-plugin-svelte@npm:^3.0.1, @sveltejs/vite-plugin-svelte@npm:^3.0.2": version: 3.0.2 resolution: "@sveltejs/vite-plugin-svelte@npm:3.0.2" dependencies: @@ -7601,10 +7583,10 @@ __metadata: languageName: node linkType: hard -"@types/estree@npm:*, @types/estree@npm:^1.0.0, @types/estree@npm:^1.0.1": - version: 1.0.2 - resolution: "@types/estree@npm:1.0.2" - checksum: 4b5c601d435ea8e2205458de15fd1556b5ae6c9a8323bad8a940ea502d6c824664faca94234c0bf76bf9c87cbf6ac41abee550c9e20433256549d589c9b543bd +"@types/estree@npm:*, @types/estree@npm:^1.0.0, @types/estree@npm:^1.0.1, @types/estree@npm:^1.0.5": + version: 1.0.5 + resolution: "@types/estree@npm:1.0.5" + checksum: b3b0e334288ddb407c7b3357ca67dbee75ee22db242ca7c56fe27db4e1a31989cb8af48a84dd401deb787fe10cc6b2ab1ee82dc4783be87ededbe3d53c79c70d languageName: node linkType: hard @@ -7615,13 +7597,6 @@ __metadata: languageName: node linkType: hard -"@types/estree@npm:^1.0.5": - version: 1.0.5 - resolution: "@types/estree@npm:1.0.5" - checksum: b3b0e334288ddb407c7b3357ca67dbee75ee22db242ca7c56fe27db4e1a31989cb8af48a84dd401deb787fe10cc6b2ab1ee82dc4783be87ededbe3d53c79c70d - languageName: node - linkType: hard - "@types/express-serve-static-core@npm:*, @types/express-serve-static-core@npm:^4.17.33": version: 4.17.37 resolution: "@types/express-serve-static-core@npm:4.17.37" @@ -9564,16 +9539,7 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.0.0, acorn@npm:^8.10.0, acorn@npm:^8.11.2, acorn@npm:^8.4.1, acorn@npm:^8.6.0, acorn@npm:^8.7.1, acorn@npm:^8.8.2, acorn@npm:^8.9.0": - version: 8.11.2 - resolution: "acorn@npm:8.11.2" - bin: - acorn: bin/acorn - checksum: a3ed76c761b75ec54b1ec3068fb7f113a182e95aea7f322f65098c2958d232e3d211cb6dac35ff9c647024b63714bc528a26d54a925d1fef2c25585b4c8e4017 - languageName: node - linkType: hard - -"acorn@npm:^8.11.3": +"acorn@npm:^8.0.0, acorn@npm:^8.10.0, acorn@npm:^8.11.2, acorn@npm:^8.11.3, acorn@npm:^8.4.1, acorn@npm:^8.6.0, acorn@npm:^8.7.1, acorn@npm:^8.8.2, acorn@npm:^8.9.0": version: 8.11.3 resolution: "acorn@npm:8.11.3" bin: @@ -25026,20 +24992,7 @@ __metadata: languageName: node linkType: hard -"recast@npm:^0.23.1, recast@npm:^0.23.3": - version: 0.23.4 - resolution: "recast@npm:0.23.4" - dependencies: - assert: "npm:^2.0.0" - ast-types: "npm:^0.16.1" - esprima: "npm:~4.0.0" - source-map: "npm:~0.6.1" - tslib: "npm:^2.0.1" - checksum: d719633be8029e28f23b8191d4a525c5dbdac721792ab3cb5e9dfcf1694fb93f3c147b186916195a9c7fa0711f1e4990ba457cdcee02faed3899d4a80da1bd1f - languageName: node - linkType: hard - -"recast@npm:^0.23.5": +"recast@npm:^0.23.1, recast@npm:^0.23.3, recast@npm:^0.23.5": version: 0.23.5 resolution: "recast@npm:0.23.5" dependencies: @@ -28077,14 +28030,7 @@ __metadata: languageName: node linkType: hard -"tiny-invariant@npm:^1.3.1": - version: 1.3.1 - resolution: "tiny-invariant@npm:1.3.1" - checksum: 5b87c1d52847d9452b60d0dcb77011b459044e0361ca8253bfe7b43d6288106e12af926adb709a6fc28900e3864349b91dad9a4ac93c39aa15f360b26c2ff4db - languageName: node - linkType: hard - -"tiny-invariant@npm:^1.3.3": +"tiny-invariant@npm:^1.3.1, tiny-invariant@npm:^1.3.3": version: 1.3.3 resolution: "tiny-invariant@npm:1.3.3" checksum: 65af4a07324b591a059b35269cd696aba21bef2107f29b9f5894d83cc143159a204b299553435b03874ebb5b94d019afa8b8eff241c8a4cfee95872c2e1c1c4a diff --git a/scripts/package.json b/scripts/package.json index e2f19d61148b..542bca5d2fd0 100644 --- a/scripts/package.json +++ b/scripts/package.json @@ -122,7 +122,7 @@ "detect-port": "^1.3.0", "ejs": "^3.1.8", "ejs-lint": "^2.0.0", - "esbuild": "^0.18.0", + "esbuild": "^0.20.1", "esbuild-plugin-alias": "^0.2.1", "esbuild-register": "^3.5.0", "eslint": "^8.56.0", diff --git a/scripts/yarn.lock b/scripts/yarn.lock index 8e10967d94ab..4bd7c8b5c0c3 100644 --- a/scripts/yarn.lock +++ b/scripts/yarn.lock @@ -2769,7 +2769,7 @@ __metadata: detect-port: "npm:^1.3.0" ejs: "npm:^3.1.8" ejs-lint: "npm:^2.0.0" - esbuild: "npm:^0.18.0" + esbuild: "npm:^0.20.1" esbuild-plugin-alias: "npm:^0.2.1" esbuild-register: "npm:^3.5.0" eslint: "npm:^8.56.0" @@ -14563,14 +14563,7 @@ __metadata: languageName: node linkType: hard -"tiny-invariant@npm:^1.3.1": - version: 1.3.1 - resolution: "tiny-invariant@npm:1.3.1" - checksum: 5b87c1d52847d9452b60d0dcb77011b459044e0361ca8253bfe7b43d6288106e12af926adb709a6fc28900e3864349b91dad9a4ac93c39aa15f360b26c2ff4db - languageName: node - linkType: hard - -"tiny-invariant@npm:^1.3.3": +"tiny-invariant@npm:^1.3.1, tiny-invariant@npm:^1.3.3": version: 1.3.3 resolution: "tiny-invariant@npm:1.3.3" checksum: 65af4a07324b591a059b35269cd696aba21bef2107f29b9f5894d83cc143159a204b299553435b03874ebb5b94d019afa8b8eff241c8a4cfee95872c2e1c1c4a From ba64b33839a065ed27bfdb6a786d8beb8bc0c72c Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Tue, 5 Mar 2024 17:41:15 +0100 Subject: [PATCH 72/79] use h helper in vue3 decorators instead, update migration notes --- MIGRATION.md | 42 +++++++++++-------- .../composeStories/portable-stories.test.ts | 8 ++-- code/renderers/vue3/src/portable-stories.ts | 14 +++---- 3 files changed, 34 insertions(+), 30 deletions(-) diff --git a/MIGRATION.md b/MIGRATION.md index dd4bfee85ee6..6488919f513b 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -90,17 +90,17 @@ - [Tab addons cannot manually route, Tool addons can filter their visibility via tabId](#tab-addons-cannot-manually-route-tool-addons-can-filter-their-visibility-via-tabid) - [Removed `config` preset](#removed-config-preset-1) - [From version 7.5.0 to 7.6.0](#from-version-750-to-760) - - [CommonJS with Vite is deprecated](#commonjs-with-vite-is-deprecated) - - [Using implicit actions during rendering is deprecated](#using-implicit-actions-during-rendering-is-deprecated) - - [typescript.skipBabel deprecated](#typescriptskipbabel-deprecated) - - [Primary doc block accepts of prop](#primary-doc-block-accepts-of-prop) - - [Addons no longer need a peer dependency on React](#addons-no-longer-need-a-peer-dependency-on-react) + - [CommonJS with Vite is deprecated](#commonjs-with-vite-is-deprecated) + - [Using implicit actions during rendering is deprecated](#using-implicit-actions-during-rendering-is-deprecated) + - [typescript.skipBabel deprecated](#typescriptskipbabel-deprecated) + - [Primary doc block accepts of prop](#primary-doc-block-accepts-of-prop) + - [Addons no longer need a peer dependency on React](#addons-no-longer-need-a-peer-dependency-on-react) - [From version 7.4.0 to 7.5.0](#from-version-740-to-750) - - [`storyStoreV6` and `storiesOf` is deprecated](#storystorev6-and-storiesof-is-deprecated) - - [`storyIndexers` is replaced with `experimental_indexers`](#storyindexers-is-replaced-with-experimental_indexers) + - [`storyStoreV6` and `storiesOf` is deprecated](#storystorev6-and-storiesof-is-deprecated) + - [`storyIndexers` is replaced with `experimental_indexers`](#storyindexers-is-replaced-with-experimental_indexers) - [From version 7.0.0 to 7.2.0](#from-version-700-to-720) - - [Addon API is more type-strict](#addon-api-is-more-type-strict) - - [Addon-controls hideNoControlsWarning parameter is deprecated](#addon-controls-hidenocontrolswarning-parameter-is-deprecated) + - [Addon API is more type-strict](#addon-api-is-more-type-strict) + - [Addon-controls hideNoControlsWarning parameter is deprecated](#addon-controls-hidenocontrolswarning-parameter-is-deprecated) - [From version 6.5.x to 7.0.0](#from-version-65x-to-700) - [7.0 breaking changes](#70-breaking-changes) - [Dropped support for Node 15 and below](#dropped-support-for-node-15-and-below) @@ -126,7 +126,7 @@ - [Deploying build artifacts](#deploying-build-artifacts) - [Dropped support for file URLs](#dropped-support-for-file-urls) - [Serving with nginx](#serving-with-nginx) - - [Ignore story files from node\_modules](#ignore-story-files-from-node_modules) + - [Ignore story files from node_modules](#ignore-story-files-from-node_modules) - [7.0 Core changes](#70-core-changes) - [7.0 feature flags removed](#70-feature-flags-removed) - [Story context is prepared before for supporting fine grained updates](#story-context-is-prepared-before-for-supporting-fine-grained-updates) @@ -140,7 +140,7 @@ - [Addon-interactions: Interactions debugger is now default](#addon-interactions-interactions-debugger-is-now-default) - [7.0 Vite changes](#70-vite-changes) - [Vite builder uses Vite config automatically](#vite-builder-uses-vite-config-automatically) - - [Vite cache moved to node\_modules/.cache/.vite-storybook](#vite-cache-moved-to-node_modulescachevite-storybook) + - [Vite cache moved to node_modules/.cache/.vite-storybook](#vite-cache-moved-to-node_modulescachevite-storybook) - [7.0 Webpack changes](#70-webpack-changes) - [Webpack4 support discontinued](#webpack4-support-discontinued) - [Babel mode v7 exclusively](#babel-mode-v7-exclusively) @@ -190,7 +190,7 @@ - [Dropped addon-docs manual babel configuration](#dropped-addon-docs-manual-babel-configuration) - [Dropped addon-docs manual configuration](#dropped-addon-docs-manual-configuration) - [Autoplay in docs](#autoplay-in-docs) - - [Removed STORYBOOK\_REACT\_CLASSES global](#removed-storybook_react_classes-global) + - [Removed STORYBOOK_REACT_CLASSES global](#removed-storybook_react_classes-global) - [7.0 Deprecations and default changes](#70-deprecations-and-default-changes) - [storyStoreV7 enabled by default](#storystorev7-enabled-by-default) - [`Story` type deprecated](#story-type-deprecated) @@ -470,9 +470,17 @@ test("snapshots the story with custom id", () => { #### Composed Vue stories are now components instead of functions -`composeStory` (and `composeStories`) from `@storybook/vue3` now returns Vue components rather than story functions that return components. This means that when rendering these composed stories you just pass the composed story _without_ first calling it. +`composeStory` (and `composeStories`) from `@storybook/vue3` now return Vue components rather than story functions that return components. This means that when rendering these composed stories you just pass the composed story _without_ first calling it. -Previously when using `composeStory` from `@storybook/testing-vue` you would render composed stories with eg. `render(MyStoryComposedStory({ someProps: true}))`. That is now changed to more [closely match how you would render regular Vue components](https://testing-library.com/docs/vue-testing-library/examples). Here's an example using `@testing-library/vue` and Vitest: +Previously when using `composeStory` from `@storybook/testing-vue3`, you would render composed stories with e.g. `render(MyStoryComposedStory({ someProp: true}))`. That is now changed to more [closely match how you would render regular Vue components](https://testing-library.com/docs/vue-testing-library/examples). + +When migrating from `@storybook/testing-vue3`, you will likely hit the following error: + +```ts +TypeError: Cannot read properties of undefined (reading 'devtoolsRawSetupState') +``` + +To fix it, you should change the usage of the composed story to reference it instead of calling it as a function. Here's an example using `@testing-library/vue` and Vitest: ```diff import { it } from 'vitest'; @@ -481,9 +489,9 @@ import * as stories from './Button.stories'; import { composeStory } from '@storybook/vue3'; it('renders primary button', () => { - const ComposedButton = composeStory(sotries.Primary); -- render(ComposedButton({ label: 'Hello world' })); -+ render(ComposedButton, { props: { label: 'Hello world' } }); + const Primary = composeStory(stories.Primary, stories.default); +- render(Primary({ label: 'Hello world' })); ++ render(Primary, { props: { label: 'Hello world' } }); }); ``` diff --git a/code/renderers/vue3/src/__tests__/composeStories/portable-stories.test.ts b/code/renderers/vue3/src/__tests__/composeStories/portable-stories.test.ts index 00257ba3aba0..7491a376e07c 100644 --- a/code/renderers/vue3/src/__tests__/composeStories/portable-stories.test.ts +++ b/code/renderers/vue3/src/__tests__/composeStories/portable-stories.test.ts @@ -103,9 +103,9 @@ describe('CSF3', () => { it('renders with play function', async () => { const CSF3InputFieldFilled = composeStory(stories.CSF3InputFieldFilled, stories.default); - const { container } = render(CSF3InputFieldFilled); + render(CSF3InputFieldFilled); - await CSF3InputFieldFilled.play!({ canvasElement: container as HTMLElement }); + await CSF3InputFieldFilled.play!(); const input = screen.getByTestId('input') as HTMLInputElement; expect(input.value).toEqual('Hello world!'); @@ -151,8 +151,8 @@ it.each(testCases)('Renders %s story', async (_storyName, Story) => { } await Story.load(); - const { container, baseElement } = await render(Story()); - await Story.play?.({ canvasElement: container as HTMLElement }); + const { baseElement } = await render(Story); + await Story.play?.(); await new Promise((resolve) => setTimeout(resolve, 0)); expect(baseElement).toMatchSnapshot(); diff --git a/code/renderers/vue3/src/portable-stories.ts b/code/renderers/vue3/src/portable-stories.ts index 6321e4957bcd..73c7991f16a6 100644 --- a/code/renderers/vue3/src/portable-stories.ts +++ b/code/renderers/vue3/src/portable-stories.ts @@ -20,13 +20,9 @@ import type { VueRenderer } from './types'; const defaultProjectAnnotations: ProjectAnnotations = { ...vueProjectAnnotations, decorators: [ - function addStorybookId(story, { id }) { - return { - components: { story }, - template: `
- -
`, - }; + function (story, { id }) { + const wrapperProps = { 'data-story': true, id: getPortableStoryWrapperId(id) }; + return h('div', wrapperProps, h(story())); }, ], }; @@ -69,7 +65,7 @@ export function setProjectAnnotations( * const Primary = composeStory(PrimaryStory, Meta); * * test('renders primary button with Hello World', () => { - * const { getByText } = render(Primary({label: "Hello world"})); + * const { getByText } = render(Primary, { props: { label: "Hello world" } }); * expect(getByText(/Hello world/i)).not.toBeNull(); * }); *``` @@ -119,7 +115,7 @@ export function composeStory( * const { Primary, Secondary } = composeStories(stories); * * test('renders primary button with Hello World', () => { - * const { getByText } = render(Primary({label: "Hello world"})); + * const { getByText } = render(Primary, { props: { label: "Hello world" } }); * expect(getByText(/Hello world/i)).not.toBeNull(); * }); *``` From e37e194e2d71e1aeebe74dcacbb60d1c83b37943 Mon Sep 17 00:00:00 2001 From: jonniebigodes Date: Tue, 5 Mar 2024 16:58:41 +0000 Subject: [PATCH 73/79] Docs: Fix FAQ --- docs/faq.md | 57 ++--------------------------------------------------- 1 file changed, 2 insertions(+), 55 deletions(-) diff --git a/docs/faq.md b/docs/faq.md index 1cceba208102..af3aa33158c9 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -2,36 +2,7 @@ title: 'Frequently Asked Questions' --- -Here are some answers to frequently asked questions. If you have a question, you can ask it by opening an issue on the [Storybook Repository](https://github.com/storybookjs/storybook/). - -- [Error: No angular.json file found](#error-no-angularjson-file-found) -- [How can I opt-out of Angular Ivy?](#how-can-i-opt-out-of-angular-ivy) -- [How can I opt-out of Angular ngcc?](#how-can-i-opt-out-of-angular-ngcc) -- [How can I run coverage tests with Create React App and leave out stories?](#how-can-i-run-coverage-tests-with-create-react-app-and-leave-out-stories) -- [How do I setup Storybook to share Webpack configuration with Next.js?](#how-do-i-setup-storybook-to-share-webpack-configuration-with-nextjs) -- [How do I fix module resolution in special environments?](#how-do-i-fix-module-resolution-in-special-environments) -- [How do I setup the new React Context Root API with Storybook?](#how-do-i-setup-the-new-react-context-root-api-with-storybook) -- [Why is there no addons channel?](#why-is-there-no-addons-channel) -- [Why aren't Controls visible in the Canvas panel but visible in Docs?](#why-arent-controls-visible-in-the-canvas-panel-but-visible-in-docs) -- [Why aren't the addons working in a composed Storybook?](#why-arent-the-addons-working-in-a-composed-storybook) -- [Can I have a Storybook with no local stories?](#can-i-have-a-storybook-with-no-local-stories) -- [Which community addons are compatible with the latest version of Storybook?](#which-community-addons-are-compatible-with-the-latest-version-of-storybook) -- [Is it possible to browse the documentation for past versions of Storybook?](#is-it-possible-to-browse-the-documentation-for-past-versions-of-storybook) -- [What icons are available for my toolbar or my addon?](#what-icons-are-available-for-my-toolbar-or-my-addon) -- [I see a "No Preview" error with a Storybook production build](#i-see-a-no-preview-error-with-a-storybook-production-build) -- [Can I use Storybook with Vue 2?](#can-i-use-storybook-with-vue-2) -- [Why aren't my code blocks highlighted with Storybook MDX](#why-arent-my-code-blocks-highlighted-with-storybook-mdx) -- [Why aren't my MDX stories working in Storybook?](#why-arent-my-mdx-stories-working-in-storybook) -- [Why are my mocked GraphQL queries failing with Storybook's MSW addon?](#why-are-my-mocked-graphql-queries-failing-with-storybooks-msw-addon) -- [Can I use other GraphQL providers with Storybook's MSW addon?](#can-i-use-other-graphql-providers-with-storybooks-msw-addon) -- [Can I mock GraphQL mutations with Storybook's MSW addon?](#can-i-mock-graphql-mutations-with-storybooks-msw-addon) -- [How can my code detect if it is running in Storybook?](#how-can-my-code-detect-if-it-is-running-in-storybook) -- [Why are my stories not showing up correctly when using certain characters?](#why-are-my-stories-not-showing-up-correctly-when-using-certain-characters) -- [Why are the TypeScript examples and documentation using `as` for type safety?](#why-are-the-typescript-examples-and-documentation-using-as-for-type-safety) -- [Why is Storybook's source loader returning undefined with curried functions?](#why-is-storybooks-source-loader-returning-undefined-with-curried-functions) -- [Why are my args no longer displaying the default values?](#why-are-my-args-no-longer-displaying-the-default-values) -- [Why isn't Storybook's test runner working?](#why-isnt-storybooks-test-runner-working) -- [How does Storybook handle environment variables?](#how-does-storybook-handle-environment-variables) +Here are some answers to frequently asked questions. If you have a question, you can ask it in our [GitHub discussions](https://github.com/storybookjs/storybook/discussions/new?category=help). ## Error: No angular.json file found @@ -222,7 +193,7 @@ Starting with Storybook version 6.0, we've introduced some great features aimed With this, we would like to point out that if you plan on using addons created by our fantastic community, you need to consider that some of those addons might be working with an outdated version of Storybook. -We're actively working to provide a better way to address this situation, but in the meantime, we would ask for a bit of caution on your end so that you don't run into unexpected problems. Let us know by creating an issue in the [Storybook repo](https://github.com/storybookjs/storybook/issues) so that we can gather information and create a curated list with those addons to help not only you but the rest of the community. +We're actively working to provide a better way to address this situation, but in the meantime, we'd like to ask for a bit of caution on your end so that you don't run into unexpected problems. Let us know by leaving a comment in the following [GitHub issue](https://github.com/storybookjs/storybook/issues/26031) so that we can gather information and expand the current list of addons that need to be updated to work with the latest version of Storybook. ## Is it possible to browse the documentation for past versions of Storybook? @@ -465,30 +436,6 @@ You can do this by checking for the `IS_STORYBOOK` global variable, which will e Storybook allows you to use most characters while naming your stories. Still, specific characters (e.g., `#`) can lead to issues when Storybook generates the internal identifier for the story, leading to collisions and incorrectly outputting the correct story. We recommend using such characters sparsely. -## Why are the TypeScript examples and documentation using `as` for type safety? - -We're aware that the default Typescript story construct might seem outdated and could potentially introduce a less than ideal way of handling type safety and strictness and could be rewritten as such: - -```ts -// Button.stories.ts|tsx - -import React from 'react'; -import type { ComponentStory, ComponentMeta } from '@storybook/react'; - -const StoryMeta: ComponentMeta = { - /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/configure/#configure-story-loading - * to learn how to generate automatic titles - */ - title: 'Button', - component: Button, -}; - -export default meta; -``` - -Although valid, it introduces additional boilerplate code to the story definition. Instead, we're working towards implementing a safer mechanism based on what's currently being discussed in the following [issue](https://github.com/microsoft/TypeScript/issues/7481). Once the feature is released, we'll migrate our existing examples and documentation accordingly. - ## Why is Storybook's source loader returning undefined with curried functions? This is a known issue with Storybook. If you're interested in getting it fixed, open an issue with a [working reproduction](./contribute/how-to-reproduce.md) so that it can be triaged and fixed in future releases. From ad2f10dd19e190ab5c5945ed9184efe4c522f03c Mon Sep 17 00:00:00 2001 From: storybook-bot <32066757+storybook-bot@users.noreply.github.com> Date: Tue, 5 Mar 2024 17:28:00 +0000 Subject: [PATCH 74/79] Write changelog for 8.0.0-rc.2 [skip ci] --- CHANGELOG.prerelease.md | 16 ++++++++++++++++ code/package.json | 3 ++- docs/versions/next.json | 2 +- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.prerelease.md b/CHANGELOG.prerelease.md index 6e9e1eb4ba44..dce7c33f53c7 100644 --- a/CHANGELOG.prerelease.md +++ b/CHANGELOG.prerelease.md @@ -1,3 +1,19 @@ +## 8.0.0-rc.2 + +- CLI: Add @storybook/addons automigration - [#26295](https://github.com/storybookjs/storybook/pull/26295), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! +- CLI: Fix vite config automigration to resolve from project root - [#26262](https://github.com/storybookjs/storybook/pull/26262), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! +- CLI: Improve `add` command & add tests - [#26298](https://github.com/storybookjs/storybook/pull/26298), thanks [@ndelangen](https://github.com/ndelangen)! +- CLI: Update minimum Node.js version requirement - [#26312](https://github.com/storybookjs/storybook/pull/26312), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! +- CSF-tools/Codemods: Upgrade recast - [#26286](https://github.com/storybookjs/storybook/pull/26286), thanks [@43081j](https://github.com/43081j)! +- Controls: Fix type summary when table.type unset - [#26283](https://github.com/storybookjs/storybook/pull/26283), thanks [@shilman](https://github.com/shilman)! +- Core: Add event when serverChannel disconnects - [#26322](https://github.com/storybookjs/storybook/pull/26322), thanks [@ndelangen](https://github.com/ndelangen)! +- Core: Fix composition of storybooks on same origin - [#26304](https://github.com/storybookjs/storybook/pull/26304), thanks [@ndelangen](https://github.com/ndelangen)! +- Portable stories: Improve existing APIs, add loaders support - [#26267](https://github.com/storybookjs/storybook/pull/26267), thanks [@yannbf](https://github.com/yannbf)! +- React: Handle TypeScript path aliases in react-docgen loader - [#26273](https://github.com/storybookjs/storybook/pull/26273), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! +- Svelte: Support `5.0.0-next.65` prerelease - [#26188](https://github.com/storybookjs/storybook/pull/26188), thanks [@JReinhold](https://github.com/JReinhold)! +- Upgrade: Add missing isUpgrade parameter to automigrate function - [#26293](https://github.com/storybookjs/storybook/pull/26293), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! +- Vue: Return component from `composeStory` - [#26317](https://github.com/storybookjs/storybook/pull/26317), thanks [@JReinhold](https://github.com/JReinhold)! + ## 8.0.0-rc.1 - CLI: Fix addon compatibility check error reporting in storybook dev - [#26258](https://github.com/storybookjs/storybook/pull/26258), thanks [@yannbf](https://github.com/yannbf)! diff --git a/code/package.json b/code/package.json index b929f5390127..2055b55ef7e6 100644 --- a/code/package.json +++ b/code/package.json @@ -294,5 +294,6 @@ "Dependency Upgrades" ] ] - } + }, + "deferredNextVersion": "8.0.0-rc.2" } diff --git a/docs/versions/next.json b/docs/versions/next.json index a1c6e9350e50..aefc27f51f56 100644 --- a/docs/versions/next.json +++ b/docs/versions/next.json @@ -1 +1 @@ -{"version":"8.0.0-rc.1","info":{"plain":"- CLI: Fix addon compatibility check error reporting in storybook dev - [#26258](https://github.com/storybookjs/storybook/pull/26258), thanks [@yannbf](https://github.com/yannbf)!\n- Onboarding: Fix manager dist reference - [#26282](https://github.com/storybookjs/storybook/pull/26282), thanks [@shilman](https://github.com/shilman)!\n- ReactVite: Docgen ignore un-parsable files - [#26254](https://github.com/storybookjs/storybook/pull/26254), thanks [@ndelangen](https://github.com/ndelangen)!"}} +{"version":"8.0.0-rc.2","info":{"plain":"- CLI: Add @storybook/addons automigration - [#26295](https://github.com/storybookjs/storybook/pull/26295), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)!\n- CLI: Fix vite config automigration to resolve from project root - [#26262](https://github.com/storybookjs/storybook/pull/26262), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)!\n- CLI: Improve `add` command & add tests - [#26298](https://github.com/storybookjs/storybook/pull/26298), thanks [@ndelangen](https://github.com/ndelangen)!\n- CLI: Update minimum Node.js version requirement - [#26312](https://github.com/storybookjs/storybook/pull/26312), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)!\n- CSF-tools/Codemods: Upgrade recast - [#26286](https://github.com/storybookjs/storybook/pull/26286), thanks [@43081j](https://github.com/43081j)!\n- Controls: Fix type summary when table.type unset - [#26283](https://github.com/storybookjs/storybook/pull/26283), thanks [@shilman](https://github.com/shilman)!\n- Core: Add event when serverChannel disconnects - [#26322](https://github.com/storybookjs/storybook/pull/26322), thanks [@ndelangen](https://github.com/ndelangen)!\n- Core: Fix composition of storybooks on same origin - [#26304](https://github.com/storybookjs/storybook/pull/26304), thanks [@ndelangen](https://github.com/ndelangen)!\n- Portable stories: Improve existing APIs, add loaders support - [#26267](https://github.com/storybookjs/storybook/pull/26267), thanks [@yannbf](https://github.com/yannbf)!\n- React: Handle TypeScript path aliases in react-docgen loader - [#26273](https://github.com/storybookjs/storybook/pull/26273), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)!\n- Svelte: Support `5.0.0-next.65` prerelease - [#26188](https://github.com/storybookjs/storybook/pull/26188), thanks [@JReinhold](https://github.com/JReinhold)!\n- Upgrade: Add missing isUpgrade parameter to automigrate function - [#26293](https://github.com/storybookjs/storybook/pull/26293), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)!\n- Vue: Return component from `composeStory` - [#26317](https://github.com/storybookjs/storybook/pull/26317), thanks [@JReinhold](https://github.com/JReinhold)!"}} From ebec658a5fe730385260ad03183827ce3a184199 Mon Sep 17 00:00:00 2001 From: storybook-bot <32066757+storybook-bot@users.noreply.github.com> Date: Tue, 5 Mar 2024 18:02:09 +0000 Subject: [PATCH 75/79] Bump version from "8.0.0-rc.1" to "8.0.0-rc.2" [skip ci] --- code/addons/a11y/package.json | 2 +- code/addons/actions/package.json | 2 +- code/addons/backgrounds/package.json | 2 +- code/addons/controls/package.json | 2 +- code/addons/docs/package.json | 2 +- code/addons/essentials/package.json | 2 +- code/addons/gfm/package.json | 2 +- code/addons/highlight/package.json | 2 +- code/addons/interactions/package.json | 2 +- code/addons/jest/package.json | 2 +- code/addons/links/package.json | 2 +- code/addons/measure/package.json | 2 +- code/addons/onboarding/package.json | 2 +- code/addons/outline/package.json | 2 +- code/addons/storysource/package.json | 2 +- code/addons/themes/package.json | 2 +- code/addons/toolbars/package.json | 2 +- code/addons/viewport/package.json | 2 +- code/builders/builder-manager/package.json | 2 +- code/builders/builder-vite/package.json | 2 +- code/builders/builder-webpack5/package.json | 2 +- code/frameworks/angular/package.json | 2 +- code/frameworks/ember/package.json | 2 +- code/frameworks/html-vite/package.json | 2 +- code/frameworks/html-webpack5/package.json | 2 +- code/frameworks/nextjs/package.json | 2 +- code/frameworks/preact-vite/package.json | 2 +- code/frameworks/preact-webpack5/package.json | 2 +- code/frameworks/react-vite/package.json | 2 +- code/frameworks/react-webpack5/package.json | 2 +- code/frameworks/server-webpack5/package.json | 2 +- code/frameworks/svelte-vite/package.json | 2 +- code/frameworks/svelte-webpack5/package.json | 2 +- code/frameworks/sveltekit/package.json | 2 +- code/frameworks/vue3-vite/package.json | 2 +- code/frameworks/vue3-webpack5/package.json | 2 +- .../web-components-vite/package.json | 2 +- .../web-components-webpack5/package.json | 2 +- code/lib/channels/package.json | 2 +- code/lib/cli-sb/package.json | 2 +- code/lib/cli-storybook/package.json | 2 +- code/lib/cli/package.json | 2 +- code/lib/client-logger/package.json | 2 +- code/lib/codemod/package.json | 2 +- code/lib/core-common/package.json | 2 +- code/lib/core-common/src/versions.ts | 160 +++++++++--------- code/lib/core-events/package.json | 2 +- code/lib/core-server/package.json | 2 +- code/lib/core-webpack/package.json | 2 +- code/lib/csf-plugin/package.json | 2 +- code/lib/csf-tools/package.json | 2 +- code/lib/docs-tools/package.json | 2 +- code/lib/instrumenter/package.json | 2 +- code/lib/manager-api/package.json | 2 +- code/lib/manager-api/src/version.ts | 2 +- code/lib/node-logger/package.json | 2 +- code/lib/preview-api/package.json | 2 +- code/lib/preview/package.json | 2 +- code/lib/react-dom-shim/package.json | 2 +- code/lib/router/package.json | 2 +- code/lib/source-loader/package.json | 2 +- code/lib/telemetry/package.json | 2 +- code/lib/test/package.json | 2 +- code/lib/theming/package.json | 2 +- code/lib/types/package.json | 2 +- code/package.json | 5 +- code/presets/create-react-app/package.json | 2 +- code/presets/html-webpack/package.json | 2 +- code/presets/preact-webpack/package.json | 2 +- code/presets/react-webpack/package.json | 2 +- code/presets/server-webpack/package.json | 2 +- code/presets/svelte-webpack/package.json | 2 +- code/presets/vue3-webpack/package.json | 2 +- code/renderers/html/package.json | 2 +- code/renderers/preact/package.json | 2 +- code/renderers/react/package.json | 2 +- code/renderers/server/package.json | 2 +- code/renderers/svelte/package.json | 2 +- code/renderers/vue3/package.json | 2 +- code/renderers/web-components/package.json | 2 +- code/ui/blocks/package.json | 2 +- code/ui/components/package.json | 2 +- code/ui/manager/package.json | 2 +- 83 files changed, 163 insertions(+), 164 deletions(-) diff --git a/code/addons/a11y/package.json b/code/addons/a11y/package.json index ebae68256c87..abe43c249f6b 100644 --- a/code/addons/a11y/package.json +++ b/code/addons/a11y/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-a11y", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Test component compliance with web accessibility standards", "keywords": [ "a11y", diff --git a/code/addons/actions/package.json b/code/addons/actions/package.json index bc89e2f5e5c7..5dcdd61e3c52 100644 --- a/code/addons/actions/package.json +++ b/code/addons/actions/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-actions", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Get UI feedback when an action is performed on an interactive element", "keywords": [ "storybook", diff --git a/code/addons/backgrounds/package.json b/code/addons/backgrounds/package.json index 4fbdfc5c027c..17a842b06f13 100644 --- a/code/addons/backgrounds/package.json +++ b/code/addons/backgrounds/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-backgrounds", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Switch backgrounds to view components in different settings", "keywords": [ "addon", diff --git a/code/addons/controls/package.json b/code/addons/controls/package.json index 588947d02c70..3df650748609 100644 --- a/code/addons/controls/package.json +++ b/code/addons/controls/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-controls", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Interact with component inputs dynamically in the Storybook UI", "keywords": [ "addon", diff --git a/code/addons/docs/package.json b/code/addons/docs/package.json index a159c03063b6..a74ff2e67653 100644 --- a/code/addons/docs/package.json +++ b/code/addons/docs/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-docs", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Document component usage and properties in Markdown", "keywords": [ "addon", diff --git a/code/addons/essentials/package.json b/code/addons/essentials/package.json index 61dbf507bbb1..5b01bbd974b1 100644 --- a/code/addons/essentials/package.json +++ b/code/addons/essentials/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-essentials", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Curated addons to bring out the best of Storybook", "keywords": [ "addon", diff --git a/code/addons/gfm/package.json b/code/addons/gfm/package.json index 5491ba3a58e4..031416826745 100644 --- a/code/addons/gfm/package.json +++ b/code/addons/gfm/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-mdx-gfm", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "GitHub Flavored Markdown in Storybook", "keywords": [ "addon", diff --git a/code/addons/highlight/package.json b/code/addons/highlight/package.json index 28f331bf4dc8..e4802d08da43 100644 --- a/code/addons/highlight/package.json +++ b/code/addons/highlight/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-highlight", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Highlight DOM nodes within your stories", "keywords": [ "storybook-addons", diff --git a/code/addons/interactions/package.json b/code/addons/interactions/package.json index daece4716036..29d753da6fbf 100644 --- a/code/addons/interactions/package.json +++ b/code/addons/interactions/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-interactions", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Automate, test and debug user interactions", "keywords": [ "storybook-addons", diff --git a/code/addons/jest/package.json b/code/addons/jest/package.json index 3b194968932c..7284de78eec3 100644 --- a/code/addons/jest/package.json +++ b/code/addons/jest/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-jest", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "React storybook addon that show component jest report", "keywords": [ "addon", diff --git a/code/addons/links/package.json b/code/addons/links/package.json index d1777a65aa4d..a23690c6e9b2 100644 --- a/code/addons/links/package.json +++ b/code/addons/links/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-links", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Link stories together to build demos and prototypes with your UI components", "keywords": [ "addon", diff --git a/code/addons/measure/package.json b/code/addons/measure/package.json index 2d23660bdac2..843dd37f5197 100644 --- a/code/addons/measure/package.json +++ b/code/addons/measure/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-measure", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Inspect layouts by visualizing the box model", "keywords": [ "storybook-addons", diff --git a/code/addons/onboarding/package.json b/code/addons/onboarding/package.json index 057221c7df4e..5064aa48addb 100644 --- a/code/addons/onboarding/package.json +++ b/code/addons/onboarding/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-onboarding", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook Addon Onboarding - Introduces a new onboarding experience", "keywords": [ "storybook-addons", diff --git a/code/addons/outline/package.json b/code/addons/outline/package.json index a0a1ff61ab03..b5b5771d6049 100644 --- a/code/addons/outline/package.json +++ b/code/addons/outline/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-outline", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Outline all elements with CSS to help with layout placement and alignment", "keywords": [ "storybook-addons", diff --git a/code/addons/storysource/package.json b/code/addons/storysource/package.json index c9fc3680601d..e060751d1a6f 100644 --- a/code/addons/storysource/package.json +++ b/code/addons/storysource/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-storysource", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "View a story’s source code to see how it works and paste into your app", "keywords": [ "addon", diff --git a/code/addons/themes/package.json b/code/addons/themes/package.json index c28b3426d2e1..a13dcf595c17 100644 --- a/code/addons/themes/package.json +++ b/code/addons/themes/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-themes", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Switch between multiple themes for you components in Storybook", "keywords": [ "css", diff --git a/code/addons/toolbars/package.json b/code/addons/toolbars/package.json index f9aa8edb217e..b1bdae2a70cd 100644 --- a/code/addons/toolbars/package.json +++ b/code/addons/toolbars/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-toolbars", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Create your own toolbar items that control story rendering", "keywords": [ "addon", diff --git a/code/addons/viewport/package.json b/code/addons/viewport/package.json index 55459bde0a95..ae6af334349d 100644 --- a/code/addons/viewport/package.json +++ b/code/addons/viewport/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-viewport", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Build responsive components by adjusting Storybook’s viewport size and orientation", "keywords": [ "addon", diff --git a/code/builders/builder-manager/package.json b/code/builders/builder-manager/package.json index e892d2dbf0e9..8f4a9c8c964a 100644 --- a/code/builders/builder-manager/package.json +++ b/code/builders/builder-manager/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/builder-manager", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook manager builder", "keywords": [ "storybook" diff --git a/code/builders/builder-vite/package.json b/code/builders/builder-vite/package.json index b1dd337500cb..affa9c2fa59b 100644 --- a/code/builders/builder-vite/package.json +++ b/code/builders/builder-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/builder-vite", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "A plugin to run and build Storybooks with Vite", "homepage": "https://github.com/storybookjs/storybook/tree/next/code/builders/builder-vite/#readme", "bugs": { diff --git a/code/builders/builder-webpack5/package.json b/code/builders/builder-webpack5/package.json index 09e2717e316a..9565198092f8 100644 --- a/code/builders/builder-webpack5/package.json +++ b/code/builders/builder-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/builder-webpack5", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook framework-agnostic API", "keywords": [ "storybook" diff --git a/code/frameworks/angular/package.json b/code/frameworks/angular/package.json index b58cb37738cf..8639c28d08c2 100644 --- a/code/frameworks/angular/package.json +++ b/code/frameworks/angular/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/angular", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook for Angular: Develop Angular components in isolation with hot reloading.", "keywords": [ "storybook", diff --git a/code/frameworks/ember/package.json b/code/frameworks/ember/package.json index f279db33b3ed..db1b2cfe14aa 100644 --- a/code/frameworks/ember/package.json +++ b/code/frameworks/ember/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/ember", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook for Ember: Develop Ember Component in isolation with Hot Reloading.", "homepage": "https://github.com/storybookjs/storybook/tree/next/code/frameworks/ember", "bugs": { diff --git a/code/frameworks/html-vite/package.json b/code/frameworks/html-vite/package.json index c4004391a219..5fb64a4a8c48 100644 --- a/code/frameworks/html-vite/package.json +++ b/code/frameworks/html-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/html-vite", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook for HTML and Vite: Develop HTML in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/html-webpack5/package.json b/code/frameworks/html-webpack5/package.json index 81cc4e41b756..55e6496baa3c 100644 --- a/code/frameworks/html-webpack5/package.json +++ b/code/frameworks/html-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/html-webpack5", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook for HTML: View HTML snippets in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/nextjs/package.json b/code/frameworks/nextjs/package.json index 73b56bd55c4b..f622f9eeaabe 100644 --- a/code/frameworks/nextjs/package.json +++ b/code/frameworks/nextjs/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/nextjs", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook for Next.js", "keywords": [ "storybook", diff --git a/code/frameworks/preact-vite/package.json b/code/frameworks/preact-vite/package.json index e059321937b6..19e035c0740d 100644 --- a/code/frameworks/preact-vite/package.json +++ b/code/frameworks/preact-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preact-vite", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook for Preact and Vite: Develop Preact components in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/preact-webpack5/package.json b/code/frameworks/preact-webpack5/package.json index 1bfffc99ab65..8423ab98fade 100644 --- a/code/frameworks/preact-webpack5/package.json +++ b/code/frameworks/preact-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preact-webpack5", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook for Preact: Develop Preact Component in isolation.", "keywords": [ "storybook" diff --git a/code/frameworks/react-vite/package.json b/code/frameworks/react-vite/package.json index 5673d4caf9dd..a76d1c4cbddc 100644 --- a/code/frameworks/react-vite/package.json +++ b/code/frameworks/react-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/react-vite", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook for React and Vite: Develop React components in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/react-webpack5/package.json b/code/frameworks/react-webpack5/package.json index 448905c2a899..a2096ef8e059 100644 --- a/code/frameworks/react-webpack5/package.json +++ b/code/frameworks/react-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/react-webpack5", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook for React: Develop React Component in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/server-webpack5/package.json b/code/frameworks/server-webpack5/package.json index 8b00bc35433d..7c3771652cfd 100644 --- a/code/frameworks/server-webpack5/package.json +++ b/code/frameworks/server-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/server-webpack5", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook for Server: View HTML snippets from a server in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/svelte-vite/package.json b/code/frameworks/svelte-vite/package.json index be8d6b0c228e..edac75e5589d 100644 --- a/code/frameworks/svelte-vite/package.json +++ b/code/frameworks/svelte-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/svelte-vite", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook for Svelte and Vite: Develop Svelte components in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/svelte-webpack5/package.json b/code/frameworks/svelte-webpack5/package.json index 3979794e33b1..85a17dfc6a76 100644 --- a/code/frameworks/svelte-webpack5/package.json +++ b/code/frameworks/svelte-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/svelte-webpack5", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook for Svelte: Develop Svelte Component in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/sveltekit/package.json b/code/frameworks/sveltekit/package.json index 8dd860c61d21..b6450c030f5f 100644 --- a/code/frameworks/sveltekit/package.json +++ b/code/frameworks/sveltekit/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/sveltekit", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook for SvelteKit", "keywords": [ "storybook", diff --git a/code/frameworks/vue3-vite/package.json b/code/frameworks/vue3-vite/package.json index ad452ade8d46..58e9602305b1 100644 --- a/code/frameworks/vue3-vite/package.json +++ b/code/frameworks/vue3-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/vue3-vite", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook for Vue3 and Vite: Develop Vue3 components in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/vue3-webpack5/package.json b/code/frameworks/vue3-webpack5/package.json index 6b6504531dbf..a23d5980b17f 100644 --- a/code/frameworks/vue3-webpack5/package.json +++ b/code/frameworks/vue3-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/vue3-webpack5", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook for Vue 3: Develop Vue 3 Components in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/web-components-vite/package.json b/code/frameworks/web-components-vite/package.json index c4151a92ca89..6c559ff1a849 100644 --- a/code/frameworks/web-components-vite/package.json +++ b/code/frameworks/web-components-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/web-components-vite", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook for web-components and Vite: Develop Web Components in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/web-components-webpack5/package.json b/code/frameworks/web-components-webpack5/package.json index 7e0ab8ec6130..04f0b31cbf1f 100644 --- a/code/frameworks/web-components-webpack5/package.json +++ b/code/frameworks/web-components-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/web-components-webpack5", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook for web-components: View web components snippets in isolation with Hot Reloading.", "keywords": [ "lit", diff --git a/code/lib/channels/package.json b/code/lib/channels/package.json index 6abecbb236fc..6020059195b0 100644 --- a/code/lib/channels/package.json +++ b/code/lib/channels/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/channels", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "", "keywords": [ "storybook" diff --git a/code/lib/cli-sb/package.json b/code/lib/cli-sb/package.json index fb2741dc33a2..821450e6252c 100644 --- a/code/lib/cli-sb/package.json +++ b/code/lib/cli-sb/package.json @@ -1,6 +1,6 @@ { "name": "sb", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook CLI", "keywords": [ "storybook" diff --git a/code/lib/cli-storybook/package.json b/code/lib/cli-storybook/package.json index f4e2319a57cb..17585083a303 100644 --- a/code/lib/cli-storybook/package.json +++ b/code/lib/cli-storybook/package.json @@ -1,6 +1,6 @@ { "name": "storybook", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook CLI", "keywords": [ "storybook" diff --git a/code/lib/cli/package.json b/code/lib/cli/package.json index ed8b9f90bcf6..0f8d72361143 100644 --- a/code/lib/cli/package.json +++ b/code/lib/cli/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/cli", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook's CLI - install, dev, build, upgrade, and more", "keywords": [ "cli", diff --git a/code/lib/client-logger/package.json b/code/lib/client-logger/package.json index f5f6f32ed843..60716ac1c3cb 100644 --- a/code/lib/client-logger/package.json +++ b/code/lib/client-logger/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/client-logger", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "", "keywords": [ "storybook" diff --git a/code/lib/codemod/package.json b/code/lib/codemod/package.json index cdb05de5da4d..dbcac376c369 100644 --- a/code/lib/codemod/package.json +++ b/code/lib/codemod/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/codemod", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "A collection of codemod scripts written with JSCodeshift", "keywords": [ "storybook" diff --git a/code/lib/core-common/package.json b/code/lib/core-common/package.json index 169977d00655..b4804a0b2772 100644 --- a/code/lib/core-common/package.json +++ b/code/lib/core-common/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/core-common", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook framework-agnostic API", "keywords": [ "storybook" diff --git a/code/lib/core-common/src/versions.ts b/code/lib/core-common/src/versions.ts index 346f3d272c65..1de3269c4e5b 100644 --- a/code/lib/core-common/src/versions.ts +++ b/code/lib/core-common/src/versions.ts @@ -1,83 +1,83 @@ // auto generated file, do not edit export default { - '@storybook/addon-a11y': '8.0.0-rc.1', - '@storybook/addon-actions': '8.0.0-rc.1', - '@storybook/addon-backgrounds': '8.0.0-rc.1', - '@storybook/addon-controls': '8.0.0-rc.1', - '@storybook/addon-docs': '8.0.0-rc.1', - '@storybook/addon-essentials': '8.0.0-rc.1', - '@storybook/addon-highlight': '8.0.0-rc.1', - '@storybook/addon-interactions': '8.0.0-rc.1', - '@storybook/addon-jest': '8.0.0-rc.1', - '@storybook/addon-links': '8.0.0-rc.1', - '@storybook/addon-mdx-gfm': '8.0.0-rc.1', - '@storybook/addon-measure': '8.0.0-rc.1', - '@storybook/addon-onboarding': '8.0.0-rc.1', - '@storybook/addon-outline': '8.0.0-rc.1', - '@storybook/addon-storysource': '8.0.0-rc.1', - '@storybook/addon-themes': '8.0.0-rc.1', - '@storybook/addon-toolbars': '8.0.0-rc.1', - '@storybook/addon-viewport': '8.0.0-rc.1', - '@storybook/angular': '8.0.0-rc.1', - '@storybook/blocks': '8.0.0-rc.1', - '@storybook/builder-manager': '8.0.0-rc.1', - '@storybook/builder-vite': '8.0.0-rc.1', - '@storybook/builder-webpack5': '8.0.0-rc.1', - '@storybook/channels': '8.0.0-rc.1', - '@storybook/cli': '8.0.0-rc.1', - '@storybook/client-logger': '8.0.0-rc.1', - '@storybook/codemod': '8.0.0-rc.1', - '@storybook/components': '8.0.0-rc.1', - '@storybook/core-common': '8.0.0-rc.1', - '@storybook/core-events': '8.0.0-rc.1', - '@storybook/core-server': '8.0.0-rc.1', - '@storybook/core-webpack': '8.0.0-rc.1', - '@storybook/csf-plugin': '8.0.0-rc.1', - '@storybook/csf-tools': '8.0.0-rc.1', - '@storybook/docs-tools': '8.0.0-rc.1', - '@storybook/ember': '8.0.0-rc.1', - '@storybook/html': '8.0.0-rc.1', - '@storybook/html-vite': '8.0.0-rc.1', - '@storybook/html-webpack5': '8.0.0-rc.1', - '@storybook/instrumenter': '8.0.0-rc.1', - '@storybook/manager': '8.0.0-rc.1', - '@storybook/manager-api': '8.0.0-rc.1', - '@storybook/nextjs': '8.0.0-rc.1', - '@storybook/node-logger': '8.0.0-rc.1', - '@storybook/preact': '8.0.0-rc.1', - '@storybook/preact-vite': '8.0.0-rc.1', - '@storybook/preact-webpack5': '8.0.0-rc.1', - '@storybook/preset-create-react-app': '8.0.0-rc.1', - '@storybook/preset-html-webpack': '8.0.0-rc.1', - '@storybook/preset-preact-webpack': '8.0.0-rc.1', - '@storybook/preset-react-webpack': '8.0.0-rc.1', - '@storybook/preset-server-webpack': '8.0.0-rc.1', - '@storybook/preset-svelte-webpack': '8.0.0-rc.1', - '@storybook/preset-vue3-webpack': '8.0.0-rc.1', - '@storybook/preview': '8.0.0-rc.1', - '@storybook/preview-api': '8.0.0-rc.1', - '@storybook/react': '8.0.0-rc.1', - '@storybook/react-dom-shim': '8.0.0-rc.1', - '@storybook/react-vite': '8.0.0-rc.1', - '@storybook/react-webpack5': '8.0.0-rc.1', - '@storybook/router': '8.0.0-rc.1', - '@storybook/server': '8.0.0-rc.1', - '@storybook/server-webpack5': '8.0.0-rc.1', - '@storybook/source-loader': '8.0.0-rc.1', - '@storybook/svelte': '8.0.0-rc.1', - '@storybook/svelte-vite': '8.0.0-rc.1', - '@storybook/svelte-webpack5': '8.0.0-rc.1', - '@storybook/sveltekit': '8.0.0-rc.1', - '@storybook/telemetry': '8.0.0-rc.1', - '@storybook/test': '8.0.0-rc.1', - '@storybook/theming': '8.0.0-rc.1', - '@storybook/types': '8.0.0-rc.1', - '@storybook/vue3': '8.0.0-rc.1', - '@storybook/vue3-vite': '8.0.0-rc.1', - '@storybook/vue3-webpack5': '8.0.0-rc.1', - '@storybook/web-components': '8.0.0-rc.1', - '@storybook/web-components-vite': '8.0.0-rc.1', - '@storybook/web-components-webpack5': '8.0.0-rc.1', - sb: '8.0.0-rc.1', - storybook: '8.0.0-rc.1', + '@storybook/addon-a11y': '8.0.0-rc.2', + '@storybook/addon-actions': '8.0.0-rc.2', + '@storybook/addon-backgrounds': '8.0.0-rc.2', + '@storybook/addon-controls': '8.0.0-rc.2', + '@storybook/addon-docs': '8.0.0-rc.2', + '@storybook/addon-essentials': '8.0.0-rc.2', + '@storybook/addon-highlight': '8.0.0-rc.2', + '@storybook/addon-interactions': '8.0.0-rc.2', + '@storybook/addon-jest': '8.0.0-rc.2', + '@storybook/addon-links': '8.0.0-rc.2', + '@storybook/addon-mdx-gfm': '8.0.0-rc.2', + '@storybook/addon-measure': '8.0.0-rc.2', + '@storybook/addon-onboarding': '8.0.0-rc.2', + '@storybook/addon-outline': '8.0.0-rc.2', + '@storybook/addon-storysource': '8.0.0-rc.2', + '@storybook/addon-themes': '8.0.0-rc.2', + '@storybook/addon-toolbars': '8.0.0-rc.2', + '@storybook/addon-viewport': '8.0.0-rc.2', + '@storybook/angular': '8.0.0-rc.2', + '@storybook/blocks': '8.0.0-rc.2', + '@storybook/builder-manager': '8.0.0-rc.2', + '@storybook/builder-vite': '8.0.0-rc.2', + '@storybook/builder-webpack5': '8.0.0-rc.2', + '@storybook/channels': '8.0.0-rc.2', + '@storybook/cli': '8.0.0-rc.2', + '@storybook/client-logger': '8.0.0-rc.2', + '@storybook/codemod': '8.0.0-rc.2', + '@storybook/components': '8.0.0-rc.2', + '@storybook/core-common': '8.0.0-rc.2', + '@storybook/core-events': '8.0.0-rc.2', + '@storybook/core-server': '8.0.0-rc.2', + '@storybook/core-webpack': '8.0.0-rc.2', + '@storybook/csf-plugin': '8.0.0-rc.2', + '@storybook/csf-tools': '8.0.0-rc.2', + '@storybook/docs-tools': '8.0.0-rc.2', + '@storybook/ember': '8.0.0-rc.2', + '@storybook/html': '8.0.0-rc.2', + '@storybook/html-vite': '8.0.0-rc.2', + '@storybook/html-webpack5': '8.0.0-rc.2', + '@storybook/instrumenter': '8.0.0-rc.2', + '@storybook/manager': '8.0.0-rc.2', + '@storybook/manager-api': '8.0.0-rc.2', + '@storybook/nextjs': '8.0.0-rc.2', + '@storybook/node-logger': '8.0.0-rc.2', + '@storybook/preact': '8.0.0-rc.2', + '@storybook/preact-vite': '8.0.0-rc.2', + '@storybook/preact-webpack5': '8.0.0-rc.2', + '@storybook/preset-create-react-app': '8.0.0-rc.2', + '@storybook/preset-html-webpack': '8.0.0-rc.2', + '@storybook/preset-preact-webpack': '8.0.0-rc.2', + '@storybook/preset-react-webpack': '8.0.0-rc.2', + '@storybook/preset-server-webpack': '8.0.0-rc.2', + '@storybook/preset-svelte-webpack': '8.0.0-rc.2', + '@storybook/preset-vue3-webpack': '8.0.0-rc.2', + '@storybook/preview': '8.0.0-rc.2', + '@storybook/preview-api': '8.0.0-rc.2', + '@storybook/react': '8.0.0-rc.2', + '@storybook/react-dom-shim': '8.0.0-rc.2', + '@storybook/react-vite': '8.0.0-rc.2', + '@storybook/react-webpack5': '8.0.0-rc.2', + '@storybook/router': '8.0.0-rc.2', + '@storybook/server': '8.0.0-rc.2', + '@storybook/server-webpack5': '8.0.0-rc.2', + '@storybook/source-loader': '8.0.0-rc.2', + '@storybook/svelte': '8.0.0-rc.2', + '@storybook/svelte-vite': '8.0.0-rc.2', + '@storybook/svelte-webpack5': '8.0.0-rc.2', + '@storybook/sveltekit': '8.0.0-rc.2', + '@storybook/telemetry': '8.0.0-rc.2', + '@storybook/test': '8.0.0-rc.2', + '@storybook/theming': '8.0.0-rc.2', + '@storybook/types': '8.0.0-rc.2', + '@storybook/vue3': '8.0.0-rc.2', + '@storybook/vue3-vite': '8.0.0-rc.2', + '@storybook/vue3-webpack5': '8.0.0-rc.2', + '@storybook/web-components': '8.0.0-rc.2', + '@storybook/web-components-vite': '8.0.0-rc.2', + '@storybook/web-components-webpack5': '8.0.0-rc.2', + sb: '8.0.0-rc.2', + storybook: '8.0.0-rc.2', }; diff --git a/code/lib/core-events/package.json b/code/lib/core-events/package.json index 03a63f346e27..8ada1c3ee9a4 100644 --- a/code/lib/core-events/package.json +++ b/code/lib/core-events/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/core-events", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Event names used in storybook core", "keywords": [ "storybook" diff --git a/code/lib/core-server/package.json b/code/lib/core-server/package.json index 663facee0635..1d4f1d43c88b 100644 --- a/code/lib/core-server/package.json +++ b/code/lib/core-server/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/core-server", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook framework-agnostic API", "keywords": [ "storybook" diff --git a/code/lib/core-webpack/package.json b/code/lib/core-webpack/package.json index 46f38e226ea1..84199b59fc20 100644 --- a/code/lib/core-webpack/package.json +++ b/code/lib/core-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/core-webpack", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook framework-agnostic API", "keywords": [ "storybook" diff --git a/code/lib/csf-plugin/package.json b/code/lib/csf-plugin/package.json index c447831f6657..7c69964a2bf5 100644 --- a/code/lib/csf-plugin/package.json +++ b/code/lib/csf-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/csf-plugin", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Enrich CSF files via static analysis", "keywords": [ "storybook" diff --git a/code/lib/csf-tools/package.json b/code/lib/csf-tools/package.json index 9004d3e3beae..3aecb2b4c989 100644 --- a/code/lib/csf-tools/package.json +++ b/code/lib/csf-tools/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/csf-tools", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Parse and manipulate CSF and Storybook config files", "keywords": [ "storybook" diff --git a/code/lib/docs-tools/package.json b/code/lib/docs-tools/package.json index 06e103124ee1..faead07c757d 100644 --- a/code/lib/docs-tools/package.json +++ b/code/lib/docs-tools/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/docs-tools", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Shared utility functions for frameworks to implement docs", "keywords": [ "storybook" diff --git a/code/lib/instrumenter/package.json b/code/lib/instrumenter/package.json index 32c7c06686a8..29aafd117e78 100644 --- a/code/lib/instrumenter/package.json +++ b/code/lib/instrumenter/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/instrumenter", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "", "keywords": [ "storybook" diff --git a/code/lib/manager-api/package.json b/code/lib/manager-api/package.json index a790395da7a3..6ce5d7c94478 100644 --- a/code/lib/manager-api/package.json +++ b/code/lib/manager-api/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/manager-api", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Core Storybook Manager API & Context", "keywords": [ "storybook" diff --git a/code/lib/manager-api/src/version.ts b/code/lib/manager-api/src/version.ts index 156fd9c6a94a..7900754c895d 100644 --- a/code/lib/manager-api/src/version.ts +++ b/code/lib/manager-api/src/version.ts @@ -1 +1 @@ -export const version = '8.0.0-rc.1'; +export const version = '8.0.0-rc.2'; diff --git a/code/lib/node-logger/package.json b/code/lib/node-logger/package.json index 12672e9c0278..eab0c64bfa00 100644 --- a/code/lib/node-logger/package.json +++ b/code/lib/node-logger/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/node-logger", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "", "keywords": [ "storybook" diff --git a/code/lib/preview-api/package.json b/code/lib/preview-api/package.json index 75d64c9a87b8..8706fb1e6f0e 100644 --- a/code/lib/preview-api/package.json +++ b/code/lib/preview-api/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preview-api", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "", "keywords": [ "storybook" diff --git a/code/lib/preview/package.json b/code/lib/preview/package.json index cea251ed2dad..d7f6a6bf9713 100644 --- a/code/lib/preview/package.json +++ b/code/lib/preview/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preview", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "", "keywords": [ "storybook" diff --git a/code/lib/react-dom-shim/package.json b/code/lib/react-dom-shim/package.json index 417322b679f2..52f45ceba617 100644 --- a/code/lib/react-dom-shim/package.json +++ b/code/lib/react-dom-shim/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/react-dom-shim", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "", "keywords": [ "storybook" diff --git a/code/lib/router/package.json b/code/lib/router/package.json index 28bc6525c2d2..79520d10ffbb 100644 --- a/code/lib/router/package.json +++ b/code/lib/router/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/router", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Core Storybook Router", "keywords": [ "storybook" diff --git a/code/lib/source-loader/package.json b/code/lib/source-loader/package.json index 634c33cf3d8c..dfd1ee424bc4 100644 --- a/code/lib/source-loader/package.json +++ b/code/lib/source-loader/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/source-loader", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Source loader", "keywords": [ "lib", diff --git a/code/lib/telemetry/package.json b/code/lib/telemetry/package.json index bacd55a2207c..430a2add1bdf 100644 --- a/code/lib/telemetry/package.json +++ b/code/lib/telemetry/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/telemetry", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Telemetry logging for crash reports and usage statistics", "keywords": [ "storybook" diff --git a/code/lib/test/package.json b/code/lib/test/package.json index 5258ec216e55..d0ae52a03d6f 100644 --- a/code/lib/test/package.json +++ b/code/lib/test/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/test", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "", "keywords": [ "storybook" diff --git a/code/lib/theming/package.json b/code/lib/theming/package.json index dc6f964b604e..ab85acf2481c 100644 --- a/code/lib/theming/package.json +++ b/code/lib/theming/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/theming", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Core Storybook Components", "keywords": [ "storybook" diff --git a/code/lib/types/package.json b/code/lib/types/package.json index 96f6089b73dc..0eb61cdce388 100644 --- a/code/lib/types/package.json +++ b/code/lib/types/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/types", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Core Storybook TS Types", "keywords": [ "storybook" diff --git a/code/package.json b/code/package.json index 2055b55ef7e6..687106394b60 100644 --- a/code/package.json +++ b/code/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/root", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "private": true, "description": "Storybook root", "homepage": "https://storybook.js.org/", @@ -294,6 +294,5 @@ "Dependency Upgrades" ] ] - }, - "deferredNextVersion": "8.0.0-rc.2" + } } diff --git a/code/presets/create-react-app/package.json b/code/presets/create-react-app/package.json index 5275fade6100..ed53ffee0fe9 100644 --- a/code/presets/create-react-app/package.json +++ b/code/presets/create-react-app/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-create-react-app", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook for Create React App preset", "keywords": [ "storybook" diff --git a/code/presets/html-webpack/package.json b/code/presets/html-webpack/package.json index c85346ee246a..1ca061b42459 100644 --- a/code/presets/html-webpack/package.json +++ b/code/presets/html-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-html-webpack", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook for HTML: View HTML snippets in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/presets/preact-webpack/package.json b/code/presets/preact-webpack/package.json index 0edddb4d473d..0fff0481f38d 100644 --- a/code/presets/preact-webpack/package.json +++ b/code/presets/preact-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-preact-webpack", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook for Preact: Develop Preact Component in isolation.", "keywords": [ "storybook" diff --git a/code/presets/react-webpack/package.json b/code/presets/react-webpack/package.json index b3f4377f9da2..dd5f11b03793 100644 --- a/code/presets/react-webpack/package.json +++ b/code/presets/react-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-react-webpack", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook for React: Develop React Component in isolation with Hot Reloading", "keywords": [ "storybook" diff --git a/code/presets/server-webpack/package.json b/code/presets/server-webpack/package.json index 0c57f088153d..39e509374b67 100644 --- a/code/presets/server-webpack/package.json +++ b/code/presets/server-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-server-webpack", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook for Server: View HTML snippets from a server in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/presets/svelte-webpack/package.json b/code/presets/svelte-webpack/package.json index d80d06b70c22..efcbd040827c 100644 --- a/code/presets/svelte-webpack/package.json +++ b/code/presets/svelte-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-svelte-webpack", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook for Svelte: Develop Svelte Component in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/presets/vue3-webpack/package.json b/code/presets/vue3-webpack/package.json index 774e7247eafb..f19a6e689a0e 100644 --- a/code/presets/vue3-webpack/package.json +++ b/code/presets/vue3-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-vue3-webpack", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook for Vue 3: Develop Vue 3 Components in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/renderers/html/package.json b/code/renderers/html/package.json index ce6c017145aa..d65de0340b40 100644 --- a/code/renderers/html/package.json +++ b/code/renderers/html/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/html", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook HTML renderer", "keywords": [ "storybook" diff --git a/code/renderers/preact/package.json b/code/renderers/preact/package.json index 685eb8e50aaa..964a280e875c 100644 --- a/code/renderers/preact/package.json +++ b/code/renderers/preact/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preact", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook Preact renderer", "keywords": [ "storybook" diff --git a/code/renderers/react/package.json b/code/renderers/react/package.json index de60e151b77c..a42882c38ebf 100644 --- a/code/renderers/react/package.json +++ b/code/renderers/react/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/react", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook React renderer", "keywords": [ "storybook" diff --git a/code/renderers/server/package.json b/code/renderers/server/package.json index f4c892e2a87a..e17abd07240a 100644 --- a/code/renderers/server/package.json +++ b/code/renderers/server/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/server", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook Server renderer", "keywords": [ "storybook" diff --git a/code/renderers/svelte/package.json b/code/renderers/svelte/package.json index da7ad794fca2..f33c169654cd 100644 --- a/code/renderers/svelte/package.json +++ b/code/renderers/svelte/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/svelte", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook Svelte renderer", "keywords": [ "storybook" diff --git a/code/renderers/vue3/package.json b/code/renderers/vue3/package.json index ec3d8037453a..cc5a72a3cde1 100644 --- a/code/renderers/vue3/package.json +++ b/code/renderers/vue3/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/vue3", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook Vue 3 renderer", "keywords": [ "storybook" diff --git a/code/renderers/web-components/package.json b/code/renderers/web-components/package.json index fcd133473b18..1483eb3de461 100644 --- a/code/renderers/web-components/package.json +++ b/code/renderers/web-components/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/web-components", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook web-components renderer", "keywords": [ "lit", diff --git a/code/ui/blocks/package.json b/code/ui/blocks/package.json index c48cbadc893a..790612807846 100644 --- a/code/ui/blocks/package.json +++ b/code/ui/blocks/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/blocks", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Storybook Doc Blocks", "keywords": [ "storybook" diff --git a/code/ui/components/package.json b/code/ui/components/package.json index 248ed68c73c5..fcb4235f18e1 100644 --- a/code/ui/components/package.json +++ b/code/ui/components/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/components", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Core Storybook Components", "keywords": [ "storybook" diff --git a/code/ui/manager/package.json b/code/ui/manager/package.json index b13135e4eb4f..05c4b076ed7b 100644 --- a/code/ui/manager/package.json +++ b/code/ui/manager/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/manager", - "version": "8.0.0-rc.1", + "version": "8.0.0-rc.2", "description": "Core Storybook UI", "keywords": [ "storybook" From 96213412f4726f9ce7bd14d3baba514342e699bb Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Tue, 5 Mar 2024 21:11:10 +0100 Subject: [PATCH 76/79] use dynamic vite imports in docs snippets --- docs/snippets/common/main-config-vite-final-env.js.mdx | 4 ++-- docs/snippets/common/main-config-vite-final.js.mdx | 4 ++-- docs/snippets/common/main-config-vite-final.ts-4-9.mdx | 4 ++-- docs/snippets/common/main-config-vite-final.ts.mdx | 3 ++- docs/snippets/common/storybook-vite-builder-aliasing.js.mdx | 4 ++-- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/docs/snippets/common/main-config-vite-final-env.js.mdx b/docs/snippets/common/main-config-vite-final-env.js.mdx index 73926f408471..e1ddc08d9644 100644 --- a/docs/snippets/common/main-config-vite-final-env.js.mdx +++ b/docs/snippets/common/main-config-vite-final-env.js.mdx @@ -1,14 +1,14 @@ ```js // .storybook/main.js|ts -import { mergeConfig } from 'vite'; - export default { stories: ['../src/**/*.mdx', '../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)'], core: { builder: '@storybook/builder-vite', }, async viteFinal(config, { configType }) { + const { mergeConfig } = await import('vite'); + if (configType === 'DEVELOPMENT') { // Your development configuration goes here } diff --git a/docs/snippets/common/main-config-vite-final.js.mdx b/docs/snippets/common/main-config-vite-final.js.mdx index b2987dcd412c..dbb5d70555ba 100644 --- a/docs/snippets/common/main-config-vite-final.js.mdx +++ b/docs/snippets/common/main-config-vite-final.js.mdx @@ -1,13 +1,13 @@ ```js // .storybook/main.js -import { mergeConfig } from 'vite'; - export default { // Replace your-framework with the framework you are using (e.g., react-vite, vue3-vite) framework: '@storybook/your-framework', stories: ['../src/**/*.mdx', '../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)'], async viteFinal(config, { configType }) { + const { mergeConfig } = await import('vite'); + if (configType === 'DEVELOPMENT') { // Your development configuration goes here } diff --git a/docs/snippets/common/main-config-vite-final.ts-4-9.mdx b/docs/snippets/common/main-config-vite-final.ts-4-9.mdx index 42d7f8cf8b9d..f5f36cdafdba 100644 --- a/docs/snippets/common/main-config-vite-final.ts-4-9.mdx +++ b/docs/snippets/common/main-config-vite-final.ts-4-9.mdx @@ -4,13 +4,13 @@ // Replace your-framework with the framework you are using (e.g., react-vite, vue3-vite) import type { StorybookConfig } from '@storybook/your-framework'; -import { mergeConfig } from 'vite'; - const config: StorybookConfig = { // Replace your-framework with the framework you are using (e.g., react-vite, vue3-vite) framework: '@storybook/your-framework', stories: ['../src/**/*.mdx', '../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)'], async viteFinal(config, { configType }) { + const { mergeConfig } = await import('vite'); + if (configType === 'DEVELOPMENT') { // Your development configuration goes here } diff --git a/docs/snippets/common/main-config-vite-final.ts.mdx b/docs/snippets/common/main-config-vite-final.ts.mdx index a82973f98afc..2df5faf42cd5 100644 --- a/docs/snippets/common/main-config-vite-final.ts.mdx +++ b/docs/snippets/common/main-config-vite-final.ts.mdx @@ -3,12 +3,13 @@ // Replace your-framework with the framework you are using (e.g., react-vite, vue3-vite) import type { StorybookConfig } from '@storybook/your-framework'; -import { mergeConfig } from 'vite'; const config = { framework: '@storybook/your-framework', stories: ['../src/**/*.mdx', '../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)'], async viteFinal(config, { configType }) { + const { mergeConfig } = await import('vite'); + if (configType === 'DEVELOPMENT') { // Your development configuration goes here } diff --git a/docs/snippets/common/storybook-vite-builder-aliasing.js.mdx b/docs/snippets/common/storybook-vite-builder-aliasing.js.mdx index ea5f2e7550de..c6dfb19d7581 100644 --- a/docs/snippets/common/storybook-vite-builder-aliasing.js.mdx +++ b/docs/snippets/common/storybook-vite-builder-aliasing.js.mdx @@ -1,8 +1,6 @@ ```js // .storybook/main.js|ts -import { mergeConfig } from 'vite'; - export default { stories: ['../src/**/*.mdx', '../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)'], addons: ['@storybook/addon-links', '@storybook/addon-essentials'], @@ -11,6 +9,8 @@ export default { }, async viteFinal(config) { // Merge custom configuration into the default config + const { mergeConfig } = await import('vite'); + return mergeConfig(config, { // Add dependencies to pre-optimization optimizeDeps: { From 9d90dc19f8197909d33686897607ca7cf8c269b0 Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Tue, 5 Mar 2024 22:19:26 +0100 Subject: [PATCH 77/79] don't re-render sidebar whenever any manager UI state changes --- .../manager/src/components/sidebar/Sidebar.tsx | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/code/ui/manager/src/components/sidebar/Sidebar.tsx b/code/ui/manager/src/components/sidebar/Sidebar.tsx index 3ea23f6b48a5..f881e3d68d4d 100644 --- a/code/ui/manager/src/components/sidebar/Sidebar.tsx +++ b/code/ui/manager/src/components/sidebar/Sidebar.tsx @@ -17,7 +17,7 @@ import { Explorer } from './Explorer'; import { Search } from './Search'; import { SearchResults } from './SearchResults'; -import type { Refs, CombinedDataset, Selection } from './types'; +import type { CombinedDataset, Selection } from './types'; import { useLastViewed } from './useLastViewed'; import { MEDIA_DESKTOP_BREAKPOINT } from '../../constants'; @@ -79,20 +79,26 @@ const Swap = React.memo(function Swap({ }); const useCombination = ( - defaultRefData: API_LoadedRefData & { status: State['status'] }, - refs: Refs + index: SidebarProps['index'], + indexError: SidebarProps['indexError'], + previewInitialized: SidebarProps['previewInitialized'], + status: SidebarProps['status'], + refs: SidebarProps['refs'] ): CombinedDataset => { const hash = useMemo( () => ({ [DEFAULT_REF_ID]: { - ...defaultRefData, + index, + indexError, + previewInitialized, + status, title: null, id: DEFAULT_REF_ID, url: 'iframe.html', }, ...refs, }), - [refs, defaultRefData] + [refs, index, indexError, previewInitialized, status] ); return useMemo(() => ({ hash, entries: Object.entries(hash) }), [hash]); }; @@ -126,7 +132,7 @@ export const Sidebar = React.memo(function Sidebar({ onMenuClick, }: SidebarProps) { const selected: Selection = useMemo(() => storyId && { storyId, refId }, [storyId, refId]); - const dataset = useCombination({ index, indexError, previewInitialized, status }, refs); + const dataset = useCombination(index, indexError, previewInitialized, status, refs); const isLoading = !index && !indexError; const lastViewedProps = useLastViewed(selected); From cd2dac32d9fae818e86f5f8c9bb164a4e5ef853a Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Wed, 6 Mar 2024 08:00:00 +0100 Subject: [PATCH 78/79] add story for testing scroll behavior --- .../components/sidebar/Sidebar.stories.tsx | 96 +++++++++++++++++-- 1 file changed, 87 insertions(+), 9 deletions(-) diff --git a/code/ui/manager/src/components/sidebar/Sidebar.stories.tsx b/code/ui/manager/src/components/sidebar/Sidebar.stories.tsx index 3e7b7e2b23f3..e8af8d457021 100644 --- a/code/ui/manager/src/components/sidebar/Sidebar.stories.tsx +++ b/code/ui/manager/src/components/sidebar/Sidebar.stories.tsx @@ -1,14 +1,13 @@ import React from 'react'; import type { IndexHash, State } from '@storybook/manager-api'; -import { types } from '@storybook/manager-api'; +import { ManagerContext, types } from '@storybook/manager-api'; import type { StoryObj, Meta } from '@storybook/react'; -import { within, userEvent } from '@storybook/testing-library'; +import { within, userEvent, expect } from '@storybook/test'; import { Button, IconButton } from '@storybook/components'; import { FaceHappyIcon } from '@storybook/icons'; import { Sidebar, DEFAULT_REF_ID } from './Sidebar'; import { standardData as standardHeaderData } from './Heading.stories'; -import * as ExplorerStories from './Explorer.stories'; import { mockDataset } from './mockdata'; import type { RefType } from './types'; import { LayoutProvider } from '../layout/LayoutProvider'; @@ -25,15 +24,34 @@ const meta = { excludeStories: /.*Data$/, parameters: { layout: 'fullscreen' }, decorators: [ - ExplorerStories.default.decorators[0], (storyFn) => ( - - - {storyFn()} - + {}, + on: () => {}, + off: () => {}, + getShortcutKeys: () => ({ search: ['control', 'shift', 's'] }), + }, + } as any + } + > + + + {storyFn()} + + ), ], -} as Meta; +} satisfies Meta; export default meta; @@ -57,6 +75,7 @@ const refs: Record = { }, }; +// eslint-disable-next-line local-rules/no-uncategorized-errors const indexError = new Error('Failed to load index'); const refsError = { @@ -328,3 +347,62 @@ export const Bottom: Story = { /> ), }; + +/** + * Given the following sequence of events: + * 1. Story is selected at the top of the sidebar + * 2. The sidebar is scrolled to the bottom + * 3. Some re-rendering happens because of a changed state/prop + * The sidebar should remain scrolled to the bottom + */ +export const Scrolled: Story = { + parameters: { + // we need a very short viewport + viewport: { + defaultViewport: 'mobile1', + defaultOrientation: 'landscape', + }, + }, + render: (args) => { + const [, setState] = React.useState(0); + return ( + <> + + + + ); + }, + play: async ({ canvasElement, step }) => { + const canvas = await within(canvasElement); + const scrollable = await canvasElement.querySelector('[data-radix-scroll-area-viewport]'); + await step('expand component', async () => { + const componentNode = await canvas.queryAllByText('Child A2')[1]; + userEvent.click(componentNode); + }); + await wait(100); + await step('scroll to bottom', async () => { + scrollable.scrollTo(0, scrollable.scrollHeight); + }); + await step('toggle parent state', async () => { + const button = await canvas.findByRole('button', { name: 'Change state' }); + button.click(); + }); + await wait(100); + + // expect the scrollable to be scrolled to the bottom + expect(scrollable.scrollTop).toBe(scrollable.scrollHeight - scrollable.clientHeight); + }, +}; From 43a70e9af82560fa48d7aa06c0059a319a5e8535 Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Wed, 6 Mar 2024 08:11:52 +0100 Subject: [PATCH 79/79] refactor Sidebar stories --- .../components/sidebar/Sidebar.stories.tsx | 249 +++++------------- 1 file changed, 70 insertions(+), 179 deletions(-) diff --git a/code/ui/manager/src/components/sidebar/Sidebar.stories.tsx b/code/ui/manager/src/components/sidebar/Sidebar.stories.tsx index e8af8d457021..253775bc07c7 100644 --- a/code/ui/manager/src/components/sidebar/Sidebar.stories.tsx +++ b/code/ui/manager/src/components/sidebar/Sidebar.stories.tsx @@ -4,6 +4,7 @@ import type { IndexHash, State } from '@storybook/manager-api'; import { ManagerContext, types } from '@storybook/manager-api'; import type { StoryObj, Meta } from '@storybook/react'; import { within, userEvent, expect } from '@storybook/test'; +import type { Addon_SidebarTopType } from '@storybook/types'; import { Button, IconButton } from '@storybook/components'; import { FaceHappyIcon } from '@storybook/icons'; import { Sidebar, DEFAULT_REF_ID } from './Sidebar'; @@ -18,11 +19,28 @@ const wait = (ms: number) => setTimeout(resolve, ms); }); +const { menu } = standardHeaderData; +const index = mockDataset.withRoot as IndexHash; +const storyId = 'root-1-child-a2--grandchild-a1-1'; + +export const simpleData = { menu, index, storyId }; +export const loadingData = { menu }; + const meta = { component: Sidebar, title: 'Sidebar/Sidebar', excludeStories: /.*Data$/, parameters: { layout: 'fullscreen' }, + args: { + previewInitialized: true, + menu, + extra: [] as Addon_SidebarTopType[], + index: index, + storyId, + refId: DEFAULT_REF_ID, + refs: {}, + status: {}, + }, decorators: [ (storyFn) => ( ; -const { menu } = standardHeaderData; -const index = mockDataset.withRoot as IndexHash; -const storyId = 'root-1-child-a2--grandchild-a1-1'; - -export const simpleData = { menu, index, storyId }; -export const loadingData = { menu }; - const refs: Record = { optimized: { id: 'optimized', @@ -94,146 +105,56 @@ const refsEmpty = { }, }; -export const Simple: Story = { - args: { previewInitialized: true }, - render: (args) => ( - - ), -}; +export const Simple: Story = {}; export const Loading: Story = { - args: { previewInitialized: false }, - render: (args) => ( - - ), + args: { + previewInitialized: false, + index: undefined, + }, }; export const Empty: Story = { args: { - previewInitialized: true, + index: {}, }, - render: (args) => ( - - ), }; export const IndexError: Story = { args: { - previewInitialized: true, + indexError, }, - render: (args) => ( - - ), }; export const WithRefs: Story = { args: { - previewInitialized: true, + refs, }, - render: (args) => ( - - ), }; export const LoadingWithRefs: Story = { args: { - previewInitialized: false, + ...Loading.args, + refs, }, - render: (args) => ( - - ), }; export const LoadingWithRefError: Story = { args: { - previewInitialized: false, + ...Loading.args, + refs: refsError, }, - render: (args) => ( - - ), }; export const WithRefEmpty: Story = { args: { - previewInitialized: true, + ...Empty.args, + refs: refsEmpty, }, - render: (args) => ( - - ), }; export const StatusesCollapsed: Story = { args: { - previewInitialized: true, status: Object.entries(index).reduce((acc, [id, item]) => { if (item.type !== 'story') { return acc; @@ -251,17 +172,6 @@ export const StatusesCollapsed: Story = { return acc; }, {}), }, - render: (args) => ( - - ), }; export const StatusesOpen: Story = { @@ -286,7 +196,7 @@ export const StatusesOpen: Story = { export const Searching: Story = { ...StatusesOpen, - parameters: { theme: 'light', chromatic: { delay: 2200 } }, + parameters: { chromatic: { delay: 2200 } }, play: async ({ canvasElement, step }) => { await step('wait 2000ms', () => wait(2000)); const canvas = await within(canvasElement); @@ -298,54 +208,40 @@ export const Searching: Story = { export const Bottom: Story = { args: { - previewInitialized: true, + bottom: [ + { + id: '1', + type: types.experimental_SIDEBAR_BOTTOM, + render: () => ( + + ), + }, + { + id: '2', + type: types.experimental_SIDEBAR_BOTTOM, + render: () => ( + + ), + }, + { + id: '3', + type: types.experimental_SIDEBAR_BOTTOM, + render: () => ( + + {' '} + + + ), + }, + ], }, - parameters: { theme: 'light' }, - render: (args) => ( - ( - - ), - }, - { - id: '2', - type: types.experimental_SIDEBAR_BOTTOM, - render: () => ( - - ), - }, - { - id: '3', - type: types.experimental_SIDEBAR_BOTTOM, - render: () => ( - - {' '} - - - ), - }, - ]} - /> - ), }; /** @@ -363,6 +259,9 @@ export const Scrolled: Story = { defaultOrientation: 'landscape', }, }, + args: { + storyId: 'group-1--child-b1', + }, render: (args) => { const [, setState] = React.useState(0); return ( @@ -373,15 +272,7 @@ export const Scrolled: Story = { > Change state - + ); },