Initial commit

This commit is contained in:
Samraaj Bath
2026-06-29 15:11:48 -07:00
commit 66dfdcc58d
404 changed files with 45970 additions and 0 deletions
+63
View File
@@ -0,0 +1,63 @@
/**
* Breakpoint discovery using the browser as the layout oracle.
*
* We capture at a few fixed widths and force the responsive bands onto Tailwind's default
* breakpoints — which is wrong for any site whose real cut points differ, and can spawn extra bands
* when our sample widths happen to straddle a breakpoint that isn't really there. Instead, ASK the
* page: sweep the viewport width and find the exact widths where the layout actually changes.
*
* Media queries cause DISCRETE jumps in structural properties (display, flex-direction, flex-wrap,
* grid track count, position, float, text-align, visibility) — those flip only at a breakpoint,
* whereas widths/heights scale smoothly. So we hash that discrete signature across a coarse width
* scan, then binary-search each interval where the hash changed down to 1px. The result is the
* site's REAL breakpoint set, to drive both the capture sample widths and the emitted band edges.
*/
import type { Page } from "playwright";
/** In-page: a hash of every element's discrete (media-query-toggled) layout properties. Pure
* structural — excludes widths/heights/font-size, which vary continuously and would mask the steps. */
const DISCRETE_SIGNATURE = (): string => {
let s = "";
const walk = (el: Element): void => {
const cs = getComputedStyle(el);
const cols = (cs.gridTemplateColumns || "none") === "none" ? 0 : cs.gridTemplateColumns.split(" ").filter(Boolean).length;
const painted = (el as HTMLElement).offsetParent !== null || cs.position === "fixed" ? 1 : 0;
s += `${cs.display}|${cs.flexDirection}|${cs.flexWrap}|${cols}|${cs.position}|${cs.float}|${cs.textAlign}|${cs.visibility}|${painted};`;
for (let i = 0; i < el.children.length; i++) walk(el.children[i]!);
};
walk(document.body);
let h = 0;
for (let i = 0; i < s.length; i++) h = (Math.imul(h, 31) + s.charCodeAt(i)) | 0;
return `${s.length}:${h}`;
};
export async function discoverBreakpoints(
page: Page,
opts?: { min?: number; max?: number; coarseStep?: number; height?: number },
): Promise<number[]> {
const min = opts?.min ?? 320;
const max = opts?.max ?? 1920;
const step = opts?.coarseStep ?? 16;
const height = opts?.height ?? 1200;
const sig = async (w: number): Promise<string> => {
await page.setViewportSize({ width: w, height });
return page.evaluate(DISCRETE_SIGNATURE);
};
// Coarse scan: record where the signature changes between adjacent samples.
const coarse: { w: number; sig: string }[] = [];
for (let w = min; w <= max; w += step) coarse.push({ w, sig: await sig(w) });
// Binary-search each changed interval down to 1px — the edge where the NEW layout begins.
const edges: number[] = [];
for (let i = 1; i < coarse.length; i++) {
if (coarse[i]!.sig === coarse[i - 1]!.sig) continue;
let lo = coarse[i - 1]!.w, hi = coarse[i]!.w; const loSig = coarse[i - 1]!.sig;
while (hi - lo > 1) {
const mid = (lo + hi) >> 1;
if ((await sig(mid)) === loSig) lo = mid; else hi = mid;
}
edges.push(hi);
}
return edges;
}