144 lines
4.1 KiB
TypeScript
144 lines
4.1 KiB
TypeScript
'use client'
|
|
|
|
import React from 'react'
|
|
import type { Editor } from '@tiptap/core'
|
|
import {
|
|
Bold, Italic, Highlighter, Link2, List, CheckSquare,
|
|
Heading, Code, Sparkles, MessageSquare, Quote, AlignLeft
|
|
} from 'lucide-react'
|
|
import { cn } from '@/lib/utils'
|
|
|
|
export type MobileEditorToolbarProps = {
|
|
editor: Editor | null
|
|
onOpenActionSheet: () => void
|
|
onInsertImage?: () => void
|
|
}
|
|
|
|
export function MobileEditorToolbar({
|
|
editor,
|
|
onOpenActionSheet,
|
|
onInsertImage,
|
|
}: MobileEditorToolbarProps) {
|
|
if (!editor) return null
|
|
|
|
// Format states
|
|
const isBold = editor.isActive('bold')
|
|
const isItalic = editor.isActive('italic')
|
|
const isHighlight = editor.isActive('highlight')
|
|
const isLink = editor.isActive('link')
|
|
const isBulletList = editor.isActive('bulletList')
|
|
const isTaskList = editor.isActive('taskList')
|
|
const isCodeBlock = editor.isActive('codeBlock')
|
|
const isHeading = editor.isActive('heading')
|
|
|
|
const toggleHeadingCycle = () => {
|
|
if (editor.isActive('heading', { level: 1 })) {
|
|
editor.chain().focus().toggleHeading({ level: 2 }).run()
|
|
} else if (editor.isActive('heading', { level: 2 })) {
|
|
editor.chain().focus().toggleHeading({ level: 3 }).run()
|
|
} else if (editor.isActive('heading', { level: 3 })) {
|
|
editor.chain().focus().setParagraph().run()
|
|
} else {
|
|
editor.chain().focus().toggleHeading({ level: 1 }).run()
|
|
}
|
|
}
|
|
|
|
const handleLinkPress = () => {
|
|
if (isLink) {
|
|
editor.chain().focus().unsetLink().run()
|
|
} else {
|
|
const url = window.prompt('URL:')
|
|
if (url && url.trim()) {
|
|
editor.chain().focus().setLink({ href: url.trim() }).run()
|
|
}
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div className="mobile-editor-toolbar-container">
|
|
<div className="mobile-editor-toolbar-scroll">
|
|
<button
|
|
type="button"
|
|
className={cn('mobile-toolbar-btn', isBold && 'active')}
|
|
onClick={() => editor.chain().focus().toggleBold().run()}
|
|
aria-label="Bold"
|
|
>
|
|
<Bold size={18} />
|
|
</button>
|
|
|
|
<button
|
|
type="button"
|
|
className={cn('mobile-toolbar-btn', isItalic && 'active')}
|
|
onClick={() => editor.chain().focus().toggleItalic().run()}
|
|
aria-label="Italic"
|
|
>
|
|
<Italic size={18} />
|
|
</button>
|
|
|
|
<button
|
|
type="button"
|
|
className={cn('mobile-toolbar-btn', isHighlight && 'active')}
|
|
onClick={() => editor.chain().focus().toggleHighlight().run()}
|
|
aria-label="Highlight"
|
|
>
|
|
<Highlighter size={18} />
|
|
</button>
|
|
|
|
<button
|
|
type="button"
|
|
className={cn('mobile-toolbar-btn', isLink && 'active')}
|
|
onClick={handleLinkPress}
|
|
aria-label="Link"
|
|
>
|
|
<Link2 size={18} />
|
|
</button>
|
|
|
|
<button
|
|
type="button"
|
|
className={cn('mobile-toolbar-btn', isBulletList && 'active')}
|
|
onClick={() => editor.chain().focus().toggleBulletList().run()}
|
|
aria-label="Bullet List"
|
|
>
|
|
<List size={18} />
|
|
</button>
|
|
|
|
<button
|
|
type="button"
|
|
className={cn('mobile-toolbar-btn', isTaskList && 'active')}
|
|
onClick={() => editor.chain().focus().toggleTaskList().run()}
|
|
aria-label="Task List"
|
|
>
|
|
<CheckSquare size={18} />
|
|
</button>
|
|
|
|
<button
|
|
type="button"
|
|
className={cn('mobile-toolbar-btn', isHeading && 'active')}
|
|
onClick={toggleHeadingCycle}
|
|
aria-label="Heading"
|
|
>
|
|
<Heading size={18} />
|
|
</button>
|
|
|
|
<button
|
|
type="button"
|
|
className={cn('mobile-toolbar-btn', isCodeBlock && 'active')}
|
|
onClick={() => editor.chain().focus().toggleCodeBlock().run()}
|
|
aria-label="Code Block"
|
|
>
|
|
<Code size={18} />
|
|
</button>
|
|
|
|
<button
|
|
type="button"
|
|
className="mobile-toolbar-btn highlight-btn"
|
|
onClick={onOpenActionSheet}
|
|
aria-label="Plus"
|
|
>
|
|
<Sparkles size={18} className="text-amber-500 animate-pulse" />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|