feat: Add customizable fonts for editor and preview
- Added Google Fonts: Source Code Pro, Roboto Mono, Inconsolata (editor) and Merriweather, Crimson Pro, Roboto Serif, Average (preview) - Font face and size selectors in Categories sidebar with polished UI - Editor font applied to markdown textarea - Preview font applied to preview mode and PDF export - Code blocks always render in monospace - Settings persist in localStorage - Fixed textarea height recalculation when switching from preview to edit
This commit is contained in:
@@ -5,6 +5,12 @@
|
|||||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Tauri + React + Typescript</title>
|
<title>Tauri + React + Typescript</title>
|
||||||
|
<!-- Editor fonts (monospace) -->
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Inconsolata:wght@200..900&family=Roboto+Mono:ital,wght@0,100..700;1,100..700&family=Source+Code+Pro:ital,wght@0,200..900;1,200..900&display=swap" rel="stylesheet">
|
||||||
|
<!-- Preview fonts (serif) -->
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Average&family=Crimson+Pro:ital,wght@0,200..900;1,200..900&family=Merriweather:ital,opsz,wght@0,18..144,300..900;1,18..144,300..900&family=Roboto+Serif:ital,opsz,wght@0,8..144,100..900;1,8..144,100..900&display=swap" rel="stylesheet">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
52
src/App.tsx
52
src/App.tsx
@@ -22,16 +22,36 @@ function App() {
|
|||||||
const [theme, setTheme] = useState<'light' | 'dark' | 'system'>('system');
|
const [theme, setTheme] = useState<'light' | 'dark' | 'system'>('system');
|
||||||
const [effectiveTheme, setEffectiveTheme] = useState<'light' | 'dark'>('light');
|
const [effectiveTheme, setEffectiveTheme] = useState<'light' | 'dark'>('light');
|
||||||
const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
|
const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
|
||||||
|
const [editorFont, setEditorFont] = useState('Source Code Pro');
|
||||||
|
const [editorFontSize, setEditorFontSize] = useState(14);
|
||||||
|
const [previewFont, setPreviewFont] = useState('Merriweather');
|
||||||
|
const [previewFontSize, setPreviewFontSize] = useState(16);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const savedServer = localStorage.getItem('serverURL');
|
const savedServer = localStorage.getItem('serverURL');
|
||||||
const savedUsername = localStorage.getItem('username');
|
const savedUsername = localStorage.getItem('username');
|
||||||
const savedPassword = localStorage.getItem('password');
|
const savedPassword = localStorage.getItem('password');
|
||||||
const savedTheme = localStorage.getItem('theme') as 'light' | 'dark' | 'system' | null;
|
const savedTheme = localStorage.getItem('theme') as 'light' | 'dark' | 'system' | null;
|
||||||
|
const savedEditorFont = localStorage.getItem('editorFont');
|
||||||
|
const savedPreviewFont = localStorage.getItem('previewFont');
|
||||||
|
|
||||||
if (savedTheme) {
|
if (savedTheme) {
|
||||||
setTheme(savedTheme);
|
setTheme(savedTheme);
|
||||||
}
|
}
|
||||||
|
if (savedEditorFont) {
|
||||||
|
setEditorFont(savedEditorFont);
|
||||||
|
}
|
||||||
|
if (savedPreviewFont) {
|
||||||
|
setPreviewFont(savedPreviewFont);
|
||||||
|
}
|
||||||
|
const savedEditorFontSize = localStorage.getItem('editorFontSize');
|
||||||
|
const savedPreviewFontSize = localStorage.getItem('previewFontSize');
|
||||||
|
if (savedEditorFontSize) {
|
||||||
|
setEditorFontSize(parseInt(savedEditorFontSize, 10));
|
||||||
|
}
|
||||||
|
if (savedPreviewFontSize) {
|
||||||
|
setPreviewFontSize(parseInt(savedPreviewFontSize, 10));
|
||||||
|
}
|
||||||
|
|
||||||
if (savedServer && savedUsername && savedPassword) {
|
if (savedServer && savedUsername && savedPassword) {
|
||||||
const apiInstance = new NextcloudAPI({
|
const apiInstance = new NextcloudAPI({
|
||||||
@@ -117,6 +137,26 @@ function App() {
|
|||||||
localStorage.setItem('theme', newTheme);
|
localStorage.setItem('theme', newTheme);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleEditorFontChange = (font: string) => {
|
||||||
|
setEditorFont(font);
|
||||||
|
localStorage.setItem('editorFont', font);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePreviewFontChange = (font: string) => {
|
||||||
|
setPreviewFont(font);
|
||||||
|
localStorage.setItem('previewFont', font);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEditorFontSizeChange = (size: number) => {
|
||||||
|
setEditorFontSize(size);
|
||||||
|
localStorage.setItem('editorFontSize', size.toString());
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePreviewFontSizeChange = (size: number) => {
|
||||||
|
setPreviewFontSize(size);
|
||||||
|
localStorage.setItem('previewFontSize', size.toString());
|
||||||
|
};
|
||||||
|
|
||||||
const handleCreateNote = async () => {
|
const handleCreateNote = async () => {
|
||||||
if (!api) return;
|
if (!api) return;
|
||||||
try {
|
try {
|
||||||
@@ -207,6 +247,14 @@ function App() {
|
|||||||
onLogout={handleLogout}
|
onLogout={handleLogout}
|
||||||
theme={theme}
|
theme={theme}
|
||||||
onThemeChange={handleThemeChange}
|
onThemeChange={handleThemeChange}
|
||||||
|
editorFont={editorFont}
|
||||||
|
onEditorFontChange={handleEditorFontChange}
|
||||||
|
editorFontSize={editorFontSize}
|
||||||
|
onEditorFontSizeChange={handleEditorFontSizeChange}
|
||||||
|
previewFont={previewFont}
|
||||||
|
onPreviewFontChange={handlePreviewFontChange}
|
||||||
|
previewFontSize={previewFontSize}
|
||||||
|
onPreviewFontSizeChange={handlePreviewFontSizeChange}
|
||||||
/>
|
/>
|
||||||
<NotesList
|
<NotesList
|
||||||
notes={filteredNotes}
|
notes={filteredNotes}
|
||||||
@@ -231,6 +279,10 @@ function App() {
|
|||||||
categories={categories}
|
categories={categories}
|
||||||
isFocusMode={isFocusMode}
|
isFocusMode={isFocusMode}
|
||||||
onToggleFocusMode={() => setIsFocusMode(!isFocusMode)}
|
onToggleFocusMode={() => setIsFocusMode(!isFocusMode)}
|
||||||
|
editorFont={editorFont}
|
||||||
|
editorFontSize={editorFontSize}
|
||||||
|
previewFont={previewFont}
|
||||||
|
previewFontSize={previewFontSize}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,5 +1,20 @@
|
|||||||
import { useState, useEffect, useRef } from 'react';
|
import { useState, useEffect, useRef } from 'react';
|
||||||
|
|
||||||
|
const EDITOR_FONTS = [
|
||||||
|
{ name: 'Source Code Pro', value: 'Source Code Pro' },
|
||||||
|
{ name: 'Roboto Mono', value: 'Roboto Mono' },
|
||||||
|
{ name: 'Inconsolata', value: 'Inconsolata' },
|
||||||
|
{ name: 'System Mono', value: 'ui-monospace, monospace' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const PREVIEW_FONTS = [
|
||||||
|
{ name: 'Merriweather', value: 'Merriweather' },
|
||||||
|
{ name: 'Crimson Pro', value: 'Crimson Pro' },
|
||||||
|
{ name: 'Roboto Serif', value: 'Roboto Serif' },
|
||||||
|
{ name: 'Average', value: 'Average' },
|
||||||
|
{ name: 'System Serif', value: 'ui-serif, Georgia, serif' },
|
||||||
|
];
|
||||||
|
|
||||||
interface CategoriesSidebarProps {
|
interface CategoriesSidebarProps {
|
||||||
categories: string[];
|
categories: string[];
|
||||||
selectedCategory: string;
|
selectedCategory: string;
|
||||||
@@ -11,6 +26,14 @@ interface CategoriesSidebarProps {
|
|||||||
onLogout: () => void;
|
onLogout: () => void;
|
||||||
theme: 'light' | 'dark' | 'system';
|
theme: 'light' | 'dark' | 'system';
|
||||||
onThemeChange: (theme: 'light' | 'dark' | 'system') => void;
|
onThemeChange: (theme: 'light' | 'dark' | 'system') => void;
|
||||||
|
editorFont: string;
|
||||||
|
onEditorFontChange: (font: string) => void;
|
||||||
|
editorFontSize: number;
|
||||||
|
onEditorFontSizeChange: (size: number) => void;
|
||||||
|
previewFont: string;
|
||||||
|
onPreviewFontChange: (font: string) => void;
|
||||||
|
previewFontSize: number;
|
||||||
|
onPreviewFontSizeChange: (size: number) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function CategoriesSidebar({
|
export function CategoriesSidebar({
|
||||||
@@ -24,6 +47,14 @@ export function CategoriesSidebar({
|
|||||||
onLogout,
|
onLogout,
|
||||||
theme,
|
theme,
|
||||||
onThemeChange,
|
onThemeChange,
|
||||||
|
editorFont,
|
||||||
|
onEditorFontChange,
|
||||||
|
editorFontSize,
|
||||||
|
onEditorFontSizeChange,
|
||||||
|
previewFont,
|
||||||
|
onPreviewFontChange,
|
||||||
|
previewFontSize,
|
||||||
|
onPreviewFontSizeChange,
|
||||||
}: CategoriesSidebarProps) {
|
}: CategoriesSidebarProps) {
|
||||||
const [isCreating, setIsCreating] = useState(false);
|
const [isCreating, setIsCreating] = useState(false);
|
||||||
const [newCategoryName, setNewCategoryName] = useState('');
|
const [newCategoryName, setNewCategoryName] = useState('');
|
||||||
@@ -174,7 +205,7 @@ export function CategoriesSidebar({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Theme Toggle */}
|
{/* Theme Toggle */}
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between mb-3">
|
||||||
<span className="text-xs text-gray-500 dark:text-gray-400">Theme</span>
|
<span className="text-xs text-gray-500 dark:text-gray-400">Theme</span>
|
||||||
<div className="flex items-center space-x-1 bg-gray-100 dark:bg-gray-700 rounded-lg p-1">
|
<div className="flex items-center space-x-1 bg-gray-100 dark:bg-gray-700 rounded-lg p-1">
|
||||||
<button
|
<button
|
||||||
@@ -218,6 +249,78 @@ export function CategoriesSidebar({
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Font Settings */}
|
||||||
|
<div className="mt-4 pt-3 border-t border-gray-200 dark:border-gray-700 space-y-3">
|
||||||
|
<span className="text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">Fonts</span>
|
||||||
|
|
||||||
|
{/* Editor Font */}
|
||||||
|
<div className="bg-gray-50 dark:bg-gray-800 rounded-lg p-3">
|
||||||
|
<div className="flex items-center gap-2 mb-2">
|
||||||
|
<svg className="w-4 h-4 text-gray-500 dark:text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4" />
|
||||||
|
</svg>
|
||||||
|
<span className="text-xs font-medium text-gray-600 dark:text-gray-300">Editor</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex gap-2">
|
||||||
|
<select
|
||||||
|
value={editorFont}
|
||||||
|
onChange={(e) => onEditorFontChange(e.target.value)}
|
||||||
|
className="flex-1 min-w-0 text-sm px-3 py-1.5 bg-white dark:bg-gray-700 border border-gray-200 dark:border-gray-600 rounded-lg text-gray-700 dark:text-gray-200 focus:ring-2 focus:ring-blue-500 focus:border-transparent cursor-pointer"
|
||||||
|
style={{ fontFamily: editorFont }}
|
||||||
|
>
|
||||||
|
{EDITOR_FONTS.map((font) => (
|
||||||
|
<option key={font.value} value={font.value} style={{ fontFamily: font.value }}>
|
||||||
|
{font.name}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
<select
|
||||||
|
value={editorFontSize}
|
||||||
|
onChange={(e) => onEditorFontSizeChange(parseInt(e.target.value, 10))}
|
||||||
|
className="w-16 flex-shrink-0 text-sm px-2 py-1.5 bg-white dark:bg-gray-700 border border-gray-200 dark:border-gray-600 rounded-lg text-gray-700 dark:text-gray-200 focus:ring-2 focus:ring-blue-500 focus:border-transparent cursor-pointer text-center"
|
||||||
|
>
|
||||||
|
{[12, 13, 14, 15, 16, 17, 18, 20, 22, 24].map((size) => (
|
||||||
|
<option key={size} value={size}>{size}</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Preview Font */}
|
||||||
|
<div className="bg-gray-50 dark:bg-gray-800 rounded-lg p-3">
|
||||||
|
<div className="flex items-center gap-2 mb-2">
|
||||||
|
<svg className="w-4 h-4 text-gray-500 dark:text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" />
|
||||||
|
</svg>
|
||||||
|
<span className="text-xs font-medium text-gray-600 dark:text-gray-300">Preview</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex gap-2">
|
||||||
|
<select
|
||||||
|
value={previewFont}
|
||||||
|
onChange={(e) => onPreviewFontChange(e.target.value)}
|
||||||
|
className="flex-1 min-w-0 text-sm px-3 py-1.5 bg-white dark:bg-gray-700 border border-gray-200 dark:border-gray-600 rounded-lg text-gray-700 dark:text-gray-200 focus:ring-2 focus:ring-blue-500 focus:border-transparent cursor-pointer"
|
||||||
|
style={{ fontFamily: previewFont }}
|
||||||
|
>
|
||||||
|
{PREVIEW_FONTS.map((font) => (
|
||||||
|
<option key={font.value} value={font.value} style={{ fontFamily: font.value }}>
|
||||||
|
{font.name}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
<select
|
||||||
|
value={previewFontSize}
|
||||||
|
onChange={(e) => onPreviewFontSizeChange(parseInt(e.target.value, 10))}
|
||||||
|
className="w-16 flex-shrink-0 text-sm px-2 py-1.5 bg-white dark:bg-gray-700 border border-gray-200 dark:border-gray-600 rounded-lg text-gray-700 dark:text-gray-200 focus:ring-2 focus:ring-blue-500 focus:border-transparent cursor-pointer text-center"
|
||||||
|
>
|
||||||
|
{[12, 13, 14, 15, 16, 17, 18, 20, 22, 24].map((size) => (
|
||||||
|
<option key={size} value={size}>{size}</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -13,10 +13,14 @@ interface NoteEditorProps {
|
|||||||
categories: string[];
|
categories: string[];
|
||||||
isFocusMode?: boolean;
|
isFocusMode?: boolean;
|
||||||
onToggleFocusMode?: () => void;
|
onToggleFocusMode?: () => void;
|
||||||
|
editorFont?: string;
|
||||||
|
editorFontSize?: number;
|
||||||
|
previewFont?: string;
|
||||||
|
previewFontSize?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function NoteEditor({ note, onUpdateNote, fontSize, onUnsavedChanges, categories, isFocusMode, onToggleFocusMode }: NoteEditorProps) {
|
export function NoteEditor({ note, onUpdateNote, fontSize, onUnsavedChanges, categories, isFocusMode, onToggleFocusMode, editorFont = 'Source Code Pro', editorFontSize = 14, previewFont = 'Merriweather', previewFontSize = 16 }: NoteEditorProps) {
|
||||||
const [localTitle, setLocalTitle] = useState('');
|
const [localTitle, setLocalTitle] = useState('');
|
||||||
const [localContent, setLocalContent] = useState('');
|
const [localContent, setLocalContent] = useState('');
|
||||||
const [localCategory, setLocalCategory] = useState('');
|
const [localCategory, setLocalCategory] = useState('');
|
||||||
@@ -45,13 +49,18 @@ export function NoteEditor({ note, onUpdateNote, fontSize, onUnsavedChanges, cat
|
|||||||
return () => document.removeEventListener('keydown', handleKeyDown);
|
return () => document.removeEventListener('keydown', handleKeyDown);
|
||||||
}, [isFocusMode, onToggleFocusMode]);
|
}, [isFocusMode, onToggleFocusMode]);
|
||||||
|
|
||||||
// Auto-resize textarea when content changes
|
// Auto-resize textarea when content changes, switching from preview to edit, or font size changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (textareaRef.current && !isPreviewMode) {
|
||||||
|
// Use setTimeout to ensure DOM has updated
|
||||||
|
setTimeout(() => {
|
||||||
if (textareaRef.current) {
|
if (textareaRef.current) {
|
||||||
textareaRef.current.style.height = 'auto';
|
textareaRef.current.style.height = 'auto';
|
||||||
textareaRef.current.style.height = textareaRef.current.scrollHeight + 'px';
|
textareaRef.current.style.height = textareaRef.current.scrollHeight + 'px';
|
||||||
}
|
}
|
||||||
}, [localContent]);
|
}, 0);
|
||||||
|
}
|
||||||
|
}, [localContent, isPreviewMode, editorFontSize]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const loadNewNote = () => {
|
const loadNewNote = () => {
|
||||||
@@ -136,7 +145,7 @@ export function NoteEditor({ note, onUpdateNote, fontSize, onUnsavedChanges, cat
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const container = document.createElement('div');
|
const container = document.createElement('div');
|
||||||
container.style.fontFamily = 'Arial, sans-serif';
|
container.style.fontFamily = `"${previewFont}", Georgia, serif`;
|
||||||
container.style.fontSize = '12px';
|
container.style.fontSize = '12px';
|
||||||
container.style.lineHeight = '1.6';
|
container.style.lineHeight = '1.6';
|
||||||
container.style.color = '#000000';
|
container.style.color = '#000000';
|
||||||
@@ -149,6 +158,7 @@ export function NoteEditor({ note, onUpdateNote, fontSize, onUnsavedChanges, cat
|
|||||||
titleElement.style.fontWeight = 'bold';
|
titleElement.style.fontWeight = 'bold';
|
||||||
titleElement.style.color = '#000000';
|
titleElement.style.color = '#000000';
|
||||||
titleElement.style.textAlign = 'center';
|
titleElement.style.textAlign = 'center';
|
||||||
|
titleElement.style.fontFamily = `"${previewFont}", Georgia, serif`;
|
||||||
container.appendChild(titleElement);
|
container.appendChild(titleElement);
|
||||||
|
|
||||||
const contentElement = document.createElement('div');
|
const contentElement = document.createElement('div');
|
||||||
@@ -159,6 +169,15 @@ export function NoteEditor({ note, onUpdateNote, fontSize, onUnsavedChanges, cat
|
|||||||
contentElement.style.color = '#000000';
|
contentElement.style.color = '#000000';
|
||||||
container.appendChild(contentElement);
|
container.appendChild(contentElement);
|
||||||
|
|
||||||
|
// Apply monospace font to code elements
|
||||||
|
const style = document.createElement('style');
|
||||||
|
style.textContent = `
|
||||||
|
code, pre { font-family: "Source Code Pro", ui-monospace, monospace !important; }
|
||||||
|
pre { background: #f5f5f5; padding: 10px; border-radius: 4px; overflow-x: auto; }
|
||||||
|
code { background: #f0f0f0; padding: 2px 4px; border-radius: 2px; }
|
||||||
|
`;
|
||||||
|
container.appendChild(style);
|
||||||
|
|
||||||
// Create PDF using jsPDF's html() method (like dompdf)
|
// Create PDF using jsPDF's html() method (like dompdf)
|
||||||
const pdf = new jsPDF({
|
const pdf = new jsPDF({
|
||||||
orientation: 'portrait',
|
orientation: 'portrait',
|
||||||
@@ -561,8 +580,8 @@ export function NoteEditor({ note, onUpdateNote, fontSize, onUnsavedChanges, cat
|
|||||||
<div className={`min-h-full ${isFocusMode ? 'max-w-3xl mx-auto w-full' : ''}`}>
|
<div className={`min-h-full ${isFocusMode ? 'max-w-3xl mx-auto w-full' : ''}`}>
|
||||||
{isPreviewMode ? (
|
{isPreviewMode ? (
|
||||||
<div
|
<div
|
||||||
className={`prose prose-slate dark:prose-invert p-8 ${isFocusMode ? '' : 'max-w-none'}`}
|
className={`prose prose-slate dark:prose-invert p-8 ${isFocusMode ? '' : 'max-w-none'} [&_code]:font-mono [&_pre]:font-mono`}
|
||||||
style={{ fontSize: `${fontSize}px` }}
|
style={{ fontSize: `${previewFontSize}px`, fontFamily: previewFont }}
|
||||||
dangerouslySetInnerHTML={{
|
dangerouslySetInnerHTML={{
|
||||||
__html: marked.parse(localContent || '', { async: false }) as string
|
__html: marked.parse(localContent || '', { async: false }) as string
|
||||||
}}
|
}}
|
||||||
@@ -579,8 +598,8 @@ export function NoteEditor({ note, onUpdateNote, fontSize, onUnsavedChanges, cat
|
|||||||
e.target.style.height = 'auto';
|
e.target.style.height = 'auto';
|
||||||
e.target.style.height = e.target.scrollHeight + 'px';
|
e.target.style.height = e.target.scrollHeight + 'px';
|
||||||
}}
|
}}
|
||||||
className="w-full resize-none border-none outline-none focus:ring-0 bg-transparent text-gray-900 dark:text-gray-100 font-mono overflow-hidden"
|
className="w-full resize-none border-none outline-none focus:ring-0 bg-transparent text-gray-900 dark:text-gray-100 overflow-hidden"
|
||||||
style={{ fontSize: `${fontSize}px`, lineHeight: '1.6', minHeight: '100%' }}
|
style={{ fontSize: `${editorFontSize}px`, lineHeight: '1.6', minHeight: '100%', fontFamily: editorFont }}
|
||||||
placeholder="Start writing in markdown..."
|
placeholder="Start writing in markdown..."
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user