diff --git a/editor-packages/editor-debugger/package.json b/editor-packages/editor-debugger/package.json deleted file mode 100644 index 7569c855..00000000 --- a/editor-packages/editor-debugger/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "@code-editor/debugger", - "version": "0.0.0", - "private": false -} \ No newline at end of file diff --git a/editor-packages/editor-devtools/components/console-feed/index.ts b/editor-packages/editor-devtools/components/console-feed/index.ts new file mode 100644 index 00000000..9977fad1 --- /dev/null +++ b/editor-packages/editor-devtools/components/console-feed/index.ts @@ -0,0 +1 @@ +export * from "./window-console-feed"; diff --git a/editor-packages/editor-devtools/components/console-feed/window-console-feed.tsx b/editor-packages/editor-devtools/components/console-feed/window-console-feed.tsx new file mode 100644 index 00000000..4d01f97f --- /dev/null +++ b/editor-packages/editor-devtools/components/console-feed/window-console-feed.tsx @@ -0,0 +1,24 @@ +import React, { useEffect, useState } from "react"; +import { Console, Hook, Unhook } from "@code-editor/console-feed"; + +export function WindowConsoleFeed({ style }: { style?: React.CSSProperties }) { + const [logs, setLogs] = useState([]); + + useEffect(() => { + // run once + Hook( + window.console, + (log) => setLogs((currLogs) => [...currLogs, log]), + false + ); + return () => { + Unhook(window.console as any); + }; + }, []); + + return ( +
+ +
+ ); +} diff --git a/editor-packages/editor-devtools/components/index.ts b/editor-packages/editor-devtools/components/index.ts new file mode 100644 index 00000000..72091986 --- /dev/null +++ b/editor-packages/editor-devtools/components/index.ts @@ -0,0 +1,4 @@ +export * from "./tab"; +export * from "./tab-badge"; +export * from "./console-feed"; +export * from "./visualization"; diff --git a/editor-packages/editor-devtools/components/tab-badge/index.tsx b/editor-packages/editor-devtools/components/tab-badge/index.tsx new file mode 100644 index 00000000..e1293e22 --- /dev/null +++ b/editor-packages/editor-devtools/components/tab-badge/index.tsx @@ -0,0 +1,52 @@ +import React from "react"; +import styled from "@emotion/styled"; + +const bgcolortypemap = { + default: "rgba(255, 255, 255, 0.1)", + warning: "rgba(255, 230, 0, 0.1)", + error: "rgba(255, 0, 0, 0.1)", +}; + +export function TabBadge({ + type = "default", + value, +}: { + type?: "default" | "warning" | "error"; + value: string | number; +}) { + const background = bgcolortypemap[type]; + + if (value === undefined || value === null) { + return <>; + } + + return ( + + {value} + + ); +} + +const Value = styled.span` + color: rgb(151, 151, 151); + text-overflow: ellipsis; + font-size: 10px; + font-family: Inter, sans-serif; + font-weight: 400; + text-align: center; +`; + +const BaseDevtoolsTabBadge = styled.div<{ background: string }>` + display: flex; + justify-content: center; + flex-direction: column; + align-items: center; + flex: none; + gap: 10px; + border-radius: 50%; + width: 18px; + height: 18px; + background-color: ${(p) => p.background}; + box-sizing: border-box; + padding: 10px; +`; diff --git a/editor-packages/editor-devtools/components/tab/index.tsx b/editor-packages/editor-devtools/components/tab/index.tsx new file mode 100644 index 00000000..e3238b62 --- /dev/null +++ b/editor-packages/editor-devtools/components/tab/index.tsx @@ -0,0 +1,50 @@ +import React from "react"; +import styled from "@emotion/styled"; +import { TabBadge } from "../tab-badge"; + +export function DevtoolsTab({ + label, + badge, + selected, + onTap, +}: { + selected?: boolean; + label: string; + badge?: string | number; + onTap?: () => void; +}) { + return ( + + + + + ); +} + +const TabBase = styled.div` + cursor: pointer; + user-select: none; + display: flex; + justify-content: flex-start; + flex-direction: row; + align-items: center; + gap: 8px; + box-sizing: border-box; +`; + +const Label = styled.span` + color: rgb(151, 151, 151); + text-overflow: ellipsis; + font-size: 12px; + font-family: Inter, sans-serif; + font-weight: 400; + text-align: left; + + &:hover { + color: white; + } + + &[data-selected="true"] { + color: white; + } +`; diff --git a/editor-packages/editor-debugger/components/visualization/README.md b/editor-packages/editor-devtools/components/visualization/README.md similarity index 100% rename from editor-packages/editor-debugger/components/visualization/README.md rename to editor-packages/editor-devtools/components/visualization/README.md diff --git a/editor-packages/editor-debugger/components/visualization/index.ts b/editor-packages/editor-devtools/components/visualization/index.ts similarity index 100% rename from editor-packages/editor-debugger/components/visualization/index.ts rename to editor-packages/editor-devtools/components/visualization/index.ts diff --git a/editor-packages/editor-debugger/components/visualization/json-visualization/json-tree.tsx b/editor-packages/editor-devtools/components/visualization/json-visualization/json-tree.tsx similarity index 100% rename from editor-packages/editor-debugger/components/visualization/json-visualization/json-tree.tsx rename to editor-packages/editor-devtools/components/visualization/json-visualization/json-tree.tsx diff --git a/editor-packages/editor-debugger/components/visualization/node-visualization/index.ts b/editor-packages/editor-devtools/components/visualization/node-visualization/index.ts similarity index 100% rename from editor-packages/editor-debugger/components/visualization/node-visualization/index.ts rename to editor-packages/editor-devtools/components/visualization/node-visualization/index.ts diff --git a/editor-packages/editor-debugger/components/visualization/node-visualization/tree-view.tsx b/editor-packages/editor-devtools/components/visualization/node-visualization/tree-view.tsx similarity index 100% rename from editor-packages/editor-debugger/components/visualization/node-visualization/tree-view.tsx rename to editor-packages/editor-devtools/components/visualization/node-visualization/tree-view.tsx diff --git a/editor-packages/editor-debugger/debugger-panel.tsx b/editor-packages/editor-devtools/debugger-panel.tsx similarity index 95% rename from editor-packages/editor-debugger/debugger-panel.tsx rename to editor-packages/editor-devtools/debugger-panel.tsx index f3a851ad..74660f5e 100644 --- a/editor-packages/editor-debugger/debugger-panel.tsx +++ b/editor-packages/editor-devtools/debugger-panel.tsx @@ -2,7 +2,7 @@ import React, { useEffect, useRef, useState } from "react"; import styled from "@emotion/styled"; import { useRouter } from "next/router"; import { ClearRemoteDesignSessionCache } from "components/clear-remote-design-session-cache"; -import { WidgetTree } from "@code-editor/debugger/components/visualization/json-visualization/json-tree"; +import { WidgetTree } from "@code-editor/devtools/components/visualization/json-visualization/json-tree"; import Link from "next/link"; export const Debugger = ({ diff --git a/editor-packages/editor-debugger/index.ts b/editor-packages/editor-devtools/index.ts similarity index 53% rename from editor-packages/editor-debugger/index.ts rename to editor-packages/editor-devtools/index.ts index 86b95544..3c4e44c4 100644 --- a/editor-packages/editor-debugger/index.ts +++ b/editor-packages/editor-devtools/index.ts @@ -1 +1,2 @@ export * from "./debugger-panel"; +export * from "./components"; diff --git a/editor-packages/editor-devtools/package.json b/editor-packages/editor-devtools/package.json new file mode 100644 index 00000000..a3451301 --- /dev/null +++ b/editor-packages/editor-devtools/package.json @@ -0,0 +1,8 @@ +{ + "name": "@code-editor/devtools", + "version": "0.0.0", + "private": false, + "dependencies": { + "@code-editor/console-feed": "^3.3.1" + } +} \ No newline at end of file diff --git a/editor-packages/editor-preview-pip/lib/resizable-pip.tsx b/editor-packages/editor-preview-pip/lib/resizable-pip.tsx index ed71e430..66054b0f 100644 --- a/editor-packages/editor-preview-pip/lib/resizable-pip.tsx +++ b/editor-packages/editor-preview-pip/lib/resizable-pip.tsx @@ -2,7 +2,10 @@ import React from "react"; import PIP from "./pip"; import { ResizableBox } from "react-resizable"; import "react-resizable/css/styles.css"; -import type { ResizableBoxProps as RawResizableBoxProps } from "react-resizable"; +import type { + ResizableBoxProps as RawResizableBoxProps, + ResizableProps, +} from "react-resizable"; import styled from "@emotion/styled"; interface ResizableBoxProps @@ -17,7 +20,7 @@ interface ResizableBoxProps * resize handle to display - a react component * @default none */ - resizeHandle?: React.ReactNode; + resizeHandle?: ResizableProps["handle"]; /** * @default 500 */ diff --git a/editor-packages/editor-services-esbuild/index.ts b/editor-packages/editor-services-esbuild/index.ts index 724ac3e3..d3cd8782 100644 --- a/editor-packages/editor-services-esbuild/index.ts +++ b/editor-packages/editor-services-esbuild/index.ts @@ -44,7 +44,6 @@ const bundler = async (rawCode: string, lang: Loader) => { return { code: result.outputFiles[0].text, err: null }; } catch (error: any) { - console.error("esbuild error: ", error); return { code: null, err: { method: "error", data: [error.message], id: nanoid() }, diff --git a/editor/components/app-runner/vanilla-esbuild-app-runner.tsx b/editor/components/app-runner/vanilla-esbuild-app-runner.tsx index 7a5b9aec..27d4549d 100644 --- a/editor/components/app-runner/vanilla-esbuild-app-runner.tsx +++ b/editor/components/app-runner/vanilla-esbuild-app-runner.tsx @@ -1,5 +1,6 @@ import React, { useCallback, useEffect, useRef, useState } from "react"; import { VanillaRunner } from "components/app-runner/vanilla-app-runner"; +import { useDispatch } from "core/dispatch"; export function VanillaESBuildAppRunner({ doc, @@ -13,6 +14,17 @@ export function VanillaESBuildAppRunner({ }; }) { const ref = useRef(); + const dispatch = useDispatch(); + + const consoleLog = useCallback( + (p: { method; data }) => { + dispatch({ + type: "devtools-console", + log: p, + }); + }, + [dispatch] + ); const loadCode = useCallback( (e: HTMLIFrameElement) => { @@ -29,6 +41,22 @@ export function VanillaESBuildAppRunner({ } }, [doc?.html, doc?.css, doc?.javascript]); + useEffect(() => { + const handler = (event: any) => { + if (event.data.type === "console") { + console[event.data.method](JSON.parse(event.data.data).join(" ")); + consoleLog({ + method: event.data.method, + data: JSON.parse(event.data.data), + }); + } + }; + + window.addEventListener("message", handler); + + return () => window.removeEventListener("message", handler); + }, []); + return ( {} @@ -35,8 +35,10 @@ export function CodeEditor({ diff --git a/editor/components/editor-hierarchy/editor-layer-hierarchy/index.tsx b/editor/components/editor-hierarchy/editor-layer-hierarchy/index.tsx index 2da02d95..0cdf2a58 100644 --- a/editor/components/editor-hierarchy/editor-layer-hierarchy/index.tsx +++ b/editor/components/editor-hierarchy/editor-layer-hierarchy/index.tsx @@ -1,9 +1,9 @@ import React, { useState } from "react"; import styled from "@emotion/styled"; -import TreeView from "@material-ui/lab/TreeView"; -import ExpandMoreIcon from "@material-ui/icons/ExpandMore"; -import ChevronRightIcon from "@material-ui/icons/ChevronRight"; -import TreeItem from "@material-ui/lab/TreeItem"; +import TreeView from "@mui/lab/TreeView"; +import TreeItem from "@mui/lab/TreeItem"; +import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; +import ChevronRightIcon from "@mui/icons-material/ChevronRight"; import { SideNavigation } from "components/side-navigation"; interface LayerTree { diff --git a/editor/components/editor/editor-appbar/editor-appbar-fragment-for-sidebar.tsx b/editor/components/editor/editor-appbar/editor-appbar-fragment-for-sidebar.tsx index e0cc5d59..93819795 100644 --- a/editor/components/editor/editor-appbar/editor-appbar-fragment-for-sidebar.tsx +++ b/editor/components/editor/editor-appbar/editor-appbar-fragment-for-sidebar.tsx @@ -1,6 +1,6 @@ import React from "react"; import styled from "@emotion/styled"; -import { ArrowBack } from "@material-ui/icons"; +import { ArrowBack } from "@mui/icons-material"; import { useRouter } from "next/router"; import { colors } from "theme"; import ClientOnly from "components/client-only"; diff --git a/editor/components/index.ts b/editor/components/index.ts index 301a4145..d6613956 100644 --- a/editor/components/index.ts +++ b/editor/components/index.ts @@ -2,5 +2,5 @@ export * as figmacomp from "./figma"; export * as canvas from "./design-preview-as-is"; export * as code from "./code-editor"; export * as runner from "./app-runner"; -export * as visualization from "../../editor-packages/editor-debugger/components/visualization"; +export * as visualization from "../../editor-packages/editor-devtools/components/visualization"; export * from "./client-only"; diff --git a/editor/core/actions/index.ts b/editor/core/actions/index.ts index 784ee1a1..54187be4 100644 --- a/editor/core/actions/index.ts +++ b/editor/core/actions/index.ts @@ -1,5 +1,5 @@ import type { FrameworkConfig } from "@designto/config"; -import type { EditorState, ScenePreviewData } from "core/states"; +import type { ConsoleLog, EditorState, ScenePreviewData } from "core/states"; export type WorkspaceAction = // @@ -20,7 +20,8 @@ export type Action = | HighlightLayerAction | CanvasModeAction | PreviewAction - | CodeEditorAction; + | CodeEditorAction + | DevtoolsAction; export type ActionType = Action["type"]; @@ -74,3 +75,13 @@ export interface CodeEditorEditComponentCodeAction { componentName: string; raw: string; } + +export type DevtoolsAction = DevtoolsConsoleAction | DevtoolsConsoleClearAction; +export interface DevtoolsConsoleAction { + type: "devtools-console"; + log: ConsoleLog; +} + +export interface DevtoolsConsoleClearAction { + type: "devtools-console-clear"; +} diff --git a/editor/core/reducers/editor-reducer.ts b/editor/core/reducers/editor-reducer.ts index c8e97dca..91e2e05d 100644 --- a/editor/core/reducers/editor-reducer.ts +++ b/editor/core/reducers/editor-reducer.ts @@ -8,6 +8,8 @@ import type { CanvasModeGobackAction, PreviewBuildingStateUpdateAction, PreviewSetAction, + DevtoolsConsoleAction, + DevtoolsConsoleClearAction, } from "core/actions"; import { EditorState } from "core/states"; import { useRouter } from "next/router"; @@ -153,6 +155,35 @@ export function editorReducer(state: EditorState, action: Action): EditorState { draft.currentPreview = data; // set }); } + case "devtools-console": { + const { log } = action; + return produce(state, (draft) => { + if (!draft.devtoolsConsole?.logs?.length) { + draft.devtoolsConsole = { logs: [] }; + } + + const logs = Array.from(state.devtoolsConsole?.logs ?? []); + logs.push(log); + + draft.devtoolsConsole.logs = logs; + }); + break; + } + case "devtools-console-clear": { + const {} = action; + return produce(state, (draft) => { + if (draft.devtoolsConsole?.logs?.length) { + draft.devtoolsConsole.logs = [ + { + id: "clear", + method: "info", + data: ["Console was cleared"], + }, + ]; + } + }); + break; + } default: throw new Error(`Unhandled action type: ${action["type"]}`); } diff --git a/editor/core/states/editor-state.ts b/editor/core/states/editor-state.ts index 8bbe99a8..855ec2f2 100644 --- a/editor/core/states/editor-state.ts +++ b/editor/core/states/editor-state.ts @@ -27,6 +27,7 @@ export interface EditorState { currentPreview?: ScenePreviewData; code?: CodeRepository; editingModule?: EditingModule; + devtoolsConsole?: DevtoolsConsole; } export interface EditorSnapshot { @@ -109,3 +110,24 @@ export interface EditingModule { lang: string; raw: string; } + +interface DevtoolsConsole { + logs: ConsoleLog[]; +} + +export interface ConsoleLog { + id?: string; + data: any[]; + method: + | "log" + | "debug" + | "info" + | "warn" + | "error" + | "table" + | "clear" + | "time" + | "timeEnd" + | "count" + | "assert"; +} diff --git a/editor/icons/icon-angle-down.tsx b/editor/icons/icon-angle-down.tsx new file mode 100644 index 00000000..2ebd19ef --- /dev/null +++ b/editor/icons/icon-angle-down.tsx @@ -0,0 +1,21 @@ +import React from "react"; + +export const AngleDownIcon = (props) => { + return ( + + + + ); +}; diff --git a/editor/icons/icon-angle-up.tsx b/editor/icons/icon-angle-up.tsx new file mode 100644 index 00000000..9d8e9041 --- /dev/null +++ b/editor/icons/icon-angle-up.tsx @@ -0,0 +1,21 @@ +import React from "react"; + +export const AngleUpIcon = (props) => { + return ( + + + + ); +}; diff --git a/editor/icons/icon-trash.tsx b/editor/icons/icon-trash.tsx new file mode 100644 index 00000000..753f2593 --- /dev/null +++ b/editor/icons/icon-trash.tsx @@ -0,0 +1,28 @@ +import React from "react"; + +export const TrashIcon = (props) => { + return ( + + + + + ); +}; diff --git a/editor/layouts/app-menu/app-menu.tsx b/editor/layouts/app-menu/app-menu.tsx deleted file mode 100644 index 450d8931..00000000 --- a/editor/layouts/app-menu/app-menu.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import React from "react"; -import Button from "@material-ui/core/Button"; -import Menu from "@material-ui/core/Menu"; -import MenuItem from "@material-ui/core/MenuItem"; -import styled from "@emotion/styled"; - -export function AppMenu() { - const [anchorEl, setAnchorEl] = React.useState(null); - - const handleClick = (event: React.MouseEvent) => { - setAnchorEl(event.currentTarget); - }; - - const handleClose = () => { - setAnchorEl(null); - }; - - const handleLoadDesignClick = () => { - console.log("load design click. open design loader prompt"); - handleClose(); - }; - - return ( - - - - Load design - - - ); -} - -const AppMenuRoot = styled.div` - flex-grow: 0; -`; diff --git a/editor/layouts/app-menu/index.ts b/editor/layouts/app-menu/index.ts deleted file mode 100644 index 2d3bd3ec..00000000 --- a/editor/layouts/app-menu/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./app-menu"; diff --git a/editor/layouts/default-editor-workspace-layout.tsx b/editor/layouts/default-editor-workspace-layout.tsx index 470bc6de..1c8a1bdb 100644 --- a/editor/layouts/default-editor-workspace-layout.tsx +++ b/editor/layouts/default-editor-workspace-layout.tsx @@ -1,6 +1,5 @@ import styled from "@emotion/styled"; import React from "react"; -import { AppMenu } from "./app-menu"; import { Resizable } from "re-resizable"; type SidebarElementSignature = diff --git a/editor/next.config.js b/editor/next.config.js index 29a4f9a2..68120387 100644 --- a/editor/next.config.js +++ b/editor/next.config.js @@ -3,7 +3,7 @@ const withTM = require("next-transpile-modules")([ // region @editor-app "@editor-app/live-session", "@code-editor/preview-pip", // TODO: remove me. this is for development. for production, use npm ver instead. - "@code-editor/debugger", + "@code-editor/devtools", "@code-editor/canvas", // region editor-submodule deps diff --git a/editor/package.json b/editor/package.json index 32c94541..23792f53 100644 --- a/editor/package.json +++ b/editor/package.json @@ -19,11 +19,11 @@ "@emotion/css": "^11.5.0", "@emotion/react": "^11.1.5", "@emotion/styled": "^11.1.5", - "@material-ui/core": "^4.12.3", - "@material-ui/icons": "^4.11.2", - "@material-ui/lab": "^4.0.0-alpha.60", "@modulz/design-system": "^0.6.1", "@monaco-editor/react": "^4.4.1", + "@mui/icons-material": "^5.6.1", + "@mui/lab": "^5.0.0-alpha.77", + "@mui/material": "^5.6.1", "@reflect-blocks/figma-embed": "^0.0.5", "@use-gesture/react": "^10.2.11", "@visx/gradient": "^1.7.0", diff --git a/editor/pages/_app.tsx b/editor/pages/_app.tsx index 1aa02f62..0caa7db1 100644 --- a/editor/pages/_app.tsx +++ b/editor/pages/_app.tsx @@ -3,6 +3,7 @@ import { Global, css } from "@emotion/react"; import Head from "next/head"; import Script from "next/script"; import { EditorThemeProvider } from "@editor-ui/theme"; +import { MuiThemeProvider } from "theme/mui"; import { colors } from "theme"; import { useRouter } from "next/router"; @@ -146,9 +147,11 @@ function EditorApp({ Component, pageProps }) { return ( - - - + + + + + ); } diff --git a/editor/pages/_development/code-editor/index.tsx b/editor/pages/_development/code-editor/index.tsx index 61ea4395..c4392672 100644 --- a/editor/pages/_development/code-editor/index.tsx +++ b/editor/pages/_development/code-editor/index.tsx @@ -8,11 +8,11 @@ export default function CodeEditorDevPage() { language: "typescript", raw: `export * from "./components"`, }, - "components/index.ts": { - name: "index.ts", - language: "typescript", - raw: `export * from "./app-bar"`, - }, + // "components/index.ts": { + // name: "index.ts", + // language: "typescript", + // raw: `export * from "./app-bar"`, + // }, }; return ; diff --git a/editor/pages/figma/inspect-component.tsx b/editor/pages/figma/inspect-component.tsx index f3cdac37..18cb5e25 100644 --- a/editor/pages/figma/inspect-component.tsx +++ b/editor/pages/figma/inspect-component.tsx @@ -4,12 +4,12 @@ import { tokenize } from "@designto/token"; import React from "react"; import { canvas } from "components"; import { LayerHierarchy } from "components/editor-hierarchy"; -import { visualize_node } from "@code-editor/debugger/components/visualization"; +import { visualize_node } from "@code-editor/devtools/components/visualization"; import { JsonTree, WidgetTree, WidgetTreeLegend, -} from "@code-editor/debugger/components/visualization/json-visualization/json-tree"; +} from "@code-editor/devtools/components/visualization/json-visualization/json-tree"; import { DefaultEditorWorkspaceLayout } from "layouts/default-editor-workspace-layout"; import LoadingLayout from "layouts/loading-overlay"; import { diff --git a/editor/pages/figma/to-reflect.tsx b/editor/pages/figma/to-reflect.tsx index 7f5145b3..b4e7217d 100644 --- a/editor/pages/figma/to-reflect.tsx +++ b/editor/pages/figma/to-reflect.tsx @@ -1,8 +1,8 @@ import React, { useState } from "react"; import { canvas } from "components"; import { ReflectSceneNode } from "@design-sdk/core"; -import { visualize_node } from "@code-editor/debugger/components/visualization"; -import { JsonTree } from "@code-editor/debugger/components/visualization/json-visualization/json-tree"; +import { visualize_node } from "@code-editor/devtools/components/visualization"; +import { JsonTree } from "@code-editor/devtools/components/visualization/json-visualization/json-tree"; import { useReflectTargetNode } from "../../query/from-figma"; export default function FigmaToReflectNodePage() { diff --git a/editor/pages/figma/to-token.tsx b/editor/pages/figma/to-token.tsx index ae27ff47..7b0f04f5 100644 --- a/editor/pages/figma/to-token.tsx +++ b/editor/pages/figma/to-token.tsx @@ -4,7 +4,7 @@ import { tokenize } from "@designto/token"; import { JsonTree, WidgetTree, -} from "@code-editor/debugger/components/visualization/json-visualization/json-tree"; +} from "@code-editor/devtools/components/visualization/json-visualization/json-tree"; import { DefaultEditorWorkspaceLayout } from "layouts/default-editor-workspace-layout"; import { LayerHierarchy } from "components/editor-hierarchy"; import { WorkspaceContentPanelGridLayout } from "layouts/panel/workspace-content-panel-grid-layout"; diff --git a/editor/pages/integrations/index.tsx b/editor/pages/integrations/index.tsx index 1e5f812d..a5675359 100644 --- a/editor/pages/integrations/index.tsx +++ b/editor/pages/integrations/index.tsx @@ -1,5 +1,4 @@ -import React, { useEffect, useState } from "react"; -import styled from "@emotion/styled"; +import React from "react"; import { DefaultEditorWorkspaceLayout } from "layouts/default-editor-workspace-layout"; import { HomeHeading, HomeSidebar } from "components/home"; import Link from "next/link"; diff --git a/editor/pages/preferences/access-tokens.tsx b/editor/pages/preferences/access-tokens.tsx index 3d0b960e..6e0e7da1 100644 --- a/editor/pages/preferences/access-tokens.tsx +++ b/editor/pages/preferences/access-tokens.tsx @@ -1,6 +1,6 @@ import React, { useState } from "react"; import styled from "@emotion/styled"; -import { TextField } from "@material-ui/core"; +import { TextField } from "@mui/material"; import { personal } from "@design-sdk/figma-auth-store"; export default function AccessTokenConfigurationPage_Dev() { diff --git a/editor/pages/preferences/index.tsx b/editor/pages/preferences/index.tsx index 286d32a2..4efaff0a 100644 --- a/editor/pages/preferences/index.tsx +++ b/editor/pages/preferences/index.tsx @@ -2,9 +2,9 @@ import React from "react"; import Link from "next/link"; import styled from "@emotion/styled"; -import FormGroup from "@material-ui/core/FormGroup"; -import FormControlLabel from "@material-ui/core/FormControlLabel"; -import Checkbox from "@material-ui/core/Checkbox"; +import FormGroup from "@mui/material/FormGroup"; +import FormControlLabel from "@mui/material/FormControlLabel"; +import Checkbox from "@mui/material/Checkbox"; import { WorkspacePreferenceStore } from "store/workspace-preference-store"; export default function PreferencesHomePage() { diff --git a/editor/scaffolds/canvas/canvas.tsx b/editor/scaffolds/canvas/canvas.tsx index e79d81f1..2838b932 100644 --- a/editor/scaffolds/canvas/canvas.tsx +++ b/editor/scaffolds/canvas/canvas.tsx @@ -7,7 +7,7 @@ import useMeasure from "react-use-measure"; import { useDispatch } from "core/dispatch"; import { FrameTitleRenderer } from "./render/frame-title"; import { IsolateModeCanvas } from "./isolate-mode"; -import { Dialog } from "@material-ui/core"; +import { Dialog } from "@mui/material"; import { FullScreenPreview } from "scaffolds/preview-full-screen"; /** diff --git a/editor/scaffolds/canvas/isolate-mode.tsx b/editor/scaffolds/canvas/isolate-mode.tsx index 7e4c28ae..3924e6b7 100644 --- a/editor/scaffolds/canvas/isolate-mode.tsx +++ b/editor/scaffolds/canvas/isolate-mode.tsx @@ -3,6 +3,7 @@ import { IsolatedCanvas } from "components/canvas"; import { PreviewAndRunPanel } from "components/preview-and-run"; import { useEditorState } from "core/states"; import { VanillaDedicatedPreviewRenderer } from "components/app-runner"; +import { Devtools } from "scaffolds/devtools"; export function IsolateModeCanvas({ hidden = false, @@ -50,6 +51,7 @@ export function IsolateModeCanvas({ )} + ); } diff --git a/editor/scaffolds/devtools/console-feed.tsx b/editor/scaffolds/devtools/console-feed.tsx new file mode 100644 index 00000000..4e4a0966 --- /dev/null +++ b/editor/scaffolds/devtools/console-feed.tsx @@ -0,0 +1,16 @@ +import React from "react"; +import { Console } from "@code-editor/console-feed"; +import { useEditorState } from "core/states"; + +export function EditorConsoleFeed({ style }: { style?: React.CSSProperties }) { + const [state] = useEditorState(); + + return ( +
+ +
+ ); +} diff --git a/editor/scaffolds/devtools/index.tsx b/editor/scaffolds/devtools/index.tsx new file mode 100644 index 00000000..68ab587d --- /dev/null +++ b/editor/scaffolds/devtools/index.tsx @@ -0,0 +1,193 @@ +import React, { useCallback, useEffect, useState } from "react"; +import styled from "@emotion/styled"; +import { DevtoolsTab } from "@code-editor/devtools"; +import { colors } from "theme"; +import { Resizable } from "re-resizable"; +import { AngleDownIcon } from "icons/icon-angle-down"; +import { AngleUpIcon } from "icons/icon-angle-up"; +import { TrashIcon } from "icons/icon-trash"; +import { useDispatch } from "core/dispatch"; +import { EditorConsoleFeed } from "./console-feed"; +import { useEditorState } from "core/states"; + +const min_body_height = 120; +const max_body_height = 500; +const precalculated_bar_height = 44; +const expand_default_height = min_body_height + precalculated_bar_height; + +const height_store = { + get: () => { + const stored = localStorage.getItem("devtools-height"); + if (stored) { + return parseInt(stored); + } + return expand_default_height; + }, + set: (height) => { + localStorage.setItem("devtools-height", height.toString()); + }, +}; + +export function Devtools() { + const [expanded, setExpended] = useState(false); + const [height, setHeight] = useState( + expanded ? height_store.get() : precalculated_bar_height + ); + + const dispatch = useDispatch(); + + const clearConsole = useCallback(() => { + dispatch({ + type: "devtools-console-clear", + }); + }, [dispatch]); + + // save height + useEffect(() => { + if (expanded) { + height_store.set(height); + } + }, [height, expanded]); + + return ( + { + if (!expanded && di === "top") { + setExpended(true); + setHeight(expand_default_height); + } + }} + onResizeStop={(e, di, r, { height: dh }) => { + const nh = height + dh; + setHeight(nh); + if (nh <= precalculated_bar_height) { + setExpended(false); + } + }} + enable={{ + top: true, + right: false, + bottom: false, + left: false, + }} + size={{ + width: "auto", + height: height, + }} + minHeight={precalculated_bar_height} + style={{ + opacity: expanded ? 1 : 0.8, + transition: "opacity 0.2s", + overflow: "hidden", + marginLeft: 21, + marginRight: 21, + marginBottom: 16, + boxShadow: "0px 4px 32px 4px rgba(0, 0, 0, 0.25)", + border: "solid 1px rgba(255, 255, 255, 0.04)", + borderRadius: 6, + boxSizing: "border-box", + position: "absolute", + bottom: 0, + left: 0, + right: 0, + display: "flex", + flexDirection: "column", + background: colors.color_editor_bg_on_dark, + }} + > + { + if (expanded) { + setHeight(precalculated_bar_height); + } else { + setHeight(height_store.get()); + } + setExpended(!expanded); + }} + onClearConsole={clearConsole} + /> + + ); +} + +function ContentBody({ hidden = false }: { hidden?: boolean }) { + return ( +