Skip to content

⬅️ Back to Table of Contents

📄 Playground.tsx

📊 Analysis Summary

Metric Count
🔧 Functions 1
📦 Imports 33
📊 Variables & Constants 1
💠 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

Variables & Constants

Name Type Kind Value Exported
ActiveVisualEditor any const `!isLoading &&
{
code: undefined,
eslintrc: visualEslintRc && ConfigEslint,
tsconfig: visualTSConfig && ConfigTypeScript,
}[activeTab]`

JSX Elements

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

Functions

Playground(): React.JSX.Element

Code
function Playground(): React.JSX.Element {
  const windowSize = useWindowSize();
  const [state, setState] = useHashState(defaultConfig);
  const [astModel, setAstModel] = useState<UpdateModel>();
  const [markers, setMarkers] = useState<ErrorGroup[]>();
  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?.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} />
            )}
          </div>
        </Panel>
      </PanelGroup>
    </div>
  );
}
  • Return Type: 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?.reduce
  • setState