diff --git a/src/app/editor.ts b/src/app/editor.ts new file mode 100644 index 0000000..fc39d14 --- /dev/null +++ b/src/app/editor.ts @@ -0,0 +1,31 @@ +import { basicSetup } from "codemirror"; +import { EditorView } from "@codemirror/view"; +import { oneDark } from "@codemirror/theme-one-dark"; + +const fixedHeightEditor = EditorView.theme({ + "&": { + height: "100%", + minHeight: "0px", + resize: "horizontal", + overflow: "auto", + width: "600px", + minWidth: "8em", + flex: "none", + }, + ".cm-scroller": { overflow: "auto" }, +}); + +export class Editor { + view: EditorView; + + constructor() { + this.view = new EditorView({ + doc: "Start document", + extensions: [basicSetup, oneDark, fixedHeightEditor], + }); + } + + get dom() { + return this.view.dom; + } +} diff --git a/src/app/foldernav.ts b/src/app/foldernav.ts index 91350b6..cde7229 100644 --- a/src/app/foldernav.ts +++ b/src/app/foldernav.ts @@ -12,7 +12,7 @@ async function openFolder() { folderTreeState.val = folderTree; } -const FolderTreeView = () => { +export const FolderTreeView = () => { if (!folderTreeState.val) { return v.div( { class: "text-center m-4" }, @@ -21,10 +21,11 @@ const FolderTreeView = () => { ); } return v.div( + { class: "mx-1" }, v.div( { class: "flex w-full" }, v.span( - { class: "font-bold mx-1 flex-1" }, + { class: "font-bold flex-1" }, folderTreeState.val?.name ?? "No folder", ), u.InlineButton(openFolder, "Refresh current folder", "⟳"), @@ -37,20 +38,21 @@ const FolderTreeView = () => { // TODO: determine if lazy DOM creation is better or not. // Alternatively, investigate lazy FS traversal in main. const FsItemView = (tree: FolderTree): HTMLElement => { - if (tree.type === "file") return v.p(tree.name); + if (tree.type === "file") return v.p(v.span("📄"), tree.name); const isOpen = van.state(false); const children = () => isOpen.val - ? v.div({ class: "ml-4" }, tree.children?.map(FsItemView)) + ? v.ul({}, tree.children?.map(FsItemView)) : v.div({ ariaBusy: true }); const folder = v.details( - { ontoggle: () => (isOpen.val = folder.open) }, + { class: "inline", ontoggle: () => (isOpen.val = folder.open) }, v.summary(tree.name), children, ); - return folder; + return v.div( + { class: "flex" }, + v.span(() => (isOpen.val ? "📂" : "📁")), + folder, + ); }; - -// Mount the folder tree view to the nav -van.add(document.querySelector("aside nav"), FolderTreeView); diff --git a/src/app/index.css b/src/app/index.css index f1d8c73..653c0f8 100644 --- a/src/app/index.css +++ b/src/app/index.css @@ -1 +1,8 @@ @import "tailwindcss"; + +details > summary { + list-style: none; +} +details > summary::-webkit-details-marker { + display: none; +} diff --git a/src/app/renderer.ts b/src/app/renderer.ts index 66b2290..65b83b1 100644 --- a/src/app/renderer.ts +++ b/src/app/renderer.ts @@ -1,31 +1,3 @@ -/** - * This file will automatically be loaded by vite and run in the "renderer" context. - * To learn more about the differences between the "main" and the "renderer" context in - * Electron, visit: - * - * https://electronjs.org/docs/tutorial/process-model - * - * By default, Node.js integration in this file is disabled. When enabling Node.js integration - * in a renderer process, please be aware of potential security implications. You can read - * more about security risks here: - * - * https://electronjs.org/docs/tutorial/security - * - * To enable Node.js integration in this file, open up `main.ts` and enable the `nodeIntegration` - * flag: - * - * ``` - * // Create the browser window. - * mainWindow = new BrowserWindow({ - * width: 800, - * height: 600, - * webPreferences: { - * nodeIntegration: true - * } - * }); - * ``` - */ - // import "./pico.jade.css"; import "./index.css"; @@ -33,50 +5,32 @@ import van from "vanjs-core"; import * as vanX from "vanjs-ext"; const v = van.tags; -import { basicSetup } from "codemirror"; -import { EditorView } from "@codemirror/view"; -import { oneDark } from "@codemirror/theme-one-dark"; +import { Editor } from "./editor"; +import { FolderTreeView } from "./foldernav"; +import * as u from "./utils"; -import "./foldernav.ts"; - -const fixedHeightEditor = EditorView.theme({ - "&": { - height: "100%", - minHeight: "0px", - resize: "horizontal", - overflow: "auto", - width: "600px", - minWidth: "8em", - flex: "none", - }, - ".cm-scroller": { overflow: "auto" }, -}); - -class EditorColumn { - view: EditorView; - wrapper: HTMLElement; - - constructor() { - this.view = new EditorView({ - doc: "Start document", - extensions: [basicSetup, oneDark, fixedHeightEditor], - }); - console.log("Character width: ", this.view.defaultCharacterWidth); - this.wrapper = v.div({ class: "editorWrapper min-h-0" }, this.view.dom); - } - get dom() { - return this.wrapper; - } -} +const EditorWrapper = (editor: any, del: any, k: any) => + v.div( + { class: "flex flex-col" }, + v.div( + { class: "flex" }, + v.span({ class: "mx-1 flex-1" }, "Editor " + k), + u.InlineButton(del, "Close", "❌"), + ), + v.div({ class: "h-full" }, editor.val.dom), + ); // Create and mount editor list const editors = vanX.reactive([]); -vanX.list(document.getElementById("editorGrid"), editors, (v) => v.val.dom); +vanX.list(document.getElementById("editorGrid"), editors, EditorWrapper); function addView() { - editors.push(vanX.noreactive(new EditorColumn())); + editors.push(vanX.noreactive(new Editor())); } document.getElementById("addEditor")?.addEventListener("click", addView); addView(); + +// Mount the folder tree view to the nav +van.add(document.querySelector("aside nav"), FolderTreeView);