@samitouri / QOS-React-2 / commits / b932ce19a7

[playground] TabbedWindowItem lifting tabs state up

- List local state in TabbedWindowItem to Editor/index

jacdebug committed Nov 25, 2022 at 09:00 UTC b932ce19a712223a0a1961ccf0f26bf2b1775a70
3 files changed +57 -13
compiler/forget/packages/playground/components/Editor/Output.tsx
+6 -2
@@ -17,7 +17,7 @@ import prettierParserBabel from "prettier/parser-babel";
17 import { memo, useMemo } from "react";
18 import compileOldArchitecture from "../../lib/compilerDriver";
19 import type { Store } from "../../lib/stores";
20 -import TabbedWindow from "../TabbedWindow";
20 +import TabbedWindow, { TabTypes } from "../TabbedWindow";
21 import { monacoOptions } from "./monacoOptions";
22 const {
23 parseFunctions,
@@ -38,6 +38,8 @@ export default MemoizedOutput;
38 type Props = {
39 store: Store;
40 updateDiagnostics: (newDiags: Diagnostic[]) => void;
41 + tabsOpen: Map<TabTypes, boolean>;
42 + setTabsOpen: (newTab: Map<TabTypes, boolean>) => void;
43 };
44
45 type CompilerOutput = {
@@ -118,7 +120,7 @@ function compile(source: string): CompilerOutput | CompilerError {
120 }
121
122 // TODO(gsn: Update diagnostics ƒrom HIR output
121 -function Output({ store }: Props) {
123 +function Output({ store, setTabsOpen, tabsOpen }: Props) {
124 const compilerOutput = useMemo(() => compile(store.source), [store.source]);
125 const { outputs: oldCompilerOutputs } = useMemo(
126 () => compileOldArchitecture(store.source, store.compilerFlags),
@@ -139,6 +141,8 @@ function Output({ store }: Props) {
141 return (
142 <TabbedWindow
143 defaultTab="HIR"
144 + setTabsOpen={setTabsOpen}
145 + tabsOpen={tabsOpen}
146 tabs={{
147 HIR: (
148 <TextTabContent output={compilerOutput.hirOutput}></TextTabContent>
compiler/forget/packages/playground/components/Editor/index.tsx
+8 -1
@@ -21,6 +21,7 @@ import {
21 type Store,
22 } from "../../lib/stores";
23 import { useStore, useStoreDispatch } from "../StoreContext";
24 +import { TabTypes } from "../TabbedWindow";
25 import Input from "./Input";
26 import Output from "./Output";
27
@@ -41,6 +42,7 @@ export default function Editor() {
42 (newDiags: Diagnostic[]) => setDiagnostics(newDiags),
43 [setDiagnostics]
44 );
45 + const [tabsOpen, setTabsOpen] = useState<Map<TabTypes, boolean>>(new Map());
46
47 /**
48 * Initialize store from encoded data or fallback to the default store.
@@ -90,7 +92,12 @@ export default function Editor() {
92 hidden: !showOutputOnMobile,
93 })}
94 >
93 - <Output store={deferredStore} updateDiagnostics={updateDiagnostics} />
95 + <Output
96 + tabsOpen={tabsOpen}
97 + setTabsOpen={setTabsOpen}
98 + store={deferredStore}
99 + updateDiagnostics={updateDiagnostics}
100 + />
101 </div>
102 </div>
103 <button
compiler/forget/packages/playground/components/TabbedWindow.tsx
+43 -10
@@ -6,16 +6,39 @@
6 */
7
8 import clsx from "clsx";
9 -import React, { useState } from "react";
9 +import React, { useCallback, useState } from "react";
10 +
11 +export type TabTypes =
12 + | "HIR"
13 + | "SSA"
14 + | "EliminateRedundantPhi"
15 + | "InferReferenceEffects"
16 + | "InferMutableRanges"
17 + | "LeaveSSA"
18 + | "JS"
19 + | "SourceMap"
20 + | "OldArchitecture";
21 +
22 +type TabsRecord = Record<TabTypes, React.ReactNode>;
23
24 export default function TabbedWindow(props: {
25 defaultTab: string | null;
13 - tabs: { [name: string]: React.ReactNode };
26 + tabs: TabsRecord;
27 + tabsOpen: Map<TabTypes, boolean>;
28 + setTabsOpen: (newTab: Map<TabTypes, boolean>) => void;
29 }): React.ReactElement {
30 return (
31 <div className="flex flex-row h-full">
32 {Object.keys(props.tabs).map((name, index, all) => {
18 - return <TabbedWindowItem name={name} key={index} tabs={props.tabs} />;
33 + return (
34 + <TabbedWindowItem
35 + name={name as TabTypes}
36 + key={index}
37 + tabs={props.tabs}
38 + tabsOpen={props.tabsOpen}
39 + setTabsOpen={props.setTabsOpen}
40 + />
41 + );
42 })}
43 </div>
44 );
@@ -24,19 +47,29 @@ export default function TabbedWindow(props: {
47 function TabbedWindowItem({
48 name,
49 tabs,
50 + tabsOpen,
51 + setTabsOpen,
52 }: {
28 - name: string;
29 - tabs: { [name: string]: React.ReactNode };
53 + name: TabTypes;
54 + tabs: TabsRecord;
55 + tabsOpen: Map<TabTypes, boolean>;
56 + setTabsOpen: (newTab: Map<TabTypes, boolean>) => void;
57 }): React.ReactElement {
31 - const [isShow, setIsShow] = useState<boolean>(false);
58 + const isShow = tabsOpen.get(name) ?? false;
59 +
60 + const toggleTabs = useCallback(() => {
61 + const nextState = new Map(tabsOpen);
62 + nextState.set(name, !isShow);
63 + setTabsOpen(nextState);
64 + }, [tabsOpen, name, isShow, setTabsOpen]);
65
66 return (
67 <div key={name} className="flex flex-row">
68 {isShow ? (
69 <div style={{ minWidth: 500 }}>
70 <h2
38 - onClick={() => setIsShow(!isShow)}
39 - className="p-4 border-b cursor-pointer border-grey-200"
71 + onClick={toggleTabs}
72 + className="p-4 duration-150 ease-in border-b cursor-pointer border-grey-200 text-secondary hover:text-link"
73 >
74 - {name}
75 </h2>
@@ -46,8 +79,8 @@ function TabbedWindowItem({
79 <div className="relative items-center h-full px-4 py-8 align-middle border-r border-grey-200">
80 <button
81 style={{ transform: "rotate(90deg) translate(-50%)" }}
49 - onClick={() => setIsShow(!isShow)}
50 - className="flex-grow-0 w-5 transition-colors duration-150 ease-in"
82 + onClick={toggleTabs}
83 + className="flex-grow-0 w-5 transition-colors duration-150 ease-in text-secondary hover:text-link"
84 >
85 {`+${name}`}
86 </button>