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.
This commit is contained in:
@@ -512,6 +512,18 @@ export const IconPlayOutline16 = ({ size = 16, className }: IconProps) => (
|
||||
</svg>
|
||||
)
|
||||
|
||||
/** ic_ds_pause_outline_16 */
|
||||
export const IconPauseOutline16 = ({ size = 16, className }: IconProps) => (
|
||||
<svg width={size} height={size} className={className} viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M14.1448 8.00024C14.1448 4.60644 11.394 1.85563 8.00024 1.85563C4.60644 1.85563 1.85563 4.60644 1.85563 8.00024C1.85563 11.394 4.60644 14.1448 8.00024 14.1448C11.394 14.1448 14.1448 11.394 14.1448 8.00024ZM15.5112 8.00024C15.5112 12.1482 12.1482 15.5112 8.00024 15.5112C3.85226 15.5112 0.489258 12.1482 0.489258 8.00024C0.489258 3.85226 3.85226 0.489258 8.00024 0.489258C12.1482 0.489258 15.5112 3.85226 15.5112 8.00024Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path d="M7.14244 5.14258V10.8569H5.71387V5.14258H7.14244Z" fill="currentColor" />
|
||||
<path d="M10.286 5.14258V10.8569H8.85742V5.14258H10.286Z" fill="currentColor" />
|
||||
</svg>
|
||||
)
|
||||
|
||||
/** ic_ds_fullscreen_outline_16 */
|
||||
export const IconFullscreenOutline16 = ({ size = 16, className }: IconProps) => (
|
||||
<svg width={size} height={size} className={className} viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
|
||||
@@ -10,6 +10,7 @@ export { Pill } from './Pill.tsx'
|
||||
export { Input } from './Input.tsx'
|
||||
export { Menu } from './Menu.tsx'
|
||||
export type { MenuEntry, MenuItem, MenuSeparator, MenuLabel } from './Menu.tsx'
|
||||
export { useAnchoredMaxHeight } from './useAnchoredMaxHeight.ts'
|
||||
export { HoverCard } from './HoverCard.tsx'
|
||||
export { Modal } from './Modal.tsx'
|
||||
export { ConnectionBanner } from './ConnectionBanner.tsx'
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* 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
|
||||
}
|
||||
Reference in New Issue
Block a user