diff --git a/memento-note/components/note-input.tsx b/memento-note/components/note-input.tsx
index 0c40154..8e27cdb 100644
--- a/memento-note/components/note-input.tsx
+++ b/memento-note/components/note-input.tsx
@@ -16,13 +16,12 @@ import {
MoreVertical,
Undo2,
Redo2,
- FileText,
Eye,
Link as LinkIcon
} from 'lucide-react'
import { createNote } from '@/app/actions/notes'
import { fetchLinkMetadata } from '@/app/actions/scrape'
-import { CheckItem, NOTE_COLORS, NoteColor, LinkMetadata, Note } from '@/lib/types'
+import { CheckItem, NOTE_COLORS, NoteColor, LinkMetadata, Note, NoteType } from '@/lib/types'
import { ContextualAIChat } from './contextual-ai-chat'
import { Maximize2, Minimize2, Sparkles, Loader2 } from 'lucide-react'
import { useNotebooks } from '@/context/notebooks-context'
@@ -41,6 +40,8 @@ import {
import { cn } from '@/lib/utils'
import { toast } from 'sonner'
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from '@/components/ui/dialog'
+import { NoteTypeSelector } from '@/components/note-type-selector'
+import { RichTextEditor } from '@/components/rich-text-editor'
import { MarkdownContent } from './markdown-content'
import { LabelSelector } from './label-selector'
import { LabelBadge } from './label-badge'
@@ -107,7 +108,7 @@ export function NoteInput({
useEffect(() => {
if (forceExpanded) setIsExpanded(true)
}, [forceExpanded])
- const [type, setType] = useState<'text' | 'checklist'>('text')
+ const [type, setType] = useState
('richtext')
const [isSubmitting, setIsSubmitting] = useState(false)
const [color, setColor] = useState('default')
const [isArchived, setIsArchived] = useState(false)
@@ -126,8 +127,9 @@ export function NoteInput({
const [checkItems, setCheckItems] = useState([])
const [images, setImages] = useState([])
const [links, setLinks] = useState([])
- const [isMarkdown, setIsMarkdown] = useState(false)
const [showMarkdownPreview, setShowMarkdownPreview] = useState(false)
+ const isMarkdown = type === 'markdown'
+ const isRichText = type === 'richtext'
// Auto-resize textarea based on content
useEffect(() => {
@@ -145,14 +147,14 @@ export function NoteInput({
// Auto-tagging hook
const { suggestions, isAnalyzing } = useAutoTagging({
- content: type === 'text' ? fullContentForAI : '',
- enabled: type === 'text' && isExpanded && autoLabelingEnabled,
+ content: type !== 'checklist' ? fullContentForAI : '',
+ enabled: type !== 'checklist' && isExpanded && autoLabelingEnabled,
notebookId: currentNotebookId
})
// Title suggestions
- const titleSuggestionsEnabled = type === 'text' && isExpanded && !title
- const titleSuggestionsContent = type === 'text' ? fullContentForAI : ''
+ const titleSuggestionsEnabled = (type === 'text' || type === 'markdown' || type === 'richtext') && isExpanded && !title
+ const titleSuggestionsContent = type !== 'checklist' ? fullContentForAI : ''
// Title suggestions hook
const { suggestions: titleSuggestions, isAnalyzing: isAnalyzingTitles } = useTitleSuggestions({
@@ -357,9 +359,8 @@ export function NoteInput({
const data = await response.json()
if (!response.ok) throw new Error(data.error || 'Failed to transform')
- // Set the transformed markdown content and enable markdown mode
setContent(data.transformedText)
- setIsMarkdown(true)
+ setType('markdown')
setShowMarkdownPreview(false)
toast.success(t('ai.transformSuccess'))
@@ -556,11 +557,11 @@ export function NoteInput({
const handleSubmit = async () => {
// Validation: Allow submit if content OR images OR links exist
- const hasContent = content.trim().length > 0;
- const hasMedia = images.length > 0 || links.length > 0;
- const hasCheckItems = checkItems.some(i => i.text.trim().length > 0);
+ const hasContent = type === 'checklist' ? false : content.trim().length > 0
+ const hasCheckItems = type === 'checklist' ? checkItems.some(item => item.text.trim()) : false
+ const hasMedia = (images && images.length > 0) || (links && links.length > 0)
- if (type === 'text' && !hasContent && !hasMedia) {
+ if (type !== 'checklist' && !hasContent && !hasMedia) {
toast.warning(t('notes.contentOrMediaRequired'))
return
}
@@ -573,7 +574,7 @@ export function NoteInput({
try {
const createdNote = await createNote({
title: title.trim() || undefined,
- content: type === 'text' ? content : '',
+ content: type === 'checklist' ? '' : content,
type,
checkItems: type === 'checklist' ? checkItems : undefined,
color,
@@ -597,12 +598,11 @@ export function NoteInput({
setCheckItems([])
setImages([])
setLinks([])
- setIsMarkdown(false)
setShowMarkdownPreview(false)
setHistory([{ title: '', content: '' }])
setHistoryIndex(0)
setIsExpanded(false)
- setType('text')
+ setType('richtext')
setColor('default')
setIsArchived(false)
setCurrentReminder(null)
@@ -643,7 +643,6 @@ export function NoteInput({
setCheckItems([])
setImages([])
setLinks([])
- setIsMarkdown(false)
setShowMarkdownPreview(false)
setHistory([{ title: '', content: '' }])
setHistoryIndex(0)
@@ -765,7 +764,13 @@ export function NoteInput({
{/* Content area — scrolls internally when constrained by max-h */}
- {type === 'text' ? (
+ {type === 'richtext' ? (
+
+ ) : type === 'text' || type === 'markdown' ? (
<>
{showMarkdownPreview && isMarkdown ? (
{t('notes.remindMe')}
- {type === 'text' && (
-
-
- {t('notes.markdown')}
- )}
+ { setType(newType); if (newType !== 'markdown') setShowMarkdownPreview(false) }} />
- {type === 'text' && isMarkdown && (
+ {type === 'markdown' && (