### Pretext Wiring Patterns Use these patterns based on the tier selected in Step 2. These are the correct Pretext API usage patterns. Follow them exactly. **Pattern 1: Basic height computation (Simple layout, Card/grid)** ```js import { prepare, layout } from './pretext-inline.js' // Or if inlined: const { prepare, layout } = window.Pretext // 1. PREPARE — one-time, after fonts load await document.fonts.ready const elements = document.querySelectorAll('[data-pretext]') const prepared = new Map() for (const el of elements) { const text = el.textContent const font = getComputedStyle(el).font prepared.set(el, prepare(text, font)) } // 2. LAYOUT — cheap, call on every resize function relayout() { for (const [el, handle] of prepared) { const { height } = layout(handle, el.clientWidth, parseFloat(getComputedStyle(el).lineHeight)) el.style.height = `${height}px` } } // 3. RESIZE-AWARE new ResizeObserver(() => relayout()).observe(document.body) relayout() // 4. CONTENT-EDITABLE — re-prepare when text changes for (const el of elements) { if (el.contentEditable === 'true') { new MutationObserver(() => { const font = getComputedStyle(el).font prepared.set(el, prepare(el.textContent, font)) relayout() }).observe(el, { characterData: true, subtree: true, childList: true }) } } ``` **Pattern 2: Shrinkwrap / tight-fit containers (Chat bubbles)** ```js import { prepareWithSegments, walkLineRanges } from './pretext-inline.js' // Find the tightest width that produces the same line count function shrinkwrap(text, font, maxWidth, lineHeight) { const segs = prepareWithSegments(text, font) let bestWidth = maxWidth walkLineRanges(segs, maxWidth, (lineCount, startIdx, endIdx) => { // walkLineRanges calls back with progressively narrower widths // The first call gives us the line count at maxWidth // We want the narrowest width that still produces this line count }) // Binary search for tightest width with same line count const { lineCount: targetLines } = layout(prepare(text, font), maxWidth, lineHeight) let lo = 0, hi = maxWidth while (hi - lo > 1) { const mid = (lo + hi) / 2 const { lineCount } = layout(prepare(text, font), mid, lineHeight) if (lineCount === targetLines) hi = mid else lo = mid } return hi } ``` **Pattern 3: Text around obstacles (Editorial layout)** ```js import { prepareWithSegments, layoutNextLine } from './pretext-inline.js' function layoutAroundObstacles(text, font, containerWidth, lineHeight, obstacles) { const segs = prepareWithSegments(text, font) let state = null let y = 0 const lines = [] while (true) { // Calculate available width at current y position, accounting for obstacles let availWidth = containerWidth for (const obs of obstacles) { if (y >= obs.top && y < obs.top + obs.height) { availWidth -= obs.width } } const result = layoutNextLine(segs, state, availWidth, lineHeight) if (!result) break lines.push({ text: result.text, width: result.width, x: 0, y }) state = result.state y += lineHeight } return { lines, totalHeight: y } } ``` **Pattern 4: Full line-by-line rendering (Complex editorial)** ```js import { prepareWithSegments, layoutWithLines } from './pretext-inline.js' const segs = prepareWithSegments(text, font) const { lines, height } = layoutWithLines(segs, containerWidth, lineHeight) // lines = [{ text, width, x, y }, ...] // Use for Canvas/SVG rendering or custom DOM positioning for (const line of lines) { const span = document.createElement('span') span.textContent = line.text span.style.position = 'absolute' span.style.left = `${line.x}px` span.style.top = `${line.y}px` container.appendChild(span) } ``` ### Pretext API Reference ``` PRETEXT API CHEATSHEET: prepare(text, font) → handle One-time text measurement. Call after document.fonts.ready. Font: CSS shorthand like '16px Inter' or 'bold 24px Georgia'. layout(prepared, maxWidth, lineHeight) → { height, lineCount } Fast layout computation. Call on every resize. Sub-millisecond. prepareWithSegments(text, font) → handle Like prepare() but enables line-level APIs below. layoutWithLines(segs, maxWidth, lineHeight) → { lines: [{text, width, x, y}...], height } Full line-by-line breakdown. For Canvas/SVG rendering. walkLineRanges(segs, maxWidth, onLine) → void Calls onLine(lineCount, startIdx, endIdx) for each possible layout. Find minimum width for N lines. For tight-fit containers. layoutNextLine(segs, state, maxWidth, lineHeight) → { text, width, state } | null Iterator. Different maxWidth per line = text around obstacles. Pass null as initial state. Returns null when text is exhausted. clearCache() → void Clears internal measurement caches. Use when cycling many fonts. setLocale(locale?) → void Retargets word segmenter for future prepare() calls. ```