diff --git a/package.json b/package.json index d253eab..6924cdd 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "@emmetio/codemirror6-plugin": "^0.3.0", "@hookform/resolvers": "^3.3.4", "@radix-ui/react-dialog": "^1.0.5", + "@radix-ui/react-dropdown-menu": "^2.0.6", "@radix-ui/react-slot": "^1.0.2", "@replit/codemirror-vscode-keymap": "^6.0.2", "@tanstack/react-query": "^5.21.7", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 817c9ec..ffe6c1e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,6 +23,9 @@ dependencies: '@radix-ui/react-dialog': specifier: ^1.0.5 version: 1.0.5(@types/react-dom@18.2.19)(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-dropdown-menu': + specifier: ^2.0.6 + version: 2.0.6(@types/react-dom@18.2.19)(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0) '@radix-ui/react-slot': specifier: ^1.0.2 version: 1.0.2(@types/react@18.2.56)(react@18.2.0) @@ -842,6 +845,34 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true + /@floating-ui/core@1.6.0: + resolution: {integrity: sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g==} + dependencies: + '@floating-ui/utils': 0.2.1 + dev: false + + /@floating-ui/dom@1.6.3: + resolution: {integrity: sha512-RnDthu3mzPlQ31Ss/BTwQ1zjzIhr3lk1gZB1OC56h/1vEtaXkESrOqL5fQVMfXpwGtRwX+YsZBdyHtJMQnkArw==} + dependencies: + '@floating-ui/core': 1.6.0 + '@floating-ui/utils': 0.2.1 + dev: false + + /@floating-ui/react-dom@2.0.8(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-HOdqOt3R3OGeTKidaLvJKcgg75S6tibQ3Tif4eyd91QnIJWr0NLvoXFpJA/j8HqkFSL68GDca9AuyWEHlhyClw==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + dependencies: + '@floating-ui/dom': 1.6.3 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@floating-ui/utils@0.2.1: + resolution: {integrity: sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==} + dev: false + /@hookform/resolvers@3.3.4(react-hook-form@7.50.1): resolution: {integrity: sha512-o5cgpGOuJYrd+iMKvkttOclgwRW86EsWJZZRC23prf0uU2i48Htq4PuT73AVb9ionFyZrwYEITuOFGF+BydEtQ==} peerDependencies: @@ -1095,6 +1126,51 @@ packages: '@babel/runtime': 7.23.9 dev: false + /@radix-ui/react-arrow@1.0.3(@types/react-dom@18.2.19)(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-wSP+pHsB/jQRaL6voubsQ/ZlrGBHHrOjmBnr19hxYgtS0WvAFwZhK2WP/YY5yF9uKECCEEDGxuLxq1NBK51wFA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.9 + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.19)(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0) + '@types/react': 18.2.56 + '@types/react-dom': 18.2.19 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@radix-ui/react-collection@1.0.3(@types/react-dom@18.2.19)(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.9 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.56)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.56)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.19)(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-slot': 1.0.2(@types/react@18.2.56)(react@18.2.0) + '@types/react': 18.2.56 + '@types/react-dom': 18.2.19 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-compose-refs@1.0.1(@types/react@18.2.56)(react@18.2.0): resolution: {integrity: sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==} peerDependencies: @@ -1157,6 +1233,20 @@ packages: react-remove-scroll: 2.5.5(@types/react@18.2.56)(react@18.2.0) dev: false + /@radix-ui/react-direction@1.0.1(@types/react@18.2.56)(react@18.2.0): + resolution: {integrity: sha512-RXcvnXgyvYvBEOhCBuddKecVkoMiI10Jcm5cTI7abJRAHYfFxeu+FBQs/DvdxSYucxR5mna0dNsL6QFlds5TMA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.23.9 + '@types/react': 18.2.56 + react: 18.2.0 + dev: false + /@radix-ui/react-dismissable-layer@1.0.5(@types/react-dom@18.2.19)(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-aJeDjQhywg9LBu2t/At58hCvr7pEm0o2Ke1x33B+MhjNmmZ17sy4KImo0KPLgsnc/zN7GPdce8Cnn0SWvwZO7g==} peerDependencies: @@ -1182,6 +1272,33 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false + /@radix-ui/react-dropdown-menu@2.0.6(@types/react-dom@18.2.19)(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-i6TuFOoWmLWq+M/eCLGd/bQ2HfAX1RJgvrBQ6AQLmzfvsLdefxbWu8G9zczcPFfcSPehz9GcpF6K9QYreFV8hA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.9 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.56)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.56)(react@18.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@18.2.56)(react@18.2.0) + '@radix-ui/react-menu': 2.0.6(@types/react-dom@18.2.19)(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.19)(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.56)(react@18.2.0) + '@types/react': 18.2.56 + '@types/react-dom': 18.2.19 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-focus-guards@1.0.1(@types/react@18.2.56)(react@18.2.0): resolution: {integrity: sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==} peerDependencies: @@ -1234,6 +1351,74 @@ packages: react: 18.2.0 dev: false + /@radix-ui/react-menu@2.0.6(@types/react-dom@18.2.19)(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-BVkFLS+bUC8HcImkRKPSiVumA1VPOOEC5WBMiT+QAVsPzW1FJzI9KnqgGxVDPBcql5xXrHkD3JOVoXWEXD8SYA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.9 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-collection': 1.0.3(@types/react-dom@18.2.19)(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.56)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.56)(react@18.2.0) + '@radix-ui/react-direction': 1.0.1(@types/react@18.2.56)(react@18.2.0) + '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.2.19)(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-focus-guards': 1.0.1(@types/react@18.2.56)(react@18.2.0) + '@radix-ui/react-focus-scope': 1.0.4(@types/react-dom@18.2.19)(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@18.2.56)(react@18.2.0) + '@radix-ui/react-popper': 1.1.3(@types/react-dom@18.2.19)(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.2.19)(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.19)(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.19)(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-roving-focus': 1.0.4(@types/react-dom@18.2.19)(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-slot': 1.0.2(@types/react@18.2.56)(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.56)(react@18.2.0) + '@types/react': 18.2.56 + '@types/react-dom': 18.2.19 + aria-hidden: 1.2.3 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-remove-scroll: 2.5.5(@types/react@18.2.56)(react@18.2.0) + dev: false + + /@radix-ui/react-popper@1.1.3(@types/react-dom@18.2.19)(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-cKpopj/5RHZWjrbF2846jBNacjQVwkP068DfmgrNJXpvVWrOvlAmE9xSiy5OqeE+Gi8D9fP+oDhUnPqNMY8/5w==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.9 + '@floating-ui/react-dom': 2.0.8(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-arrow': 1.0.3(@types/react-dom@18.2.19)(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.56)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.56)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.19)(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.56)(react@18.2.0) + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.56)(react@18.2.0) + '@radix-ui/react-use-rect': 1.0.1(@types/react@18.2.56)(react@18.2.0) + '@radix-ui/react-use-size': 1.0.1(@types/react@18.2.56)(react@18.2.0) + '@radix-ui/rect': 1.0.1 + '@types/react': 18.2.56 + '@types/react-dom': 18.2.19 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-portal@1.0.4(@types/react-dom@18.2.19)(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q==} peerDependencies: @@ -1298,6 +1483,35 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false + /@radix-ui/react-roving-focus@1.0.4(@types/react-dom@18.2.19)(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-2mUg5Mgcu001VkGy+FfzZyzbmuUWzgWkj3rvv4yu+mLw03+mTzbxZHvfcGyFp2b8EkQeMkpRQ5FiA2Vr2O6TeQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.9 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-collection': 1.0.3(@types/react-dom@18.2.19)(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.56)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.56)(react@18.2.0) + '@radix-ui/react-direction': 1.0.1(@types/react@18.2.56)(react@18.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@18.2.56)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.19)(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.56)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.56)(react@18.2.0) + '@types/react': 18.2.56 + '@types/react-dom': 18.2.19 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-slot@1.0.2(@types/react@18.2.56)(react@18.2.0): resolution: {integrity: sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==} peerDependencies: @@ -1371,6 +1585,42 @@ packages: react: 18.2.0 dev: false + /@radix-ui/react-use-rect@1.0.1(@types/react@18.2.56)(react@18.2.0): + resolution: {integrity: sha512-Cq5DLuSiuYVKNU8orzJMbl15TXilTnJKUCltMVQg53BQOF1/C5toAaGrowkgksdBQ9H+SRL23g0HDmg9tvmxXw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.23.9 + '@radix-ui/rect': 1.0.1 + '@types/react': 18.2.56 + react: 18.2.0 + dev: false + + /@radix-ui/react-use-size@1.0.1(@types/react@18.2.56)(react@18.2.0): + resolution: {integrity: sha512-ibay+VqrgcaI6veAojjofPATwledXiSmX+C0KrBk/xgpX9rBzPV3OsfwlhQdUOFbh+LKQorLYT+xTXW9V8yd0g==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.23.9 + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.56)(react@18.2.0) + '@types/react': 18.2.56 + react: 18.2.0 + dev: false + + /@radix-ui/rect@1.0.1: + resolution: {integrity: sha512-fyrgCaedtvMg9NK3en0pnOYJdtfwxUcNolezkNPUsoX57X8oQk+NkqcvzHXD2uKNij6GXmWU9NDru2IWjrO4BQ==} + dependencies: + '@babel/runtime': 7.23.9 + dev: false + /@replit/codemirror-vscode-keymap@6.0.2(@codemirror/autocomplete@6.12.0)(@codemirror/commands@6.3.3)(@codemirror/language@6.10.1)(@codemirror/lint@6.5.0)(@codemirror/search@6.5.6)(@codemirror/state@6.4.0)(@codemirror/view@6.24.0): resolution: {integrity: sha512-j45qTwGxzpsv82lMD/NreGDORFKSctMDVkGRopaP+OrzSzv+pXDQuU3LnFvKpasyjVT0lf+PKG1v2DSCn/vxxg==} peerDependencies: diff --git a/src/app/page.tsx b/src/app/page.tsx deleted file mode 100644 index b013513..0000000 --- a/src/app/page.tsx +++ /dev/null @@ -1,261 +0,0 @@ -"use client"; - -import React, { - useCallback, - useEffect, - useMemo, - useRef, - useState, -} from "react"; -import { - ResizableHandle, - ResizablePanel, - ResizablePanelGroup, -} from "@/components/ui/resizable"; -import { useScreen } from "usehooks-ts"; -import Panel from "@/components/ui/panel"; - -import { cn } from "@/lib/utils"; -import Tabs, { Tab } from "@/components/ui/tabs"; -import FilePreview from "@/components/containers/file-preview"; -import trpc from "@/lib/trpc"; -import CreateFileDialog from "@/components/containers/createfile-dialog"; -import { useDisclose } from "@/hooks/useDisclose"; -import { Button } from "@/components/ui/button"; -import { FaFileAlt } from "react-icons/fa"; - -const HomePage = () => { - const frameRef = useRef(null); - const [isMounted, setMounted] = useState(false); - const screen = useScreen(); - const isPortrait = screen?.width < screen?.height; - - const files = trpc.file.getAll.useQuery(); - const [curTabIdx, setCurTabIdx] = useState(0); - const [curOpenFiles, setOpenFiles] = useState([]); - const createFileDlg = useDisclose(); - const [iframeLogs, setIframeLogs] = useState([]); - - const refreshPreview = useCallback(() => { - if (frameRef.current) { - frameRef.current.src = `/api/file/index.html?index=true`; - } - setIframeLogs([]); - }, []); - - useEffect(() => { - setMounted(true); - - const onMessage = (event: MessageEvent) => { - const { data } = event; - if (!data) { - return; - } - - if (!["log", "warn", "error"].includes(data.type) || !data.args?.length) { - return; - } - - if (data.args[0]?.includes("Babel transformer")) { - return; - } - - setIframeLogs((i) => [data, ...i]); - }; - - window.addEventListener("message", onMessage); - return () => { - window.removeEventListener("message", onMessage); - }; - }, [setIframeLogs]); - - useEffect(() => { - if (isMounted) { - refreshPreview(); - } - }, [isMounted]); - - const onOpenFile = (fileId: number) => { - const idx = curOpenFiles.indexOf(fileId); - if (idx >= 0) { - return setCurTabIdx(idx); - } - - setOpenFiles((state) => { - setCurTabIdx(state.length); - return [...state, fileId]; - }); - }; - - const onFileChange = (_fileId: number) => { - refreshPreview(); - }; - - useEffect(() => { - if (files.data && files.data?.length > 0 && !curOpenFiles.length) { - files.data.forEach((file) => onOpenFile(file.id)); - } - }, [files.data]); - - const openFileList = useMemo(() => { - return curOpenFiles.map((fileId) => { - const fileData = files.data?.find((i) => i.id === fileId); - - return { - title: fileData?.filename || "...", - render: () => ( - onFileChange(fileId)} /> - ), - }; - }) satisfies Tab[]; - }, [curOpenFiles, files]); - - if (!isMounted) { - return null; - } - - return ( - - -
- - - -
-

- My Project -

- -
-
- {files.data?.map((file) => ( - - ))} -
- - { - files.refetch(); - if (type === "create") { - onOpenFile(file.id); - } - }} - /> -
- - - - - - - - - - {!isPortrait ? ( - <> - - -
-
- {iframeLogs.map((item, idx) => ( -

- {item.args - ?.map((arg: any) => { - if (typeof arg === "object") { - return JSON.stringify(arg, null, 2); - } - return arg; - }) - .join(" ")} -

- ))} -
-
-
- - ) : null} -
-
-
-
-
-
- - -
- -