@samitouri / QOS-React / commits / 6eda534718

[playground] bug fixes & UX improvements (#34499)

<!-- Thanks for submitting a pull request! We appreciate you spending the time to work on these changes. Please provide enough information so that others can review your pull request. The three fields below are mandatory. Before submitting a pull request, please make sure the following is done: 1. Fork [the repository](https://github.com/facebook/react) and create your branch from `main`. 2. Run `yarn` in the repository root. 3. If you've fixed a bug or added code that should be tested, add tests! 4. Ensure the test suite passes (`yarn test`). Tip: `yarn test --watch TestName` is helpful in development. 5. Run `yarn test --prod` to test in the production environment. It supports the same options as `yarn test`. 6. If you need a debugger, run `yarn test --debug --watch TestName`, open `chrome://inspect`, and press "Inspect". 7. Format your code with [prettier](https://github.com/prettier/prettier) (`yarn prettier`). 8. Make sure your code lints (`yarn lint`). Tip: `yarn linc` to only check changed files. 9. Run the [Flow](https://flowtype.org/) type checks (`yarn flow`). 10. If you haven't already, complete the CLA. Learn more about contributing: https://reactjs.org/docs/how-to-contribute.html --> ## Summary Made many small changes to the compiler playground to improve user experience. Removed any "Loading" indicators that would flash in before a component would finish loading in. Additionally, before users would see the "Show Internals" button toggling from false to true if they had set it at true previously. I was able to refactor the URL/local storage loading so that the `Store` would be fully initialized before the components would load in. Attempted to integrate `<Activity>` into showing/hiding these different editors, but the current state of [monaco editors](https://github.com/suren-atoyan/monaco-react) does not allow for this. I created an issue for them to address: https://github.com/suren-atoyan/monaco-react/issues/753 Added a debounce to the config editor so every key type wouldn't cause the output panel to respond instantly. Users can type for 500 ms before an error is thrown at them. <!-- Explain the **motivation** for making this change. What existing problem does the pull request solve? --> ## How did you test this change? Here is what loading the page would look like before (not sure why its so blurry): https://github.com/user-attachments/assets/58f4281a-cc02-4141-b9b5-f70d6ace12a2 Here is how it looks now: https://github.com/user-attachments/assets/40535165-fc7c-44fb-9282-9c7fa76e7d53 Here is the debouncing: https://github.com/user-attachments/assets/e4ab29e4-1afd-4249-beca-671fb6542f5e <!-- Demonstrate the code is solid. Example: The exact commands you ran and their output, screenshots / videos if the pull request changes the user interface. How exactly did you verify that your PR solves the issue you wanted to solve? If you leave this empty, your PR will very likely be closed. -->

Eugene Choi committed Sep 18, 2025 at 15:44 UTC 6eda534718d09a26d58d65c0a376e05d7e2a3358
15 files changed +149 -230
compiler/apps/playground/__tests__/e2e/page.spec.ts
+3 -3
@@ -136,7 +136,7 @@ test('editor should compile from hash successfully', async ({page}) => {
136 path: 'test-results/01-compiles-from-hash.png',
137 });
138 const text =
139 - (await page.locator('.monaco-editor').nth(1).allInnerTexts()) ?? [];
139 + (await page.locator('.monaco-editor').nth(3).allInnerTexts()) ?? [];
140 const output = await formatPrint(text);
141
142 expect(output).not.toEqual('');
@@ -162,7 +162,7 @@ test('reset button works', async ({page}) => {
162 path: 'test-results/02-reset-button-works.png',
163 });
164 const text =
165 - (await page.locator('.monaco-editor').nth(1).allInnerTexts()) ?? [];
165 + (await page.locator('.monaco-editor').nth(3).allInnerTexts()) ?? [];
166 const output = await formatPrint(text);
167
168 expect(output).not.toEqual('');
@@ -183,7 +183,7 @@ TEST_CASE_INPUTS.forEach((t, idx) =>
183 });
184
185 const text =
186 - (await page.locator('.monaco-editor').nth(1).allInnerTexts()) ?? [];
186 + (await page.locator('.monaco-editor').nth(3).allInnerTexts()) ?? [];
187 let output: string;
188 if (t.noFormat) {
189 output = text.join('');
compiler/apps/playground/app/index.tsx deleted
-56
@@ -1,56 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - */
7 -
8 -import type {NextPage} from 'next';
9 -import Head from 'next/head';
10 -import {SnackbarProvider} from 'notistack';
11 -import {Editor, Header, StoreProvider} from '../components';
12 -import MessageSnackbar from '../components/Message';
13 -
14 -const Home: NextPage = () => {
15 - return (
16 - <div className="flex flex-col w-screen h-screen font-light">
17 - <Head>
18 - <title>
19 - {process.env.NODE_ENV === 'development'
20 - ? '[DEV] React Compiler Playground'
21 - : 'React Compiler Playground'}
22 - </title>
23 - <meta
24 - name="viewport"
25 - content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"></meta>
26 - <link rel="icon" href="/favicon.ico" />
27 - <link rel="manifest" href="/site.webmanifest" />
28 - <link
29 - rel="preload"
30 - href="/fonts/Source-Code-Pro-Regular.woff2"
31 - as="font"
32 - type="font/woff2"
33 - crossOrigin="anonymous"
34 - />
35 - <link
36 - rel="preload"
37 - href="/fonts/Optimistic_Display_W_Lt.woff2"
38 - as="font"
39 - type="font/woff2"
40 - crossOrigin="anonymous"
41 - />
42 - </Head>
43 - <StoreProvider>
44 - <SnackbarProvider
45 - preventDuplicate
46 - maxSnack={10}
47 - Components={{message: MessageSnackbar}}>
48 - <Header />
49 - <Editor />
50 - </SnackbarProvider>
51 - </StoreProvider>
52 - </div>
53 - );
54 -};
55 -
56 -export default Home;
compiler/apps/playground/components/AccordionWindow.tsx
-9
@@ -17,15 +17,6 @@ export default function AccordionWindow(props: {
17 setTabsOpen: (newTab: Set<string>) => void;
18 changedPasses: Set<string>;
19 }): React.ReactElement {
20 - if (props.tabs.size === 0) {
21 - return (
22 - <div
23 - className="flex items-center justify-center"
24 - style={{width: 'calc(100vw - 650px)'}}>
25 - No compiler output detected, see errors below
26 - </div>
27 - );
28 - }
20 return (
21 <div className="flex flex-row h-full">
22 {Array.from(props.tabs.keys()).map(name => {
compiler/apps/playground/components/Editor/ConfigEditor.tsx
+38 -19
@@ -9,7 +9,7 @@ import MonacoEditor, {loader, type Monaco} from '@monaco-editor/react';
9 import {PluginOptions} from 'babel-plugin-react-compiler';
10 import type {editor} from 'monaco-editor';
11 import * as monaco from 'monaco-editor';
12 -import React, {useState} from 'react';
12 +import React, {useState, useRef, useEffect} from 'react';
13 import {Resizable} from 're-resizable';
14 import {useStore, useStoreDispatch} from '../StoreContext';
15 import {monacoOptions} from './monacoOptions';
@@ -28,10 +28,25 @@ export default function ConfigEditor({
28 }): React.ReactElement {
29 const [isExpanded, setIsExpanded] = useState(false);
30
31 - return isExpanded ? (
32 - <ExpandedEditor onToggle={setIsExpanded} appliedOptions={appliedOptions} />
33 - ) : (
34 - <CollapsedEditor onToggle={setIsExpanded} />
31 + return (
32 + // TODO: Use <Activity> when it is compatible with Monaco: https://github.com/suren-atoyan/monaco-react/issues/753
33 + <>
34 + <div
35 + style={{
36 + display: isExpanded ? 'block' : 'none',
37 + }}>
38 + <ExpandedEditor
39 + onToggle={setIsExpanded}
40 + appliedOptions={appliedOptions}
41 + />
42 + </div>
43 + <div
44 + style={{
45 + display: !isExpanded ? 'block' : 'none',
46 + }}>
47 + <CollapsedEditor onToggle={setIsExpanded} />
48 + </div>
49 + </>
50 );
51 }
52
@@ -44,16 +59,25 @@ function ExpandedEditor({
59 }): React.ReactElement {
60 const store = useStore();
61 const dispatchStore = useStoreDispatch();
62 + const debounceTimerRef = useRef<NodeJS.Timeout | null>(null);
63
48 - const handleChange: (value: string | undefined) => void = value => {
64 + const handleChange: (value: string | undefined) => void = (
65 + value: string | undefined,
66 + ) => {
67 if (value === undefined) return;
68
51 - dispatchStore({
52 - type: 'updateConfig',
53 - payload: {
54 - config: value,
55 - },
56 - });
69 + if (debounceTimerRef.current) {
70 + clearTimeout(debounceTimerRef.current);
71 + }
72 +
73 + debounceTimerRef.current = setTimeout(() => {
74 + dispatchStore({
75 + type: 'updateConfig',
76 + payload: {
77 + config: value,
78 + },
79 + });
80 + }, 500); // 500ms debounce delay
81 };
82
83 const handleMount: (
@@ -77,12 +101,6 @@ function ExpandedEditor({
101 allowSyntheticDefaultImports: true,
102 jsx: monaco.languages.typescript.JsxEmit.React,
103 });
80 -
81 - const uri = monaco.Uri.parse(`file:///config.ts`);
82 - const model = monaco.editor.getModel(uri);
83 - if (model) {
84 - model.updateOptions({tabSize: 2});
85 - }
104 };
105
106 const formattedAppliedOptions = appliedOptions
@@ -126,6 +144,7 @@ function ExpandedEditor({
144 value={store.config}
145 onMount={handleMount}
146 onChange={handleChange}
147 + loading={''}
148 options={{
149 ...monacoOptions,
150 lineNumbers: 'off',
@@ -139,7 +158,6 @@ function ExpandedEditor({
158 />
159 </div>
160 </div>
142 -
161 <div className="flex-1 flex flex-col m-2">
162 <div className="pb-2">
163 <h2 className="inline-block text-blue-50 py-1.5 px-1.5 xs:px-3 sm:px-4 text-sm">
@@ -151,6 +169,7 @@ function ExpandedEditor({
169 path={'applied-config.js'}
170 language={'javascript'}
171 value={formattedAppliedOptions}
172 + loading={''}
173 options={{
174 ...monacoOptions,
175 lineNumbers: 'off',
compiler/apps/playground/components/Editor/EditorImpl.tsx
+1 -41
@@ -24,19 +24,8 @@ import BabelPluginReactCompiler, {
24 printFunctionWithOutlined,
25 type LoggerEvent,
26 } from 'babel-plugin-react-compiler';
27 -import invariant from 'invariant';
28 -import {useSnackbar} from 'notistack';
27 import {useDeferredValue, useMemo} from 'react';
30 -import {useMountEffect} from '../../hooks';
31 -import {defaultStore} from '../../lib/defaultStore';
32 -import {
33 - createMessage,
34 - initStoreFromUrlOrLocalStorage,
35 - MessageLevel,
36 - MessageSource,
37 - type Store,
38 -} from '../../lib/stores';
39 -import {useStore, useStoreDispatch} from '../StoreContext';
28 +import {useStore} from '../StoreContext';
29 import ConfigEditor from './ConfigEditor';
30 import Input from './Input';
31 import {
@@ -174,7 +163,6 @@ function parseOptions(
163 // Parse config overrides from config editor
164 let configOverrideOptions: any = {};
165 const configMatch = configOverrides.match(/^\s*import.*?\n\n\((.*)\)/s);
177 - // TODO: initialize store with URL params, not empty store
166 if (configOverrides.trim()) {
167 if (configMatch && configMatch[1]) {
168 const configString = configMatch[1].replace(/satisfies.*$/, '').trim();
@@ -327,8 +315,6 @@ function compile(
315 export default function Editor(): JSX.Element {
316 const store = useStore();
317 const deferredStore = useDeferredValue(store);
330 - const dispatchStore = useStoreDispatch();
331 - const {enqueueSnackbar} = useSnackbar();
318 const [compilerOutput, language, appliedOptions] = useMemo(
319 () => compile(deferredStore.source, 'compiler', deferredStore.config),
320 [deferredStore.source, deferredStore.config],
@@ -338,32 +324,6 @@ export default function Editor(): JSX.Element {
324 [deferredStore.source, deferredStore.config],
325 );
326
341 - useMountEffect(() => {
342 - // Initialize store
343 - let mountStore: Store;
344 - try {
345 - mountStore = initStoreFromUrlOrLocalStorage();
346 - } catch (e) {
347 - invariant(e instanceof Error, 'Only Error may be caught.');
348 - enqueueSnackbar(e.message, {
349 - variant: 'warning',
350 - ...createMessage(
351 - 'Bad URL - fell back to the default Playground.',
352 - MessageLevel.Info,
353 - MessageSource.Playground,
354 - ),
355 - });
356 - mountStore = defaultStore;
357 - }
358 -
359 - dispatchStore({
360 - type: 'setStore',
361 - payload: {
362 - store: mountStore,
363 - },
364 - });
365 - });
366 -
327 let mergedOutput: CompilerOutput;
328 let errors: Array<CompilerErrorDetail | CompilerDiagnostic>;
329 if (compilerOutput.kind === 'ok') {
compiler/apps/playground/components/Editor/Input.tsx
+10 -30
@@ -13,7 +13,6 @@ import {
13 import invariant from 'invariant';
14 import type {editor} from 'monaco-editor';
15 import * as monaco from 'monaco-editor';
16 -import {Resizable} from 're-resizable';
16 import {useEffect, useState} from 'react';
17 import {renderReactCompilerMarkers} from '../../lib/reactCompilerMonacoDiagnostics';
18 import {useStore, useStoreDispatch} from '../StoreContext';
@@ -46,11 +45,6 @@ export default function Input({errors, language}: Props): JSX.Element {
45 details: errors,
46 source: store.source,
47 });
49 - /**
50 - * N.B. that `tabSize` is a model property, not an editor property.
51 - * So, the tab size has to be set per model.
52 - */
53 - model.updateOptions({tabSize: 2});
48 }, [monaco, errors, store.source]);
49
50 useEffect(() => {
@@ -152,38 +146,24 @@ export default function Input({errors, language}: Props): JSX.Element {
146 onMount={handleMount}
147 onChange={handleChange}
148 options={monacoOptions}
149 + loading={''}
150 />
151 );
152
153 const tabs = new Map([['Input', editorContent]]);
154 const [activeTab, setActiveTab] = useState('Input');
155
161 - const tabbedContent = (
162 - <div className="flex flex-col h-full">
163 - <TabbedWindow
164 - tabs={tabs}
165 - activeTab={activeTab}
166 - onTabChange={setActiveTab}
167 - />
168 - </div>
169 - );
170 -
156 return (
157 <div className="relative flex flex-col flex-none border-r border-gray-200">
173 - {store.showInternals ? (
174 - <Resizable
175 - minWidth={550}
176 - enable={{right: true}}
177 - /**
178 - * Restrict MonacoEditor's height, since the config autoLayout:true
179 - * will grow the editor to fit within parent element
180 - */
181 - className="!h-[calc(100vh_-_3.5rem)]">
182 - {tabbedContent}
183 - </Resizable>
184 - ) : (
185 - <div className="!h-[calc(100vh_-_3.5rem)]">{tabbedContent}</div>
186 - )}
158 + <div className="!h-[calc(100vh_-_3.5rem)]">
159 + <div className="flex flex-col h-full">
160 + <TabbedWindow
161 + tabs={tabs}
162 + activeTab={activeTab}
163 + onTabChange={setActiveTab}
164 + />
165 + </div>
166 + </div>
167 </div>
168 );
169 }
compiler/apps/playground/components/Editor/Output.tsx
+2
@@ -324,6 +324,7 @@ function TextTabContent({
324 <DiffEditor
325 original={diff}
326 modified={output}
327 + loading={''}
328 options={{
329 ...monacoOptions,
330 readOnly: true,
@@ -338,6 +339,7 @@ function TextTabContent({
339 <MonacoEditor
340 language={language ?? 'javascript'}
341 value={output}
342 + loading={''}
343 options={{
344 ...monacoOptions,
345 readOnly: true,
compiler/apps/playground/components/Editor/monacoOptions.ts
+2
@@ -29,4 +29,6 @@ export const monacoOptions: Partial<EditorProps['options']> = {
29 automaticLayout: true,
30 wordWrap: 'on',
31 wrappingIndent: 'same',
32 +
33 + tabSize: 2,
34 };
compiler/apps/playground/components/StoreContext.tsx
+22 -4
@@ -6,10 +6,14 @@
6 */
7
8 import type {Dispatch, ReactNode} from 'react';
9 -import {useEffect, useReducer} from 'react';
9 +import {useState, useEffect, useReducer} from 'react';
10 import createContext from '../lib/createContext';
11 -import {emptyStore} from '../lib/defaultStore';
12 -import {saveStore, type Store} from '../lib/stores';
11 +import {emptyStore, defaultStore} from '../lib/defaultStore';
12 +import {
13 + saveStore,
14 + initStoreFromUrlOrLocalStorage,
15 + type Store,
16 +} from '../lib/stores';
17
18 const StoreContext = createContext<Store>();
19
@@ -30,6 +34,20 @@ export const useStoreDispatch = StoreDispatchContext.useContext;
34 */
35 export function StoreProvider({children}: {children: ReactNode}): JSX.Element {
36 const [store, dispatch] = useReducer(storeReducer, emptyStore);
37 + const [isPageReady, setIsPageReady] = useState<boolean>(false);
38 +
39 + useEffect(() => {
40 + let mountStore: Store;
41 + try {
42 + mountStore = initStoreFromUrlOrLocalStorage();
43 + } catch (e) {
44 + console.error('Failed to initialize store from URL or local storage', e);
45 + mountStore = defaultStore;
46 + }
47 + dispatch({type: 'setStore', payload: {store: mountStore}});
48 + setIsPageReady(true);
49 + }, []);
50 +
51 useEffect(() => {
52 if (store !== emptyStore) {
53 saveStore(store);
@@ -39,7 +57,7 @@ export function StoreProvider({children}: {children: ReactNode}): JSX.Element {
57 return (
58 <StoreContext.Provider value={store}>
59 <StoreDispatchContext.Provider value={dispatch}>
42 - {children}
60 + {isPageReady ? children : null}
61 </StoreDispatchContext.Provider>
62 </StoreContext.Provider>
63 );
compiler/apps/playground/components/TabbedWindow.tsx
-7
@@ -16,13 +16,6 @@ export default function TabbedWindow({
16 activeTab: string;
17 onTabChange: (tab: string) => void;
18 }): React.ReactElement {
19 - if (tabs.size === 0) {
20 - return (
21 - <div className="flex items-center justify-center flex-1 max-w-full">
22 - No compiler output detected, see errors below
23 - </div>
24 - );
25 - }
19 return (
20 <div className="flex flex-col h-full max-w-full">
21 <div className="flex p-2 flex-shrink-0">
compiler/apps/playground/lib/stores/store.ts
+1 -1
@@ -71,7 +71,7 @@ export function initStoreFromUrlOrLocalStorage(): Store {
71 // Make sure all properties are populated
72 return {
73 source: raw.source,
74 - config: 'config' in raw ? raw.config : defaultConfig,
74 + config: 'config' in raw && raw['config'] ? raw.config : defaultConfig,
75 showInternals: 'showInternals' in raw ? raw.showInternals : false,
76 };
77 }
compiler/apps/playground/next-env.d.ts
+1 -1
@@ -1,6 +1,6 @@
1 /// <reference types="next" />
2 /// <reference types="next/image-types/global" />
3 -/// <reference path="./.next/types/routes.d.ts" />
3 +import "./.next/types/routes.d.ts";
4
5 // NOTE: This file should not be edited
6 // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
compiler/apps/playground/package.json
+2 -2
@@ -34,7 +34,7 @@
34 "invariant": "^2.2.4",
35 "lz-string": "^1.5.0",
36 "monaco-editor": "^0.52.0",
37 - "next": "15.5.2",
37 + "next": "15.6.0-canary.7",
38 "notistack": "^3.0.0-alpha.7",
39 "prettier": "^3.3.3",
40 "pretty-format": "^29.3.1",
@@ -44,7 +44,7 @@
44 },
45 "devDependencies": {
46 "@types/node": "18.11.9",
47 - "@types/react": "19.1.12",
47 + "@types/react": "19.1.13",
48 "@types/react-dom": "19.1.9",
49 "autoprefixer": "^10.4.13",
50 "clsx": "^1.2.1",
compiler/apps/playground/tsconfig.json
+4 -1
@@ -6,6 +6,9 @@
6 "dom.iterable",
7 "esnext"
8 ],
9 + "types": [
10 + "react/experimental"
11 + ],
12 "allowJs": true,
13 "skipLibCheck": true,
14 "strict": true,
@@ -16,7 +19,7 @@
19 "moduleResolution": "node",
20 "resolveJsonModule": true,
21 "isolatedModules": true,
19 - "jsx": "preserve",
22 + "jsx": "react-jsx",
23 "incremental": true,
24 "plugins": [
25 {
compiler/apps/playground/yarn.lock
+63 -56
@@ -715,10 +715,10 @@
715 dependencies:
716 "@monaco-editor/loader" "^1.4.0"
717
718 -"@next/env@15.5.2":
719 - version "15.5.2"
720 - resolved "https://registry.yarnpkg.com/@next/env/-/env-15.5.2.tgz#0c6b959313cd6e71afb69bf0deb417237f1d2f8a"
721 - integrity sha512-Qe06ew4zt12LeO6N7j8/nULSOe3fMXE4dM6xgpBQNvdzyK1sv5y4oAP3bq4LamrvGCZtmRYnW8URFCeX5nFgGg==
718 +"@next/env@15.6.0-canary.7":
719 + version "15.6.0-canary.7"
720 + resolved "https://registry.yarnpkg.com/@next/env/-/env-15.6.0-canary.7.tgz#cdbf2967a9437ef09eef755e203f315acc4d8d8f"
721 + integrity sha512-LNZ7Yd3Cl9rKvjYdeJmszf2HmSDP76SQmfafKep2Ux16ZXKoN5OjwVHFTltKNdsB3vt2t+XJzLP2rhw5lBoFBA==
722
723 "@next/eslint-plugin-next@15.5.2":
724 version "15.5.2"
@@ -727,45 +727,45 @@
727 dependencies:
728 fast-glob "3.3.1"
729
730 -"@next/swc-darwin-arm64@15.5.2":
731 - version "15.5.2"
732 - resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.5.2.tgz#f69713326fc08f2eff3726fe19165cdb429d67c7"
733 - integrity sha512-8bGt577BXGSd4iqFygmzIfTYizHb0LGWqH+qgIF/2EDxS5JsSdERJKA8WgwDyNBZgTIIA4D8qUtoQHmxIIquoQ==
734 -
735 -"@next/swc-darwin-x64@15.5.2":
736 - version "15.5.2"
737 - resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-15.5.2.tgz#560a9da4126bae75cbbd6899646ad7a2e4fdcc9b"
738 - integrity sha512-2DjnmR6JHK4X+dgTXt5/sOCu/7yPtqpYt8s8hLkHFK3MGkka2snTv3yRMdHvuRtJVkPwCGsvBSwmoQCHatauFQ==
739 -
740 -"@next/swc-linux-arm64-gnu@15.5.2":
741 - version "15.5.2"
742 - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.5.2.tgz#80b2be276e775e5a9286369ae54e536b0cdf8c3a"
743 - integrity sha512-3j7SWDBS2Wov/L9q0mFJtEvQ5miIqfO4l7d2m9Mo06ddsgUK8gWfHGgbjdFlCp2Ek7MmMQZSxpGFqcC8zGh2AA==
744 -
745 -"@next/swc-linux-arm64-musl@15.5.2":
746 - version "15.5.2"
747 - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.5.2.tgz#68cf676301755fd99aca11a7ebdb5eae88d7c2e4"
748 - integrity sha512-s6N8k8dF9YGc5T01UPQ08yxsK6fUow5gG1/axWc1HVVBYQBgOjca4oUZF7s4p+kwhkB1bDSGR8QznWrFZ/Rt5g==
749 -
750 -"@next/swc-linux-x64-gnu@15.5.2":
751 - version "15.5.2"
752 - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.5.2.tgz#209d9a79d0f2333544f863b0daca3f7e29f2eaff"
753 - integrity sha512-o1RV/KOODQh6dM6ZRJGZbc+MOAHww33Vbs5JC9Mp1gDk8cpEO+cYC/l7rweiEalkSm5/1WGa4zY7xrNwObN4+Q==
754 -
755 -"@next/swc-linux-x64-musl@15.5.2":
756 - version "15.5.2"
757 - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.5.2.tgz#d4ad1cfb5e99e51db669fe2145710c1abeadbd7f"
758 - integrity sha512-/VUnh7w8RElYZ0IV83nUcP/J4KJ6LLYliiBIri3p3aW2giF+PAVgZb6mk8jbQSB3WlTai8gEmCAr7kptFa1H6g==
759 -
760 -"@next/swc-win32-arm64-msvc@15.5.2":
761 - version "15.5.2"
762 - resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.5.2.tgz#070e10e370a5447a198c2db100389646aca2c496"
763 - integrity sha512-sMPyTvRcNKXseNQ/7qRfVRLa0VhR0esmQ29DD6pqvG71+JdVnESJaHPA8t7bc67KD5spP3+DOCNLhqlEI2ZgQg==
764 -
765 -"@next/swc-win32-x64-msvc@15.5.2":
766 - version "15.5.2"
767 - resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.5.2.tgz#9237d40b82eaf2efc88baeba15b784d4126caf4a"
768 - integrity sha512-W5VvyZHnxG/2ukhZF/9Ikdra5fdNftxI6ybeVKYvBPDtyx7x4jPPSNduUkfH5fo3zG0JQ0bPxgy41af2JX5D4Q==
730 +"@next/swc-darwin-arm64@15.6.0-canary.7":
731 + version "15.6.0-canary.7"
732 + resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.6.0-canary.7.tgz#628cd34ce9120000f1cb5b08963426431174fc57"
733 + integrity sha512-POsBrxhrR3qvqXV+JZ6ZoBc8gJf8rhYe+OedceI1piPVqtJYOJa3EB4eaqcc+kMsllKRrH/goNlhLwtyhE+0Qg==
734 +
735 +"@next/swc-darwin-x64@15.6.0-canary.7":
736 + version "15.6.0-canary.7"
737 + resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-15.6.0-canary.7.tgz#37d4ebab14da74a2f8028daf6d76aab410153e06"
738 + integrity sha512-lmk9ysBuSiPlAJZTCo/3O4mXNFosg6EDIf4GrmynIwCG2as6/KxzyD1WqFp56Exp8eFDjP7SFapD10sV43vCsA==
739 +
740 +"@next/swc-linux-arm64-gnu@15.6.0-canary.7":
741 + version "15.6.0-canary.7"
742 + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.6.0-canary.7.tgz#ce700cc0e0d24763136838223105a524b36694fa"
743 + integrity sha512-why8k6d0SBm3AKoOD5S7ir3g+BF34l9oFKIoZrLaZaKBvNGpFcjc7Ovc2TunNMeaMJzv9k1dHYSap0EI5oSuzg==
744 +
745 +"@next/swc-linux-arm64-musl@15.6.0-canary.7":
746 + version "15.6.0-canary.7"
747 + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.6.0-canary.7.tgz#c791b8e15bf2c338b4cc0387fe7afb3ef83ecfcf"
748 + integrity sha512-HzvTRsKvYj32Va4YuJN3n3xOxvk+6QwB63d/EsgmdkeA/vrqciUAmJDYpuzZEvRc3Yp2nyPq8KZxtHAr6ISZ2Q==
749 +
750 +"@next/swc-linux-x64-gnu@15.6.0-canary.7":
751 + version "15.6.0-canary.7"
752 + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.6.0-canary.7.tgz#c01c3a3d8e71660c49298dd053d078379b6b5919"
753 + integrity sha512-6yRFrg2qWXOqa+1BI53J9EmHWFzKg9U2r+5R7n7BFUp8PH5SC92WBsmYTnh/RkvAYvdupiVzMervwwswCs6kFg==
754 +
755 +"@next/swc-linux-x64-musl@15.6.0-canary.7":
756 + version "15.6.0-canary.7"
757 + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.6.0-canary.7.tgz#3f4b39faef4a5f88b13e4c726b008ddc9717f819"
758 + integrity sha512-O/JjvOvNK/Wao/OIQaA6evDkxkmFFQgJ1/hI1dVk6/PAeKmW2/Q+6Dodh97eAkOwedS1ZdQl2mojf87TzLvzdQ==
759 +
760 +"@next/swc-win32-arm64-msvc@15.6.0-canary.7":
761 + version "15.6.0-canary.7"
762 + resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.6.0-canary.7.tgz#9bc5da0907b7ce67eedda02a6d56a09d9a539ccf"
763 + integrity sha512-p9DvrDgnePofZCtiWVY7qZtwXxiOGJlAyy2LoGPYSGOUDhjbTG8j6XMUFXpV9UwpH+l7st522psO1BVzbpT8IQ==
764 +
765 +"@next/swc-win32-x64-msvc@15.6.0-canary.7":
766 + version "15.6.0-canary.7"
767 + resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.6.0-canary.7.tgz#5b271c591ccbe67d5fa966dd22db86c547414fd1"
768 + integrity sha512-f1ywT3xWu4StWKA1mZRyGfelu/h+W0OEEyBxQNXzXyYa0VGZb9LyCNb5cYoNKBm0Bw18Hp1PVe0bHuusemGCcw==
769
770 "@nodelib/fs.scandir@2.1.5":
771 version "2.1.5"
@@ -866,6 +866,13 @@
866 dependencies:
867 csstype "^3.0.2"
868
869 +"@types/react@19.1.13":
870 + version "19.1.13"
871 + resolved "https://registry.yarnpkg.com/@types/react/-/react-19.1.13.tgz#fc650ffa680d739a25a530f5d7ebe00cdd771883"
872 + integrity sha512-hHkbU/eoO3EG5/MZkuFSKmYqPbSVk5byPFa3e7y/8TybHiLMACgI8seVYlicwk7H5K/rI2px9xrQp/C+AUDTiQ==
873 + dependencies:
874 + csstype "^3.0.2"
875 +
876 "@typescript-eslint/eslint-plugin@^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0":
877 version "8.10.0"
878 resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.10.0.tgz#9c8218ed62f9a322df10ded7c34990f014df44f2"
@@ -3199,25 +3206,25 @@ natural-compare@^1.4.0:
3206 resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
3207 integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
3208
3202 -next@15.5.2:
3203 - version "15.5.2"
3204 - resolved "https://registry.yarnpkg.com/next/-/next-15.5.2.tgz#5e50102443fb0328a9dfcac2d82465c7bac93693"
3205 - integrity sha512-H8Otr7abj1glFhbGnvUt3gz++0AF1+QoCXEBmd/6aKbfdFwrn0LpA836Ed5+00va/7HQSDD+mOoVhn3tNy3e/Q==
3209 +next@15.6.0-canary.7:
3210 + version "15.6.0-canary.7"
3211 + resolved "https://registry.yarnpkg.com/next/-/next-15.6.0-canary.7.tgz#bfc2ac3c9a78e23d550c303d18247a263e6b5bc1"
3212 + integrity sha512-4ukX2mxat9wWT6E0Gw/3TOR9ULV1q399E42F86cwsPSFgTWa04ABhcTqO0r9J/QR1YWPR8WEgh9qUzmWA/1yEw==
3213 dependencies:
3207 - "@next/env" "15.5.2"
3214 + "@next/env" "15.6.0-canary.7"
3215 "@swc/helpers" "0.5.15"
3216 caniuse-lite "^1.0.30001579"
3217 postcss "8.4.31"
3218 styled-jsx "5.1.6"
3219 optionalDependencies:
3213 - "@next/swc-darwin-arm64" "15.5.2"
3214 - "@next/swc-darwin-x64" "15.5.2"
3215 - "@next/swc-linux-arm64-gnu" "15.5.2"
3216 - "@next/swc-linux-arm64-musl" "15.5.2"
3217 - "@next/swc-linux-x64-gnu" "15.5.2"
3218 - "@next/swc-linux-x64-musl" "15.5.2"
3219 - "@next/swc-win32-arm64-msvc" "15.5.2"
3220 - "@next/swc-win32-x64-msvc" "15.5.2"
3220 + "@next/swc-darwin-arm64" "15.6.0-canary.7"
3221 + "@next/swc-darwin-x64" "15.6.0-canary.7"
3222 + "@next/swc-linux-arm64-gnu" "15.6.0-canary.7"
3223 + "@next/swc-linux-arm64-musl" "15.6.0-canary.7"
3224 + "@next/swc-linux-x64-gnu" "15.6.0-canary.7"
3225 + "@next/swc-linux-x64-musl" "15.6.0-canary.7"
3226 + "@next/swc-win32-arm64-msvc" "15.6.0-canary.7"
3227 + "@next/swc-win32-x64-msvc" "15.6.0-canary.7"
3228 sharp "^0.34.3"
3229
3230 node-releases@^2.0.18: