Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
1e18d65
Remove OVERRIDE pragma and apply button, make config panel source of …
EugeneChoi4 Sep 9, 2025
88ccbb4
Remove config override gating
EugeneChoi4 Sep 9, 2025
09e8ef7
Initial palyground changes
EugeneChoi4 Sep 10, 2025
6faa9f1
Add styling to panels and chevron opener
EugeneChoi4 Sep 10, 2025
0788958
Add consistent styling
EugeneChoi4 Sep 11, 2025
c8fb918
Fix formatting
EugeneChoi4 Sep 11, 2025
46ffa19
Merge branch 'main' into compiler-playground-design
EugeneChoi4 Sep 11, 2025
5e5a84d
Update test
EugeneChoi4 Sep 11, 2025
a7bb236
update test
EugeneChoi4 Sep 11, 2025
16561a4
Initial changes
EugeneChoi4 Sep 12, 2025
10d938c
Merge branch 'main' into playground-applied-configs
EugeneChoi4 Sep 12, 2025
ef87362
update style
EugeneChoi4 Sep 12, 2025
0e0fcb0
Finalize config panel
EugeneChoi4 Sep 12, 2025
c0769ce
Update default config
EugeneChoi4 Sep 12, 2025
a128cac
Test changes
EugeneChoi4 Sep 15, 2025
84f2e54
Change versioning for experimental
EugeneChoi4 Sep 15, 2025
2004c12
Merge branch 'main' into playground-bug-fixes
EugeneChoi4 Sep 15, 2025
f527d55
add debouncing, improve show/hide
EugeneChoi4 Sep 16, 2025
d84a587
Remove loading indicator
EugeneChoi4 Sep 17, 2025
b201a1d
remove old index
EugeneChoi4 Sep 17, 2025
bdde8ec
Try new store loading
EugeneChoi4 Sep 17, 2025
87339bb
Remove unecessary text
EugeneChoi4 Sep 17, 2025
8263b5e
Merge branch 'main' into playground-bug-fixes
EugeneChoi4 Sep 17, 2025
201301e
update tests
EugeneChoi4 Sep 17, 2025
8a7d036
update yarn
EugeneChoi4 Sep 17, 2025
59f54a2
Revert experimental react for now
EugeneChoi4 Sep 18, 2025
d158da1
remove cleanup effect
EugeneChoi4 Sep 18, 2025
030099e
typo fix
EugeneChoi4 Sep 18, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions compiler/apps/playground/__tests__/e2e/page.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ test('editor should compile from hash successfully', async ({page}) => {
path: 'test-results/01-compiles-from-hash.png',
});
const text =
(await page.locator('.monaco-editor').nth(1).allInnerTexts()) ?? [];
(await page.locator('.monaco-editor').nth(3).allInnerTexts()) ?? [];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like this has gone back and forth a couple times. As a follow up there could be a test that starts the app both with internals showing and not showing.

Also/alternatively adding some testID to the tabs would allow for better selecting. like '[data-testid="config-tab"] .monaco-editor'

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, I'm actually cleaning up/adding more tests in another PR right now so this will be addressed there.

const output = await formatPrint(text);

expect(output).not.toEqual('');
Expand All @@ -162,7 +162,7 @@ test('reset button works', async ({page}) => {
path: 'test-results/02-reset-button-works.png',
});
const text =
(await page.locator('.monaco-editor').nth(1).allInnerTexts()) ?? [];
(await page.locator('.monaco-editor').nth(3).allInnerTexts()) ?? [];
const output = await formatPrint(text);

expect(output).not.toEqual('');
Expand All @@ -183,7 +183,7 @@ TEST_CASE_INPUTS.forEach((t, idx) =>
});

const text =
(await page.locator('.monaco-editor').nth(1).allInnerTexts()) ?? [];
(await page.locator('.monaco-editor').nth(3).allInnerTexts()) ?? [];
let output: string;
if (t.noFormat) {
output = text.join('');
Expand Down
56 changes: 0 additions & 56 deletions compiler/apps/playground/app/index.tsx

This file was deleted.

9 changes: 0 additions & 9 deletions compiler/apps/playground/components/AccordionWindow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,6 @@ export default function AccordionWindow(props: {
setTabsOpen: (newTab: Set<string>) => void;
changedPasses: Set<string>;
}): React.ReactElement {
if (props.tabs.size === 0) {
return (
<div
className="flex items-center justify-center"
style={{width: 'calc(100vw - 650px)'}}>
No compiler output detected, see errors below
</div>
);
}
return (
<div className="flex flex-row h-full">
{Array.from(props.tabs.keys()).map(name => {
Expand Down
57 changes: 38 additions & 19 deletions compiler/apps/playground/components/Editor/ConfigEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import MonacoEditor, {loader, type Monaco} from '@monaco-editor/react';
import {PluginOptions} from 'babel-plugin-react-compiler';
import type {editor} from 'monaco-editor';
import * as monaco from 'monaco-editor';
import React, {useState} from 'react';
import React, {useState, useRef, useEffect} from 'react';
import {Resizable} from 're-resizable';
import {useStore, useStoreDispatch} from '../StoreContext';
import {monacoOptions} from './monacoOptions';
Expand All @@ -28,10 +28,25 @@ export default function ConfigEditor({
}): React.ReactElement {
const [isExpanded, setIsExpanded] = useState(false);

return isExpanded ? (
<ExpandedEditor onToggle={setIsExpanded} appliedOptions={appliedOptions} />
) : (
<CollapsedEditor onToggle={setIsExpanded} />
return (
// TODO: Use <Activity> when it is compatible with Monaco: https://github.com/suren-atoyan/monaco-react/issues/753
<>
<div
style={{
display: isExpanded ? 'block' : 'none',
}}>
<ExpandedEditor
onToggle={setIsExpanded}
appliedOptions={appliedOptions}
/>
</div>
<div
style={{
display: !isExpanded ? 'block' : 'none',
}}>
<CollapsedEditor onToggle={setIsExpanded} />
</div>
</>
);
}

Expand All @@ -44,16 +59,25 @@ function ExpandedEditor({
}): React.ReactElement {
const store = useStore();
const dispatchStore = useStoreDispatch();
const debounceTimerRef = useRef<NodeJS.Timeout | null>(null);

const handleChange: (value: string | undefined) => void = value => {
const handleChange: (value: string | undefined) => void = (
value: string | undefined,
) => {
if (value === undefined) return;

dispatchStore({
type: 'updateConfig',
payload: {
config: value,
},
});
if (debounceTimerRef.current) {
clearTimeout(debounceTimerRef.current);
}

debounceTimerRef.current = setTimeout(() => {
dispatchStore({
type: 'updateConfig',
payload: {
config: value,
},
});
}, 500); // 500ms debounce delay
Copy link
Member

@josephsavona josephsavona Sep 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use useDeferredValue() instead of manually debouncing?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

useDeferredValue was already being used previously to update the output: https://github.com/facebook/react/blob/main/compiler/apps/playground/components/Editor/EditorImpl.tsx#L329.

It seemed like these updates were still happening too quickly while typing in the config editor so I tried adding a manual debouncing mechanism with a longer timeout window.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@josephsavona we're adding debouncing to reduce thrash in the output panel from JS parse errors

};

const handleMount: (
Expand All @@ -77,12 +101,6 @@ function ExpandedEditor({
allowSyntheticDefaultImports: true,
jsx: monaco.languages.typescript.JsxEmit.React,
});

const uri = monaco.Uri.parse(`file:///config.ts`);
const model = monaco.editor.getModel(uri);
if (model) {
model.updateOptions({tabSize: 2});
}
};

const formattedAppliedOptions = appliedOptions
Expand Down Expand Up @@ -126,6 +144,7 @@ function ExpandedEditor({
value={store.config}
onMount={handleMount}
onChange={handleChange}
loading={''}
options={{
...monacoOptions,
lineNumbers: 'off',
Expand All @@ -139,7 +158,6 @@ function ExpandedEditor({
/>
</div>
</div>

<div className="flex-1 flex flex-col m-2">
<div className="pb-2">
<h2 className="inline-block text-blue-50 py-1.5 px-1.5 xs:px-3 sm:px-4 text-sm">
Expand All @@ -151,6 +169,7 @@ function ExpandedEditor({
path={'applied-config.js'}
language={'javascript'}
value={formattedAppliedOptions}
loading={''}
options={{
...monacoOptions,
lineNumbers: 'off',
Expand Down
42 changes: 1 addition & 41 deletions compiler/apps/playground/components/Editor/EditorImpl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,8 @@ import BabelPluginReactCompiler, {
printFunctionWithOutlined,
type LoggerEvent,
} from 'babel-plugin-react-compiler';
import invariant from 'invariant';
import {useSnackbar} from 'notistack';
import {useDeferredValue, useMemo} from 'react';
import {useMountEffect} from '../../hooks';
import {defaultStore} from '../../lib/defaultStore';
import {
createMessage,
initStoreFromUrlOrLocalStorage,
MessageLevel,
MessageSource,
type Store,
} from '../../lib/stores';
import {useStore, useStoreDispatch} from '../StoreContext';
import {useStore} from '../StoreContext';
import ConfigEditor from './ConfigEditor';
import Input from './Input';
import {
Expand Down Expand Up @@ -174,7 +163,6 @@ function parseOptions(
// Parse config overrides from config editor
let configOverrideOptions: any = {};
const configMatch = configOverrides.match(/^\s*import.*?\n\n\((.*)\)/s);
// TODO: initialize store with URL params, not empty store
if (configOverrides.trim()) {
if (configMatch && configMatch[1]) {
const configString = configMatch[1].replace(/satisfies.*$/, '').trim();
Expand Down Expand Up @@ -327,8 +315,6 @@ function compile(
export default function Editor(): JSX.Element {
const store = useStore();
const deferredStore = useDeferredValue(store);
const dispatchStore = useStoreDispatch();
const {enqueueSnackbar} = useSnackbar();
const [compilerOutput, language, appliedOptions] = useMemo(
() => compile(deferredStore.source, 'compiler', deferredStore.config),
[deferredStore.source, deferredStore.config],
Expand All @@ -338,32 +324,6 @@ export default function Editor(): JSX.Element {
[deferredStore.source, deferredStore.config],
);

useMountEffect(() => {
// Initialize store
let mountStore: Store;
try {
mountStore = initStoreFromUrlOrLocalStorage();
} catch (e) {
invariant(e instanceof Error, 'Only Error may be caught.');
enqueueSnackbar(e.message, {
variant: 'warning',
...createMessage(
'Bad URL - fell back to the default Playground.',
MessageLevel.Info,
MessageSource.Playground,
),
});
mountStore = defaultStore;
}

dispatchStore({
type: 'setStore',
payload: {
store: mountStore,
},
});
});

let mergedOutput: CompilerOutput;
let errors: Array<CompilerErrorDetail | CompilerDiagnostic>;
if (compilerOutput.kind === 'ok') {
Expand Down
40 changes: 10 additions & 30 deletions compiler/apps/playground/components/Editor/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
import invariant from 'invariant';
import type {editor} from 'monaco-editor';
import * as monaco from 'monaco-editor';
import {Resizable} from 're-resizable';
import {useEffect, useState} from 'react';
import {renderReactCompilerMarkers} from '../../lib/reactCompilerMonacoDiagnostics';
import {useStore, useStoreDispatch} from '../StoreContext';
Expand Down Expand Up @@ -46,11 +45,6 @@ export default function Input({errors, language}: Props): JSX.Element {
details: errors,
source: store.source,
});
/**
* N.B. that `tabSize` is a model property, not an editor property.
* So, the tab size has to be set per model.
*/
model.updateOptions({tabSize: 2});
}, [monaco, errors, store.source]);

useEffect(() => {
Expand Down Expand Up @@ -152,38 +146,24 @@ export default function Input({errors, language}: Props): JSX.Element {
onMount={handleMount}
onChange={handleChange}
options={monacoOptions}
loading={''}
/>
);

const tabs = new Map([['Input', editorContent]]);
const [activeTab, setActiveTab] = useState('Input');

const tabbedContent = (
<div className="flex flex-col h-full">
<TabbedWindow
tabs={tabs}
activeTab={activeTab}
onTabChange={setActiveTab}
/>
</div>
);

return (
<div className="relative flex flex-col flex-none border-r border-gray-200">
{store.showInternals ? (
<Resizable
minWidth={550}
enable={{right: true}}
/**
* Restrict MonacoEditor's height, since the config autoLayout:true
* will grow the editor to fit within parent element
*/
className="!h-[calc(100vh_-_3.5rem)]">
{tabbedContent}
</Resizable>
) : (
<div className="!h-[calc(100vh_-_3.5rem)]">{tabbedContent}</div>
)}
<div className="!h-[calc(100vh_-_3.5rem)]">
<div className="flex flex-col h-full">
<TabbedWindow
tabs={tabs}
activeTab={activeTab}
onTabChange={setActiveTab}
/>
</div>
</div>
</div>
);
}
2 changes: 2 additions & 0 deletions compiler/apps/playground/components/Editor/Output.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@ function TextTabContent({
<DiffEditor
original={diff}
modified={output}
loading={''}
options={{
...monacoOptions,
readOnly: true,
Expand All @@ -338,6 +339,7 @@ function TextTabContent({
<MonacoEditor
language={language ?? 'javascript'}
value={output}
loading={''}
options={{
...monacoOptions,
readOnly: true,
Expand Down
2 changes: 2 additions & 0 deletions compiler/apps/playground/components/Editor/monacoOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,6 @@ export const monacoOptions: Partial<EditorProps['options']> = {
automaticLayout: true,
wordWrap: 'on',
wrappingIndent: 'same',

tabSize: 2,
};
Loading
Loading