compiler/apps/playground/components/Editor/ConfigEditor.tsx TYPESCRIPT 207 lines View on github.com → Search inside
1/**2 * Copyright (c) Meta Platforms, Inc. and affiliates.3 *4 * This source code is licensed under the MIT license found in the5 * LICENSE file in the root directory of this source tree.6 */78import MonacoEditor, {loader, type Monaco} from '@monaco-editor/react';9import type {editor} from 'monaco-editor';10import * as monaco from 'monaco-editor';11import React, {12  useState,13  useRef,14  unstable_ViewTransition as ViewTransition,15  unstable_addTransitionType as addTransitionType,16  startTransition,17} from 'react';18import {Resizable} from 're-resizable';19import {useStore, useStoreDispatch} from '../StoreContext';20import {monacoConfigOptions} from './monacoOptions';21import {IconChevron} from '../Icons/IconChevron';22import {CONFIG_PANEL_TRANSITION} from '../../lib/transitionTypes';2324loader.config({monaco});2526export default function ConfigEditor({27  formattedAppliedConfig,28}: {29  formattedAppliedConfig: string;30}): React.ReactElement {31  const [isExpanded, setIsExpanded] = useState(false);3233  // TODO: Add back <Activity> after upgrading next.js34  return (35    <>36      <div37        style={{38          display: isExpanded ? 'block' : 'none',39        }}>40        {/* <Activity mode={isExpanded ? 'visible' : 'hidden'}> */}41        <ExpandedEditor42          onToggle={() => {43            startTransition(() => {44              addTransitionType(CONFIG_PANEL_TRANSITION);45              setIsExpanded(false);46            });47          }}48          formattedAppliedConfig={formattedAppliedConfig}49        />50      </div>51      <div52        style={{53          display: !isExpanded ? 'block' : 'none',54        }}>55        {/* </Activity>56        <Activity mode={isExpanded ? 'hidden' : 'visible'}></Activity> */}57        <CollapsedEditor58          onToggle={() => {59            startTransition(() => {60              addTransitionType(CONFIG_PANEL_TRANSITION);61              setIsExpanded(true);62            });63          }}64        />65      </div>66      {/* </Activity> */}67    </>68  );69}7071function ExpandedEditor({72  onToggle,73  formattedAppliedConfig,74}: {75  onToggle: (expanded: boolean) => void;76  formattedAppliedConfig: string;77}): React.ReactElement {78  const store = useStore();79  const dispatchStore = useStoreDispatch();80  const debounceTimerRef = useRef<NodeJS.Timeout | null>(null);8182  const handleChange: (value: string | undefined) => void = (83    value: string | undefined,84  ) => {85    if (value === undefined) return;8687    if (debounceTimerRef.current) {88      clearTimeout(debounceTimerRef.current);89    }9091    debounceTimerRef.current = setTimeout(() => {92      dispatchStore({93        type: 'updateConfig',94        payload: {95          config: value,96        },97      });98    }, 500); // 500ms debounce delay99  };100101  const handleMount: (102    _: editor.IStandaloneCodeEditor,103    monaco: Monaco,104  ) => void = (_, monaco) => {105    // Enable comments in JSON for JSON5-style config106    monaco.languages.json.jsonDefaults.setDiagnosticsOptions({107      allowComments: true,108      trailingCommas: 'ignore',109    });110  };111112  return (113    <ViewTransition114      update={{[CONFIG_PANEL_TRANSITION]: 'slide-in', default: 'none'}}>115      {/* enter={{[CONFIG_PANEL_TRANSITION]: 'slide-in', default: 'none'}}116      exit={{[CONFIG_PANEL_TRANSITION]: 'slide-out', default: 'none'}}> */}117      <Resizable118        minWidth={300}119        maxWidth={600}120        defaultSize={{width: 350}}121        enable={{right: true, bottom: false}}>122        <div className="bg-blue-10 relative h-full flex flex-col !h-[calc(100vh_-_3.5rem)] border border-gray-300">123          <div124            className="absolute w-8 h-16 bg-blue-10 rounded-r-full flex items-center justify-center z-[2] cursor-pointer border border-l-0 border-gray-300"125            title="Minimize config editor"126            onClick={onToggle}127            style={{128              top: '50%',129              marginTop: '-32px',130              right: '-32px',131              borderTopLeftRadius: 0,132              borderBottomLeftRadius: 0,133            }}>134            <IconChevron displayDirection="left" className="text-blue-50" />135          </div>136137          <div className="flex-1 flex flex-col m-2 mb-2">138            <div className="pb-2">139              <h2 className="inline-block text-blue-50 py-1.5 px-1.5 xs:px-3 sm:px-4 text-sm">140                Config Overrides141              </h2>142            </div>143            <div className="flex-1 border border-gray-300">144              <MonacoEditor145                path={'config.json5'}146                language={'json'}147                value={store.config}148                onMount={handleMount}149                onChange={handleChange}150                loading={''}151                className="monaco-editor-config"152                options={monacoConfigOptions}153              />154            </div>155          </div>156          <div className="flex-1 flex flex-col m-2">157            <div className="pb-2">158              <h2 className="inline-block text-blue-50 py-1.5 px-1.5 xs:px-3 sm:px-4 text-sm">159                Applied Configs160              </h2>161            </div>162            <div className="flex-1 border border-gray-300">163              <MonacoEditor164                path={'applied-config.js'}165                language={'javascript'}166                value={formattedAppliedConfig}167                loading={''}168                className="monaco-editor-applied-config"169                options={{170                  ...monacoConfigOptions,171                  readOnly: true,172                }}173              />174            </div>175          </div>176        </div>177      </Resizable>178    </ViewTransition>179  );180}181182function CollapsedEditor({183  onToggle,184}: {185  onToggle: () => void;186}): React.ReactElement {187  return (188    <div189      className="w-4 !h-[calc(100vh_-_3.5rem)]"190      style={{position: 'relative'}}>191      <div192        className="absolute w-10 h-16 bg-blue-10 hover:translate-x-2 transition-transform rounded-r-full flex items-center justify-center z-[2] cursor-pointer border border-gray-300"193        title="Expand config editor"194        onClick={onToggle}195        style={{196          top: '50%',197          marginTop: '-32px',198          left: '-8px',199          borderTopLeftRadius: 0,200          borderBottomLeftRadius: 0,201        }}>202        <IconChevron displayDirection="right" className="text-blue-50" />203      </div>204    </div>205  );206}

Findings

✓ No findings reported for this file.

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.