export interface VisibilitySample { x: number; y: number; status: "visible" | "occluded" | "outside-viewport" | "no-element"; occluderTag?: string; occluderClass?: string; } export type CssHiddenReason = "display-none" | "visibility-hidden" | "opacity-zero" | "content-visibility-hidden" | "pointer-events-none-with-opacity-zero" | "unknown"; export interface VisibilityResult { selector: string; found: boolean; inViewport: boolean; partiallyInViewport: boolean; rect: { x: number; y: number; width: number; height: number; }; /** * Pure CSS-level visibility via `Element.checkVisibility()` with opacity + * visibility + content-visibility checks enabled, plus an ancestor walk * to identify which property is hiding the element. Catches the class of * bug where an element is in layout (has rect, is in viewport) but is * painted with opacity:0 / visibility:hidden / display:none: invisible * to the user but invisible to occlusion-only checks too. */ cssVisible: boolean; /** Which property+element actually hides it. Null when cssVisible=true. */ hiddenBy: { reason: CssHiddenReason; ancestorTag: string; ancestorClass: string; ancestorId: string; propertyValue: string; } | null; /** Fraction of in-viewport samples where the target (or a descendant) was the topmost element. 0 = fully occluded, 1 = fully visible. Always 0 when cssVisible=false (sampling skipped). */ visibleRatio: number; samples: VisibilitySample[]; occludedBy: { tagName: string; className: string; id: string; outerHTML: string; computedStyles: { position?: string; zIndex?: string; backgroundColor?: string; }; rect: { x: number; y: number; width: number; height: number; }; } | null; elementOuterHTML: string; } export interface CheckVisibilityOptions { /** Grid size: sampleGrid × sampleGrid points across the target's rect. Default 3 (9 samples). */ sampleGrid?: number; } /** * Build the JS function passed to Playwright's `page.evaluate`. Returns * a function reference (not a string) so Playwright serializes args * properly. Caller invokes via `page.evaluate(fn, { selectors, sampleGrid })`. */ export declare function buildVisibilityCheck(): (args: { selectors: string[]; sampleGrid: number; }) => VisibilityResult[]; /** * Build a script that injects overlay rectangles for each visibility result. * Green border = target, red border = dominant occluder. Caller injects via * `page.evaluate`, takes the screenshot, then clears via * `buildClearAnnotationsScript`. Boxes are absolutely positioned at the * target/occluder's `getBoundingClientRect()` location, so they survive * scroll changes between sample-time and screenshot-time only if nothing * has scrolled. The recommended flow is sample → annotate → screenshot → * clear without intervening scrolls. */ export declare function buildAnnotateScript(): (args: { results: VisibilityResult[]; }) => void; export declare function buildClearAnnotationsScript(): () => void; //# sourceMappingURL=visibility.d.ts.map