Skip to content

⬅️ Back to Table of Contents

📄 Playground

📊 Analysis Summary

Metric Count
🔧 Functions 1
📦 Imports 33
💠 JSX Elements 23

📚 Table of Contents

🛠️ File Location:

📂 packages/website/src/components/Playground.tsx

📦 Imports

Name Source
ImperativePanelHandle react-resizable-panels
useWindowSize @docusaurus/theme-common
clsx clsx
useCallback react
useEffect react
useMemo react
useRef react
useState react
React react
Panel react-resizable-panels
PanelGroup react-resizable-panels
PanelResizeHandle react-resizable-panels
UpdateModel ./linter/types
ErrorGroup ./types
RuleDetails ./types
SelectedRange ./types
TabType ./types
ASTViewer ./ast/ASTViewer
ConfigEslint ./config/ConfigEslint
ConfigTypeScript ./config/ConfigTypeScript
EditorEmbed ./editor/EditorEmbed
LoadingEditor ./editor/LoadingEditor
ErrorsViewer ./ErrorsViewer
ErrorViewer ./ErrorsViewer
ESQueryFilter ./ESQueryFilter
useHashState ./hooks/useHashState
EditorTabs ./layout/EditorTabs
Loader ./layout/Loader
defaultConfig ./options
detailTabs ./options
OptionsSelector ./OptionsSelector
styles ./Playground.module.css
TypesDetails ./typeDetails/TypesDetails

JSX Elements

