mirror of
https://github.com/backnotprop/plannotator.git
synced 2026-09-14 14:17:26 +08:00
352f880ebc
* feat(ui): add Viewer-owned document header * chore(guides): refresh viewer integrity manifest * fix(ui): harden Viewer document header transitions * fix(ui): exclude document header from annotations
53 lines
1.9 KiB
TypeScript
53 lines
1.9 KiB
TypeScript
/** Responsive presentation chosen for a measured compact document header. */
|
|
export type CompactHeaderLayout = 'wide' | 'tight' | 'narrow';
|
|
|
|
/** Measurements used to place a compact leading lane beside trailing actions. */
|
|
export interface CompactHeaderMeasurements {
|
|
/** Measured width of the full header container. */
|
|
readonly containerWidth: number;
|
|
/** Measured width occupied by the trailing action cluster. */
|
|
readonly trailingWidth: number;
|
|
/** Leading inset that is unavailable to the compact controls. */
|
|
readonly leadingInset: number;
|
|
}
|
|
|
|
/** Resolved responsive geometry for a compact document header. */
|
|
export interface CompactHeaderGeometry {
|
|
/** Pixels available to the leading controls after actions and spacing. */
|
|
readonly availableForLeading: number;
|
|
/** Whether controls keep labels, become icon-only, or stack. */
|
|
readonly layout: CompactHeaderLayout;
|
|
/** Whether both required measurements have arrived. */
|
|
readonly measured: boolean;
|
|
}
|
|
|
|
const GRID_SIZE = 16;
|
|
const CLUSTER_GAP = 16;
|
|
const WIDE_LEADING_WIDTH = 460;
|
|
const MIN_LEADING_WIDTH = 300;
|
|
|
|
/**
|
|
* Quantize a ResizeObserver width to avoid rendering for every dragged pixel.
|
|
* Floors toward the more conservative responsive layout.
|
|
*/
|
|
export function snapCompactHeaderWidth(width: number): number {
|
|
return Math.floor(width / GRID_SIZE) * GRID_SIZE;
|
|
}
|
|
|
|
/** Resolve the shared wide, tight, and narrow compact-header states. */
|
|
export function resolveCompactHeaderGeometry({
|
|
containerWidth,
|
|
trailingWidth,
|
|
leadingInset,
|
|
}: CompactHeaderMeasurements): CompactHeaderGeometry {
|
|
const measured = containerWidth > 0 && trailingWidth > 0;
|
|
const availableForLeading = containerWidth - leadingInset - trailingWidth - CLUSTER_GAP;
|
|
const layout = !measured || availableForLeading >= WIDE_LEADING_WIDTH
|
|
? 'wide'
|
|
: availableForLeading >= MIN_LEADING_WIDTH
|
|
? 'tight'
|
|
: 'narrow';
|
|
|
|
return { availableForLeading, layout, measured };
|
|
}
|