/** * Keeps the full-screen panel inside the part of the screen the reader can * actually see. * * On a phone the panel is `position: fixed` across the whole viewport, and * that viewport is not what is on screen once a keyboard slides up: the * layout viewport keeps its full height, so the composer — and with it the * last few messages — ends up behind the keyboard. iOS then scrolls the page * to chase the focused field, which moves the fixed panel out of frame * instead of helping. `dvh` is no use here either; it tracks the browser's * own chrome collapsing, not the keyboard. * * `visualViewport` is the one thing that does report the visible box, so the * panel is pinned to it: its top to `offsetTop`, its height to `height`. The * composer lands just above the keyboard, and the conversation gets whatever * is left. * * A pinch is left alone. Zooming is how a reader gets a closer look, and a * panel that re-fitted itself to the magnified box would take that away by * reflowing the text back to the same apparent size. * * @implements {ReactiveController} */ export class ViewportController implements ReactiveController { /** * @param {LitElement} host * @param {{ enabled: () => boolean }} options */ constructor(host: LitElement, { enabled }: { enabled: () => boolean; }); hostConnected(): void; hostDisconnected(): void; hostUpdated(): void; #private; } import type { ReactiveController } from 'lit'; import type { LitElement } from 'lit';