import { NodeViewContent, NodeViewWrapper } from '@tiptap/react' import React, { useState, useRef, useEffect } from 'react' import Picker from '@emoji-mart/react' import { ArrowRight, ChevronDown, ChevronRight, EllipsisVertical, Palette, Plus } from 'lucide-react' import { twMerge } from 'tailwind-merge' import { useEditorProvider } from '@components/Contexts/Editor/EditorContext' const BadgesExtension: React.FC = (props: any) => { const [color, setColor] = useState(props.node.attrs.color) const [emoji, setEmoji] = useState(props.node.attrs.emoji) const [showEmojiPicker, setShowEmojiPicker] = useState(false) const [showColorPicker, setShowColorPicker] = useState(false) const [showPredefinedCallouts, setShowPredefinedCallouts] = useState(false) const pickerRef = useRef(null) const colorPickerRef = useRef(null) const editorState = useEditorProvider() as any const isEditable = editorState.isEditable useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if ( (pickerRef.current && !pickerRef.current.contains(event.target as Node)) || (colorPickerRef.current && !colorPickerRef.current.contains(event.target as Node)) ) { setShowEmojiPicker(false) setShowColorPicker(false) } } document.addEventListener('mousedown', handleClickOutside) return () => { document.removeEventListener('mousedown', handleClickOutside) } }, []) const handleEmojiSelect = (emoji: any) => { setEmoji(emoji.native) setShowEmojiPicker(false) props.updateAttributes({ emoji: emoji.native, }) } const handleColorSelect = (selectedColor: string) => { setColor(selectedColor) setShowColorPicker(false) props.updateAttributes({ color: selectedColor, }) } const handlePredefinedBadgeSelect = (badge: typeof predefinedBadges[0]) => { setEmoji(badge.emoji) setColor(badge.color) props.updateAttributes({ emoji: badge.emoji, color: badge.color, }) // Insert the predefined content const { editor } = props if (editor) { editor.commands.setTextSelection({ from: props.getPos() + 1, to: props.getPos() + props.node.nodeSize - 1 }) editor.commands.insertContent(badge.content) } setShowPredefinedCallouts(false) } const colors = ['sky', 'green', 'yellow', 'red', 'purple', 'teal', 'amber', 'indigo', 'neutral'] const predefinedBadges = [ { emoji: '📝', color: 'sky', content: 'Key Concept' }, { emoji: '💡', color: 'yellow', content: 'Example' }, { emoji: '🔍', color: 'teal', content: 'Deep Dive' }, { emoji: '⚠️', color: 'red', content: 'Important Note' }, { emoji: '🧠', color: 'purple', content: 'Remember This' }, { emoji: '🏋️', color: 'green', content: 'Exercise' }, { emoji: '🎯', color: 'amber', content: 'Learning Objective' }, { emoji: '📚', color: 'indigo', content: 'Further Reading' }, { emoji: '💬', color: 'neutral', content: 'Discussion Topic' } ] const getBadgeColor = (color: string) => { switch (color) { case 'sky': return 'bg-sky-400 text-sky-50'; case 'green': return 'bg-green-400 text-green-50'; case 'yellow': return 'bg-yellow-400 text-black'; case 'red': return 'bg-red-500 text-red-50'; case 'purple': return 'bg-purple-400 text-purple-50'; case 'pink': return 'bg-pink-400 text-pink-50'; case 'teal': return 'bg-teal-400 text-teal-900'; case 'amber': return 'bg-amber-600 text-amber-100'; case 'indigo': return 'bg-indigo-400 text-indigo-50'; case 'neutral': return 'bg-neutral-800 text-white'; default: return 'bg-sky-400 text-white'; } } return (
{emoji} {isEditable && ( )}
{isEditable && (
{showColorPicker && (
{colors.map((c) => (
)}
)}
{isEditable && ( )} {isEditable && showPredefinedCallouts && (
{predefinedBadges.map((badge, index) => ( ))}
)}
{isEditable && showEmojiPicker && (
)}
) } export default BadgesExtension;