Component Type Props Children
div element className={styles.codeContainer}
PanelGroup component autoSaveId="playground-size", className={styles.panelGroup}, direction={windo... , , , ,
Panel component className={styles.PanelColumn}, collapsible={true}, defaultSize={windowSize =...
div element className={styles.playgroundMenu}
OptionsSelector component setState={setState}, state={state}, tsVersions={tsVersions} none
PanelResizeHandle component className={styles.PanelResizeHandle}, style={windowSize === 'mobile' ? { disp... none
Panel component className={styles.PanelColumn}, collapsible={true}, id="playgroundEditor" {isLoading && }, , {ActiveVisualEditor && ( <ActiveVisu...
Loader component none none
EditorTabs component active={activeTab}, change={setTab}, showModal={onVisualEditor}, showVisualEd... none
ActiveVisualEditor component className={styles.tabCode}, config={state[activeTab]}, onChange={setState}, r... none
div element className={clsx( styles.tabCode, ActiveVisualEditor && styles.hidden, )}, key...
EditorEmbed component none none
LoadingEditor component activeTab={activeTab}, onASTChange={setAstModel}, onChange={setState}, onLoad... none
PanelResizeHandle component className={styles.PanelResizeHandle} none
Panel component className={styles.PanelColumn}, collapsible={true}, id="playgroundInfo"
,
div element none , {state.showAST === 'es' && ( <ESQueryFilter defaultValue={state...
EditorTabs component active={state.showAST ?? false}, additionalTabsInfo={{ Errors: markers[active... none
ESQueryFilter component defaultValue={state.esQuery?.filter}, onChange={(filter, selector) => setStat... none
div element className={styles.playgroundInfoContainer} {state.showAST === 'es' && esQueryError ? ( <ErrorViewer title="Invalid Selec...
ErrorViewer component title="Invalid Selector", type="warning", value={esQueryError} none
TypesDetails component cursorPosition={position}, onHoverNode={setSelectedRange}, typeChecker={astMo... none
ASTViewer component cursorPosition={position}, enableScrolling={state.scroll}, filter={ state.sho... none
ErrorsViewer component value={markers[activeTab]} none

Functions

Playground(): React.JSX.Element

Returns: React.JSX.Element

Calls:

  • useWindowSize (from @docusaurus/theme-common)
  • useHashState (from ./hooks/useHashState)
  • useState (from react)
  • useRef (from react)
  • useMemo (from react)
  • Math.round
  • parseFloat
  • getComputedStyle
  • useCallback (from react)
  • setRuleNames
  • setTSVersion
  • setIsLoading
  • setVisualTSConfig
  • setVisualEslintRc
  • useEffect (from react)
  • playgroundMenuRef.current?.collapse
  • playgroundMenuRef.current?.expand
  • clsx (from clsx)
  • markers[activeTab].reduce
  • setState
Code
function Playground(): React.JSX.Element {
  const windowSize = useWindowSize();
  const [state, setState] = useHashState(defaultConfig);
  const [astModel, setAstModel] = useState<UpdateModel>();
  const [markers, setMarkers] = useState<Record<TabType, ErrorGroup[]>>({
    code: [],
    eslintrc: [],
    tsconfig: [],
  });
  const [ruleNames, setRuleNames] = useState<RuleDetails[]>([]);
  const [isLoading, setIsLoading] = useState(true);
  const [tsVersions, setTSVersion] = useState<readonly string[]>([]);
  const [selectedRange, setSelectedRange] = useState<SelectedRange>();
  const [position, setPosition] = useState<number>();
  const [activeTab, setTab] = useState<TabType>('code');
  const [esQueryError, setEsQueryError] = useState<Error>();
  const [visualEslintRc, setVisualEslintRc] = useState(false);
  const [visualTSConfig, setVisualTSConfig] = useState(false);
  const playgroundMenuRef = useRef<ImperativePanelHandle>(null);
  const optionsSize = useMemo(
    () =>
      Math.round(
        (parseFloat(getComputedStyle(document.documentElement).fontSize) *
          2000) /
          innerWidth,
      ),
    [],
  );

  const onLoaded = useCallback(
    (ruleNames: RuleDetails[], tsVersions: readonly string[]) => {
      setRuleNames(ruleNames);
      setTSVersion(tsVersions);
      setIsLoading(false);
    },
    [],
  );

  const ActiveVisualEditor =
    !isLoading &&
    {
      code: undefined,
      eslintrc: visualEslintRc && ConfigEslint,
      tsconfig: visualTSConfig && ConfigTypeScript,
    }[activeTab];

  const onVisualEditor = useCallback((tab: TabType) => {
    if (tab === 'tsconfig') {
      setVisualTSConfig(val => !val);
    } else if (tab === 'eslintrc') {
      setVisualEslintRc(val => !val);
    }
  }, []);

  useEffect(() => {
    if (windowSize === 'mobile') {
      playgroundMenuRef.current?.collapse();
    } else if (windowSize === 'desktop') {
      playgroundMenuRef.current?.expand();
    }
  }, [windowSize]);

  return (
    <div className={styles.codeContainer}>
      <PanelGroup
        autoSaveId="playground-size"
        className={styles.panelGroup}
        direction={windowSize === 'mobile' ? 'vertical' : 'horizontal'}
      >
        <Panel
          className={styles.PanelColumn}
          collapsible={true}
          defaultSize={windowSize === 'mobile' ? 0 : optionsSize}
          id="playgroundMenu"
          ref={playgroundMenuRef}
        >
          <div className={styles.playgroundMenu}>
            <OptionsSelector
              setState={setState}
              state={state}
              tsVersions={tsVersions}
            />
          </div>
        </Panel>
        <PanelResizeHandle
          className={styles.PanelResizeHandle}
          style={windowSize === 'mobile' ? { display: 'none' } : {}}
        />
        <Panel
          className={styles.PanelColumn}
          collapsible={true}
          id="playgroundEditor"
        >
          {isLoading && <Loader />}
          <EditorTabs
            active={activeTab}
            change={setTab}
            showModal={onVisualEditor}
            showVisualEditor={activeTab !== 'code'}
            tabs={['code', 'tsconfig', 'eslintrc']}
          />
          {ActiveVisualEditor && (
            <ActiveVisualEditor
              className={styles.tabCode}
              config={state[activeTab]}
              onChange={setState}
              ruleOptions={ruleNames}
            />
          )}
          <div
            className={clsx(
              styles.tabCode,
              ActiveVisualEditor && styles.hidden,
            )}
            key="monacoEditor"
          >
            <EditorEmbed />
          </div>
          <LoadingEditor
            {...state}
            activeTab={activeTab}
            onASTChange={setAstModel}
            onChange={setState}
            onLoaded={onLoaded}
            onMarkersChange={setMarkers}
            onSelect={setPosition}
            selectedRange={selectedRange}
          />
        </Panel>
        <PanelResizeHandle className={styles.PanelResizeHandle} />
        <Panel
          className={styles.PanelColumn}
          collapsible={true}
          id="playgroundInfo"
        >
          <div>
            <EditorTabs
              active={state.showAST ?? false}
              additionalTabsInfo={{
                Errors:
                  markers[activeTab].reduce(
                    (prev, cur) => prev + cur.items.length,
                    0,
                  ) || 0,
              }}
              change={showAST => setState({ showAST })}
              tabs={detailTabs}
            />
            {state.showAST === 'es' && (
              <ESQueryFilter
                defaultValue={state.esQuery?.filter}
                onChange={(filter, selector) =>
                  setState({ esQuery: { filter, selector } })
                }
                onError={setEsQueryError}
              />
            )}
          </div>
          <div className={styles.playgroundInfoContainer}>
            {state.showAST === 'es' && esQueryError ? (
              <ErrorViewer
                title="Invalid Selector"
                type="warning"
                value={esQueryError}
              />
            ) : state.showAST && astModel ? (
              state.showAST === 'types' && astModel.storedTsAST ? (
                <TypesDetails
                  cursorPosition={position}
                  onHoverNode={setSelectedRange}
                  typeChecker={astModel.typeChecker}
                  value={astModel.storedTsAST}
                />
              ) : (
                <ASTViewer
                  cursorPosition={position}
                  enableScrolling={state.scroll}
                  filter={
                    state.showAST === 'es' ? state.esQuery?.selector : undefined
                  }
                  key={state.showAST}
                  onHoverNode={setSelectedRange}
                  showTokens={state.showTokens}
                  value={
                    state.showAST === 'types'
                      ? undefined
                      : astModel[
                          `stored${({ es: 'AST', scope: 'Scope', ts: 'TsAST' } as const)[state.showAST]}` as const
                        ]
                  }
                />
              )
            ) : (
              <ErrorsViewer value={markers[activeTab]} />
            )}
          </div>
        </Panel>
      </PanelGroup>
    </div>
  );
}

Generated by Syntax Scribe