Messing around with frontend structure
This commit is contained in:
parent
80d5f76840
commit
95ca7301d6
@ -1,138 +0,0 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
|
||||||
import { Card } from '@/components/ui/card';
|
|
||||||
import { Button } from '@/components/ui/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;
|
|
5
justfile
5
justfile
@ -9,3 +9,8 @@ run-android *args:
|
|||||||
export NDK_HOME="$ANDROID_HOME/ndk/28.0.12433566"
|
export NDK_HOME="$ANDROID_HOME/ndk/28.0.12433566"
|
||||||
{{args}}
|
{{args}}
|
||||||
|
|
||||||
|
|
||||||
|
dev-server:
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
cd notes && bun run tauri dev
|
||||||
|
|
||||||
|
BIN
notes/bun.lockb
BIN
notes/bun.lockb
Binary file not shown.
@ -14,7 +14,8 @@
|
|||||||
"@emotion/styled": "^11.13.0",
|
"@emotion/styled": "^11.13.0",
|
||||||
"@mui/material": "^6.1.7",
|
"@mui/material": "^6.1.7",
|
||||||
"@tauri-apps/api": "^2",
|
"@tauri-apps/api": "^2",
|
||||||
"@tauri-apps/plugin-shell": "^2"
|
"@tauri-apps/plugin-shell": "^2",
|
||||||
|
"lucide-react": "^0.460.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tauri-apps/cli": "^2",
|
"@tauri-apps/cli": "^2",
|
||||||
|
@ -1 +0,0 @@
|
|||||||
{ "dependencies": { "lucide-react": "^0.460.0", "react-dom": "^18.3.1" } }
|
|
Loading…
Reference in New Issue
Block a user