diff --git a/packages/akiradocs/src/app/[locale]/[type]/[...slug]/page.tsx b/packages/akiradocs/src/app/[locale]/[type]/[...slug]/page.tsx index fd8bc61..db4fce9 100644 --- a/packages/akiradocs/src/app/[locale]/[type]/[...slug]/page.tsx +++ b/packages/akiradocs/src/app/[locale]/[type]/[...slug]/page.tsx @@ -134,17 +134,19 @@ export default async function ContentPage({ params }: Props) { {t(post.title)} {t(post.description)} - {post.blocks.map((block) => ( - block.content !== post.title && ( +
+ {post.blocks.map((block) => ( + block.content !== post.title && ( - ) - ))} + }} + /> + ) + ))} +
diff --git a/packages/akiradocs/src/components/blocks/ArticleHeaders.tsx b/packages/akiradocs/src/components/blocks/ArticleHeaders.tsx index 4afe7f2..ab5808e 100644 --- a/packages/akiradocs/src/components/blocks/ArticleHeaders.tsx +++ b/packages/akiradocs/src/components/blocks/ArticleHeaders.tsx @@ -26,13 +26,13 @@ export function ArticleHeaders({ title, setTitle, subtitle, setSubtitle, showPre value={title} onChange={(e) => setTitle(e.target.value)} placeholder="Article title" - className="text-4xl font-bold mb-4 border-none px-0" + className="text-4xl font-bold mb-4 border-none px-0 max-w-4xl break-words" /> setSubtitle(e.target.value)} placeholder="Add a subtitle" - className="text-xl mb-4 border-none px-0" + className="text-xl mb-4 border-none px-0 max-w-4xl break-words" /> ) diff --git a/packages/akiradocs/src/components/blocks/AudioBlock.tsx b/packages/akiradocs/src/components/blocks/AudioBlock.tsx index f1e81ca..ece5a5d 100644 --- a/packages/akiradocs/src/components/blocks/AudioBlock.tsx +++ b/packages/akiradocs/src/components/blocks/AudioBlock.tsx @@ -1,32 +1,198 @@ -import React from 'react'; -import { cn } from "@/lib/utils"; - -interface AudioProps { - id?: string; - src: string; - caption?: string; - align?: 'left' | 'center' | 'right'; - styles?: { - bold?: boolean; - italic?: boolean; - underline?: boolean; - }; +"use client" + +import { cn } from '@/lib/utils' +import { Button } from '@/components/ui/button' +import { Music, Pause, Play } from 'lucide-react' +import { useState, useRef, useEffect } from 'react' + +interface AudioBlockProps { + content: string + id: string + onUpdate?: (content: string) => void + isEditing?: boolean + metadata?: { + caption?: string + alignment?: 'left' | 'center' | 'right' + styles?: { + bold?: boolean + italic?: boolean + underline?: boolean + } + } } -export function Audio({ id, src, caption, align = 'left', styles }: AudioProps) { - const alignClass = align === 'center' ? 'mx-auto' : align === 'right' ? 'ml-auto' : ''; - return ( -
- - {caption &&

{caption}

} -
- ); +interface AudioBlockContent { + url: string + caption?: string + alignment?: 'left' | 'center' | 'right' } + +export function AudioBlock({ content, id, onUpdate, isEditing, metadata }: AudioBlockProps) { + const [isHovered, setIsHovered] = useState(false) + const [isPlaying, setIsPlaying] = useState(false) + const audioRef = useRef(null) + + const handlePlayPause = (e: React.MouseEvent) => { + e.stopPropagation() + if (audioRef.current) { + if (isPlaying) { + audioRef.current.pause() + } else { + audioRef.current.play() + } + setIsPlaying(!isPlaying) + } + } + + // Add event listeners to sync the isPlaying state with audio events + useEffect(() => { + const audio = audioRef.current + if (!audio) return + + const handlePlay = () => setIsPlaying(true) + const handlePause = () => setIsPlaying(false) + const handleEnded = () => setIsPlaying(false) + + audio.addEventListener('play', handlePlay) + audio.addEventListener('pause', handlePause) + audio.addEventListener('ended', handleEnded) + + return () => { + audio.removeEventListener('play', handlePlay) + audio.removeEventListener('pause', handlePause) + audio.removeEventListener('ended', handleEnded) + } + }, []) + + const parseAudioContent = (content: string): AudioBlockContent => { + try { + return typeof content === 'string' ? JSON.parse(content) : content + } catch { + return { + url: content, + caption: metadata?.caption || '', + alignment: metadata?.alignment || 'center' + } + } + } + + const UploadButton = () => ( +
+ +
+ +
+
+ ) + + if (!content && isEditing) { + return ( +
+ +
+ ) + } + + const audioContent = parseAudioContent(content) + const alignment = audioContent.alignment || metadata?.alignment || 'center' + + return ( +
setIsHovered(true)} + onMouseLeave={() => setIsHovered(false)} + > +
+
+
+ +
+
+ {isEditing && isHovered && ( +
e.stopPropagation()} + > + + + +
+ )} +
+ {audioContent.caption && ( +
+ {audioContent.caption} +
+ )} +
+ ) +} \ No newline at end of file diff --git a/packages/akiradocs/src/components/blocks/BlockquoteBlock.tsx b/packages/akiradocs/src/components/blocks/BlockquoteBlock.tsx index 4873b24..5230dfc 100644 --- a/packages/akiradocs/src/components/blocks/BlockquoteBlock.tsx +++ b/packages/akiradocs/src/components/blocks/BlockquoteBlock.tsx @@ -40,7 +40,7 @@ export function Blockquote({ id, children, align = 'left', styles, isEditing, on if (isEditing) { return ( -
+