From f77be85ee15020f559c57bd609a8f3925f5e0cc0 Mon Sep 17 00:00:00 2001 From: Cody Olsen Date: Fri, 3 Jan 2025 17:54:20 +0100 Subject: [PATCH] chore: upgrade test studios to react 19, remove next studios --- .eslintignore.react-compiler | 1 - dev/starter-next-studio/.depcheckignore.json | 3 - dev/starter-next-studio/.eslintrc | 3 - dev/starter-next-studio/.gitignore | 4 - dev/starter-next-studio/components/Studio.tsx | 13 - dev/starter-next-studio/next-env.d.ts | 5 - dev/starter-next-studio/next.config.js | 16 - dev/starter-next-studio/package.json | 19 - dev/starter-next-studio/pages/_app.tsx | 8 - dev/starter-next-studio/pages/index.tsx | 17 - .../pages/studio/[[...tool]].tsx | 11 - dev/starter-next-studio/reset.css | 9 - dev/starter-next-studio/sanity.cli.ts | 8 - dev/starter-next-studio/sanity.config.ts | 25 - dev/starter-next-studio/tsconfig.json | 18 - dev/studio-e2e-testing/package.json | 5 +- dev/studio-e2e-testing/sanity.cli.ts | 2 +- dev/test-next-studio/.depcheckignore.json | 13 - dev/test-next-studio/.depcheckrc.json | 3 - dev/test-next-studio/.gitignore | 2 - dev/test-next-studio/app/GlobalStyle.tsx | 107 --- dev/test-next-studio/app/PreloadResources.tsx | 12 - .../app/[[...tool]]/Studio.tsx | 8 - dev/test-next-studio/app/[[...tool]]/page.tsx | 9 - dev/test-next-studio/app/layout.tsx | 17 - dev/test-next-studio/app/registry.tsx | 33 - dev/test-next-studio/next-env.d.ts | 5 - dev/test-next-studio/next.config.mjs | 158 ---- dev/test-next-studio/package.json | 25 - dev/test-next-studio/tsconfig.json | 24 - dev/test-next-studio/turbo.json | 16 - dev/test-studio/package.json | 5 +- dev/test-studio/sanity.cli.ts | 52 +- dev/test-studio/turbo.json | 2 +- package.json | 3 +- .../examples/prj-with-react-19/package.json | 4 +- .../overlay/ConnectorsOverlay.tsx | 39 +- .../src/core/components/scroll/index.ts | 1 - .../components/scroll/scrollContainer.tsx | 29 +- .../core/components/scroll/scrollMonitor.tsx | 16 - .../document-layout/DocumentLayout.tsx | 9 +- .../header/DocumentPanelHeader.tsx | 172 ++-- perf/.depcheckrc.json | 2 +- perf/efps/.depcheckrc.json | 3 +- perf/efps/package.json | 5 +- perf/studio/package.json | 5 +- perf/studio/sanity.cli.ts | 2 +- pnpm-lock.yaml | 849 ++++++++---------- 48 files changed, 535 insertions(+), 1262 deletions(-) delete mode 100644 dev/starter-next-studio/.depcheckignore.json delete mode 100644 dev/starter-next-studio/.eslintrc delete mode 100644 dev/starter-next-studio/.gitignore delete mode 100644 dev/starter-next-studio/components/Studio.tsx delete mode 100644 dev/starter-next-studio/next-env.d.ts delete mode 100644 dev/starter-next-studio/next.config.js delete mode 100644 dev/starter-next-studio/package.json delete mode 100644 dev/starter-next-studio/pages/_app.tsx delete mode 100644 dev/starter-next-studio/pages/index.tsx delete mode 100644 dev/starter-next-studio/pages/studio/[[...tool]].tsx delete mode 100644 dev/starter-next-studio/reset.css delete mode 100644 dev/starter-next-studio/sanity.cli.ts delete mode 100644 dev/starter-next-studio/sanity.config.ts delete mode 100644 dev/starter-next-studio/tsconfig.json delete mode 100644 dev/test-next-studio/.depcheckignore.json delete mode 100644 dev/test-next-studio/.depcheckrc.json delete mode 100644 dev/test-next-studio/.gitignore delete mode 100644 dev/test-next-studio/app/GlobalStyle.tsx delete mode 100644 dev/test-next-studio/app/PreloadResources.tsx delete mode 100644 dev/test-next-studio/app/[[...tool]]/Studio.tsx delete mode 100644 dev/test-next-studio/app/[[...tool]]/page.tsx delete mode 100644 dev/test-next-studio/app/layout.tsx delete mode 100644 dev/test-next-studio/app/registry.tsx delete mode 100644 dev/test-next-studio/next-env.d.ts delete mode 100644 dev/test-next-studio/next.config.mjs delete mode 100644 dev/test-next-studio/package.json delete mode 100644 dev/test-next-studio/tsconfig.json delete mode 100644 dev/test-next-studio/turbo.json delete mode 100644 packages/sanity/src/core/components/scroll/scrollMonitor.tsx diff --git a/.eslintignore.react-compiler b/.eslintignore.react-compiler index 90aa9428070..41f084b2cee 100644 --- a/.eslintignore.react-compiler +++ b/.eslintignore.react-compiler @@ -19,7 +19,6 @@ dev/test-studio/workshop/scopes.js dev/design-studio/* dev/embedded-studio/* dev/starter-cra-studio/* -dev/starter-next-studio/* dev/starter-studio/* dev/strict-studio/* dev/studio-e2e-studio/* diff --git a/dev/starter-next-studio/.depcheckignore.json b/dev/starter-next-studio/.depcheckignore.json deleted file mode 100644 index 33db52f0a1e..00000000000 --- a/dev/starter-next-studio/.depcheckignore.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "ignore": ["styled-components", "react", "react-dom", "sanity", "eslint-config-next"] -} diff --git a/dev/starter-next-studio/.eslintrc b/dev/starter-next-studio/.eslintrc deleted file mode 100644 index b1fe994d14a..00000000000 --- a/dev/starter-next-studio/.eslintrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": ["@sanity/eslint-config-studio"] -} diff --git a/dev/starter-next-studio/.gitignore b/dev/starter-next-studio/.gitignore deleted file mode 100644 index f0f5197150f..00000000000 --- a/dev/starter-next-studio/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -.next - -public/static/*.create-schema.json -public/static/create-manifest.json diff --git a/dev/starter-next-studio/components/Studio.tsx b/dev/starter-next-studio/components/Studio.tsx deleted file mode 100644 index 11aa0e3ce65..00000000000 --- a/dev/starter-next-studio/components/Studio.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import {Studio} from 'sanity' - -import config from '../sanity.config' - -const wrapperStyles = {height: '100vh', width: '100vw'} - -export default function StudioRoot({basePath}: {basePath: string}) { - return ( -
- -
- ) -} diff --git a/dev/starter-next-studio/next-env.d.ts b/dev/starter-next-studio/next-env.d.ts deleted file mode 100644 index 4f11a03dc6c..00000000000 --- a/dev/starter-next-studio/next-env.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -/// -/// - -// NOTE: This file should not be edited -// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/dev/starter-next-studio/next.config.js b/dev/starter-next-studio/next.config.js deleted file mode 100644 index 5b6982f8a8d..00000000000 --- a/dev/starter-next-studio/next.config.js +++ /dev/null @@ -1,16 +0,0 @@ -module.exports = { - env: { - // Matches the behavior of `sanity dev` which sets styled-components to use the fastest way of inserting CSS rules in both dev and production. It's default behavior is to disable it in dev mode. - SC_DISABLE_SPEEDY: 'false', - }, - async redirects() { - return [ - { - // the studio will redirect to /structure after load, we do it here so it's already done before load - source: '/studio', - destination: '/studio/structure', - permanent: false, - }, - ] - }, -} diff --git a/dev/starter-next-studio/package.json b/dev/starter-next-studio/package.json deleted file mode 100644 index 1077e9a4e59..00000000000 --- a/dev/starter-next-studio/package.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "sanity-starter-next-studio", - "version": "3.68.3", - "private": true, - "license": "MIT", - "author": "Sanity.io ", - "scripts": { - "build": "sanity manifest extract --path public/static && next build", - "dev": "next dev", - "start": "next start" - }, - "dependencies": { - "next": "^14.0.0", - "react": "^18.3.1", - "react-dom": "^18.3.1", - "sanity": "workspace:*", - "styled-components": "^6.1.0" - } -} diff --git a/dev/starter-next-studio/pages/_app.tsx b/dev/starter-next-studio/pages/_app.tsx deleted file mode 100644 index 4ab91d94233..00000000000 --- a/dev/starter-next-studio/pages/_app.tsx +++ /dev/null @@ -1,8 +0,0 @@ -// eslint-disable-next-line import/no-unassigned-import -import '../reset.css' - -import {type AppProps} from 'next/app' - -export default function App({Component, pageProps}: AppProps) { - return -} diff --git a/dev/starter-next-studio/pages/index.tsx b/dev/starter-next-studio/pages/index.tsx deleted file mode 100644 index 4d1be08b6cd..00000000000 --- a/dev/starter-next-studio/pages/index.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import Link from 'next/link' - -export default function IndexPage() { - return ( - - - Launch Sanity Studio inside Next.js! - - - ) -} diff --git a/dev/starter-next-studio/pages/studio/[[...tool]].tsx b/dev/starter-next-studio/pages/studio/[[...tool]].tsx deleted file mode 100644 index ffa257e98f3..00000000000 --- a/dev/starter-next-studio/pages/studio/[[...tool]].tsx +++ /dev/null @@ -1,11 +0,0 @@ -import {useRouter} from 'next/router' -import {useState} from 'react' - -import Studio from '../../components/Studio' - -export default function StudioPage() { - const router = useRouter() - const [basePath] = useState(() => router.route.split('/[[...tool]]')?.[0]) - - return -} diff --git a/dev/starter-next-studio/reset.css b/dev/starter-next-studio/reset.css deleted file mode 100644 index 78f6b1158d4..00000000000 --- a/dev/starter-next-studio/reset.css +++ /dev/null @@ -1,9 +0,0 @@ -html, -body, -#__next { - margin: 0; - padding: 0; - height: 100%; - width: 100%; - overscroll-behavior: none; -} diff --git a/dev/starter-next-studio/sanity.cli.ts b/dev/starter-next-studio/sanity.cli.ts deleted file mode 100644 index fac247bf8cf..00000000000 --- a/dev/starter-next-studio/sanity.cli.ts +++ /dev/null @@ -1,8 +0,0 @@ -import {defineCliConfig} from 'sanity/cli' - -export default defineCliConfig({ - api: { - projectId: 'ppsg7ml5', - dataset: 'test', - }, -}) diff --git a/dev/starter-next-studio/sanity.config.ts b/dev/starter-next-studio/sanity.config.ts deleted file mode 100644 index 102cbb15f94..00000000000 --- a/dev/starter-next-studio/sanity.config.ts +++ /dev/null @@ -1,25 +0,0 @@ -import {defineConfig} from 'sanity' -import {structureTool} from 'sanity/structure' - -export default defineConfig({ - plugins: [structureTool()], - title: 'Next.js Starter', - projectId: 'ppsg7ml5', - dataset: 'test', - schema: { - types: [ - { - type: 'document', - name: 'post', - title: 'Post', - fields: [ - { - type: 'string', - name: 'title', - title: 'Title', - }, - ], - }, - ], - }, -}) diff --git a/dev/starter-next-studio/tsconfig.json b/dev/starter-next-studio/tsconfig.json deleted file mode 100644 index 6a0ffdc7f4c..00000000000 --- a/dev/starter-next-studio/tsconfig.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2017", - "lib": ["dom", "dom.iterable", "esnext"], - "allowJs": true, - "skipLibCheck": true, - "strict": false, - "forceConsistentCasingInFileNames": true, - "noEmit": true, - "incremental": true, - "module": "Preserve", - "moduleDetection": "force", - "isolatedModules": true, - "jsx": "preserve" - }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], - "exclude": ["node_modules"] -} diff --git a/dev/studio-e2e-testing/package.json b/dev/studio-e2e-testing/package.json index 7837ac0ea1a..f69653e0f03 100644 --- a/dev/studio-e2e-testing/package.json +++ b/dev/studio-e2e-testing/package.json @@ -21,9 +21,8 @@ "@sanity/ui": "^2.11.0", "@sanity/vision": "3.68.3", "babel-plugin-react-compiler": "19.0.0-beta-63e3235-20250105", - "react": "^18.3.1", - "react-compiler-runtime": "19.0.0-beta-55955c9-20241229", - "react-dom": "^18.3.1", + "react": "^19.0.0", + "react-dom": "^19.0.0", "sanity": "workspace:*", "sanity-plugin-markdown": "^5.0.0", "sanity-plugin-media": "^2.3.1", diff --git a/dev/studio-e2e-testing/sanity.cli.ts b/dev/studio-e2e-testing/sanity.cli.ts index 95205d33185..f832bcab27e 100644 --- a/dev/studio-e2e-testing/sanity.cli.ts +++ b/dev/studio-e2e-testing/sanity.cli.ts @@ -9,7 +9,7 @@ export default defineCliConfig({ projectId: process.env.SANITY_E2E_PROJECT_ID, dataset: process.env.SANITY_E2E_DATASET, }, - reactCompiler: {target: '18'}, + reactCompiler: {target: '19'}, vite: { define: { 'process.env.SANITY_E2E_PROJECT_ID': JSON.stringify(process.env.SANITY_E2E_PROJECT_ID), diff --git a/dev/test-next-studio/.depcheckignore.json b/dev/test-next-studio/.depcheckignore.json deleted file mode 100644 index b417fad3e91..00000000000 --- a/dev/test-next-studio/.depcheckignore.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "//": "https://github.com/depcheck/depcheck/pull/756", - "ignore": [ - "styled-components", - "react", - "react-dom", - "react-is", - "sanity", - "eslint-config-next", - "sanity-test-studio", - "sanity" - ] -} diff --git a/dev/test-next-studio/.depcheckrc.json b/dev/test-next-studio/.depcheckrc.json deleted file mode 100644 index 6834a373eee..00000000000 --- a/dev/test-next-studio/.depcheckrc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "ignores": ["@sanity/vision", "typescript", "react-is"] -} diff --git a/dev/test-next-studio/.gitignore b/dev/test-next-studio/.gitignore deleted file mode 100644 index 55cf473c032..00000000000 --- a/dev/test-next-studio/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -.next -.vscode diff --git a/dev/test-next-studio/app/GlobalStyle.tsx b/dev/test-next-studio/app/GlobalStyle.tsx deleted file mode 100644 index f8fea653b33..00000000000 --- a/dev/test-next-studio/app/GlobalStyle.tsx +++ /dev/null @@ -1,107 +0,0 @@ -'use client' - -import {createGlobalStyle} from 'styled-components' - -export const GlobalStyle = createGlobalStyle` - @font-face { - font-family: Inter; - font-style: normal; - font-weight: 400; - font-display: swap; - src: url("https://studio-static.sanity.io/Inter-Regular.woff2") format("woff2"); - } - @font-face { - font-family: Inter; - font-style: italic; - font-weight: 400; - font-display: swap; - src: url("https://studio-static.sanity.io/Inter-Italic.woff2") format("woff2"); - } - @font-face { - font-family: Inter; - font-style: normal; - font-weight: 500; - font-display: swap; - src: url("https://studio-static.sanity.io/Inter-Medium.woff2") format("woff2"); - } - @font-face { - font-family: Inter; - font-style: italic; - font-weight: 500; - font-display: swap; - src: url("https://studio-static.sanity.io/Inter-MediumItalic.woff2") format("woff2"); - } - @font-face { - font-family: Inter; - font-style: normal; - font-weight: 600; - font-display: swap; - src: url("https://studio-static.sanity.io/Inter-SemiBold.woff2") format("woff2"); - } - @font-face { - font-family: Inter; - font-style: italic; - font-weight: 600; - font-display: swap; - src: url("https://studio-static.sanity.io/Inter-SemiBoldItalic.woff2") format("woff2"); - } - @font-face { - font-family: Inter; - font-style: normal; - font-weight: 700; - font-display: swap; - src: url("https://studio-static.sanity.io/Inter-Bold.woff2") format("woff2"); - } - @font-face { - font-family: Inter; - font-style: italic; - font-weight: 700; - font-display: swap; - src: url("https://studio-static.sanity.io/Inter-BoldItalic.woff2") format("woff2"); - } - @font-face { - font-family: Inter; - font-style: normal; - font-weight: 800; - font-display: swap; - src: url("https://studio-static.sanity.io/Inter-ExtraBold.woff2") format("woff2"); - } - @font-face { - font-family: Inter; - font-style: italic; - font-weight: 800; - font-display: swap; - src: url("https://studio-static.sanity.io/Inter-ExtraBoldItalic.woff2") format("woff2"); - } - @font-face { - font-family: Inter; - font-style: normal; - font-weight: 900; - font-display: swap; - src: url("https://studio-static.sanity.io/Inter-Black.woff2") format("woff2"); - } - @font-face { - font-family: Inter; - font-style: italic; - font-weight: 900; - font-display: swap; - src: url("https://studio-static.sanity.io/Inter-BlackItalic.woff2") format("woff2"); - } - html { - background-color: #f6f6f8; - } - html, - body, - #sanity { - height: 100%; - } - body { - margin: 0; - -webkit-font-smoothing: antialiased; - } - @media (prefers-color-scheme: dark) { - html { - background-color: #0d0e12; - } - } -` diff --git a/dev/test-next-studio/app/PreloadResources.tsx b/dev/test-next-studio/app/PreloadResources.tsx deleted file mode 100644 index 092d5a27768..00000000000 --- a/dev/test-next-studio/app/PreloadResources.tsx +++ /dev/null @@ -1,12 +0,0 @@ -'use client' - -import ReactDOM from 'react-dom' - -export function PreloadResources() { - ReactDOM.preconnect('https://studio-static.sanity.io', { - crossOrigin: 'anonymous', - }) - ReactDOM.prefetchDNS('https://studio-static.sanity.io') - - return null -} diff --git a/dev/test-next-studio/app/[[...tool]]/Studio.tsx b/dev/test-next-studio/app/[[...tool]]/Studio.tsx deleted file mode 100644 index d3a57d937f8..00000000000 --- a/dev/test-next-studio/app/[[...tool]]/Studio.tsx +++ /dev/null @@ -1,8 +0,0 @@ -'use client' - -import {Studio} from 'sanity' -import config from 'sanity-test-studio/sanity.config' - -export default function StudioPage() { - return -} diff --git a/dev/test-next-studio/app/[[...tool]]/page.tsx b/dev/test-next-studio/app/[[...tool]]/page.tsx deleted file mode 100644 index 77e06302fb8..00000000000 --- a/dev/test-next-studio/app/[[...tool]]/page.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import Studio from './Studio' - -export default function Page() { - return ( -
- -
- ) -} diff --git a/dev/test-next-studio/app/layout.tsx b/dev/test-next-studio/app/layout.tsx deleted file mode 100644 index 579679840d2..00000000000 --- a/dev/test-next-studio/app/layout.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import {GlobalStyle} from './GlobalStyle' -import {PreloadResources} from './PreloadResources' -import {StyledComponentsRegistry} from './registry' - -export default function RootLayout({children}: {children: React.ReactNode}) { - return ( - - - - - - {children} - - - - ) -} diff --git a/dev/test-next-studio/app/registry.tsx b/dev/test-next-studio/app/registry.tsx deleted file mode 100644 index 0306d343e96..00000000000 --- a/dev/test-next-studio/app/registry.tsx +++ /dev/null @@ -1,33 +0,0 @@ -// https://beta.nextjs.org/docs/styling/css-in-js#styled-components - -'use client' - -import {useServerInsertedHTML} from 'next/navigation' -import {useState, useSyncExternalStore} from 'react' -import {ServerStyleSheet, StyleSheetManager} from 'styled-components' - -export function StyledComponentsRegistry({children}: {children: React.ReactNode}): JSX.Element { - const isMounted = useSyncExternalStore( - emptySubscribe, - () => true, - () => false, - ) - // Only create stylesheet once with lazy initial state - // x-ref: https://reactjs.org/docs/hooks-reference.html#lazy-initial-state - const [styledComponentsStyleSheet] = useState(() => new ServerStyleSheet()) - - useServerInsertedHTML(() => { - const styles = styledComponentsStyleSheet.getStyleElement() - styledComponentsStyleSheet.instance.clearTag() - return <>{styles} - }) - - if (isMounted) return <>{children} - - return ( - {children} - ) -} - -// eslint-disable-next-line no-empty-function -const emptySubscribe = () => () => {} diff --git a/dev/test-next-studio/next-env.d.ts b/dev/test-next-studio/next-env.d.ts deleted file mode 100644 index 40c3d68096c..00000000000 --- a/dev/test-next-studio/next-env.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -/// -/// - -// NOTE: This file should not be edited -// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information. diff --git a/dev/test-next-studio/next.config.mjs b/dev/test-next-studio/next.config.mjs deleted file mode 100644 index 116440f3a8f..00000000000 --- a/dev/test-next-studio/next.config.mjs +++ /dev/null @@ -1,158 +0,0 @@ -function requireResolve(id) { - return import.meta.resolve(id).replace('file://', '') -} - -const reactProductionProfiling = process.env.REACT_PRODUCTION_PROFILING === 'true' - -// eslint-disable-next-line tsdoc/syntax -/** @type {import('next').NextConfig} */ -const config = { - compiler: { - styledComponents: true, - }, - typescript: { - ignoreBuildErrors: true, - }, - eslint: { - ignoreDuringBuilds: true, - }, - env: { - // Support the ability to debug log the studio, for example `DEBUG="sanity:pte:* pnpm dev:next-studio"` - DEBUG: process.env.DEBUG, - // Matches the behavior of `sanity dev` which sets styled-components to use the fastest way of inserting CSS rules in both dev and production. It's default behavior is to disable it in dev mode. - SC_DISABLE_SPEEDY: 'false', - }, - transpilePackages: [ - '@sanity/block-tools', - '@sanity/cli', - '@sanity/diff', - '@sanity/migrate', - '@sanity/mutator', - '@sanity/schema', - '@sanity/types', - '@sanity/util', - '@sanity/vision', - 'sanity-test-studio', - 'sanity', - ], - // eslint-disable-next-line @typescript-eslint/no-shadow - webpack(config) { - config.resolve.alias = { - ...config.resolve.alias, - '@sanity/block-tools': requireResolve('../../packages/@sanity/block-tools/src/index.ts'), - '@sanity/diff': requireResolve('../../packages/@sanity/diff/src/index.ts'), - '@sanity/cli': requireResolve('../../packages/@sanity/cli/src/index.ts'), - '@sanity/mutator': requireResolve('../../packages/@sanity/mutator/src/index.ts'), - '@sanity/schema/_internal': requireResolve( - '../../packages/@sanity/schema/src/_exports/_internal.ts', - ), - '@sanity/schema': requireResolve('../../packages/@sanity/schema/src/_exports/index.ts'), - '@sanity/migrate': requireResolve('../../packages/@sanity/migrate/src/_exports/index.ts'), - '@sanity/types': requireResolve('../../packages/@sanity/types/src/index.ts'), - '@sanity/util/fs': requireResolve('../../packages/@sanity/util/src/_exports/fs.ts'), - '@sanity/util/client': requireResolve('../../packages/@sanity/util/src/_exports/client.ts'), - '@sanity/util/concurrency-limiter': requireResolve( - '../../packages/@sanity/util/src/_exports/concurrency-limiter.ts', - ), - '@sanity/util/content': requireResolve('../../packages/@sanity/util/src/_exports/content.ts'), - '@sanity/util/createSafeJsonParser': requireResolve( - '../../packages/@sanity/util/src/_exports/createSafeJsonParser.ts', - ), - '@sanity/util/legacyDateFormat': requireResolve( - '../../packages/@sanity/util/src/_exports/legacyDateFormat.ts', - ), - '@sanity/util/paths': requireResolve('../../packages/@sanity/util/src/_exports/paths.ts'), - '@sanity/util': requireResolve('../../packages/@sanity/util/src/_exports/index.ts'), - '@sanity/vision': requireResolve('../../packages/@sanity/vision/src/index.ts'), - 'sanity/_internal': requireResolve('../../packages/sanity/src/_exports/_internal.ts'), - 'sanity/_singletons': requireResolve('../../packages/sanity/src/_exports/_singletons.ts'), - 'sanity/_createContext': requireResolve( - '../../packages/sanity/src/_exports/_createContext.ts', - ), - 'sanity/cli': requireResolve('../../packages/sanity/src/_exports/cli.ts'), - 'sanity/desk': requireResolve('../../packages/sanity/src/_exports/desk.ts'), - 'sanity/presentation': requireResolve('../../packages/sanity/src/_exports/presentation.ts'), - 'sanity/router': requireResolve('../../packages/sanity/src/_exports/router.ts'), - 'sanity/structure': requireResolve('../../packages/sanity/src/_exports/structure.ts'), - 'sanity/migrate': requireResolve('../../packages/sanity/src/_exports/migrate.ts'), - 'sanity': requireResolve('../../packages/sanity/src/_exports/index.ts'), - 'styled-components': requireResolve( - 'styled-components/dist/styled-components.browser.esm.js', - ), - } - return config - }, - // Makes it much easier to see which component got memoized by the react compiler - // when testing on https://test-next-studio.sanity.build - productionBrowserSourceMaps: reactProductionProfiling, - reactProductionProfiling, - experimental: { - reactCompiler: true, - turbo: { - resolveAlias: { - '@sanity/block-tools': '@sanity/block-tools/src/index.ts', - '@sanity/diff': '@sanity/diff/src/index.ts', - '@sanity/cli': '@sanity/cli/src/index.ts', - '@sanity/mutator': '@sanity/mutator/src/index.ts', - '@sanity/schema/_internal': '@sanity/schema/src/_exports/_internal.ts', - '@sanity/schema': '@sanity/schema/src/_exports/index.ts', - '@sanity/migrate': '@sanity/migrate/src/_exports/index.ts', - '@sanity/types': '@sanity/types/src/index.ts', - '@sanity/util/fs': '@sanity/util/src/_exports/fs.ts', - '@sanity/util/client': '@sanity/util/src/_exports/client.ts', - '@sanity/util/concurrency-limiter': '@sanity/util/src/_exports/concurrency-limiter.ts', - '@sanity/util/content': '@sanity/util/src/_exports/content.ts', - '@sanity/util/createSafeJsonParser': '@sanity/util/src/_exports/createSafeJsonParser.ts', - '@sanity/util/legacyDateFormat': '@sanity/util/src/_exports/legacyDateFormat.ts', - '@sanity/util/paths': '@sanity/util/src/_exports/paths.ts', - '@sanity/util': '@sanity/util/src/_exports/index.ts', - '@sanity/vision': '@sanity/vision/src/index.ts', - 'sanity/_internal': 'sanity/src/_exports/_internal.ts', - 'sanity/_singletons': 'sanity/src/_exports/_singletons.ts', - 'sanity/_createContext': 'sanity/src/_exports/_createContext.ts', - 'sanity/cli': 'sanity/src/_exports/cli.ts', - 'sanity/desk': 'sanity/src/_exports/desk.ts', - 'sanity/presentation': 'sanity/src/_exports/presentation.ts', - 'sanity/router': 'sanity/src/_exports/router.ts', - 'sanity/structure': 'sanity/src/_exports/structure.ts', - 'sanity/migrate': 'sanity/src/_exports/migrate.ts', - 'sanity': 'sanity/src/_exports/index.ts', - 'styled-components': {browser: 'styled-components/dist/styled-components.browser.esm.js'}, - }, - }, - }, - async headers() { - return [ - { - // @TODO fix Presentation to never load itself recursively in an iframe - source: '/(.*)?', // Matches all routes by default - headers: [ - { - key: 'X-Frame-Options', - value: 'DENY', - }, - ], - }, - // These routes aren't working yet anyway - // { - // source: '/workshop/frame/(.*)?', // Allow `@sanity/ui-workshop` iframe - // headers: [ - // { - // key: 'X-Frame-Options', - // value: 'SAMEORIGIN', - // }, - // ], - // }, - // { - // source: '/preview/(.*)?', // Allow Presentation test iframe - // headers: [ - // { - // key: 'X-Frame-Options', - // value: 'SAMEORIGIN', - // }, - // ], - // }, - ] - }, -} -export default config diff --git a/dev/test-next-studio/package.json b/dev/test-next-studio/package.json deleted file mode 100644 index b1c4fc29934..00000000000 --- a/dev/test-next-studio/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "sanity-test-next-studio", - "version": "3.68.3", - "private": true, - "license": "MIT", - "author": "Sanity.io ", - "scripts": { - "build": "next build", - "dev": "next dev -p 3333", - "lint": "eslint --cache .", - "start": "next start" - }, - "dependencies": { - "@sanity/vision": "workspace:*", - "babel-plugin-react-compiler": "19.0.0-beta-63e3235-20250105", - "next": "15.1.3", - "react": "rc", - "react-dom": "rc", - "react-is": "rc", - "sanity": "workspace:*", - "sanity-test-studio": "workspace:*", - "styled-components": "^6.1.12", - "typescript": "5.7.2" - } -} diff --git a/dev/test-next-studio/tsconfig.json b/dev/test-next-studio/tsconfig.json deleted file mode 100644 index bceb3bc11ee..00000000000 --- a/dev/test-next-studio/tsconfig.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "compilerOptions": { - "target": "esnext", - "lib": ["dom", "dom.iterable", "esnext"], - "allowJs": true, - "skipLibCheck": true, - "strict": false, - "forceConsistentCasingInFileNames": true, - "noEmit": true, - "incremental": true, - "module": "Preserve", - "moduleDetection": "force", - "isolatedModules": true, - "jsx": "preserve", - "plugins": [ - { - "name": "next" - } - ], - "strictNullChecks": true - }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], - "exclude": ["node_modules"] -} diff --git a/dev/test-next-studio/turbo.json b/dev/test-next-studio/turbo.json deleted file mode 100644 index 96c64879f03..00000000000 --- a/dev/test-next-studio/turbo.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "extends": ["//"], - "tasks": { - "build": { - "env": ["REACT_PRODUCTION_PROFILING", "REACT_MILLION_LINT"], - "outputs": [".next/**", "!.next/cache/**", "out/**"], - "dependsOn": ["^build"] - }, - "dev": { - "dependsOn": ["^build"], - "cache": false, - "persistent": true - } - } -} diff --git a/dev/test-studio/package.json b/dev/test-studio/package.json index e9da18621d7..a6d432ec3dc 100644 --- a/dev/test-studio/package.json +++ b/dev/test-studio/package.json @@ -51,9 +51,8 @@ "history": "^5.3.0", "lodash": "^4.17.21", "qs": "^6.10.2", - "react": "^18.3.1", - "react-compiler-runtime": "19.0.0-beta-55955c9-20241229", - "react-dom": "^18.3.1", + "react": "^19.0.0", + "react-dom": "^19.0.0", "react-refractor": "^2.1.6", "refractor": "^3.6.0", "rxjs": "^7.8.0", diff --git a/dev/test-studio/sanity.cli.ts b/dev/test-studio/sanity.cli.ts index 5e8b1869b32..149923f5d36 100644 --- a/dev/test-studio/sanity.cli.ts +++ b/dev/test-studio/sanity.cli.ts @@ -4,9 +4,10 @@ import {defineCliConfig} from 'sanity/cli' import {type UserConfig} from 'vite' const millionLintEnabled = process.env.REACT_MILLION_LINT === 'true' +const millionLintEverything = process.env.REACT_MILLION_LINT_EVERYTHING === 'true' const millionInclude: string[] = [] try { - if (millionLintEnabled) { + if (millionLintEnabled && !millionLintEverything) { for (const filePath of require('./.react-compiler-bailout-report.json')) { millionInclude.push(`**/${filePath}`) } @@ -27,23 +28,24 @@ export default defineCliConfig({ // A) `SANITY_STUDIO_REACT_STRICT_MODE=false pnpm dev` // B) creating a `.env` file locally that sets the same env variable as above reactStrictMode: true, - reactCompiler: millionLintEnabled - ? { - target: '18', - sources: (filename) => { - /** - * This is the default filter when `sources` is not defined. - * Since we're overriding it we have to ensure we don't accidentally try running the compiler on non-src files from npm. - */ - if (filename.includes('node_modules')) { - return false - } - return millionInclude.every( - (pattern) => !filename.endsWith(`/${pattern.split('**/')[1]}`), - ) - }, - } - : {target: '18'}, + reactCompiler: + millionLintEnabled && !millionLintEverything + ? { + target: '19', + sources: (filename) => { + /** + * This is the default filter when `sources` is not defined. + * Since we're overriding it we have to ensure we don't accidentally try running the compiler on non-src files from npm. + */ + if (filename.includes('node_modules')) { + return false + } + return millionInclude.every( + (pattern) => !filename.endsWith(`/${pattern.split('**/')[1]}`), + ) + }, + } + : {target: '19'}, vite(viteConfig: UserConfig): UserConfig { const reactProductionProfiling = process.env.REACT_PRODUCTION_PROFILING === 'true' @@ -55,11 +57,15 @@ export default defineCliConfig({ * We're doing a dynamic import here, instead of a static import, to avoid an issue where a WebSocket Server is created by Million for `vite dev` that isn't closed. * Which leaves `sanity build` hanging, even if the plugin itself isn't actually used. */ - require('@million/lint').vite({ - filter: { - include: millionInclude, - }, - }), + require('@million/lint').vite( + millionLintEverything + ? {} + : { + filter: { + include: millionInclude, + }, + }, + ), ...(viteConfig.plugins || []), ] : viteConfig.plugins, diff --git a/dev/test-studio/turbo.json b/dev/test-studio/turbo.json index fe29e2ba46b..dbf36f48d69 100644 --- a/dev/test-studio/turbo.json +++ b/dev/test-studio/turbo.json @@ -3,7 +3,7 @@ "extends": ["//"], "tasks": { "build": { - "env": ["REACT_PRODUCTION_PROFILING", "REACT_MILLION_LINT"], + "env": ["REACT_PRODUCTION_PROFILING", "REACT_MILLION_LINT", "REACT_MILLION_LINT_EVERYTHING"], "outputs": [".sanity/**", "dist/**", "workshop/scopes.js"] }, "start": { diff --git a/package.json b/package.json index f0fafb9814f..43af2ac2a9f 100644 --- a/package.json +++ b/package.json @@ -43,9 +43,8 @@ "dev:test-create-studio": "pnpm --filter test-create-integration-studio dev", "dev:test-studio-production-profiling": "REACT_PRODUCTION_PROFILING=true turbo run start --filter=sanity-test-studio", "dev:million-lint": "pnpm report:react-compiler-bailout && pnpm dev:test-studio-million-lint", + "dev:million-lint-everything": "REACT_MILLION_LINT=true REACT_MILLION_LINT_EVERYTHING=true pnpm --filter sanity-test-studio dev", "dev:test-studio-million-lint": "REACT_MILLION_LINT=true pnpm --filter sanity-test-studio dev", - "dev:next-studio": "pnpm --filter sanity-test-next-studio dev", - "dev:turbo-studio": "pnpm dev:next-studio --turbo", "docs:report": "node -r dotenv-flow/config -r esbuild-register scripts/doc-report/docReport", "docs:report:cleanup": "node -r dotenv-flow/config -r esbuild-register scripts/doc-report/docReportCleanup", "docs:report:create": "node -r dotenv-flow/config -r esbuild-register scripts/doc-report/docReportCreate", diff --git a/packages/sanity/fixtures/examples/prj-with-react-19/package.json b/packages/sanity/fixtures/examples/prj-with-react-19/package.json index 3e7a9bb7cd3..2c5ea924233 100644 --- a/packages/sanity/fixtures/examples/prj-with-react-19/package.json +++ b/packages/sanity/fixtures/examples/prj-with-react-19/package.json @@ -2,8 +2,8 @@ "name": "prj-with-react-19", "private": true, "dependencies": { - "react": "19.0.0-rc-f994737d14-20240522", - "react-dom": "19.0.0-rc-f994737d14-20240522", + "react": "^19.0.0", + "react-dom": "^19.0.0", "styled-components": "^6.1.0" } } diff --git a/packages/sanity/src/core/changeIndicators/overlay/ConnectorsOverlay.tsx b/packages/sanity/src/core/changeIndicators/overlay/ConnectorsOverlay.tsx index 9343598c34d..1fc11f5257b 100644 --- a/packages/sanity/src/core/changeIndicators/overlay/ConnectorsOverlay.tsx +++ b/packages/sanity/src/core/changeIndicators/overlay/ConnectorsOverlay.tsx @@ -3,7 +3,7 @@ import {sortBy} from 'lodash' import {useCallback, useMemo, useState} from 'react' import {type Reported} from '../../components/react-track-elements' -import {ScrollMonitor} from '../../components/scroll' +import {useOnScroll} from '../../components/scroll' import {DEBUG_LAYER_BOUNDS} from '../constants' import {findMostSpecificTarget} from '../helpers/findMostSpecificTarget' import {getOffsetsTo} from '../helpers/getOffsetsTo' @@ -121,27 +121,26 @@ export function ConnectorsOverlay(props: ConnectorsOverlayProps) { }, [byId, allReportedValues, hovered, rootElement]) useResizeObserver(rootElement, handleScrollOrResize) + useOnScroll(handleScrollOrResize) return ( - - - {visibleConnectors.map(({field, change}) => { - if (!change) { - return null - } - - return ( - - ) - })} - - + + {visibleConnectors.map(({field, change}) => { + if (!change) { + return null + } + + return ( + + ) + })} + ) } diff --git a/packages/sanity/src/core/components/scroll/index.ts b/packages/sanity/src/core/components/scroll/index.ts index e64e5cb3d46..fe7bd0d64c9 100644 --- a/packages/sanity/src/core/components/scroll/index.ts +++ b/packages/sanity/src/core/components/scroll/index.ts @@ -1,4 +1,3 @@ export * from './hooks' export * from './scrollContainer' -export * from './scrollMonitor' export * from './types' diff --git a/packages/sanity/src/core/components/scroll/scrollContainer.tsx b/packages/sanity/src/core/components/scroll/scrollContainer.tsx index f8a39fdb2e3..569aadd674c 100644 --- a/packages/sanity/src/core/components/scroll/scrollContainer.tsx +++ b/packages/sanity/src/core/components/scroll/scrollContainer.tsx @@ -4,6 +4,7 @@ import { type ForwardedRef, forwardRef, type HTMLProps, + memo, useContext, useEffect, useImperativeHandle, @@ -19,19 +20,9 @@ export interface ScrollContainerProps onScroll?: (event: Event) => () => void } -/** - * This provides a utility function for use within Sanity Studios to create scrollable containers - * It also provides a way for components inside a scrollable container to track onScroll on their first parent scroll container - * NOTE: this is used by different studio utilities to track positions of elements on screen - * NOTE: It will call any given `onScroll` callback with a Native DOM Event, and not a React Synthetic event - * NOTE: It will not make sure the element is actually scrollable, this still needs to be done with css as usual - * - * @internal - */ -export const ScrollContainer = forwardRef(function ScrollContainer( - props: ScrollContainerProps, - forwardedRef: ForwardedRef, -) { +const ScrollContainerComponent = forwardRef(function ScrollContainerComponent< + T extends ElementType = 'div', +>(props: ScrollContainerProps, forwardedRef: ForwardedRef) { const {as: As = 'div', onScroll, ...rest} = props const ref = useRef(null) @@ -79,3 +70,15 @@ export const ScrollContainer = forwardRef(function ScrollContainer ) }) + +/** + * This provides a utility function for use within Sanity Studios to create scrollable containers + * It also provides a way for components inside a scrollable container to track onScroll on their first parent scroll container + * NOTE: this is used by different studio utilities to track positions of elements on screen + * NOTE: It will call any given `onScroll` callback with a Native DOM Event, and not a React Synthetic event + * NOTE: It will not make sure the element is actually scrollable, this still needs to be done with css as usual + * + * @internal + */ +export const ScrollContainer = memo(ScrollContainerComponent) +ScrollContainer.displayName = 'Memo(Forwardref(ScrollContainer))' diff --git a/packages/sanity/src/core/components/scroll/scrollMonitor.tsx b/packages/sanity/src/core/components/scroll/scrollMonitor.tsx deleted file mode 100644 index 674de4029af..00000000000 --- a/packages/sanity/src/core/components/scroll/scrollMonitor.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import {type ReactNode} from 'react' - -import {useOnScroll} from './hooks' -import {type ScrollEventHandler} from './types' - -/** @internal */ -export interface ScrollMonitorProps { - onScroll: ScrollEventHandler - children?: ReactNode -} - -/** @internal */ -export function ScrollMonitor({onScroll, children}: ScrollMonitorProps) { - useOnScroll(onScroll) - return <>{children} -} diff --git a/packages/sanity/src/structure/panes/document/document-layout/DocumentLayout.tsx b/packages/sanity/src/structure/panes/document/document-layout/DocumentLayout.tsx index 54654bbf08a..646a3fe3a83 100644 --- a/packages/sanity/src/structure/panes/document/document-layout/DocumentLayout.tsx +++ b/packages/sanity/src/structure/panes/document/document-layout/DocumentLayout.tsx @@ -169,6 +169,11 @@ export function DocumentLayout() { [onPathOpen, onFocus], ) + const portalElements = useMemo( + () => ({[DOCUMENT_PANEL_PORTAL_ELEMENT]: documentPanelPortalElement}), + [documentPanelPortalElement], + ) + if (!schemaType) { return ( + {StartInCreateBanner && ( diff --git a/packages/sanity/src/structure/panes/document/documentPanel/header/DocumentPanelHeader.tsx b/packages/sanity/src/structure/panes/document/documentPanel/header/DocumentPanelHeader.tsx index 3c8da4d8a9d..6305b43538e 100644 --- a/packages/sanity/src/structure/panes/document/documentPanel/header/DocumentPanelHeader.tsx +++ b/packages/sanity/src/structure/panes/document/documentPanel/header/DocumentPanelHeader.tsx @@ -121,87 +121,111 @@ export const DocumentPanelHeader = memo( [contextMenuNodes, referenceElement], ) + const title = useMemo(() => , []) + const tabs = useMemo(() => showTabs && , [showTabs]) + const backButton = useMemo( + () => + showBackButton && ( +