From 9d933c703da6dc01d16ef07df53bf933b514b67c Mon Sep 17 00:00:00 2001 From: Guido Wagner Date: Tue, 8 Sep 2026 16:44:46 -0300 Subject: [PATCH 1/4] chore: modernize toolchain and add a test suite Drop the Babel config so Next can use SWC/Turbopack, upgrade to Next 16 and React 19, swap microbundle for tsup with a proper exports map, move to ESLint flat config, and add vitest coverage for the machine, utils and component. Replaces the vendored @reach/portal copy with a portal that renders into a detached node, avoiding an extra render and a placeholder element. --- .babelrc | 8 - .eslintignore | 7 - .eslintrc.js | 9 - .github/workflows/nodejs.yml | 16 +- .github/workflows/publish.yml | 53 +- .husky/pre-commit | 1 + docs/fixtures/Button.tsx | 2 +- docs/fixtures/CloseExample.tsx | 2 +- docs/fixtures/Code.tsx | 2 +- docs/fixtures/Kbd.tsx | 2 +- docs/fixtures/ScrollUp.tsx | 2 +- docs/fixtures/SheetContent.tsx | 2 +- docs/fixtures/SnapMarker.tsx | 2 +- eslint.config.mjs | 53 + next-env.d.ts | 4 +- package-lock.json | 22914 +++++++--------- package.json | 91 +- pages/_app.tsx | 1 - pages/fixtures/aside.tsx | 2 +- pages/fixtures/experiments.tsx | 4 +- pages/fixtures/scrollable.tsx | 4 +- pages/index.tsx | 2 +- src/BottomSheet.tsx | 2 + src/Portal.tsx | 47 + src/hooks/useAriaHider.tsx | 6 +- src/hooks/useSnapPoints.tsx | 11 +- src/index.tsx | 3 +- src/reach-portal/can-use-dom.ts | 7 - src/reach-portal/reach-portal.tsx | 107 - src/reach-portal/readme.md | 5 - src/reach-portal/use-force-update.tsx | 11 - .../use-isomorphic-layout-effect.tsx | 30 - src/utils.ts | 8 +- tailwind.config.js | 4 +- test/bottom-sheet.test.tsx | 109 + test/overlay-machine.test.ts | 129 + test/setup.ts | 82 + test/utils.test.ts | 71 + ...g.declarations.json => tsconfig.build.json | 4 +- tsconfig.json | 7 +- tsconfig.microbundle.json | 8 - tsup.config.ts | 14 + vitest.config.mts | 11 + 43 files changed, 10860 insertions(+), 12999 deletions(-) delete mode 100644 .babelrc delete mode 100644 .eslintignore delete mode 100644 .eslintrc.js create mode 100644 .husky/pre-commit create mode 100644 eslint.config.mjs create mode 100644 src/Portal.tsx delete mode 100644 src/reach-portal/can-use-dom.ts delete mode 100644 src/reach-portal/reach-portal.tsx delete mode 100644 src/reach-portal/readme.md delete mode 100644 src/reach-portal/use-force-update.tsx delete mode 100644 src/reach-portal/use-isomorphic-layout-effect.tsx create mode 100644 test/bottom-sheet.test.tsx create mode 100644 test/overlay-machine.test.ts create mode 100644 test/setup.ts create mode 100644 test/utils.test.ts rename tsconfig.declarations.json => tsconfig.build.json (56%) delete mode 100644 tsconfig.microbundle.json create mode 100644 tsup.config.ts create mode 100644 vitest.config.mts diff --git a/.babelrc b/.babelrc deleted file mode 100644 index 9a771d1d..00000000 --- a/.babelrc +++ /dev/null @@ -1,8 +0,0 @@ -{ - "presets": ["next/babel"], - "env": { - "production": { - "plugins": ["transform-remove-console"] - } - } -} diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index afaabb13..00000000 --- a/.eslintignore +++ /dev/null @@ -1,7 +0,0 @@ -# Ignore nested node_modules -node_modules/ -coverage/ -dist/ -.cache -.next -.vercel diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index d778d3cf..00000000 --- a/.eslintrc.js +++ /dev/null @@ -1,9 +0,0 @@ -const { version: reactVersion } = require('react/package.json') - -module.exports = { - extends: ['react-app'], - settings: { react: { version: reactVersion } }, - rules: { - 'jsx-a11y/anchor-is-valid': ['off'], - }, -} diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 7ace4328..7d6da65e 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -1,13 +1,14 @@ name: CI +# Pushes to main are covered by the release workflow, which runs the same checks on: - push: - branches: - - main pull_request: branches: - '**' +permissions: + contents: read + jobs: test: name: Test on Node.js ${{ matrix.node }} @@ -17,16 +18,17 @@ jobs: strategy: fail-fast: false matrix: - node: [20] + node: [22, 24] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v5 with: node-version: ${{ matrix.node }} + cache: npm - run: npm ci - name: Test - run: npm test \ No newline at end of file + run: npm test diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 41ce7e8b..562aae03 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,43 +1,46 @@ name: Release and Publish on: - pull_request: push: branches: [main] +permissions: + contents: read + jobs: test: runs-on: ubuntu-latest steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Setup Node.js - uses: actions/setup-node@v4 + - uses: actions/checkout@v5 + - uses: actions/setup-node@v5 with: - node-version: 20.x - - name: npm install - run: | - npm install - - name: npm test - run: | - npm test + node-version: 22 + cache: npm + - run: npm ci + - run: npm test + release: - if: github.event_name == 'push' && github.ref == 'refs/heads/main' runs-on: ubuntu-latest needs: [test] + permissions: + contents: write + issues: write + pull-requests: write + # Lets npm attach build provenance to the published package + id-token: write steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Setup Node.js - uses: actions/setup-node@v4 + - uses: actions/checkout@v5 + with: + fetch-depth: 0 + persist-credentials: false + - uses: actions/setup-node@v5 with: - node-version: 20.x - - name: npm install - run: | - npm install - - name: npx semantic-release - run: | - npx semantic-release + node-version: 22 + cache: npm + registry-url: https://registry.npmjs.org + - run: npm ci + - run: npx semantic-release env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} \ No newline at end of file + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + NPM_CONFIG_PROVENANCE: true diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 00000000..2312dc58 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1 @@ +npx lint-staged diff --git a/docs/fixtures/Button.tsx b/docs/fixtures/Button.tsx index 0231adb2..398dd7b0 100644 --- a/docs/fixtures/Button.tsx +++ b/docs/fixtures/Button.tsx @@ -6,7 +6,7 @@ type Props = { className?: Parameters[0] children: React.ReactNode } & Omit< - React.PropsWithoutRef, + React.PropsWithoutRef, 'children' | 'className' > diff --git a/docs/fixtures/CloseExample.tsx b/docs/fixtures/CloseExample.tsx index b2f7766b..2254efb8 100644 --- a/docs/fixtures/CloseExample.tsx +++ b/docs/fixtures/CloseExample.tsx @@ -5,7 +5,7 @@ import Link from 'next/link' type Props = { className?: Parameters[0] } & Omit< - React.PropsWithoutRef, + React.PropsWithoutRef, 'children' | 'className' > diff --git a/docs/fixtures/Code.tsx b/docs/fixtures/Code.tsx index 0083d882..da216110 100644 --- a/docs/fixtures/Code.tsx +++ b/docs/fixtures/Code.tsx @@ -4,7 +4,7 @@ import styles from './Code.module.css' type Props = { children: React.ReactNode -} & Omit, 'children'> +} & Omit, 'children'> const Code = forwardRef(({ className, ...props }, ref) => ( , 'children'> +} & Omit, 'children'> // @TODO style properly diff --git a/docs/fixtures/ScrollUp.tsx b/docs/fixtures/ScrollUp.tsx index bb5bb862..32f18bde 100644 --- a/docs/fixtures/ScrollUp.tsx +++ b/docs/fixtures/ScrollUp.tsx @@ -4,7 +4,7 @@ import styles from './ScrollUp.module.css' const ScrollUp = forwardRef< HTMLButtonElement, - Omit, 'children'> + Omit, 'children'> >(({ className, ...props }, ref) => (