@@ -53,6 +53,16 @@ export interface InteractiveBookProps {
5353 showNavigation ?: boolean
5454 /** 是否显示页角翻页热区(海浪呼吸效果),默认 true */
5555 showCornerFlip ?: boolean
56+ /** 是否启用翻页音效,默认 true */
57+ enableSound ?: boolean
58+ /** 自定义音效文件 URL,默认使用内置翻页音效 */
59+ soundSrc ?: string
60+ /** 初始是否打开书籍(跳过封面动画),默认 false */
61+ defaultOpen ?: boolean
62+ /** 受控模式:外部控制书籍开合状态。传入后会覆盖内部 isOpen */
63+ open ?: boolean
64+ /** 书籍关闭时的回调(用户点击关闭按钮时触发) */
65+ onClose ?: ( ) => void
5666}
5767
5868// ─── 图片懒加载组件 ────────────────────────────────
@@ -274,8 +284,25 @@ export default function InteractiveBook({
274284 enableKeyboard = true ,
275285 showNavigation = true ,
276286 showCornerFlip = true ,
287+ enableSound = true ,
288+ soundSrc,
289+ defaultOpen = false ,
290+ open : controlledOpen ,
291+ onClose,
277292} : InteractiveBookProps ) {
278- const [ isOpen , setIsOpen ] = useState ( false )
293+ const [ isOpen , setIsOpen ] = useState ( controlledOpen ?? defaultOpen )
294+
295+ // 受控模式:外部 open 变化时同步内部状态
296+ useEffect ( ( ) => {
297+ if ( controlledOpen === undefined ) return
298+ if ( controlledOpen !== isOpen ) {
299+ setIsOpen ( controlledOpen )
300+ if ( ! controlledOpen ) {
301+ setCurrentPageIndex ( - 1 )
302+ }
303+ }
304+ // eslint-disable-next-line react-hooks/exhaustive-deps
305+ } , [ controlledOpen ] )
279306 const [ currentPageIndex , setCurrentPageIndex ] = useState ( - 1 )
280307 const [ isHovering , setIsHovering ] = useState ( false )
281308 const [ isDragging , setIsDragging ] = useState ( false )
@@ -294,6 +321,7 @@ export default function InteractiveBook({
294321 // 使用 DOM <audio> 元素而非 new Audio(),在 Storybook iframe 中更可靠
295322 const audioRef = useRef < HTMLAudioElement | null > ( null )
296323 const playPageTurnSound = ( ) => {
324+ if ( ! enableSound ) return
297325 const audio = audioRef . current
298326 if ( ! audio ) return
299327 audio . currentTime = 0
@@ -326,6 +354,7 @@ export default function InteractiveBook({
326354 e . stopPropagation ( )
327355 setIsOpen ( false )
328356 setCurrentPageIndex ( - 1 )
357+ onClose ?.( )
329358 }
330359
331360 const nextPage = ( e : React . MouseEvent ) => {
@@ -1280,7 +1309,7 @@ export default function InteractiveBook({
12801309 ) }
12811310
12821311 { /* 翻页音效 — 使用 DOM audio 元素,兼容 Storybook iframe */ }
1283- < audio ref = { audioRef } src = { pageTurnAudio } preload = "auto" />
1312+ { enableSound && < audio ref = { audioRef } src = { soundSrc || pageTurnAudio } preload = "auto" /> }
12841313 </ div >
12851314 )
12861315}
0 commit comments