Files
shanghai-residences/src/components/hint/SceneHint.tsx
T
zhongyidian e0fa47d21a 更新依赖项及历史人物相关内容资源
- 更新 package.json 和 package-lock.json 中的依赖项
- 新增/更新陈云、黄炎培、鲁迅、孙中山的音频文件
- 新增场景和组件的图片资源
- 清理未使用的音频和图片文件
- 优化多个组件和页面的实现逻辑
2026-04-20 13:27:18 +08:00

100 lines
2.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useEffect, useMemo, useRef } from 'react'
import { hideHint, showHint } from './HintHost'
import type { HintPositionOffset, ShowHintOptions } from './HintHost'
export type SceneHintProps = {
/** 是否展示提示 */
when: boolean
/** 提示文本(建议直接传 string children) */
children: string
/** 延迟展示(ms) */
delayMs?: number
/** 自动消失时间(ms)。不传则使用默认值(2000) */
durationMs?: number
/** 是否常驻 */
persistent?: boolean
/** 相对中心点微调位置 */
offset?: HintPositionOffset
/** 自定义层级 */
zIndex?: number
/** 进入 when=true 时只展示一次(后续 when=true 的 rerender 不会重复触发) */
once?: boolean
/**
* 触发 key:当此值变化时(且 when=true)会重新触发一次 showHint。
* 用于“同一个提示需要再次弹出”的场景。
*/
triggerKey?: string | number
/** when 变为 false / 卸载时是否自动 hide */
hideOnCleanup?: boolean
}
export function SceneHint({
when,
children,
delayMs = 0,
durationMs,
persistent = false,
offset,
zIndex,
once = false,
triggerKey,
hideOnCleanup = true,
}: SceneHintProps) {
const shownOnceRef = useRef(false)
const delayTimerRef = useRef<number | null>(null)
const text = useMemo(() => {
return typeof children === 'string' ? children : String(children ?? '')
}, [children])
useEffect(() => {
if (!when) {
shownOnceRef.current = false
if (hideOnCleanup) hideHint()
return
}
if (once && shownOnceRef.current) return
const options: ShowHintOptions = {
persistent,
...(durationMs !== undefined ? { durationMs } : null),
...(offset ? { offset } : null),
...(zIndex !== undefined ? { zIndex } : null),
}
if (delayMs > 0) {
delayTimerRef.current = window.setTimeout(() => {
showHint(text, options)
shownOnceRef.current = true
}, delayMs)
} else {
showHint(text, options)
shownOnceRef.current = true
}
return () => {
if (delayTimerRef.current) {
window.clearTimeout(delayTimerRef.current)
delayTimerRef.current = null
}
if (hideOnCleanup) hideHint()
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [
when,
text,
delayMs,
durationMs,
persistent,
offset?.x,
offset?.y,
zIndex,
once,
triggerKey,
hideOnCleanup,
])
return null
}