Compare commits

...

2 Commits

Author SHA1 Message Date
Greg Shuflin
80d5f76840 Initial stab at editor 2024-11-19 20:52:58 -08:00
Greg Shuflin
e24ea90806 Delete old stuff 2024-11-19 20:52:38 -08:00
43 changed files with 605 additions and 274 deletions

BIN
bun.lockb Executable file

Binary file not shown.

BIN
notes/bun.lockb Executable file

Binary file not shown.

View File

@ -4,9 +4,8 @@
<meta charset="UTF-8" />
<link rel="stylesheet" href="/src/styles.css" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Tauri App</title>
<script type="module" src="/src/main.ts" defer></script>
<script type="module" src="/src/prosemirror.ts" defer></script>
<title>Notes</title>
<script type="module" src="/src/main.tsx" defer></script>
</head>
<body>
@ -33,6 +32,7 @@
</a>
</div>
<p>Click on the Tauri logo to learn more about the framework</p>
<div id="editor"></div>
<form class="row" id="greet-form">
<input id="greet-input" placeholder="Enter a name..." />
@ -41,7 +41,5 @@
<p id="greet-msg"></p>
</main>
<div id="editor"></div>
<div id="content">test</div>
</body>
</html>

View File

@ -1,5 +1,5 @@
{
"name": "scribe",
"name": "notes",
"private": true,
"version": "0.1.0",
"type": "module",
@ -10,13 +10,11 @@
"tauri": "tauri"
},
"dependencies": {
"@emotion/react": "^11.13.3",
"@emotion/styled": "^11.13.0",
"@mui/material": "^6.1.7",
"@tauri-apps/api": "^2",
"@tauri-apps/plugin-shell": "^2",
"prosemirror-example-setup": "^1.2.3",
"prosemirror-schema-basic": "^1.2.3",
"prosemirror-schema-list": "^1.4.1",
"prosemirror-state": "^1.4.3",
"prosemirror-view": "^1.34.3"
"@tauri-apps/plugin-shell": "^2"
},
"devDependencies": {
"@tauri-apps/cli": "^2",

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
[package]
name = "scribe"
name = "notes"
version = "0.1.0"
description = "A Tauri App"
authors = ["you"]
@ -11,7 +11,7 @@ edition = "2021"
# The `_lib` suffix may seem redundant but it is necessary
# to make the lib name unique and wouldn't conflict with the bin name.
# This seems to be only an issue on Windows, see https://github.com/rust-lang/cargo/issues/8519
name = "scribe_lib"
name = "notes_lib"
crate-type = ["staticlib", "cdylib", "rlib"]
[build-dependencies]

View File

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

Before

Width:  |  Height:  |  Size: 974 B

After

Width:  |  Height:  |  Size: 974 B

View File

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

View File

Before

Width:  |  Height:  |  Size: 903 B

After

Width:  |  Height:  |  Size: 903 B

View File

Before

Width:  |  Height:  |  Size: 8.4 KiB

After

Width:  |  Height:  |  Size: 8.4 KiB

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 85 KiB

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -2,5 +2,5 @@
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
fn main() {
scribe_lib::run()
notes_lib::run()
}

View File

@ -1,8 +1,8 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "scribe",
"productName": "notes",
"version": "0.1.0",
"identifier": "com.scribe.app",
"identifier": "com.notes.app",
"build": {
"beforeDevCommand": "bun run dev",
"devUrl": "http://localhost:1420",
@ -13,7 +13,7 @@
"withGlobalTauri": true,
"windows": [
{
"title": "scribe",
"title": "notes",
"width": 800,
"height": 600
}

View File

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,138 @@
import React, { useState, useEffect } from 'react';
import Card from '@mui/material/Card';
import Button from '@mui/material/Button';
import {
Bold,
Italic,
List,
ListOrdered,
Heading1,
Heading2,
Quote,
MoreVertical,
X
} from 'lucide-react';
const NoteEditor = () => {
const [content, setContent] = useState('');
const [isToolbarOpen, setIsToolbarOpen] = useState(false);
const [viewportHeight, setViewportHeight] = useState('100vh');
// Handle viewport resize when keyboard appears
useEffect(() => {
const handleResize = () => {
const visualViewport = window.visualViewport;
if (visualViewport) {
setViewportHeight(`${visualViewport.height}px`);
}
};
window.visualViewport?.addEventListener('resize', handleResize);
window.visualViewport?.addEventListener('scroll', handleResize);
return () => {
window.visualViewport?.removeEventListener('resize', handleResize);
window.visualViewport?.removeEventListener('scroll', handleResize);
};
}, []);
const execCommand = (command, value = false) => {
document.execCommand(command, false, value);
};
const ToolbarButton = ({ icon: Icon, command, value, label }) => (
<Button
variant="ghost"
size="lg"
className="p-4 h-auto flex flex-col items-center gap-1"
onClick={() => {
execCommand(command, value);
// Don't close toolbar for formatting commands
if (command === 'save') setIsToolbarOpen(false);
}}
>
<Icon className="w-6 h-6" />
<span className="text-xs">{label}</span>
</Button>
);
return (
<div
className="fixed inset-0 flex flex-col"
style={{ height: viewportHeight }}
>
{/* Main toolbar button */}
<Button
variant="outline"
size="icon"
className="fixed top-2 right-2 z-20"
onClick={() => setIsToolbarOpen(!isToolbarOpen)}
>
{isToolbarOpen ? <X className="w-4 h-4" /> : <MoreVertical className="w-4 h-4" />}
</Button>
{/* Expandable toolbar */}
{isToolbarOpen && (
<Card className="absolute top-12 right-2 z-10 p-2 shadow-lg">
<div className="grid grid-cols-3 gap-2">
<ToolbarButton
icon={Bold}
command="bold"
label="Bold"
/>
<ToolbarButton
icon={Italic}
command="italic"
label="Italic"
/>
<ToolbarButton
icon={List}
command="insertUnorderedList"
label="Bullet List"
/>
<ToolbarButton
icon={ListOrdered}
command="insertOrderedList"
label="Numbered List"
/>
<ToolbarButton
icon={Heading1}
command="formatBlock"
value="<h1>"
label="Heading 1"
/>
<ToolbarButton
icon={Heading2}
command="formatBlock"
value="<h2>"
label="Heading 2"
/>
<ToolbarButton
icon={Quote}
command="formatBlock"
value="<blockquote>"
label="Quote"
/>
</div>
</Card>
)}
{/* Editor area */}
<div className="flex-1 overflow-auto">
<div
className="min-h-full p-4 focus:outline-none"
contentEditable={true}
onInput={(e) => setContent(e.currentTarget.innerHTML)}
suppressContentEditableWarning={true}
style={{
WebkitUserSelect: 'text',
WebkitTouchCallout: 'none',
overflowY: 'auto',
}}
/>
</div>
</div>
);
};
export default NoteEditor;

32
notes/src/main.tsx Normal file
View File

@ -0,0 +1,32 @@
import { invoke } from "@tauri-apps/api/core";
import { createRoot } from 'react-dom/client';
import React, { useState, useEffect } from 'react';
import NoteEditor from "./claude-generated-code";
const domElem = document.getElementById("editor");
console.log(domElem);
const root = createRoot(domElem);
root.render(<NoteEditor/>);
let greetInputEl: HTMLInputElement | null;
let greetMsgEl: HTMLElement | null;
async function greet() {
if (greetMsgEl && greetInputEl) {
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
greetMsgEl.textContent = await invoke("greet", {
name: greetInputEl.value,
});
}
}
window.addEventListener("DOMContentLoaded", () => {
greetInputEl = document.querySelector("#greet-input");
greetMsgEl = document.querySelector("#greet-msg");
document.querySelector("#greet-form")?.addEventListener("submit", (e) => {
e.preventDefault();
greet();
});
});

1
package.json Normal file
View File

@ -0,0 +1 @@
{ "dependencies": { "lucide-react": "^0.460.0", "react-dom": "^18.3.1" } }

Binary file not shown.

View File

@ -1,44 +0,0 @@
import { invoke } from "@tauri-apps/api/core";
import {EditorState} from "prosemirror-state"
import {EditorView} from "prosemirror-view"
import {Schema, DOMParser} from "prosemirror-model"
import {schema} from "prosemirror-schema-basic"
import {addListNodes} from "prosemirror-schema-list"
import {exampleSetup} from "prosemirror-example-setup"
// Mix the nodes from prosemirror-schema-list into the basic schema to
// create a schema with list support.
const mySchema = new Schema({
nodes: addListNodes(schema.spec.nodes, "paragraph block*", "block"),
marks: schema.spec.marks
})
window.view = new EditorView(document.querySelector("#editor"), {
state: EditorState.create({
doc: DOMParser.fromSchema(mySchema).parse(document.querySelector("#content")),
plugins: exampleSetup({schema: mySchema})
})
})
let greetInputEl: HTMLInputElement | null;
let greetMsgEl: HTMLElement | null;
async function greet() {
if (greetMsgEl && greetInputEl) {
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
greetMsgEl.textContent = await invoke("greet", {
name: greetInputEl.value,
});
}
}
window.addEventListener("DOMContentLoaded", () => {
greetInputEl = document.querySelector("#greet-input");
greetMsgEl = document.querySelector("#greet-msg");
document.querySelector("#greet-form")?.addEventListener("submit", (e) => {
e.preventDefault();
greet();
});
});

View File

@ -1,21 +0,0 @@
import {EditorState} from "prosemirror-state"
import {EditorView} from "prosemirror-view"
import {Schema, DOMParser} from "prosemirror-model"
import {schema} from "prosemirror-schema-basic"
import {addListNodes} from "prosemirror-schema-list"
import {exampleSetup} from "prosemirror-example-setup"
// Mix the nodes from prosemirror-schema-list into the basic schema to
// create a schema with list support.
const mySchema = new Schema({
nodes: addListNodes(schema.spec.nodes, "paragraph block*", "block"),
marks: schema.spec.marks
})
window.view = new EditorView(document.querySelector("#editor"), {
state: EditorState.create({
doc: DOMParser.fromSchema(mySchema).parse(document.querySelector("#content")),
plugins: exampleSetup({schema: mySchema})
})
})