import { NodeViewContent, NodeViewWrapper } from '@tiptap/react' import React, { useState, useRef, useEffect } from 'react' import { RotateCw, Edit, AlignLeft, AlignCenter, AlignRight, Palette, Maximize2, Minimize2, Square } from 'lucide-react' import { twMerge } from 'tailwind-merge' import { useEditorProvider } from '@components/Contexts/Editor/EditorContext' const FlipcardExtension: React.FC = (props: any) => { const [isFlipped, setIsFlipped] = useState(false) const [question, setQuestion] = useState(props.node.attrs.question) const [answer, setAnswer] = useState(props.node.attrs.answer) const [color, setColor] = useState(props.node.attrs.color || 'blue') const [alignment, setAlignment] = useState(props.node.attrs.alignment || 'center') const [size, setSize] = useState(props.node.attrs.size || 'medium') const [showColorPicker, setShowColorPicker] = useState(false) const [isEditingQuestion, setIsEditingQuestion] = useState(false) const [isEditingAnswer, setIsEditingAnswer] = useState(false) const colorPickerRef = useRef(null) const questionInputRef = useRef(null) const answerInputRef = useRef(null) const editorState = useEditorProvider() as any const isEditable = editorState.isEditable useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if (colorPickerRef.current && !colorPickerRef.current.contains(event.target as Node)) { setShowColorPicker(false) } } document.addEventListener('mousedown', handleClickOutside) return () => { document.removeEventListener('mousedown', handleClickOutside) } }, []) const handleFlip = () => { // Allow flipping in both edit and view modes, but prevent when editing text if (!isEditingQuestion && !isEditingAnswer) { setIsFlipped(!isFlipped) } } const handleQuestionChange = (e: React.ChangeEvent) => { setQuestion(e.target.value) props.updateAttributes({ question: e.target.value, }) } const handleAnswerChange = (e: React.ChangeEvent) => { setAnswer(e.target.value) props.updateAttributes({ answer: e.target.value, }) } const handleAlignmentChange = (newAlignment: 'left' | 'center' | 'right') => { setAlignment(newAlignment) props.updateAttributes({ alignment: newAlignment, }) } const handleColorSelect = (selectedColor: string) => { setColor(selectedColor) setShowColorPicker(false) props.updateAttributes({ color: selectedColor, }) } const handleSizeChange = (newSize: 'small' | 'medium' | 'large') => { setSize(newSize) props.updateAttributes({ size: newSize, }) } const getAlignmentClass = () => { switch (alignment) { case 'left': return 'text-left justify-start'; case 'center': return 'text-center justify-center'; case 'right': return 'text-right justify-end'; default: return 'text-center justify-center'; } } const getSizeClass = () => { switch (size) { case 'small': return 'w-64 h-36'; case 'medium': return 'w-80 h-48'; case 'large': return 'w-96 h-60'; default: return 'w-80 h-48'; } } const getFontSizeClass = () => { switch (size) { case 'small': return 'text-sm'; case 'medium': return 'text-lg'; case 'large': return 'text-xl'; default: return 'text-lg'; } } const getIconSizeClass = () => { switch (size) { case 'small': return 16; case 'medium': return 20; case 'large': return 24; default: return 20; } } const getCardColor = (color: string, isBack: boolean = false) => { const baseColors = { sky: isBack ? 'bg-sky-600 border-sky-700' : 'bg-sky-500 border-sky-600', green: isBack ? 'bg-green-600 border-green-700' : 'bg-green-500 border-green-600', yellow: isBack ? 'bg-yellow-600 border-yellow-700' : 'bg-yellow-500 border-yellow-600', red: isBack ? 'bg-red-600 border-red-700' : 'bg-red-500 border-red-600', purple: isBack ? 'bg-purple-600 border-purple-700' : 'bg-purple-500 border-purple-600', teal: isBack ? 'bg-teal-600 border-teal-700' : 'bg-teal-500 border-teal-600', amber: isBack ? 'bg-amber-600 border-amber-700' : 'bg-amber-500 border-amber-600', indigo: isBack ? 'bg-indigo-600 border-indigo-700' : 'bg-indigo-500 border-indigo-600', neutral: isBack ? 'bg-neutral-700 border-neutral-800' : 'bg-neutral-600 border-neutral-700', blue: isBack ? 'bg-blue-600 border-blue-700' : 'bg-blue-500 border-blue-600', } return baseColors[color as keyof typeof baseColors] || baseColors.blue } const colors = ['sky', 'green', 'yellow', 'red', 'purple', 'teal', 'amber', 'indigo', 'neutral', 'blue'] const handleQuestionEdit = () => { setIsEditingQuestion(true) setTimeout(() => questionInputRef.current?.focus(), 0) } const handleAnswerEdit = () => { setIsEditingAnswer(true) setTimeout(() => answerInputRef.current?.focus(), 0) } const handleQuestionBlur = () => { setIsEditingQuestion(false) } const handleAnswerBlur = () => { setIsEditingAnswer(false) } return (
{/* Front Side (Question) */}
{isEditable && isEditingQuestion ? (