Files
deepseek-harness/packages/client/ui-primitives/src/useAnchoredMaxHeight.ts
Yif 45c9205caf feat(client): localize composer hints and rework input command interaction
Unify the /plan claimed hint with the plan placeholder through a locale
namespace, localize slash menu group titles, replace the PermissionSelect
native select with the Menu primitive, add a goal pause verb chain, clamp
anchored popups to the viewport with scroll-into-view and outside-dismiss,
and fix onPasteUpgrade insertedRange to account for the chip trailing gap.
2026-07-29 19:46:48 +08:00

39 lines
1.6 KiB
TypeScript

/**
* Viewport-fit hook for bottom-anchored overlays (slash menu, popupSelect):
* the element's bottom edge is laid out independent of its height, so it
* grows upward and only the top edge can collide with the viewport — clamp
* the design cap to the space between that edge and the viewport top.
*/
import { useLayoutEffect, useState } from 'react'
import type { RefObject } from 'react'
/** Safe distance kept between the overlay and the viewport top edge (mirrors the Menu portal margin). */
const MARGIN = 12
/**
* Clamp a bottom-anchored overlay's max-height to the viewport.
* @param ref - the overlay element; a null current (overlay closed) skips measuring.
* @param cap - design max-height in px (the clamp never exceeds it).
* @param signal - re-measure trigger: pass the overlay's render state so anchor
* moves (composer growth) re-fit; resize/scroll re-fit while mounted.
* @returns the max-height to apply inline, in px.
*/
export function useAnchoredMaxHeight(ref: RefObject<HTMLElement>, cap: number, signal: unknown): number {
const [maxHeight, setMaxHeight] = useState(cap)
useLayoutEffect(() => {
const el = ref.current
if (el === null) return
const fit = () => {
setMaxHeight(Math.min(cap, Math.max(0, el.getBoundingClientRect().bottom - MARGIN)))
}
fit()
window.addEventListener('resize', fit)
window.addEventListener('scroll', fit, true)
return () => {
window.removeEventListener('resize', fit)
window.removeEventListener('scroll', fit, true)
}
}, [ref, cap, signal])
return maxHeight
}