@weasel-js/hud 1.13.0-rc.0 → 1.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist/attach.d.ts.map +1 -1
  2. package/dist/hud.d.ts +6 -16
  3. package/dist/hud.d.ts.map +1 -1
  4. package/dist/index.d.ts +2 -1
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +665 -332
  7. package/dist/index.js.map +1 -1
  8. package/dist/layerDeps.d.ts +14 -0
  9. package/dist/layerDeps.d.ts.map +1 -0
  10. package/dist/loupe/createLoupe.d.ts +4 -2
  11. package/dist/loupe/createLoupe.d.ts.map +1 -1
  12. package/dist/menu/accessibleMenu.d.ts +3 -3
  13. package/dist/menu/accessibleMenu.d.ts.map +1 -1
  14. package/dist/menu/attachMenuHost.d.ts +1 -1
  15. package/dist/menu/attachMenuHost.d.ts.map +1 -1
  16. package/dist/menu/chipRepeat.d.ts +27 -0
  17. package/dist/menu/chipRepeat.d.ts.map +1 -0
  18. package/dist/menu/colorPicker.d.ts +20 -0
  19. package/dist/menu/colorPicker.d.ts.map +1 -0
  20. package/dist/menu/drawPanel.d.ts +17 -4
  21. package/dist/menu/drawPanel.d.ts.map +1 -1
  22. package/dist/menu/menuWidget.d.ts +6 -0
  23. package/dist/menu/menuWidget.d.ts.map +1 -1
  24. package/dist/menu/textEdit.d.ts +70 -0
  25. package/dist/menu/textEdit.d.ts.map +1 -0
  26. package/dist/menu/valueRows.d.ts +20 -2
  27. package/dist/menu/valueRows.d.ts.map +1 -1
  28. package/dist/react/index.js +1 -1
  29. package/dist/textInputHost.d.ts +19 -0
  30. package/dist/textInputHost.d.ts.map +1 -0
  31. package/dist/{tool-8LVUdM5S.js → tool-DELNnWid.js} +460 -351
  32. package/dist/tool-DELNnWid.js.map +1 -0
  33. package/dist/tool.d.ts.map +1 -1
  34. package/dist/widget.d.ts +22 -5
  35. package/dist/widget.d.ts.map +1 -1
  36. package/dist/widgets/text.d.ts.map +1 -1
  37. package/package.json +12 -11
  38. package/dist/tool-8LVUdM5S.js.map +0 -1
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["solid","pathFromD","pathFromD","solid","loupeInnerView","registerDefaultFont","cursorForZone","createRevision","isFocusable","DEFAULT_WIDGET_CLAIMS","createHudContribution","createHud","attachHud","DEFAULT_WINDOW_METRICS","HUD_AFFORDANCE_KIND","claimsOf","pathFromD$1","loupeInnerView$1","labelOf","e","menuNumberText","c","level","stack","deepest","at","checkable","open","i","accessibleMenu","BLUR_LAYERS","BLUR_LAYER_ALPHA","solid$2","roundRectD","k","r","w","h","x","y","outer","rect","b","roundRectPath","s","radius","p","color","children","step","inset","margin","hole","ring","boxShadowCommands","under","over","innerRadius","padding","layers","resolveCurrentColor","current","ROOT","INHERITED","tags","m","body","attrs","a","num","v","d","nums","transformOf","identity","fn","args","next","translate","scale","rotateAboutPoint","multiply","arcRectD","rx","ry","ellipseD","cx","cy","shapeD","name","pts","paintOf","shapeCommands","out","fill","cmd","path","alpha","stroke","dash","frameFor","parent","t","group","mat3","glyphCommands","root","skipping","glyph","top","f","cmds","numberChips","end","panelW","chipAt","inside","plus","minus","valueRowWidth","measure","solid$1","mark","pathFromD","numberCommands","cell","live","ink","low","value","menuNumberCanStep","high","textCommandFromRuns","textCommands","colorCommands","DEFAULT_MENU_METRICS","rowLayout","entries","row","shortcutOf","formatShortcut","panelSize","last","text","chip","solid","caret","check","ICON_SIZE","PANEL_SHADOW","drawPanel","ctx","fg","muted","tokenPx","font","shadow","parseBoxShadow","expandVars","rows","highlight","iconX","iconY","ref","toIconRef","icons","shown","rowAt","estimateWidth","fontSize","measureLabel","metrics","metricsOf","resolveFontVariant","fontFamily","units","prev","ch","cp","createPlacer","placed","measured","faces","faceGeneration","opts","bounds","width","height","kept","parentRow","old","size","placeMenuUnder","placeMenu","placeSubmenu","CLAIMS","underOnCanvas","toCanvas","createMenuWidget","rev","createMenuController","withLinks","href","place","family","panels","disposed","armed","hoverPanel","levelAt","union","x0","y0","x1","y1","enter","pointer","evt","choose","index","dir","key","accessibleTree","attachMenuHost","widget","returnTo","drop","hud","giveBack","sync","host","held","dismiss","wheel","unsubscribe","unfocus","createContentWatch","camera","seen","view","now","version","moved","POINTER_ENDS","followPointer","holding","local","input","onPointerMove","lens","onPointerDown","onPointerEnd","type","readbackRegion","target","dpr","gx","clamp","rw","gy","bufferHeight","rh","raw","gl","flipped","stride","src","backdropOf","LENS_VIEW","NO_RECT","lensCamera","world","aim","factor","screenToWorld","viewToTransform","createLoupe","element","interactive","pixels","dropPixels","releaseImageSource","pixelsPending","refreshWanted","landed","watch","refreshAsked","content","model","drawVector","drawPixels","backdropColor","backdrop","innerView","createViewportLayer","win","scheduleRefresh","read","cssRect","refreshPixels","data","bmp","requestRedraw","readHex","px","surface","unsubscribeFrame","createLoupeModel","teardown","unfollow","DEFAULT_FONT_FAMILY","loupeInnerView"],"sources":["../src/menu/accessibleMenu.ts","../src/boxShadow.ts","../src/glyph.ts","../src/menu/valueRows.ts","../src/menu/drawPanel.ts","../src/menu/measureLabel.ts","../src/menu/placePanels.ts","../src/menu/menuWidget.ts","../src/menu/attachMenuHost.ts","../src/loupe/contentWatch.ts","../src/loupe/pointerAim.ts","../src/loupe/readback.ts","../src/loupe/createLoupe.ts"],"sourcesContent":["import { menuNumberText, type MenuController, type MenuRowEntry } from '@weasel-js/menu';\nimport type { HudAccessibleNode } from '../widget';\n\n/** A row's name: a value row's label and the value it holds now. */\nfunction labelOf(c: MenuController, e: MenuRowEntry): string {\n if (e.kind === 'number') return `${e.label}: ${menuNumberText(c.numberValue(e), e)}`;\n if (e.kind === 'color') return `${e.label}: ${e.value ?? '—'}`;\n if (e.kind === 'text') return `${e.label}: ${c.textValue(e) ?? '—'}`;\n return e.label;\n}\n\n/** One level's rows, with the open submenu nested under the row it hangs from. */\nfunction level(c: MenuController, at: number): HudAccessibleNode[] {\n const stack = c.stack();\n const deepest = at === stack.length - 1;\n return c.entriesAt(at).map((e, i): HudAccessibleNode => {\n if (e.kind === 'separator') return { role: 'separator', key: e.key };\n const checkable = e.kind === 'item' && e.checked !== undefined;\n const open = e.kind === 'submenu' && stack[at] === i && stack.length > at + 1;\n return {\n role: checkable ? 'menuitemcheckbox' : 'menuitem',\n key: e.key,\n label: labelOf(c, e),\n ...(deepest && stack[at] === i ? { active: true } : {}),\n ...(e.kind === 'item' && e.checked !== undefined ? { checked: e.checked } : {}),\n ...(e.disabled || e.kind === 'color' || e.kind === 'text' ? { disabled: true } : {}),\n ...(e.kind === 'submenu' ? { expanded: open } : {}),\n ...(open ? { children: [{ role: 'menu', key: 'menu', label: e.label, children: level(c, at + 1) }] } : {}),\n };\n });\n}\n\n/** An open menu as the accessibility tree a DOM menu's panels show: rows with their roles and states, and the\n * highlighted row of the innermost open level active. */\nexport function accessibleMenu(c: MenuController): HudAccessibleNode {\n return { role: 'menu', key: 'menu', label: 'Context menu', children: level(c, 0) };\n}\n","import type { DrawCommand } from '@weasel-js/core/renderer';\nimport { pathFromD, roundRectPath, type Path } from '@weasel-js/geom';\nimport { resolveCurrentColor, type BoxShadow } from '@weasel-js/theme';\nimport type { WidgetBounds } from './widget';\n\n// A blurred layer is drawn as nested rounded rects reaching blur / 2 either side of its edge,\n// whose overlap builds the falloff.\nconst BLUR_LAYERS = 7;\nconst BLUR_LAYER_ALPHA = 0.16;\n\nconst solid = (color: string) => ({ paint: { kind: 'solid' as const, color } });\n\nfunction roundRectD(x: number, y: number, w: number, h: number, r: number): string {\n const k = Math.max(0, Math.min(r, w / 2, h / 2));\n if (k === 0) return `M ${x} ${y} H ${x + w} V ${y + h} H ${x} Z`;\n return `M ${x + k} ${y} H ${x + w - k} A ${k} ${k} 0 0 1 ${x + w} ${y + k} V ${y + h - k} `\n + `A ${k} ${k} 0 0 1 ${x + w - k} ${y + h} H ${x + k} A ${k} ${k} 0 0 1 ${x} ${y + h - k} `\n + `V ${y + k} A ${k} ${k} 0 0 1 ${x + k} ${y} Z`;\n}\n\nfunction outer(b: WidgetBounds, radius: number, s: BoxShadow, color: string): DrawCommand {\n const rect = (e: number): Path | null => {\n const w = b.w + e * 2;\n const h = b.h + e * 2;\n return w > 0 && h > 0 ? roundRectPath(b.x + s.x - e, b.y + s.y - e, w, h, Math.max(0, radius + e)) : null;\n };\n if (s.blur <= 0) {\n const p = rect(s.spread);\n return { kind: 'group', children: p ? [{ kind: 'path', path: p, fill: solid(color) }] : [] };\n }\n const children: DrawCommand[] = [];\n const step = s.blur / (BLUR_LAYERS - 1);\n for (let i = 0; i < BLUR_LAYERS; i++) {\n const p = rect(s.spread + s.blur / 2 - i * step);\n if (p) children.push({ kind: 'path', path: p, fill: solid(color) });\n }\n return { kind: 'group', alpha: BLUR_LAYER_ALPHA, children };\n}\n\n/** An inset layer, hard-edged whatever its blur: the box less itself moved by the offset and shrunk by the spread. */\nfunction inset(b: WidgetBounds, radius: number, s: BoxShadow, color: string): DrawCommand {\n const margin = Math.abs(s.x) + Math.abs(s.y) + Math.abs(s.spread) + 1;\n const hole = roundRectD(b.x + s.x + s.spread, b.y + s.y + s.spread, b.w - s.spread * 2, b.h - s.spread * 2,\n Math.max(0, radius - s.spread));\n const ring = pathFromD(`${roundRectD(b.x - margin, b.y - margin, b.w + margin * 2, b.h + margin * 2, 0)} ${hole}`);\n return {\n kind: 'group',\n clip: roundRectPath(b.x, b.y, b.w, b.h, radius),\n children: [{ kind: 'path', path: ring.kind === 'polygon' ? { ...ring, fillRule: 'evenodd' } : ring, fill: solid(color) }],\n };\n}\n\n/**\n * A CSS `box-shadow` list cast by a rounded box, as draw commands: `under` goes beneath the box's\n * face and `over` on top of it, for `inset` layers, which fall inside `padding` (the box less its\n * border). Layers draw last-first, so the first is topmost, as in CSS. `current` is what a layer\n * written in `currentColor` takes.\n */\nexport function boxShadowCommands(\n b: WidgetBounds, radius: number, layers: readonly BoxShadow[], current: string, padding: WidgetBounds = b,\n): { under: DrawCommand[]; over: DrawCommand[] } {\n const under: DrawCommand[] = [];\n const over: DrawCommand[] = [];\n const innerRadius = Math.max(0, radius - (padding.x - b.x));\n for (const s of [...layers].reverse()) {\n const color = resolveCurrentColor(s.color, current);\n if (s.inset) over.push(inset(padding, innerRadius, s, color));\n else under.push(outer(b, radius, s, color));\n }\n return { under, over };\n}\n","import type { DrawCommand } from '@weasel-js/core/renderer';\nimport {\n identity, mat3, multiply, pathFromD, rotateAboutPoint, scale, translate, type Affine, type Path,\n} from '@weasel-js/geom';\nimport type { IconGlyph } from '@weasel-js/icons';\n\n/** The attributes a glyph's elements inherit, as `<Icon>`'s root `<svg>` sets them. */\nconst ROOT: Readonly<Record<string, string>> = {\n fill: 'none', stroke: 'currentColor', 'stroke-width': '1.5',\n 'stroke-linecap': 'round', 'stroke-linejoin': 'round',\n};\n\nconst INHERITED = new Set([\n 'fill', 'fill-opacity', 'fill-rule', 'stroke', 'stroke-width', 'stroke-opacity',\n 'stroke-linecap', 'stroke-linejoin', 'stroke-dasharray',\n]);\n\n/** What a glyph is drawn in the place of `currentColor` with, and where. */\nexport interface GlyphPlacement {\n x: number;\n y: number;\n /** Width and height; the glyph's 20×20 viewBox scales to it. */\n size: number;\n color: string;\n}\n\ninterface Tag { close: boolean; name: string; attrs: Record<string, string>; selfClosing: boolean }\n\nfunction* tags(body: string): Generator<Tag> {\n for (const m of body.matchAll(/<(\\/?)([a-zA-Z]+)((?:\\s+[\\w:-]+=\"[^\"]*\")*)\\s*(\\/?)>/g)) {\n const attrs: Record<string, string> = {};\n for (const a of m[3]!.matchAll(/([\\w:-]+)=\"([^\"]*)\"/g)) attrs[a[1]!] = a[2]!;\n yield { close: m[1] === '/', name: m[2]!, attrs, selfClosing: m[4] === '/' };\n }\n}\n\nconst num = (v: string | undefined, d = 0) => (v === undefined || v === '' ? d : Number(v));\nconst nums = (v: string) => v.trim().split(/[\\s,]+/).filter((s) => s !== '').map(Number);\n\n/** An SVG `transform` list as one affine. */\nfunction transformOf(v: string | undefined): Affine {\n let m = identity();\n if (!v) return m;\n for (const [, fn, args] of v.matchAll(/(\\w+)\\s*\\(([^)]*)\\)/g)) {\n const a = nums(args!);\n const next: Affine | null = fn === 'translate' ? translate(a[0] ?? 0, a[1] ?? 0)\n : fn === 'scale' ? scale(a[0] ?? 1, a[1] ?? a[0] ?? 1)\n : fn === 'rotate' ? rotateAboutPoint(a[1] ?? 0, a[2] ?? 0, ((a[0] ?? 0) * Math.PI) / 180)\n : fn === 'matrix' && a.length === 6 ? (a as unknown as Affine) : null;\n if (next) m = multiply(m, next);\n }\n return m;\n}\n\nfunction arcRectD(x: number, y: number, w: number, h: number, rx: number, ry: number): string {\n if (rx <= 0 || ry <= 0) return `M ${x} ${y} H ${x + w} V ${y + h} H ${x} Z`;\n return `M ${x + rx} ${y} H ${x + w - rx} A ${rx} ${ry} 0 0 1 ${x + w} ${y + ry} V ${y + h - ry} `\n + `A ${rx} ${ry} 0 0 1 ${x + w - rx} ${y + h} H ${x + rx} A ${rx} ${ry} 0 0 1 ${x} ${y + h - ry} `\n + `V ${y + ry} A ${rx} ${ry} 0 0 1 ${x + rx} ${y} Z`;\n}\n\nconst ellipseD = (cx: number, cy: number, rx: number, ry: number) =>\n `M ${cx - rx} ${cy} A ${rx} ${ry} 0 1 0 ${cx + rx} ${cy} A ${rx} ${ry} 0 1 0 ${cx - rx} ${cy} Z`;\n\n/** A shape element's outline as path data, or undefined for an element that draws none. */\nfunction shapeD(name: string, a: Readonly<Record<string, string>>): string | undefined {\n switch (name) {\n case 'path': return a.d;\n case 'rect': {\n const w = num(a.width), h = num(a.height);\n const rx = Math.min(num(a.rx, num(a.ry)), w / 2), ry = Math.min(num(a.ry, num(a.rx)), h / 2);\n return arcRectD(num(a.x), num(a.y), w, h, rx, ry);\n }\n case 'circle': return ellipseD(num(a.cx), num(a.cy), num(a.r), num(a.r));\n case 'ellipse': return ellipseD(num(a.cx), num(a.cy), num(a.rx), num(a.ry));\n case 'line': return `M ${num(a.x1)} ${num(a.y1)} L ${num(a.x2)} ${num(a.y2)}`;\n case 'polygon':\n case 'polyline': {\n const p = nums(a.points ?? '');\n if (p.length < 4) return undefined;\n const pts = [];\n for (let i = 0; i + 1 < p.length; i += 2) pts.push(`${p[i]} ${p[i + 1]}`);\n return `M ${pts.join(' L ')}${name === 'polygon' ? ' Z' : ''}`;\n }\n default: return undefined;\n }\n}\n\nconst paintOf = (v: string | undefined, color: string): string | null =>\n (v === undefined || v === 'none' ? null : /^currentcolor$/i.test(v) ? color : v);\n\n/** One shape's commands: its fill, then its stroke, each at its own opacity. */\nfunction shapeCommands(path: Path, a: Readonly<Record<string, string>>, color: string): DrawCommand[] {\n const out: DrawCommand[] = [];\n const fill = paintOf(a.fill, color);\n if (fill) {\n const p = path.kind === 'polygon' && a['fill-rule'] === 'evenodd' ? { ...path, fillRule: 'evenodd' as const } : path;\n const cmd: DrawCommand = { kind: 'path', path: p, fill: { paint: { kind: 'solid', color: fill } } };\n const alpha = num(a['fill-opacity'], 1);\n out.push(alpha < 1 ? { kind: 'group', alpha, children: [cmd] } : cmd);\n }\n const stroke = paintOf(a.stroke, color);\n if (stroke) {\n const dash = a['stroke-dasharray'] && a['stroke-dasharray'] !== 'none' ? nums(a['stroke-dasharray']) : undefined;\n const cmd: DrawCommand = {\n kind: 'path', path,\n stroke: {\n paint: { kind: 'solid', color: stroke },\n width: num(a['stroke-width'], 1),\n cap: a['stroke-linecap'] as 'butt' | 'round' | 'square' | undefined,\n join: a['stroke-linejoin'] as 'miter' | 'round' | 'bevel' | undefined,\n ...(dash ? { dash } : {}),\n },\n };\n const alpha = num(a['stroke-opacity'], 1);\n out.push(alpha < 1 ? { kind: 'group', alpha, children: [cmd] } : cmd);\n }\n return out;\n}\n\ninterface Frame { attrs: Readonly<Record<string, string>>; children: DrawCommand[]; group: DrawCommand & { kind: 'group' } }\n\nfunction frameFor(t: Tag, parent: Readonly<Record<string, string>>): Frame {\n const attrs = { ...parent };\n for (const [k, v] of Object.entries(t.attrs)) if (INHERITED.has(k)) attrs[k] = v;\n const children: DrawCommand[] = [];\n const group: Frame['group'] = { kind: 'group', children };\n const m = transformOf(t.attrs.transform);\n if (m.some((v, i) => v !== identity()[i])) group.transform = mat3.fromAffine(m);\n // Every nested `<svg>` a glyph uses has a viewBox matching its own box, so it only clips.\n if (t.name === 'svg') {\n group.clip = { kind: 'rect', x: num(t.attrs.x), y: num(t.attrs.y), width: num(t.attrs.width), height: num(t.attrs.height) };\n }\n return { attrs, children, group };\n}\n\n/**\n * A glyph as draw commands, placed in a square and drawn in `color` wherever it says\n * `currentColor`, as `<Icon>` draws it in the DOM. Reads the elements the icon tables use — `path`,\n * `rect`, `circle`, `ellipse`, `line`, `polygon`, `polyline`, `g` and a nested `svg` — with their\n * presentation attributes and transforms. `defs` and what they hold are skipped, so a `clip-path`\n * pointing into them does not clip.\n */\nexport function glyphCommands(glyph: IconGlyph, at: GlyphPlacement): DrawCommand[] {\n const k = at.size / 20;\n const root: Frame = {\n attrs: ROOT, children: [],\n group: { kind: 'group', transform: mat3.fromAffine([k, 0, 0, k, at.x, at.y]), children: [] },\n };\n root.group.children = root.children;\n const stack: Frame[] = [root];\n let skipping = 0;\n for (const t of tags(glyph.body)) {\n const top = stack.at(-1)!;\n if (skipping > 0 || t.name === 'defs' || t.name === 'clipPath') {\n if (!t.selfClosing) skipping += t.close ? -1 : 1;\n continue;\n }\n if (t.close) {\n if ((t.name === 'g' || t.name === 'svg') && stack.length > 1) stack.pop();\n continue;\n }\n if (t.name === 'g' || t.name === 'svg') {\n const f = frameFor(t, top.attrs);\n top.children.push(f.group);\n if (!t.selfClosing) stack.push(f);\n continue;\n }\n const d = shapeD(t.name, t.attrs);\n if (d === undefined) continue;\n const f = frameFor(t, top.attrs);\n const cmds = shapeCommands(pathFromD(d), f.attrs, at.color);\n if (f.group.transform) top.children.push({ kind: 'group', transform: f.group.transform, children: cmds });\n else top.children.push(...cmds);\n }\n return [root.group];\n}\n","import type { DrawCommand } from '@weasel-js/core/renderer';\nimport { pathFromD, textCommandFromRuns } from '@weasel-js/core';\nimport { menuNumberCanStep, menuNumberText, type MenuColorEntry, type MenuEntry, type MenuNumberEntry } from '@weasel-js/menu';\nimport type { WidgetBounds } from '../widget';\nimport type { MenuMetrics } from './drawPanel';\n\n/** A span across a panel, from its left edge. */\nexport interface Span { x: number; w: number }\n\n/**\n * Where a number row's step chips and value sit, at the row's end: a minus chip, the value in a cell of fixed\n * width so a changing value moves nothing, and a plus chip. `width` is all three.\n */\nexport function numberChips(panelW: number, m: MenuMetrics): { minus: Span; value: Span; plus: Span; width: number } {\n const s = m.rowHeight;\n const end = panelW - m.padX;\n return { minus: { x: end - 4 * s, w: s }, value: { x: end - 3 * s, w: 2 * s }, plus: { x: end - s, w: s }, width: 4 * s };\n}\n\n/** Which way the chip under panel-local `x` steps a number row: 1, -1, or null off both. */\nexport function chipAt(panelW: number, m: MenuMetrics, x: number): 1 | -1 | null {\n const { minus, plus } = numberChips(panelW, m);\n const inside = (s: Span) => x >= s.x && x < s.x + s.w;\n return inside(plus) ? 1 : inside(minus) ? -1 : null;\n}\n\n/** What a value row needs past its label, for sizing the panel; undefined for any other row. */\nexport function valueRowWidth(e: MenuEntry, m: MenuMetrics, measure: (text: string, fontSize: number) => number): number | undefined {\n if (e.kind === 'number') return m.padX + numberChips(0, m).width;\n if (e.kind === 'color') return Math.max(m.rowHeight, m.padX + measure(e.value ?? '—', m.fontSize));\n if (e.kind === 'text') return m.padX + measure(e.value ?? '—', m.fontSize);\n return undefined;\n}\n\nconst solid = (color: string) => ({ paint: { kind: 'solid' as const, color } });\nconst mark = (d: string, color: string): DrawCommand => ({\n kind: 'path', path: pathFromD(d), stroke: { paint: { kind: 'solid', color }, width: 1.5, cap: 'round' },\n});\n\n/** The colors and font a value row draws in. */\nexport interface ValueInk { fg: string; muted: string; border: string; font: { fontFamily: string; fontSize: number } }\n\n/** A number row's chips and value. A chip with nowhere to step to is muted, as is all of a disabled row. */\nexport function numberCommands(\n b: WidgetBounds, r: { y: number; h: number }, e: MenuNumberEntry, value: number | undefined, m: MenuMetrics, ink: ValueInk,\n): DrawCommand[] {\n const { minus, value: cell, plus } = numberChips(b.w, m);\n const cy = b.y + r.y + r.h / 2;\n const color = (live: boolean) => (live && !e.disabled ? ink.fg : ink.muted);\n const cx = (s: Span) => b.x + s.x + s.w / 2;\n const low = value !== undefined && !menuNumberCanStep(e, value, -1);\n const high = value !== undefined && !menuNumberCanStep(e, value, 1);\n return [\n mark(`M ${cx(minus) - 4} ${cy} L ${cx(minus) + 4} ${cy}`, color(!low)),\n textCommandFromRuns(\n b.x + cell.x, b.y + r.y, [{ text: menuNumberText(value, e), fill: solid(color(true)) }],\n { ...ink.font, align: 'center' }, undefined, r.h, 'center', undefined, cell.w,\n ),\n mark(`M ${cx(plus) - 4} ${cy} L ${cx(plus) + 4} ${cy} M ${cx(plus)} ${cy - 4} L ${cx(plus)} ${cy + 4}`, color(!high)),\n ];\n}\n\n/** A text row's value at the row's end, muted: nothing in a HUD menu edits it. */\nexport function textCommands(\n b: WidgetBounds, r: { y: number; h: number }, value: string | undefined, m: MenuMetrics, ink: ValueInk,\n): DrawCommand[] {\n return [textCommandFromRuns(\n b.x + m.padX, b.y + r.y, [{ text: value ?? '—', fill: solid(ink.muted) }],\n { ...ink.font, align: 'right' }, undefined, r.h, 'center', undefined, b.w - m.padX * 2,\n )];\n}\n\n/** The swatch a color row draws in its icon column, and its hex at the row's end. */\nexport function colorCommands(\n b: WidgetBounds, r: { y: number; h: number }, e: MenuColorEntry, m: MenuMetrics, ink: ValueInk,\n): DrawCommand[] {\n const out: DrawCommand[] = [];\n if (e.value !== undefined) {\n const size = 12;\n const x = b.x + m.padX + (m.rowHeight - size) / 2;\n const y = b.y + r.y + (r.h - size) / 2;\n out.push({\n kind: 'path', path: { kind: 'rect', x, y, width: size, height: size },\n fill: solid(e.value), stroke: { paint: { kind: 'solid', color: ink.border }, width: 1 },\n });\n }\n out.push(textCommandFromRuns(\n b.x + m.padX, b.y + r.y, [{ text: e.value ?? '—', fill: solid(ink.muted) }],\n { ...ink.font, align: 'right' }, undefined, r.h, 'center', undefined, b.w - m.padX * 2,\n ));\n return out;\n}\n","import type { DrawCommand } from '@weasel-js/core/renderer';\nimport { pathFromD, textCommandFromRuns } from '@weasel-js/core';\nimport { roundRectPath } from '@weasel-js/geom';\nimport { formatShortcut } from '@weasel-js/gestures';\nimport type { MenuEntry, MenuNumberEntry } from '@weasel-js/menu';\nimport { expandVars, parseBoxShadow, resolveCurrentColor, tokenPx } from '@weasel-js/theme';\nimport { toIconRef, type IconRegistry } from '@weasel-js/icons';\nimport { boxShadowCommands } from '../boxShadow';\nimport { glyphCommands } from '../glyph';\nimport type { HudDrawCtx, WidgetBounds } from '../widget';\nimport { colorCommands, numberCommands, textCommands, valueRowWidth } from './valueRows';\n\n/** Sizes of a HUD menu panel, in CSS pixels. */\nexport interface MenuMetrics {\n rowHeight: number;\n padX: number;\n padY: number;\n separatorHeight: number;\n minWidth: number;\n fontSize: number;\n}\n\n/** The metrics a menu widget uses when given none, close to the DOM menu's. */\nexport const DEFAULT_MENU_METRICS: MenuMetrics = {\n rowHeight: 24, padX: 8, padY: 4, separatorHeight: 9, minWidth: 180, fontSize: 13,\n};\n\n/** Each entry's y offset and height inside a panel. */\nexport function rowLayout(entries: readonly MenuEntry[], m: MenuMetrics): { y: number; h: number }[] {\n let y = m.padY;\n return entries.map((e) => {\n const h = e.kind === 'separator' ? m.separatorHeight : m.rowHeight;\n const row = { y, h };\n y += h;\n return row;\n });\n}\n\n/** A row's shortcut as the DOM menu prints it, or undefined. */\nconst shortcutOf = (e: MenuEntry): string | undefined =>\n (e.kind === 'item' ? formatShortcut(e.shortcut) : undefined);\n\n/** A panel's size: its widest row — label, then a shortcut or the caret column —\n * plus the icon column, never under `minWidth`. */\nexport function panelSize(\n entries: readonly MenuEntry[], m: MenuMetrics, measure: (text: string, fontSize: number) => number,\n): { w: number; h: number } {\n const rows = rowLayout(entries, m);\n const last = rows.at(-1);\n const rowWidth = (e: MenuEntry) => {\n if (e.kind === 'separator') return 0;\n const value = valueRowWidth(e, m, measure);\n if (value !== undefined) return measure(e.label, m.fontSize) + value;\n const chip = shortcutOf(e);\n return measure(e.label, m.fontSize) + Math.max(m.rowHeight, chip ? m.padX + measure(chip, m.fontSize) : 0);\n };\n const text = Math.max(0, ...entries.map(rowWidth));\n return {\n w: Math.max(m.minWidth, Math.ceil(text) + m.padX * 2 + m.rowHeight),\n h: (last ? last.y + last.h : 0) + m.padY,\n };\n}\n\nconst solid = (color: string) => ({ paint: { kind: 'solid' as const, color } });\nconst rect = (x: number, y: number, width: number, height: number, color: string): DrawCommand => ({\n kind: 'path', path: { kind: 'rect', x, y, width, height }, fill: solid(color),\n});\n\n/** A right-pointing chevron centered on (cx, cy). The bundled atlas has no `›` glyph. */\nfunction caret(cx: number, cy: number, color: string): DrawCommand {\n const s = 3;\n return {\n kind: 'path',\n path: pathFromD(`M ${cx - s / 2} ${cy - s} L ${cx + s / 2} ${cy} L ${cx - s / 2} ${cy + s}`),\n stroke: { paint: { kind: 'solid', color }, width: 1.5, cap: 'round' },\n };\n}\n\n/** A check mark centered on (cx, cy), for a row whose action is on. */\nfunction check(cx: number, cy: number, color: string): DrawCommand {\n return {\n kind: 'path',\n path: pathFromD(`M ${cx - 4} ${cy} L ${cx - 1.5} ${cy + 2.5} L ${cx + 4} ${cy - 3}`),\n stroke: { paint: { kind: 'solid', color }, width: 1.5, cap: 'round', join: 'round' },\n };\n}\n\n/** Where a menu finds the glyph a row's `icon` names: an icon registry, or anything answering as one. */\nexport type MenuIcons = Pick<IconRegistry, 'get' | 'getVersion'>;\n\n/** The DOM row draws its icon at 16px. */\nconst ICON_SIZE = 16;\n\n// The shadow `.surface` in ui's listbox.module.css gives the DOM panel.\nconst PANEL_SHADOW = 'var(--wzl-bevel-raised, 0 8px 24px var(--wzl-shadow))';\n\n/** One panel's commands: its rounded face and the DOM panel's box shadow, a highlight behind row\n * `highlight`, and every row, with the glyph `icons` holds for each row's icon. A number row shows what\n * `shown` says it holds, by default what it opened with. */\nexport function drawPanel(\n ctx: HudDrawCtx, b: WidgetBounds, entries: readonly MenuEntry[], highlight: number | null, m: MenuMetrics,\n icons?: MenuIcons, shown: (e: MenuNumberEntry) => number | undefined = (e) => e.value,\n): DrawCommand[] {\n const t = ctx.tokens;\n const fg = t['--wzl-fg'];\n const muted = resolveCurrentColor(t['--wzl-fg-muted'], fg);\n const radius = tokenPx('--wzl-radius-md', t);\n const font = { fontFamily: ctx.defaultFont, fontSize: m.fontSize };\n const shadow = boxShadowCommands(b, radius, parseBoxShadow(expandVars(PANEL_SHADOW, t)), fg,\n { x: b.x + 1, y: b.y + 1, w: b.w - 2, h: b.h - 2 });\n const out: DrawCommand[] = [...shadow.under, {\n kind: 'path',\n path: roundRectPath(b.x, b.y, b.w, b.h, radius),\n fill: solid(t['--wzl-surface-popover']),\n stroke: { paint: { kind: 'solid', color: t['--wzl-border'] }, width: 1 },\n }, ...shadow.over];\n const rows = rowLayout(entries, m);\n entries.forEach((e, i) => {\n const r = rows[i]!;\n if (e.kind === 'separator') {\n out.push(rect(b.x + m.padX, b.y + r.y + Math.floor(r.h / 2), b.w - m.padX * 2, 1, t['--wzl-border']));\n return;\n }\n if (i === highlight) out.push(rect(b.x + 2, b.y + r.y, b.w - 4, r.h, t['--wzl-surface-hover']));\n // Nothing here edits a color or a text row, so each reads as a disabled one does.\n const color = e.disabled || e.kind === 'color' || e.kind === 'text' ? muted : fg;\n out.push(textCommandFromRuns(\n b.x + m.padX + m.rowHeight, b.y + r.y,\n [{ text: e.label, fill: solid(color) }],\n font, undefined, r.h, 'center',\n ));\n const iconX = b.x + m.padX + m.rowHeight / 2;\n const iconY = b.y + r.y + r.h / 2;\n const ref = e.kind !== 'color' && typeof e.icon === 'string' ? toIconRef(e.icon) : undefined;\n const glyph = ref ? icons?.get(ref) : undefined;\n if (e.kind === 'item' && e.checked) out.push(check(iconX, iconY, color));\n else if (glyph) out.push(...glyphCommands(glyph, { x: iconX - ICON_SIZE / 2, y: iconY - ICON_SIZE / 2, size: ICON_SIZE, color }));\n const chip = shortcutOf(e);\n if (chip) {\n out.push(textCommandFromRuns(\n b.x + m.padX, b.y + r.y, [{ text: chip, fill: solid(muted) }],\n { ...font, align: 'right' }, undefined, r.h, 'center', undefined, b.w - m.padX * 2,\n ));\n }\n const ink = { fg, muted, border: t['--wzl-border'], font };\n if (e.kind === 'number') out.push(...numberCommands(b, r, e, shown(e), m, ink));\n if (e.kind === 'color') out.push(...colorCommands(b, r, e, m, ink));\n if (e.kind === 'text') out.push(...textCommands(b, r, e.value, m, ink));\n if (e.kind === 'submenu') out.push(caret(b.x + b.w - m.padX - m.rowHeight / 2, b.y + r.y + r.h / 2, color));\n });\n return out;\n}\n\n/** Index of the entry under panel-local `y`, or null. */\nexport function rowAt(entries: readonly MenuEntry[], m: MenuMetrics, y: number): number | null {\n const i = rowLayout(entries, m).findIndex((r) => y >= r.y && y < r.y + r.h);\n return i < 0 ? null : i;\n}\n","import { metricsOf, resolveFontVariant } from '@weasel-js/font';\n\n/** A width for `text` with no face to measure it in. */\nexport function estimateWidth(text: string, fontSize: number): number {\n return text.length * fontSize * 0.55;\n}\n\n/** Width of `text` at `fontSize` in `fontFamily`, from the advances and\n * kerning of the face the text command lays it out with. A face not loaded\n * yet gives an estimate; `faceGeneration` moves when it lands. */\nexport function measureLabel(text: string, fontSize: number, fontFamily: string): number {\n const metrics = metricsOf(resolveFontVariant(fontFamily, 400, 'normal'));\n if (!metrics) return estimateWidth(text, fontSize);\n let units = 0;\n let prev: number | null = null;\n for (const ch of text) {\n const cp = ch.codePointAt(0)!;\n units += metrics.advanceOf(cp) ?? metrics.size * 0.55;\n if (prev !== null) units += metrics.kernOf(prev, cp);\n prev = cp;\n }\n return units * fontSize / metrics.size;\n}\n","import { placeMenu, placeMenuUnder, placeSubmenu, type MenuController, type MenuEntry, type Rect } from '@weasel-js/menu';\nimport { faceGeneration } from '@weasel-js/font';\nimport { panelSize, rowLayout, type MenuMetrics } from './drawPanel';\nimport { estimateWidth } from './measureLabel';\n\ntype XY = { x: number; y: number };\n\n/** What placing needs: where the menu opened, the canvas, and how to measure. */\nexport interface PlaceOptions {\n anchor: XY;\n /** The button the menu hangs from, in canvas pixels; when set, `anchor` is not used. */\n under?: Rect;\n canvasSize(): { width: number; height: number };\n measure(text: string, fontSize: number, fontFamily: string): number;\n metrics: MenuMetrics;\n}\n\ninterface Placed {\n entries: readonly MenuEntry[];\n parentRow: number | null;\n rect: Rect;\n}\n\n/**\n * Places each open level once, when it opens: a level keeps its rect for as\n * long as its entries and the parent row it hangs from stay the same. A new\n * font family, or a face landing, re-measures everything. With no family yet\n * — the hud has not drawn — widths are estimated rather than measured in a\n * guessed family.\n */\nexport function createPlacer(opts: PlaceOptions): (c: MenuController, fontFamily: string | null) => Rect[] {\n let placed: Placed[] = [];\n let measured: { family: string | null; faces: number } | null = null;\n\n return (c, fontFamily) => {\n const faces = faceGeneration();\n if (measured?.family !== fontFamily || measured.faces !== faces) {\n placed = [];\n measured = { family: fontFamily, faces };\n }\n const { width, height } = opts.canvasSize();\n const bounds = { x: 0, y: 0, w: width, h: height };\n const m = opts.metrics;\n const stack = c.stack();\n const next: Placed[] = [];\n let kept = true;\n for (let level = 0; level < stack.length; level++) {\n const entries = c.entriesAt(level);\n const parentRow = level === 0 ? null : stack[level - 1] ?? null;\n const old = placed[level];\n if (kept && old && old.entries === entries && old.parentRow === parentRow) {\n next.push(old);\n continue;\n }\n kept = false;\n const size = panelSize(entries, m, (t, s) => (fontFamily === null ? estimateWidth(t, s) : opts.measure(t, s, fontFamily)));\n let at: XY;\n if (level === 0) {\n at = opts.under ? placeMenuUnder(size, opts.under, bounds) : placeMenu(size, opts.anchor, bounds);\n } else {\n const parent = next[level - 1]!.rect;\n const row = rowLayout(c.entriesAt(level - 1), m)[parentRow!]!;\n at = placeSubmenu(size, { x: parent.x, y: parent.y + row.y, w: parent.w, h: row.h }, bounds);\n }\n const rect = { x: at.x, y: at.y, w: size.w, h: size.h };\n next.push({ entries, parentRow, rect });\n c.setPanel(level, rect);\n }\n placed = next;\n return next.map((p) => p.rect);\n };\n}\n","import { createMenuController, withLinks, type Rect } from '@weasel-js/menu';\nimport { faceGeneration } from '@weasel-js/font';\nimport type { ClaimableGesture, OpenMenu } from '@weasel-js/core';\nimport { createRevision, type HudAccessibleTree, type HudKeyEvent, type HudPointerEvent, type Widget, type WidgetBounds } from '../widget';\nimport { accessibleMenu } from './accessibleMenu';\nimport { DEFAULT_MENU_METRICS, drawPanel, rowAt, type MenuIcons, type MenuMetrics } from './drawPanel';\nimport { measureLabel } from './measureLabel';\nimport { createPlacer } from './placePanels';\nimport { chipAt } from './valueRows';\nimport type { Point } from '@weasel-js/geom';\n\nconst CLAIMS: readonly ClaimableGesture[] = ['pointer', 'doubleClick', 'contextMenu', 'longPress', 'wheel'];\n\n/** What {@link createMenuWidget} needs: the open menu, how to close it, and the canvas it draws on. */\nexport interface MenuWidgetOptions {\n open: OpenMenu;\n /** The menu is done: an item was chosen, or it was dismissed. */\n close(): void;\n /** Viewport point to canvas CSS pixels, for `open.client` and `open.under`. */\n toCanvas(client: Point): Point;\n canvasSize(): { width: number; height: number };\n /** Width of a label in the family the hud draws with. Defaults to the\n * registered face's own advances, which is what the text is laid out with. */\n measure?(text: string, fontSize: number, fontFamily: string): number;\n metrics?: MenuMetrics;\n /** Where a row's icon is looked up; without it no row draws one. */\n icons?: MenuIcons;\n onChange(): void;\n}\n\nfunction underOnCanvas(r: Rect, toCanvas: (client: Point) => Point): Rect {\n const a = toCanvas({ x: r.x, y: r.y });\n const b = toCanvas({ x: r.x + r.w, y: r.y + r.h });\n return { x: a.x, y: a.y, w: b.x - a.x, h: b.y - a.y };\n}\n\n/** A widget that draws `open` as one panel per open level, driven by a menu controller it owns. */\nexport function createMenuWidget(opts: MenuWidgetOptions): Widget {\n const m = opts.metrics ?? DEFAULT_MENU_METRICS;\n const rev = createRevision(opts.onChange);\n const c = createMenuController({\n entries: withLinks(opts.open.entries, (href) => window.location.assign(href)),\n highlightFirst: opts.open.source === 'keyboard', onClose: opts.close,\n });\n const place = createPlacer({\n anchor: opts.toCanvas(opts.open.client),\n ...(opts.open.under ? { under: underOnCanvas(opts.open.under, opts.toCanvas) } : {}),\n canvasSize: opts.canvasSize,\n measure: opts.measure ?? measureLabel, metrics: m,\n });\n // The hud's font is known only once it draws.\n let family: string | null = null;\n let panels: Rect[] = place(c, family);\n let disposed = false;\n let armed = false;\n let hoverPanel: number | null = null;\n c.subscribe(() => { panels = place(c, family); rev.changed(); });\n\n /** The topmost panel under (x, y), or -1. */\n const levelAt = (x: number, y: number): number => {\n for (let i = panels.length - 1; i >= 0; i--) {\n const p = panels[i]!;\n if (x >= p.x && x < p.x + p.w && y >= p.y && y < p.y + p.h) return i;\n }\n return -1;\n };\n\n const union = (): WidgetBounds => {\n const x0 = Math.min(...panels.map((p) => p.x));\n const y0 = Math.min(...panels.map((p) => p.y));\n const x1 = Math.max(...panels.map((p) => p.x + p.w));\n const y1 = Math.max(...panels.map((p) => p.y + p.h));\n return { x: x0, y: y0, w: x1 - x0, h: y1 - y0 };\n };\n\n /** The pointer is now over `level` (null: no panel). Leaving a panel clears\n * its row, as the DOM menu's per-panel `pointerleave` does. */\n const enter = (level: number | null) => {\n if (hoverPanel !== null && hoverPanel !== level) c.hover(hoverPanel, null);\n hoverPanel = level;\n };\n\n const pointer = (evt: HudPointerEvent) => {\n if (evt.type === 'hoverleave') { enter(null); return; }\n if (evt.type === 'cancel') { armed = false; return; }\n if (evt.type === 'down') { armed = true; return; }\n if (evt.type !== 'hovermove' && evt.type !== 'move' && evt.type !== 'up') return;\n const level = levelAt(evt.x, evt.y);\n // Only a release that follows a press here chooses: the release of the\n // right-click or long-press that opened the menu must not.\n const choose = evt.type === 'up' && armed;\n if (evt.type === 'up') armed = false;\n if (!choose) enter(level < 0 ? null : level);\n if (level < 0) return;\n const entries = c.entriesAt(level);\n const index = rowAt(entries, m, evt.y - panels[level]!.y);\n if (!choose) c.hover(level, index, { x: evt.x, y: evt.y });\n else if (index !== null) {\n c.press(level, index);\n // A number row's chips step it, since this menu has no field to type in.\n const e = entries[index];\n const dir = e?.kind === 'number' ? chipAt(panels[level]!.w, m, evt.x - panels[level]!.x) : null;\n if (e?.kind === 'number' && dir !== null) c.spin(e, dir > 0 ? 'ArrowUp' : 'ArrowDown');\n }\n };\n\n const key = (evt: HudKeyEvent): boolean => {\n if (evt.type !== 'keydown') return false;\n if (!evt.ctrlKey && !evt.metaKey && !evt.altKey) c.key(evt.key);\n // Every key belongs to the open menu, so no canvas binding fires under it.\n return true;\n };\n\n const accessibleTree: HudAccessibleTree = { read: () => accessibleMenu(c), subscribe: c.subscribe };\n\n return {\n id: `weasel-menu-${opts.open.seq}`,\n get bounds() { return union(); },\n hidden: false,\n get disposed() { return disposed; },\n claims: CLAIMS,\n focusable: true,\n focusRing: false,\n accessibleName: 'Context menu',\n accessibleTree,\n deps: (ctx) => [...rev.deps(), ctx.defaultFont, faceGeneration(), opts.icons?.getVersion()],\n draw: (ctx) => {\n family = ctx.defaultFont;\n panels = place(c, family);\n return panels.flatMap((p, level) => drawPanel(ctx, p, c.entriesAt(level), c.stack()[level] ?? null, m, opts.icons, c.numberValue));\n },\n hitTest: (x, y) => levelAt(x, y) >= 0,\n cursorAt: () => 'default',\n onPointer: pointer,\n onKey: key,\n dispose() { disposed = true; c.dispose(); },\n };\n}\n","import type { MenuHost } from '@weasel-js/core';\nimport type { Hud } from '../hud';\nimport type { Widget } from '../widget';\nimport { createMenuWidget, type MenuWidgetOptions } from './menuWidget';\n\n/** What {@link attachMenuHost} needs beyond the hud and host. */\nexport type AttachMenuHostOptions =\n Pick<MenuWidgetOptions, 'toCanvas' | 'canvasSize' | 'measure' | 'metrics' | 'icons'>;\n\n/** Draw `host`'s open menu as a widget on `hud`, focused while open. A press\n * anywhere else takes focus from it, which closes the menu, as do a wheel\n * outside it, the window losing focus and a resize. Closing any other way\n * gives focus back to the widget that held it when the menu opened. Returns a detach. */\nexport function attachMenuHost(hud: Hud, host: MenuHost, opts: AttachMenuHostOptions): () => void {\n let widget: Widget | null = null;\n let returnTo: { widget: Widget | null; visible: boolean } = { widget: null, visible: false };\n\n // Cleared before removal: removing the focused widget blurs it, and that\n // blur must not read as a press elsewhere.\n const drop = () => {\n const w = widget;\n widget = null;\n if (!w) return;\n hud.remove(w);\n if (!w.disposed) w.dispose();\n };\n\n const giveBack = () => {\n const { widget: w, visible } = returnTo;\n returnTo = { widget: null, visible: false };\n if (w) hud.focus(w, { visible });\n };\n\n const sync = () => {\n const open = host.current();\n if (!widget) returnTo = { widget: hud.focused, visible: hud.focusVisible };\n const held = widget !== null && hud.focused === widget;\n drop();\n if (!open) {\n if (held) giveBack();\n return;\n }\n const w = createMenuWidget({\n ...opts, open,\n close: () => { if (host.current() === open) host.close(); },\n onChange: () => hud.markDirty(),\n });\n widget = w;\n hud.add(w);\n // A menu that cannot take focus could never be dismissed, so it does not open.\n if (!hud.focus(w)) { drop(); host.close(); }\n };\n\n const dismiss = () => { if (widget) host.close(); };\n const wheel = (e: WheelEvent) => {\n if (!widget) return;\n const p = opts.toCanvas({ x: e.clientX, y: e.clientY });\n if (!widget.hitTest(p.x, p.y)) host.close();\n };\n\n const unsubscribe = host.subscribe(sync);\n const unfocus = hud.subscribeFocus((f) => { if (widget && f !== widget) host.close(); });\n window.addEventListener('wheel', wheel, { capture: true, passive: true });\n window.addEventListener('blur', dismiss);\n window.addEventListener('resize', dismiss);\n sync();\n return () => {\n unsubscribe();\n unfocus();\n window.removeEventListener('wheel', wheel, true);\n window.removeEventListener('blur', dismiss);\n window.removeEventListener('resize', dismiss);\n drop();\n };\n}\n","import type { View } from '@weasel-js/core';\n\n/** Says whether what a lens reads from changed between one landed frame and the next. */\nexport interface ContentWatch {\n /** The camera the lens was just drawn through. */\n drew(view: View): void;\n /** Whether the content version or the camera differs from the last time this was asked. The first ask only\n * takes its bearings, and answers `false`. */\n changed(): boolean;\n}\n\n/**\n * Watches the two things that change the pixels under an aim that holds still: the content, through `version`\n * when the lens is given one, and the camera it is drawn through. A lens redrawing itself moves neither, which is\n * what lets it read the framebuffer again on a change without that read's own redraw asking for another.\n */\nexport function createContentWatch(version: (() => number) | undefined): ContentWatch {\n let camera = '';\n let seen: { version: number | undefined; camera: string } | null = null;\n return {\n drew(view) {\n camera = `${view.x},${view.y},${view.scale.x},${view.scale.y}`;\n },\n changed() {\n const now = { version: version?.(), camera };\n const moved = seen !== null && (seen.version !== now.version || seen.camera !== now.camera);\n seen = now;\n return moved;\n },\n };\n}\n","interface Point { x: number; y: number }\n\nconst POINTER_ENDS = ['pointerup', 'pointercancel', 'lostpointercapture'] as const;\n\n/**\n * Aims a lens from the pointer moving over `input`, in CSS px relative to it. A gesture that begins where\n * `holds` answers true freezes the aim until it ends: the lens camera follows the aim, so re-aiming mid-drag\n * would move the world under the pointer. Returns a detach.\n */\nexport function followPointer(\n input: HTMLElement,\n lens: { aimAt(p: Point): void; holds(p: Point): boolean },\n): () => void {\n let holding = false;\n const local = (evt: PointerEvent): Point => {\n const r = input.getBoundingClientRect();\n return { x: evt.clientX - r.left, y: evt.clientY - r.top };\n };\n const onPointerMove = (evt: PointerEvent) => {\n if (!holding) lens.aimAt(local(evt));\n };\n const onPointerDown = (evt: PointerEvent) => {\n if (lens.holds(local(evt))) holding = true;\n };\n const onPointerEnd = () => { holding = false; };\n\n input.addEventListener('pointermove', onPointerMove);\n input.addEventListener('pointerdown', onPointerDown);\n for (const type of POINTER_ENDS) input.addEventListener(type, onPointerEnd);\n return () => {\n input.removeEventListener('pointermove', onPointerMove);\n input.removeEventListener('pointerdown', onPointerDown);\n for (const type of POINTER_ENDS) input.removeEventListener(type, onPointerEnd);\n };\n}\n","import { clamp } from '@weasel-js/geom';\n\n/**\n * Read a `rw × rh` device-pixel region of the drawing buffer centered on\n * `pointer`, returned top-down. `pointer` is in CSS px relative to `target`,\n * the rect of the buffer the canvas paints into (device px, top-left origin),\n * and the read is clamped to stay inside that rect.\n *\n * GL reports rows bottom-up; every consumer here wants top-down, so both the\n * read origin and the returned rows are flipped.\n */\nexport function readbackRegion(\n gl: WebGL2RenderingContext,\n bufferHeight: number,\n target: { x: number; y: number; width: number; height: number },\n pointer: { x: number; y: number },\n dpr: number,\n rw: number,\n rh: number,\n): ImageData {\n const cx = target.x + Math.round(pointer.x * dpr);\n const cy = target.y + Math.round(pointer.y * dpr);\n const gx = clamp(cx - Math.floor(rw / 2), target.x, target.x + Math.max(0, target.width - rw));\n const gyTop = clamp(cy - Math.floor(rh / 2), target.y, target.y + Math.max(0, target.height - rh));\n const gy = bufferHeight - gyTop - rh;\n\n const raw = new Uint8Array(rw * rh * 4);\n gl.readPixels(gx, gy, rw, rh, gl.RGBA, gl.UNSIGNED_BYTE, raw);\n\n const flipped = new Uint8ClampedArray(rw * rh * 4);\n const stride = rw * 4;\n for (let row = 0; row < rh; row++) {\n const src = (rh - 1 - row) * stride;\n flipped.set(raw.subarray(src, src + stride), row * stride);\n }\n return new ImageData(flipped, rw, rh);\n}\n","import {\n createViewportLayer, screenToWorld, viewToTransform,\n type CanvasViewHandle, type RenderLayer, type SceneCanvasApi, type View, type ViewAt,\n} from '@weasel-js/core';\nimport { releaseImageSource, type DrawCommand } from '@weasel-js/core/renderer';\nimport {\n createLoupeModel, loupeInnerView,\n type LoupeMode, type LoupeModel, type LoupeSurface,\n} from '@weasel-js/loupe';\nimport type { Hud } from '../hud';\nimport type { WindowWidget } from '../widgets/window/window';\nimport type { HudContentCtx, WidgetBounds } from '../widget';\nimport { createContentWatch } from './contentWatch';\nimport { followPointer } from './pointerAim';\nimport { readbackRegion } from './readback';\n\nexport type { LoupeMode };\n\n/** Options for `createLoupe` shared by a plain lens and an interactive one. */\nexport interface LoupeBaseOptions {\n hud: Hud;\n /** The canvas pixel mode reads back from. Supplies the GL context and the\n * drawing-buffer dimensions. */\n canvas: HTMLCanvasElement;\n /** Where the aim comes from: the element pointer events are taken from and\n * the rect client coords are measured against. Defaults to `canvas`, which\n * is right whenever the canvas is also the thing under the pointer. */\n input?: HTMLElement;\n /** The rect of `canvas` the magnified picture occupies, in its CSS px — the\n * one the aim is relative to. Pass `CanvasExtensionApi.getSurfaceRect` for\n * a pane painted into a shared canvas. Defaults to `views.getSurfaceRect`\n * when the lens is a view, and to the whole canvas otherwise. */\n region?: () => { x: number; y: number; width: number; height: number };\n requestRedraw: () => void;\n /**\n * The version of what the canvas paints, read on every landed frame: when it moves, a lens whose aim has not\n * reads the framebuffer and the color under it again. Pass `CanvasExtensionApi.getPaintedVersion`. Defaults to\n * `views.getPaintedVersion` when the lens is a view. Without one the lens follows an edit under a parked aim\n * only in vector mode, or when told through `refresh()`; a camera move it follows either way.\n */\n contentVersion?: () => number;\n mode?: LoupeMode;\n factor?: number;\n bounds?: WidgetBounds;\n title?: string;\n /** Draw the window's titlebar and close box. Default `true`. Pass `false`\n * for a bare lens; the interior then doubles as the move handle, or, for an\n * `interactive` lens, a grip strip across its top does. */\n titlebar?: boolean;\n /** Called with the hex color under the aim point whenever it changes.\n * Sampled from the framebuffer in both modes — vector content is a\n * re-render whose edge colors differ from the screen's, so reading the\n * color off it would report something the user cannot see. */\n onColorChange?: (hex: string) => void;\n /** Fired when a click inside the lens picks a color — an eyedropper on the\n * magnified surface. Where the color goes is the consumer's: the loupe\n * reports the pick and nothing else. An `interactive` lens gives its clicks\n * to the canvas, so only `pick()` reaches this. */\n onPick?: (hex: string) => void;\n /** Fired by the window's close box. The window does not hide itself —\n * whoever owns the loupe's visibility decides what closing means. */\n onClose?: () => void;\n /** Backdrop painted behind the magnified content in both modes, so the\n * outer canvas does not show through where the lens is empty. Defaults to\n * the theme's surface color. */\n background?: string;\n}\n\n/** Options for `createLoupe`. */\nexport type LoupeOptions = LoupeBaseOptions & (\n | {\n /** Layers re-rendered through the magnified inner view in vector mode. */\n source: RenderLayer<unknown>[];\n views?: undefined;\n interactive?: false;\n }\n | {\n /**\n * The canvas, as a host for views. The lens becomes a view on it: vector\n * mode paints the canvas's own stack — scene and selection chrome — and\n * the lens can take input. It magnifies the camera of whatever view is\n * under its aim: aimed over a `<CanvasView>` panel, it shows and edits\n * that panel's world at the panel's zoom times its own factor. A host\n * without `viewAt` gets the canvas's camera wherever it aims.\n */\n views: Pick<SceneCanvasApi, 'addView' | 'getSurfaceRect'> & Partial<Pick<SceneCanvasApi, 'getPaintedVersion' | 'viewAt'>>;\n /** Narrows what vector mode paints. Defaults to the canvas's stack. */\n source?: RenderLayer<unknown>[];\n /**\n * Route input inside the lens to what it shows: a press selects the node\n * magnified under the pointer, and a drag moves it by the pointer travel\n * divided by the magnification. Default `false` — the window keeps its\n * interior, and a click there picks a color.\n */\n interactive?: boolean;\n }\n);\n\nconst backdropOf = (ctx: HudContentCtx, color: string): DrawCommand => ({\n kind: 'path',\n path: { kind: 'rect', x: ctx.rect.x, y: ctx.rect.y, width: ctx.rect.w, height: ctx.rect.h },\n fill: { paint: { kind: 'solid', color } },\n});\n\n/** The id the lens's view takes on its canvas. */\nconst LENS_VIEW = 'weasel-loupe:lens';\n\n/** Where an interactive lens routes while its window is hidden: nowhere. */\nconst NO_RECT = { x: 0, y: 0, w: 0, h: 0 };\n\n/** The lens camera aimed at `aim`: magnifying the view under it, or the\n * canvas's own camera `outer` where no view is. */\nfunction lensCamera(\n aim: { x: number; y: number }, under: ViewAt | null, outer: View, rect: WidgetBounds, factor: number,\n): View {\n if (under && under.id !== null) {\n const world = {\n x: (aim.x - under.rect.x) / under.view.scale.x + under.view.x,\n y: (aim.y - under.rect.y) / under.view.scale.y + under.view.y,\n };\n return loupeInnerView(world, under.view, rect, factor);\n }\n const world = screenToWorld(aim.x, aim.y, viewToTransform(outer));\n return loupeInnerView({ x: world[0], y: world[1] }, outer, rect, factor);\n}\n\n/** Control surface for a live loupe: where it is aimed, how it magnifies,\n * what color it is over, and the window it lives in. */\nexport interface LoupeHandle {\n readonly window: WindowWidget;\n readonly mode: LoupeMode;\n readonly factor: number;\n /** Last aimed point, in screen-space CSS px relative to the canvas. */\n readonly aim: { x: number; y: number };\n /** Hex color under the aim point, read off the framebuffer on the first\n * frame to land after the aim. `null` until then, or when the GL context\n * is unavailable. */\n readonly color: string | null;\n setMode(mode: LoupeMode): void;\n setFactor(factor: number): void;\n /** Aim at a screen point. Ignored while the point is over the window —\n * that is the freeze rule that makes the borders reachable. */\n aimAt(p: { x: number; y: number }): void;\n /** Sample the color the lens is showing at `p` — a screen point inside the\n * lens — and report it to `onPick`. Omit `p` to pick at the aim point.\n * Returns the hex, or `null` when the framebuffer cannot answer for that\n * point, including before any frame has landed. Leaves the aim, and\n * `color`, alone. */\n pick(p?: { x: number; y: number }): string | null;\n /** Ask for a paint, and on the frame that lands read the picture and the color under the aim again: what is\n * under the aim changed in a way no `contentVersion` reports. */\n refresh(): void;\n dispose(): void;\n}\n\n/**\n * Build a magnifier: a HUD window whose interior shows the canvas around an\n * aim point, enlarged. Adds the window to the HUD and starts following the\n * pointer; `dispose` removes it again.\n */\nexport function createLoupe(opts: LoupeOptions): LoupeHandle {\n const { hud, canvas: element, requestRedraw } = opts;\n const host = opts.views;\n const interactive = host !== undefined && opts.interactive === true;\n const input = opts.input ?? element;\n let lens: CanvasViewHandle | null = null;\n let pixels: ImageBitmap | null = null;\n const dropPixels = () => {\n if (!pixels) return;\n releaseImageSource(pixels);\n pixels.close();\n pixels = null;\n };\n let pixelsPending = false;\n let refreshWanted = false;\n let disposed = false;\n // Until a paint lands, the context on a shared canvas may not exist yet, and\n // opening it here would give every tenant one with no stencil buffer.\n let landed = false;\n\n const b = opts.bounds ?? { x: 24, y: 24, w: 220, h: 200 };\n\n const watch = createContentWatch(opts.contentVersion ?? host?.getPaintedVersion);\n let refreshAsked = false;\n\n const content = (ctx: HudContentCtx): DrawCommand[] => {\n watch.drew(ctx.view);\n return model.mode === 'vector' ? drawVector(ctx) : drawPixels(ctx);\n };\n\n const backdropColor = (ctx: HudContentCtx): string =>\n opts.background ?? ctx.tokens['--wzl-surface'];\n const backdrop = (ctx: HudContentCtx): DrawCommand => backdropOf(ctx, backdropColor(ctx));\n\n const innerView = (outer: View, rect: WidgetBounds): View => (\n lensCamera(model.aim, host?.viewAt?.(model.aim, { except: LENS_VIEW }) ?? null, outer, rect, model.factor)\n );\n\n const drawVector = (ctx: HudContentCtx): DrawCommand[] => {\n if (host) return lens ? [backdrop(ctx), ...lens.draw(ctx.data, ctx.view, ctx.dims)] : [backdrop(ctx)];\n // A fresh lens per frame: CreateViewportLayerOpts.view is static, and the\n // inner view moves with the pointer.\n const picture = createViewportLayer<unknown>({\n id: `${win.id}:lens`,\n label: 'Loupe content',\n source: opts.source ?? [],\n view: innerView(ctx.view, ctx.rect),\n bounds: () => ctx.rect,\n background: backdropColor(ctx),\n });\n return picture.draw(ctx.data, ctx.view, ctx.dims);\n };\n\n const drawPixels = (ctx: HudContentCtx): DrawCommand[] => {\n // The backdrop paints even with a bitmap in hand: a readback of a\n // transparent framebuffer is transparent, and before the first one\n // settles there is nothing at all, either of which leaves the lens a\n // hole onto the unmagnified canvas.\n const out: DrawCommand[] = [backdrop(ctx)];\n if (pixels) {\n out.push({\n kind: 'image',\n image: pixels,\n x: ctx.rect.x, y: ctx.rect.y, w: ctx.rect.w, h: ctx.rect.h,\n sampling: 'nearest',\n });\n }\n return out;\n };\n\n // `gl.readPixels` outside a landed paint returns the *previous* frame, so an\n // aim only marks the lens dirty; the read itself happens in the frame\n // subscriber below, on the frame that painted.\n const scheduleRefresh = () => {\n if (disposed || model.mode !== 'pixel') return;\n refreshWanted = true;\n };\n\n /** Read device px of the loupe's region around `at`, sized for the\n * canvas's pixel ratio, or `null` when the framebuffer cannot answer. */\n const read = (\n at: { x: number; y: number },\n rw: (dpr: number) => number,\n rh: (dpr: number) => number,\n ): ImageData | null => {\n if (!landed) return null;\n const gl = element.getContext('webgl2');\n if (!gl) return null;\n const cssRect = element.getBoundingClientRect();\n if (cssRect.width === 0) return null;\n const dpr = element.width / cssRect.width;\n // A view-backed lens knows its canvas, so over a detached pane it reads\n // that pane's pixels without being told where the pane is.\n const r = (opts.region ?? host?.getSurfaceRect)?.();\n const target = r\n ? {\n x: Math.round(r.x * dpr), y: Math.round(r.y * dpr),\n width: Math.round(r.width * dpr), height: Math.round(r.height * dpr),\n }\n : { x: 0, y: 0, width: element.width, height: element.height };\n return readbackRegion(gl, element.height, target, at, dpr, rw(dpr), rh(dpr));\n };\n\n const refreshPixels = () => {\n if (disposed || model.mode !== 'pixel') return;\n const rect = win.contentRect;\n const data = read(\n model.aim,\n (dpr) => Math.max(1, Math.round((rect.w * dpr) / model.factor)),\n (dpr) => Math.max(1, Math.round((rect.h * dpr) / model.factor)),\n );\n if (!data) return;\n pixelsPending = true;\n createImageBitmap(data)\n .then((bmp) => {\n if (disposed) { bmp.close(); return; }\n dropPixels();\n pixels = bmp;\n pixelsPending = false;\n requestRedraw();\n })\n .catch(() => {\n pixelsPending = false;\n requestRedraw();\n });\n };\n\n const readHex = (at: { x: number; y: number }): string | null => {\n const px = read(at, () => 1, () => 1);\n if (!px || px.data[3] === 0) return null;\n return '#' + [px.data[0], px.data[1], px.data[2]]\n .map((c) => c.toString(16).padStart(2, '0')).join('');\n };\n\n const win = hud.window({\n id: 'weasel-loupe',\n x: b.x, y: b.y, w: b.w, h: b.h,\n title: opts.title ?? 'Loupe',\n titlebar: opts.titlebar,\n content,\n interior: interactive ? 'pass' : 'claim',\n onResize: () => { scheduleRefresh(); },\n ...(interactive ? {} : { onContentClick: (p: { x: number; y: number }) => { model.pick(p); } }),\n ...(opts.onClose ? { onClose: opts.onClose } : {}),\n });\n\n const surface: LoupeSurface = {\n lens: () => win.contentRect,\n covers: (p) => win.hitTest(p.x, p.y) || (win.passes?.(p.x, p.y) ?? false),\n sample: readHex,\n hidden: () => win.hidden,\n gone: () => win.disposed === true,\n changed: () => { scheduleRefresh(); requestRedraw(); },\n subscribeFrame: hud.subscribeFrame,\n };\n\n // Subscribed ahead of the model, so the frame that lands first is already\n // readable by the time the model samples on it.\n const unsubscribeFrame = hud.subscribeFrame(() => {\n landed = true;\n if (watch.changed() || refreshAsked) {\n refreshAsked = false;\n scheduleRefresh();\n model.resample();\n }\n // A refresh wanted while a bitmap is in flight is remembered rather than\n // dropped: the flag survives until a frame finds it settled, so the aim\n // the user ends a fast drag on is the one that gets read.\n if (!refreshWanted || pixelsPending) return;\n refreshWanted = false;\n refreshPixels();\n });\n\n const model: LoupeModel = createLoupeModel({\n surface,\n ...(opts.mode ? { mode: opts.mode } : {}),\n ...(opts.factor !== undefined ? { factor: opts.factor } : {}),\n ...(opts.onColorChange ? { onColorChange: opts.onColorChange } : {}),\n ...(opts.onPick ? { onPick: opts.onPick } : {}),\n onDispose: () => teardown(),\n });\n\n if (host) {\n lens = host.addView({\n id: LENS_VIEW,\n label: 'Loupe',\n bounds: () => (win.hidden ? NO_RECT : win.contentRect),\n view: (outer) => innerView(outer, win.contentRect),\n paint: false,\n interactive,\n ...(opts.source ? { layers: () => opts.source! } : {}),\n });\n }\n\n const unfollow = followPointer(input, {\n aimAt: (p) => model.aimAt(p),\n holds: (p) => interactive && surface.covers(p),\n });\n\n const teardown = () => {\n disposed = true;\n unsubscribeFrame();\n unfollow();\n lens?.remove();\n lens = null;\n dropPixels();\n };\n\n return {\n window: win,\n get mode() { return model.mode; },\n get factor() { return model.factor; },\n get aim() { return model.aim; },\n get color() { return model.color; },\n setMode: model.setMode,\n setFactor: model.setFactor,\n aimAt: model.aimAt,\n pick: model.pick,\n refresh() {\n if (disposed) return;\n refreshAsked = true;\n requestRedraw();\n },\n dispose() {\n model.dispose();\n win.dispose();\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["solid","pathFromD","pathFromD","solid","loupeInnerView","registerDefaultFont","cursorForZone","createRevision","isFocusable","DEFAULT_WIDGET_CLAIMS","createHudContribution","createHud","attachHud","DEFAULT_WINDOW_METRICS","HUD_AFFORDANCE_KIND","claimsOf","pathFromD$1","loupeInnerView$1","labelOf","e","menuNumberText","c","swatchOf","level","stack","deepest","at","checkable","open","i","accessibleMenu","BLUR_LAYERS","BLUR_LAYER_ALPHA","solid$2","roundRectD","k","r","w","h","x","y","outer","rect","b","roundRectPath","s","radius","p","color","children","step","inset","margin","hole","ring","boxShadowCommands","under","over","innerRadius","padding","layers","resolveCurrentColor","current","ROOT","INHERITED","tags","m","body","attrs","a","num","v","d","nums","transformOf","identity","fn","args","next","translate","scale","rotateAboutPoint","multiply","arcRectD","rx","ry","ellipseD","cx","cy","shapeD","name","pts","paintOf","shapeCommands","out","fill","cmd","path","alpha","stroke","dash","frameFor","parent","t","group","mat3","glyphCommands","root","skipping","glyph","top","f","cmds","editMods","isApplePlatform","shift","evt","apple","WORD","wordStop","chars","dir","inside","from","startEdit","draft","selectionOf","edit","splice","caret","text","_","rest","to","composeEdit","insertText","shownEdit","shown","moveTo","n","extend","moveFor","key","mods","start","editKey","ends","editEnd","end","createTextEditor","was","commit","changed","numberChips","panelW","chipAt","plus","minus","valueRowWidth","measure","solid$1","mark","pathFromD","numberCommands","cell","live","ink","low","value","menuNumberCanStep","high","textCommandFromRuns","textCommands","mode","typedRight","caretAt","xAt","offsetsX","best","right","caretX","typingCommands","half","selection","preedit","swatchCommand","edge","colorCommands","estimateWidth","fontSize","measureLabel","metrics","metricsOf","resolveFontVariant","fontFamily","units","prev","ch","cp","DEFAULT_MENU_METRICS","rowLayout","entries","row","shortcutOf","formatShortcut","panelSize","last","chip","solid","check","ICON_SIZE","PANEL_SHADOW","OPENED_VALUES","drawPanel","ctx","fg","muted","tokenPx","font","shadow","parseBoxShadow","expandVars","rows","values","highlight","iconX","iconY","ref","toIconRef","icons","swatch","held","rowAt","createPlacer","placed","measured","faces","faceGeneration","opts","bounds","width","height","kept","parentRow","old","size","placeMenuUnder","placeMenu","placeSubmenu","DEFAULT_MENU_PALETTE","hexColor","written","tryNormalizeHex","keep","withColorPickers","swatches","picker","now","palette","hex","sub","walk","es","levelAt","panels","chipUnder","index","entry","createChipHold","repeat","createStepRepeat","CLAIMS","underOnCanvas","toCanvas","union","x0","y0","x1","y1","menuTextInput","typing","ps","createMenuWidget","edits","createEmitter","rev","pickers","withLinks","href","createMenuController","place","family","disposed","armed","hoverPanel","chips","enter","pointer","choose","accessibleTree","attachMenuHost","widget","returnTo","drop","hud","giveBack","sync","host","unsubscribe","unfocus","undismiss","attachMenuDismiss","createContentWatch","camera","seen","view","version","moved","POINTER_ENDS","followPointer","holding","local","input","onPointerMove","lens","onPointerDown","onPointerEnd","type","readbackRegion","target","dpr","gx","clamp","rw","gy","bufferHeight","rh","raw","gl","flipped","stride","src","backdropOf","LENS_VIEW","NO_RECT","lensCamera","world","aim","factor","screenToWorld","viewToTransform","createLoupe","element","interactive","pixels","dropPixels","releaseImageSource","pixelsPending","refreshWanted","landed","watch","refreshAsked","content","model","drawVector","drawPixels","backdropColor","backdrop","aimedView","innerView","createViewportLayer","win","scheduleRefresh","read","cssRect","refreshPixels","data","bmp","requestRedraw","readHex","px","surface","unsubscribeFrame","createLoupeModel","teardown","unfollow","DEFAULT_FONT_FAMILY","loupeInnerView"],"sources":["../src/menu/accessibleMenu.ts","../src/boxShadow.ts","../src/glyph.ts","../src/menu/textEdit.ts","../src/menu/valueRows.ts","../src/menu/measureLabel.ts","../src/menu/drawPanel.ts","../src/menu/placePanels.ts","../src/menu/colorPicker.ts","../src/menu/chipRepeat.ts","../src/menu/menuWidget.ts","../src/menu/attachMenuHost.ts","../src/loupe/contentWatch.ts","../src/loupe/pointerAim.ts","../src/loupe/readback.ts","../src/loupe/createLoupe.ts"],"sourcesContent":["import { menuNumberText, type MenuController, type MenuEntry, type MenuRowEntry } from '@weasel-js/menu';\nimport type { HudAccessibleNode } from '../widget';\n\n/** A row's name: a value row's label and the value it holds now, and a color picker's label and its color. */\nfunction labelOf(c: MenuController, e: MenuRowEntry, swatchOf?: (e: MenuEntry) => string | undefined): string {\n if (e.kind === 'number') return `${e.label}: ${menuNumberText(c.numberValue(e), e)}`;\n if (e.kind === 'color') return `${e.label}: ${e.value ?? '—'}`;\n if (e.kind === 'text') return `${e.label}: ${c.textValue(e) ?? '—'}`;\n if (e.kind === 'submenu' && swatchOf?.(e) !== undefined) return `${e.label}: ${swatchOf(e)}`;\n return e.label;\n}\n\n/** One level's rows, with the open submenu nested under the row it hangs from. */\nfunction level(c: MenuController, at: number, swatchOf?: (e: MenuEntry) => string | undefined): HudAccessibleNode[] {\n const stack = c.stack();\n const deepest = at === stack.length - 1;\n return c.entriesAt(at).map((e, i): HudAccessibleNode => {\n if (e.kind === 'separator') return { role: 'separator', key: e.key };\n const checkable = e.kind === 'item' && e.checked !== undefined;\n const open = e.kind === 'submenu' && stack[at] === i && stack.length > at + 1;\n return {\n role: checkable ? 'menuitemcheckbox' : 'menuitem',\n key: e.key,\n label: labelOf(c, e, swatchOf),\n ...(deepest && stack[at] === i ? { active: true } : {}),\n ...(e.kind === 'item' && e.checked !== undefined ? { checked: e.checked } : {}),\n ...(e.disabled || e.kind === 'color' ? { disabled: true } : {}),\n ...(e.kind === 'submenu' ? { expanded: open } : {}),\n ...(open ? { children: [{ role: 'menu', key: 'menu', label: e.label, children: level(c, at + 1, swatchOf) }] } : {}),\n };\n });\n}\n\n/** An open menu as the accessibility tree a DOM menu's panels show: rows with their roles and states, and the\n * highlighted row of the innermost open level active. `swatchOf` names the color a picker holds. */\nexport function accessibleMenu(c: MenuController, swatchOf?: (e: MenuEntry) => string | undefined): HudAccessibleNode {\n return { role: 'menu', key: 'menu', label: 'Context menu', children: level(c, 0, swatchOf) };\n}\n","import type { DrawCommand } from '@weasel-js/core/renderer';\nimport { pathFromD, roundRectPath, type Path } from '@weasel-js/geom';\nimport { resolveCurrentColor, type BoxShadow } from '@weasel-js/theme';\nimport type { WidgetBounds } from './widget';\n\n// A blurred layer is drawn as nested rounded rects reaching blur / 2 either side of its edge,\n// whose overlap builds the falloff.\nconst BLUR_LAYERS = 7;\nconst BLUR_LAYER_ALPHA = 0.16;\n\nconst solid = (color: string) => ({ paint: { kind: 'solid' as const, color } });\n\nfunction roundRectD(x: number, y: number, w: number, h: number, r: number): string {\n const k = Math.max(0, Math.min(r, w / 2, h / 2));\n if (k === 0) return `M ${x} ${y} H ${x + w} V ${y + h} H ${x} Z`;\n return `M ${x + k} ${y} H ${x + w - k} A ${k} ${k} 0 0 1 ${x + w} ${y + k} V ${y + h - k} `\n + `A ${k} ${k} 0 0 1 ${x + w - k} ${y + h} H ${x + k} A ${k} ${k} 0 0 1 ${x} ${y + h - k} `\n + `V ${y + k} A ${k} ${k} 0 0 1 ${x + k} ${y} Z`;\n}\n\nfunction outer(b: WidgetBounds, radius: number, s: BoxShadow, color: string): DrawCommand {\n const rect = (e: number): Path | null => {\n const w = b.w + e * 2;\n const h = b.h + e * 2;\n return w > 0 && h > 0 ? roundRectPath(b.x + s.x - e, b.y + s.y - e, w, h, Math.max(0, radius + e)) : null;\n };\n if (s.blur <= 0) {\n const p = rect(s.spread);\n return { kind: 'group', children: p ? [{ kind: 'path', path: p, fill: solid(color) }] : [] };\n }\n const children: DrawCommand[] = [];\n const step = s.blur / (BLUR_LAYERS - 1);\n for (let i = 0; i < BLUR_LAYERS; i++) {\n const p = rect(s.spread + s.blur / 2 - i * step);\n if (p) children.push({ kind: 'path', path: p, fill: solid(color) });\n }\n return { kind: 'group', alpha: BLUR_LAYER_ALPHA, children };\n}\n\n/** An inset layer, hard-edged whatever its blur: the box less itself moved by the offset and shrunk by the spread. */\nfunction inset(b: WidgetBounds, radius: number, s: BoxShadow, color: string): DrawCommand {\n const margin = Math.abs(s.x) + Math.abs(s.y) + Math.abs(s.spread) + 1;\n const hole = roundRectD(b.x + s.x + s.spread, b.y + s.y + s.spread, b.w - s.spread * 2, b.h - s.spread * 2,\n Math.max(0, radius - s.spread));\n const ring = pathFromD(`${roundRectD(b.x - margin, b.y - margin, b.w + margin * 2, b.h + margin * 2, 0)} ${hole}`);\n return {\n kind: 'group',\n clip: roundRectPath(b.x, b.y, b.w, b.h, radius),\n children: [{ kind: 'path', path: ring.kind === 'polygon' ? { ...ring, fillRule: 'evenodd' } : ring, fill: solid(color) }],\n };\n}\n\n/**\n * A CSS `box-shadow` list cast by a rounded box, as draw commands: `under` goes beneath the box's\n * face and `over` on top of it, for `inset` layers, which fall inside `padding` (the box less its\n * border). Layers draw last-first, so the first is topmost, as in CSS. `current` is what a layer\n * written in `currentColor` takes.\n */\nexport function boxShadowCommands(\n b: WidgetBounds, radius: number, layers: readonly BoxShadow[], current: string, padding: WidgetBounds = b,\n): { under: DrawCommand[]; over: DrawCommand[] } {\n const under: DrawCommand[] = [];\n const over: DrawCommand[] = [];\n const innerRadius = Math.max(0, radius - (padding.x - b.x));\n for (const s of [...layers].reverse()) {\n const color = resolveCurrentColor(s.color, current);\n if (s.inset) over.push(inset(padding, innerRadius, s, color));\n else under.push(outer(b, radius, s, color));\n }\n return { under, over };\n}\n","import type { DrawCommand } from '@weasel-js/core/renderer';\nimport {\n identity, mat3, multiply, pathFromD, rotateAboutPoint, scale, translate, type Affine, type Path,\n} from '@weasel-js/geom';\nimport type { IconGlyph } from '@weasel-js/icons';\n\n/** The attributes a glyph's elements inherit, as `<Icon>`'s root `<svg>` sets them. */\nconst ROOT: Readonly<Record<string, string>> = {\n fill: 'none', stroke: 'currentColor', 'stroke-width': '1.5',\n 'stroke-linecap': 'round', 'stroke-linejoin': 'round',\n};\n\nconst INHERITED = new Set([\n 'fill', 'fill-opacity', 'fill-rule', 'stroke', 'stroke-width', 'stroke-opacity',\n 'stroke-linecap', 'stroke-linejoin', 'stroke-dasharray',\n]);\n\n/** What a glyph is drawn in the place of `currentColor` with, and where. */\nexport interface GlyphPlacement {\n x: number;\n y: number;\n /** Width and height; the glyph's 20×20 viewBox scales to it. */\n size: number;\n color: string;\n}\n\ninterface Tag { close: boolean; name: string; attrs: Record<string, string>; selfClosing: boolean }\n\nfunction* tags(body: string): Generator<Tag> {\n for (const m of body.matchAll(/<(\\/?)([a-zA-Z]+)((?:\\s+[\\w:-]+=\"[^\"]*\")*)\\s*(\\/?)>/g)) {\n const attrs: Record<string, string> = {};\n for (const a of m[3]!.matchAll(/([\\w:-]+)=\"([^\"]*)\"/g)) attrs[a[1]!] = a[2]!;\n yield { close: m[1] === '/', name: m[2]!, attrs, selfClosing: m[4] === '/' };\n }\n}\n\nconst num = (v: string | undefined, d = 0) => (v === undefined || v === '' ? d : Number(v));\nconst nums = (v: string) => v.trim().split(/[\\s,]+/).filter((s) => s !== '').map(Number);\n\n/** An SVG `transform` list as one affine. */\nfunction transformOf(v: string | undefined): Affine {\n let m = identity();\n if (!v) return m;\n for (const [, fn, args] of v.matchAll(/(\\w+)\\s*\\(([^)]*)\\)/g)) {\n const a = nums(args!);\n const next: Affine | null = fn === 'translate' ? translate(a[0] ?? 0, a[1] ?? 0)\n : fn === 'scale' ? scale(a[0] ?? 1, a[1] ?? a[0] ?? 1)\n : fn === 'rotate' ? rotateAboutPoint(a[1] ?? 0, a[2] ?? 0, ((a[0] ?? 0) * Math.PI) / 180)\n : fn === 'matrix' && a.length === 6 ? (a as unknown as Affine) : null;\n if (next) m = multiply(m, next);\n }\n return m;\n}\n\nfunction arcRectD(x: number, y: number, w: number, h: number, rx: number, ry: number): string {\n if (rx <= 0 || ry <= 0) return `M ${x} ${y} H ${x + w} V ${y + h} H ${x} Z`;\n return `M ${x + rx} ${y} H ${x + w - rx} A ${rx} ${ry} 0 0 1 ${x + w} ${y + ry} V ${y + h - ry} `\n + `A ${rx} ${ry} 0 0 1 ${x + w - rx} ${y + h} H ${x + rx} A ${rx} ${ry} 0 0 1 ${x} ${y + h - ry} `\n + `V ${y + ry} A ${rx} ${ry} 0 0 1 ${x + rx} ${y} Z`;\n}\n\nconst ellipseD = (cx: number, cy: number, rx: number, ry: number) =>\n `M ${cx - rx} ${cy} A ${rx} ${ry} 0 1 0 ${cx + rx} ${cy} A ${rx} ${ry} 0 1 0 ${cx - rx} ${cy} Z`;\n\n/** A shape element's outline as path data, or undefined for an element that draws none. */\nfunction shapeD(name: string, a: Readonly<Record<string, string>>): string | undefined {\n switch (name) {\n case 'path': return a.d;\n case 'rect': {\n const w = num(a.width), h = num(a.height);\n const rx = Math.min(num(a.rx, num(a.ry)), w / 2), ry = Math.min(num(a.ry, num(a.rx)), h / 2);\n return arcRectD(num(a.x), num(a.y), w, h, rx, ry);\n }\n case 'circle': return ellipseD(num(a.cx), num(a.cy), num(a.r), num(a.r));\n case 'ellipse': return ellipseD(num(a.cx), num(a.cy), num(a.rx), num(a.ry));\n case 'line': return `M ${num(a.x1)} ${num(a.y1)} L ${num(a.x2)} ${num(a.y2)}`;\n case 'polygon':\n case 'polyline': {\n const p = nums(a.points ?? '');\n if (p.length < 4) return undefined;\n const pts = [];\n for (let i = 0; i + 1 < p.length; i += 2) pts.push(`${p[i]} ${p[i + 1]}`);\n return `M ${pts.join(' L ')}${name === 'polygon' ? ' Z' : ''}`;\n }\n default: return undefined;\n }\n}\n\nconst paintOf = (v: string | undefined, color: string): string | null =>\n (v === undefined || v === 'none' ? null : /^currentcolor$/i.test(v) ? color : v);\n\n/** One shape's commands: its fill, then its stroke, each at its own opacity. */\nfunction shapeCommands(path: Path, a: Readonly<Record<string, string>>, color: string): DrawCommand[] {\n const out: DrawCommand[] = [];\n const fill = paintOf(a.fill, color);\n if (fill) {\n const p = path.kind === 'polygon' && a['fill-rule'] === 'evenodd' ? { ...path, fillRule: 'evenodd' as const } : path;\n const cmd: DrawCommand = { kind: 'path', path: p, fill: { paint: { kind: 'solid', color: fill } } };\n const alpha = num(a['fill-opacity'], 1);\n out.push(alpha < 1 ? { kind: 'group', alpha, children: [cmd] } : cmd);\n }\n const stroke = paintOf(a.stroke, color);\n if (stroke) {\n const dash = a['stroke-dasharray'] && a['stroke-dasharray'] !== 'none' ? nums(a['stroke-dasharray']) : undefined;\n const cmd: DrawCommand = {\n kind: 'path', path,\n stroke: {\n paint: { kind: 'solid', color: stroke },\n width: num(a['stroke-width'], 1),\n cap: a['stroke-linecap'] as 'butt' | 'round' | 'square' | undefined,\n join: a['stroke-linejoin'] as 'miter' | 'round' | 'bevel' | undefined,\n ...(dash ? { dash } : {}),\n },\n };\n const alpha = num(a['stroke-opacity'], 1);\n out.push(alpha < 1 ? { kind: 'group', alpha, children: [cmd] } : cmd);\n }\n return out;\n}\n\ninterface Frame { attrs: Readonly<Record<string, string>>; children: DrawCommand[]; group: DrawCommand & { kind: 'group' } }\n\nfunction frameFor(t: Tag, parent: Readonly<Record<string, string>>): Frame {\n const attrs = { ...parent };\n for (const [k, v] of Object.entries(t.attrs)) if (INHERITED.has(k)) attrs[k] = v;\n const children: DrawCommand[] = [];\n const group: Frame['group'] = { kind: 'group', children };\n const m = transformOf(t.attrs.transform);\n if (m.some((v, i) => v !== identity()[i])) group.transform = mat3.fromAffine(m);\n // Every nested `<svg>` a glyph uses has a viewBox matching its own box, so it only clips.\n if (t.name === 'svg') {\n group.clip = { kind: 'rect', x: num(t.attrs.x), y: num(t.attrs.y), width: num(t.attrs.width), height: num(t.attrs.height) };\n }\n return { attrs, children, group };\n}\n\n/**\n * A glyph as draw commands, placed in a square and drawn in `color` wherever it says\n * `currentColor`, as `<Icon>` draws it in the DOM. Reads the elements the icon tables use — `path`,\n * `rect`, `circle`, `ellipse`, `line`, `polygon`, `polyline`, `g` and a nested `svg` — with their\n * presentation attributes and transforms. `defs` and what they hold are skipped, so a `clip-path`\n * pointing into them does not clip.\n */\nexport function glyphCommands(glyph: IconGlyph, at: GlyphPlacement): DrawCommand[] {\n const k = at.size / 20;\n const root: Frame = {\n attrs: ROOT, children: [],\n group: { kind: 'group', transform: mat3.fromAffine([k, 0, 0, k, at.x, at.y]), children: [] },\n };\n root.group.children = root.children;\n const stack: Frame[] = [root];\n let skipping = 0;\n for (const t of tags(glyph.body)) {\n const top = stack.at(-1)!;\n if (skipping > 0 || t.name === 'defs' || t.name === 'clipPath') {\n if (!t.selfClosing) skipping += t.close ? -1 : 1;\n continue;\n }\n if (t.close) {\n if ((t.name === 'g' || t.name === 'svg') && stack.length > 1) stack.pop();\n continue;\n }\n if (t.name === 'g' || t.name === 'svg') {\n const f = frameFor(t, top.attrs);\n top.children.push(f.group);\n if (!t.selfClosing) stack.push(f);\n continue;\n }\n const d = shapeD(t.name, t.attrs);\n if (d === undefined) continue;\n const f = frameFor(t, top.attrs);\n const cmds = shapeCommands(pathFromD(d), f.attrs, at.color);\n if (f.group.transform) top.children.push({ kind: 'group', transform: f.group.transform, children: cmds });\n else top.children.push(...cmds);\n }\n return [root.group];\n}\n","import type { MenuController, MenuEntry, MenuTextEntry } from '@weasel-js/menu';\nimport { isApplePlatform } from '@weasel-js/gestures';\nimport { editEnd } from '@weasel-js/headless';\n\n/** A text row being typed into in a HUD menu: which row, what has been typed so far, and the caret and the other\n * end of the selection, as code-point offsets into `draft`. `anchor` equals `caret` when nothing is selected.\n * `preedit` is an input method's text still being composed, shown in place of the selection; absent with none. */\nexport interface HudTextEdit {\n entry: MenuTextEntry;\n draft: string;\n caret: number;\n anchor: number;\n preedit?: string;\n}\n\n/** What the modifiers a key arrives with ask for: `shift` extends the selection, `mod` (Ctrl or Cmd) selects all on\n * `a` and holds any other character, `line` takes an arrow, Backspace or Delete to the end of the line, and `word`\n * takes them by a word. */\nexport interface EditMods { shift?: boolean; mod?: boolean; line?: boolean; word?: boolean }\n\n/** The modifiers held for a key, read as the platform's text fields read them: on Apple, Cmd works by the line and\n * Option by the word; elsewhere Ctrl works by the word, and Ctrl with Alt is AltGr, typing a character. */\nexport function editMods(\n evt: { shiftKey: boolean; ctrlKey: boolean; metaKey: boolean; altKey: boolean }, apple = isApplePlatform(),\n): EditMods {\n const shift = evt.shiftKey;\n if (apple) return { shift, mod: evt.ctrlKey || evt.metaKey, line: evt.metaKey, word: evt.altKey };\n if (evt.ctrlKey && evt.altKey) return { shift };\n return { shift, mod: evt.ctrlKey || evt.metaKey, word: evt.ctrlKey };\n}\n\nconst WORD = /[\\p{L}\\p{N}\\p{M}_]/u;\n\n/** The start of the word before `from` (dir -1) or the end of the word after it (dir 1), skipping what lies between. */\nexport function wordStop(chars: readonly string[], from: number, dir: -1 | 1): number {\n const at = (i: number) => WORD.test(chars[dir < 0 ? i - 1 : i] ?? '');\n const inside = (i: number) => (dir < 0 ? i > 0 : i < chars.length);\n let i = from;\n while (inside(i) && !at(i)) i += dir;\n while (inside(i) && at(i)) i += dir;\n return i;\n}\n\n/** An edit of `entry` holding `draft`, with the caret at its end. */\nexport function startEdit(entry: MenuTextEntry, draft: string): HudTextEdit {\n const n = Array.from(draft).length;\n return { entry, draft, caret: n, anchor: n };\n}\n\n/** The selection's two ends, in order. */\nexport function selectionOf(edit: HudTextEdit): [number, number] {\n return edit.caret < edit.anchor ? [edit.caret, edit.anchor] : [edit.anchor, edit.caret];\n}\n\n/** `edit` with `[from, to)` replaced by `text` and the caret after it. */\nfunction splice(edit: HudTextEdit, from: number, to: number, text: string): HudTextEdit {\n const chars = Array.from(edit.draft);\n const caret = from + Array.from(text).length;\n const { preedit: _, ...rest } = edit;\n return { ...rest, draft: [...chars.slice(0, from), text, ...chars.slice(to)].join(''), caret, anchor: caret };\n}\n\n/** `edit` composing `text`, or with no composition when `text` is empty. */\nexport function composeEdit(edit: HudTextEdit, text: string): HudTextEdit {\n const { preedit: _, ...rest } = edit;\n return text ? { ...rest, preedit: text } : rest;\n}\n\n/** `edit` with `text` in place of the selection and any composition, as a finished composition enters it. */\nexport function insertText(edit: HudTextEdit, text: string): HudTextEdit {\n const [from, to] = selectionOf(edit);\n return splice(edit, from, to, text);\n}\n\n/** What `edit` shows: its preedit, if any, typed in place of the selection, and the span the preedit covers. */\nexport function shownEdit(edit: HudTextEdit): { edit: HudTextEdit; preedit?: [number, number] } {\n if (!edit.preedit) return { edit };\n const [from] = selectionOf(edit);\n const shown = insertText(edit, edit.preedit);\n return { edit: shown, preedit: [from, shown.caret] };\n}\n\n/** `edit` with the caret at `to`, dragging the selection's far end along unless `extend`. */\nfunction moveTo(edit: HudTextEdit, to: number, extend: boolean): HudTextEdit {\n const n = Array.from(edit.draft).length;\n const caret = Math.max(0, Math.min(n, to));\n return { ...edit, caret, anchor: extend ? edit.anchor : caret };\n}\n\n/** Where an arrow, Home or End puts the caret, or undefined for any other key. */\nfunction moveFor(edit: HudTextEdit, key: string, mods: EditMods): number | undefined {\n const n = Array.from(edit.draft).length;\n const [from, to] = selectionOf(edit);\n if (key === 'Home' || (key === 'ArrowLeft' && mods.line)) return 0;\n if (key === 'End' || (key === 'ArrowRight' && mods.line)) return n;\n if (mods.word && (key === 'ArrowLeft' || key === 'ArrowRight')) {\n const dir = key === 'ArrowLeft' ? -1 : 1;\n const start = mods.shift ? edit.caret : dir < 0 ? from : to;\n return wordStop(Array.from(edit.draft), start, dir);\n }\n // An arrow with no Shift collapses a selection to its side before it moves anything.\n if (key === 'ArrowLeft') return !mods.shift && from !== to ? from : edit.caret - 1;\n if (key === 'ArrowRight') return !mods.shift && from !== to ? to : edit.caret + 1;\n return undefined;\n}\n\n/** What one key does to an edit: the edit it leaves, null once Enter or Escape ends it, and on Enter the text to\n * write. A character replaces the selection, Backspace and Delete take it or the character (or the word, or the\n * rest of the line) either side of the caret, and the arrows, Home and End move the caret; any other key is held\n * and ignored. */\nexport function editKey(edit: HudTextEdit, key: string, mods: EditMods = {}): { edit: HudTextEdit | null; commit?: string } {\n const ends = editEnd({ key, shift: mods.shift === true });\n if (ends) return ends === 'commit' ? { edit: null, commit: edit.draft } : { edit: null };\n const to = moveFor(edit, key, mods);\n if (to !== undefined) return { edit: moveTo(edit, to, mods.shift === true) };\n const [from, end] = selectionOf(edit);\n if ((key === 'Backspace' || key === 'Delete') && from !== end) return { edit: splice(edit, from, end, '') };\n const chars = Array.from(edit.draft);\n if (key === 'Backspace') {\n const start = mods.line ? 0 : mods.word ? wordStop(chars, from, -1) : Math.max(0, from - 1);\n return { edit: splice(edit, start, from, '') };\n }\n if (key === 'Delete') {\n return { edit: splice(edit, from, mods.line ? chars.length : mods.word ? wordStop(chars, from, 1) : from + 1, '') };\n }\n if (mods.mod) return { edit: key.toLowerCase() === 'a' ? { ...edit, anchor: 0, caret: chars.length } : edit };\n if (Array.from(key).length === 1) return { edit: splice(edit, from, end, key) };\n return { edit };\n}\n\n/** The text row a HUD menu is typing into, kept by the widget since it has no field: what is typed, written through\n * `c` on Enter. `changed` hears every change to what is drawn. */\nexport function createTextEditor(c: Pick<MenuController, 'textValue' | 'setText'>, changed: () => void) {\n let edit: HudTextEdit | null = null;\n const end = (commit?: string) => {\n const was = edit;\n edit = null;\n if (was && commit !== undefined) c.setText(was.entry, commit);\n changed();\n };\n return {\n current: () => edit,\n /** Start typing into `e` when it is a text row that is not disabled, and not the row already typed into. */\n start(e: MenuEntry | undefined) {\n if (e?.kind !== 'text' || e.disabled || edit?.entry === e) return;\n edit = startEdit(e, c.textValue(e) ?? '');\n changed();\n },\n /** When `e` is the row being typed into, put the caret at the offset `at` finds in what is typed; `at` gives\n * undefined to leave the caret be. */\n place(e: MenuEntry | undefined, at: (draft: string) => number | undefined) {\n const to = edit && edit.entry === e ? at(edit.draft) : undefined;\n if (!edit || to === undefined) return;\n edit = moveTo(edit, to, false);\n changed();\n },\n /** End the edit keeping what was typed, as a blur does, unless it is `e`'s. */\n leave(e?: MenuEntry) { if (edit && edit.entry !== e) end(editEnd('blur') === 'commit' ? edit.draft : undefined); },\n /** Show `text` as an input method's composition in progress; '' clears it. */\n compose(text: string) {\n if (!edit || (edit.preedit ?? '') === text) return;\n edit = composeEdit(edit, text);\n changed();\n },\n /** Enter `text` without a key, as a finished composition does. */\n insert(text: string) {\n if (!edit) return;\n edit = insertText(edit, text);\n changed();\n },\n /** Feed a key to the edit; false when nothing is being typed. */\n key(key: string, mods: EditMods = {}): boolean {\n if (!edit) return false;\n const next = editKey(edit, key, mods);\n if (next.edit) { edit = next.edit; changed(); } else end(next.commit);\n return true;\n },\n };\n}\n","import type { DrawCommand } from '@weasel-js/core/renderer';\nimport { pathFromD, textCommandFromRuns } from '@weasel-js/core';\nimport { menuNumberCanStep, menuNumberText, type MenuColorEntry, type MenuEntry, type MenuNumberEntry } from '@weasel-js/menu';\nimport type { WidgetBounds } from '../widget';\nimport type { MenuMetrics } from './drawPanel';\nimport { selectionOf, shownEdit, type HudTextEdit } from './textEdit';\n\n/** A span across a panel, from its left edge. */\nexport interface Span { x: number; w: number }\n\n/**\n * Where a number row's step chips and value sit, at the row's end: a minus chip, the value in a cell of fixed\n * width so a changing value moves nothing, and a plus chip. `width` is all three.\n */\nexport function numberChips(panelW: number, m: MenuMetrics): { minus: Span; value: Span; plus: Span; width: number } {\n const s = m.rowHeight;\n const end = panelW - m.padX;\n return { minus: { x: end - 4 * s, w: s }, value: { x: end - 3 * s, w: 2 * s }, plus: { x: end - s, w: s }, width: 4 * s };\n}\n\n/** Which way the chip under panel-local `x` steps a number row: 1, -1, or null off both. */\nexport function chipAt(panelW: number, m: MenuMetrics, x: number): 1 | -1 | null {\n const { minus, plus } = numberChips(panelW, m);\n const inside = (s: Span) => x >= s.x && x < s.x + s.w;\n return inside(plus) ? 1 : inside(minus) ? -1 : null;\n}\n\n/** What a value row needs past its label, for sizing the panel; undefined for any other row. */\nexport function valueRowWidth(e: MenuEntry, m: MenuMetrics, measure: (text: string, fontSize: number) => number): number | undefined {\n if (e.kind === 'number') return m.padX + numberChips(0, m).width;\n if (e.kind === 'color') return Math.max(m.rowHeight, m.padX + measure(e.value ?? '—', m.fontSize));\n // Room to type into, as the DOM menu's 12ch field gives.\n if (e.kind === 'text') return m.padX + Math.max(measure(e.value ?? '—', m.fontSize), m.fontSize * 7);\n return undefined;\n}\n\nconst solid = (color: string) => ({ paint: { kind: 'solid' as const, color } });\nconst mark = (d: string, color: string): DrawCommand => ({\n kind: 'path', path: pathFromD(d), stroke: { paint: { kind: 'solid', color }, width: 1.5, cap: 'round' },\n});\n\n/** The colors and font a value row draws in. */\nexport interface ValueInk { fg: string; muted: string; border: string; font: { fontFamily: string; fontSize: number } }\n\n/** A number row's chips and value. A chip with nowhere to step to is muted, as is all of a disabled row. */\nexport function numberCommands(\n b: WidgetBounds, r: { y: number; h: number }, e: MenuNumberEntry, value: number | undefined, m: MenuMetrics, ink: ValueInk,\n): DrawCommand[] {\n const { minus, value: cell, plus } = numberChips(b.w, m);\n const cy = b.y + r.y + r.h / 2;\n const color = (live: boolean) => (live && !e.disabled ? ink.fg : ink.muted);\n const cx = (s: Span) => b.x + s.x + s.w / 2;\n const low = value !== undefined && !menuNumberCanStep(e, value, -1);\n const high = value !== undefined && !menuNumberCanStep(e, value, 1);\n return [\n mark(`M ${cx(minus) - 4} ${cy} L ${cx(minus) + 4} ${cy}`, color(!low)),\n textCommandFromRuns(\n b.x + cell.x, b.y + r.y, [{ text: menuNumberText(value, e), fill: solid(color(true)) }],\n { ...ink.font, align: 'center' }, undefined, r.h, 'center', undefined, cell.w,\n ),\n mark(`M ${cx(plus) - 4} ${cy} L ${cx(plus) + 4} ${cy} M ${cx(plus)} ${cy - 4} L ${cx(plus)} ${cy + 4}`, color(!high)),\n ];\n}\n\n/** A text row's value at the row's end, muted while disabled. */\nexport function textCommands(\n b: WidgetBounds, r: { y: number; h: number }, value: string | undefined, m: MenuMetrics, ink: ValueInk,\n mode: 'off' | 'live' = 'live',\n): DrawCommand[] {\n return [textCommandFromRuns(\n b.x + m.padX, b.y + r.y, [{ text: value ?? '—', fill: solid(mode === 'off' ? ink.muted : ink.fg) }],\n { ...ink.font, align: 'right' }, undefined, r.h, 'center', undefined, b.w - m.padX * 2,\n )];\n}\n\n/** The right edge typed text is set against in a row of panel width `w`, leaving room for a caret after it. */\nconst typedRight = (w: number, m: MenuMetrics) => w - m.padX - 3;\n\n/** The code-point offset in `draft`, typed into a row of panel width `w`, nearest panel-local `x`, or undefined when\n * `x` is left of the text, over the row's label. `measure` gives the width of a run of the row's text. */\nexport function caretAt(draft: string, w: number, m: MenuMetrics, x: number, measure: (text: string) => number): number | undefined {\n const chars = Array.from(draft);\n const xAt = offsetsX(draft, w, m, measure);\n if (x < xAt(0) - m.padX) return undefined;\n let best = 0;\n for (let i = 1; i <= chars.length; i++) if (Math.abs(xAt(i) - x) < Math.abs(xAt(best) - x)) best = i;\n return best;\n}\n\n/** Panel-local x of each offset into `draft`, typed into a row of panel width `w`. */\nfunction offsetsX(draft: string, w: number, m: MenuMetrics, measure: (text: string) => number): (i: number) => number {\n const right = typedRight(w, m);\n const chars = Array.from(draft);\n return (i) => right - measure(chars.slice(i).join(''));\n}\n\n/** Panel-local x of the caret `edit` draws, after any composition in progress. */\nexport function caretX(edit: HudTextEdit, w: number, m: MenuMetrics, measure: (text: string) => number): number {\n const shown = shownEdit(edit).edit;\n return offsetsX(shown.draft, w, m, measure)(shown.caret) + 1;\n}\n\n/** A text row being typed into: what is typed at the row's end, the selection behind it in `selection`, an input\n * method's composition underlined in place of the selection, and a caret where `edit` has it. `measure` gives the\n * width of a run of the row's text. */\nexport function typingCommands(\n b: WidgetBounds, r: { y: number; h: number }, edit: HudTextEdit, m: MenuMetrics, ink: ValueInk, selection: string,\n measure: (text: string) => number,\n): DrawCommand[] {\n const { edit: shown, preedit } = shownEdit(edit);\n const at = offsetsX(shown.draft, b.w, m, measure);\n const xAt = (i: number) => b.x + at(i);\n // Room after the last character, so a caret at the end clears it.\n const right = b.x + typedRight(b.w, m);\n const half = ink.font.fontSize * 0.6;\n const cy = b.y + r.y + r.h / 2;\n const out: DrawCommand[] = [];\n const [from, to] = selectionOf(shown);\n if (from !== to) {\n out.push({\n kind: 'path', path: { kind: 'rect', x: xAt(from), y: cy - half, width: xAt(to) - xAt(from), height: half * 2 },\n fill: solid(selection),\n });\n }\n out.push(textCommandFromRuns(\n b.x + m.padX, b.y + r.y, [{ text: shown.draft, fill: solid(ink.fg) }],\n { ...ink.font, align: 'right' }, undefined, r.h, 'center', undefined, right - b.x - m.padX,\n ));\n if (preedit) out.push(mark(`M ${xAt(preedit[0])} ${cy + half} L ${xAt(preedit[1])} ${cy + half}`, ink.fg));\n const x = xAt(shown.caret) + 1;\n out.push(mark(`M ${x} ${cy - half} L ${x} ${cy + half}`, ink.fg));\n return out;\n}\n\n/** A swatch of `color` in a row's icon column, outlined in `edge`; `width` 2 marks the color a picker holds. */\nexport function swatchCommand(\n b: WidgetBounds, r: { y: number; h: number }, color: string, m: MenuMetrics, edge: string, width = 1,\n): DrawCommand {\n const size = 12;\n const x = b.x + m.padX + (m.rowHeight - size) / 2;\n const y = b.y + r.y + (r.h - size) / 2;\n return {\n kind: 'path', path: { kind: 'rect', x, y, width: size, height: size },\n fill: solid(color), stroke: { paint: { kind: 'solid', color: edge }, width },\n };\n}\n\n/** The swatch a color row draws in its icon column, and its hex at the row's end. */\nexport function colorCommands(\n b: WidgetBounds, r: { y: number; h: number }, e: MenuColorEntry, m: MenuMetrics, ink: ValueInk,\n): DrawCommand[] {\n const out: DrawCommand[] = e.value === undefined ? [] : [swatchCommand(b, r, e.value, m, ink.border)];\n out.push(textCommandFromRuns(\n b.x + m.padX, b.y + r.y, [{ text: e.value ?? '—', fill: solid(ink.muted) }],\n { ...ink.font, align: 'right' }, undefined, r.h, 'center', undefined, b.w - m.padX * 2,\n ));\n return out;\n}\n","import { metricsOf, resolveFontVariant } from '@weasel-js/font';\n\n/** A width for `text` with no face to measure it in. */\nexport function estimateWidth(text: string, fontSize: number): number {\n return text.length * fontSize * 0.55;\n}\n\n/** Width of `text` at `fontSize` in `fontFamily`, from the advances and\n * kerning of the face the text command lays it out with. A face not loaded\n * yet gives an estimate; `faceGeneration` moves when it lands. */\nexport function measureLabel(text: string, fontSize: number, fontFamily: string): number {\n const metrics = metricsOf(resolveFontVariant(fontFamily, 400, 'normal'));\n if (!metrics) return estimateWidth(text, fontSize);\n let units = 0;\n let prev: number | null = null;\n for (const ch of text) {\n const cp = ch.codePointAt(0)!;\n units += metrics.advanceOf(cp) ?? metrics.size * 0.55;\n if (prev !== null) units += metrics.kernOf(prev, cp);\n prev = cp;\n }\n return units * fontSize / metrics.size;\n}\n","import type { DrawCommand } from '@weasel-js/core/renderer';\nimport { pathFromD, textCommandFromRuns } from '@weasel-js/core';\nimport { roundRectPath } from '@weasel-js/geom';\nimport { formatShortcut } from '@weasel-js/gestures';\nimport type { MenuEntry, MenuNumberEntry, MenuTextEntry } from '@weasel-js/menu';\nimport { expandVars, parseBoxShadow, resolveCurrentColor, tokenPx } from '@weasel-js/theme';\nimport { toIconRef, type IconRegistry } from '@weasel-js/icons';\nimport { boxShadowCommands } from '../boxShadow';\nimport { glyphCommands } from '../glyph';\nimport type { HudDrawCtx, WidgetBounds } from '../widget';\nimport { colorCommands, numberCommands, swatchCommand, textCommands, typingCommands, valueRowWidth } from './valueRows';\nimport { measureLabel } from './measureLabel';\nimport type { HudTextEdit } from './textEdit';\n\n/** Sizes of a HUD menu panel, in CSS pixels. */\nexport interface MenuMetrics {\n rowHeight: number;\n padX: number;\n padY: number;\n separatorHeight: number;\n minWidth: number;\n fontSize: number;\n}\n\n/** The metrics a menu widget uses when given none, close to the DOM menu's. */\nexport const DEFAULT_MENU_METRICS: MenuMetrics = {\n rowHeight: 24, padX: 8, padY: 4, separatorHeight: 9, minWidth: 180, fontSize: 13,\n};\n\n/** Each entry's y offset and height inside a panel. */\nexport function rowLayout(entries: readonly MenuEntry[], m: MenuMetrics): { y: number; h: number }[] {\n let y = m.padY;\n return entries.map((e) => {\n const h = e.kind === 'separator' ? m.separatorHeight : m.rowHeight;\n const row = { y, h };\n y += h;\n return row;\n });\n}\n\n/** A row's shortcut as the DOM menu prints it, or undefined. */\nconst shortcutOf = (e: MenuEntry): string | undefined =>\n (e.kind === 'item' ? formatShortcut(e.shortcut) : undefined);\n\n/** A panel's size: its widest row — label, then a shortcut or the caret column —\n * plus the icon column, never under `minWidth`. */\nexport function panelSize(\n entries: readonly MenuEntry[], m: MenuMetrics, measure: (text: string, fontSize: number) => number,\n): { w: number; h: number } {\n const rows = rowLayout(entries, m);\n const last = rows.at(-1);\n const rowWidth = (e: MenuEntry) => {\n if (e.kind === 'separator') return 0;\n const value = valueRowWidth(e, m, measure);\n if (value !== undefined) return measure(e.label, m.fontSize) + value;\n const chip = shortcutOf(e);\n return measure(e.label, m.fontSize) + Math.max(m.rowHeight, chip ? m.padX + measure(chip, m.fontSize) : 0);\n };\n const text = Math.max(0, ...entries.map(rowWidth));\n return {\n w: Math.max(m.minWidth, Math.ceil(text) + m.padX * 2 + m.rowHeight),\n h: (last ? last.y + last.h : 0) + m.padY,\n };\n}\n\nconst solid = (color: string) => ({ paint: { kind: 'solid' as const, color } });\nconst rect = (x: number, y: number, width: number, height: number, color: string): DrawCommand => ({\n kind: 'path', path: { kind: 'rect', x, y, width, height }, fill: solid(color),\n});\n\n/** A right-pointing chevron centered on (cx, cy). The bundled atlas has no `›` glyph. */\nfunction caret(cx: number, cy: number, color: string): DrawCommand {\n const s = 3;\n return {\n kind: 'path',\n path: pathFromD(`M ${cx - s / 2} ${cy - s} L ${cx + s / 2} ${cy} L ${cx - s / 2} ${cy + s}`),\n stroke: { paint: { kind: 'solid', color }, width: 1.5, cap: 'round' },\n };\n}\n\n/** A check mark centered on (cx, cy), for a row whose action is on. */\nfunction check(cx: number, cy: number, color: string): DrawCommand {\n return {\n kind: 'path',\n path: pathFromD(`M ${cx - 4} ${cy} L ${cx - 1.5} ${cy + 2.5} L ${cx + 4} ${cy - 3}`),\n stroke: { paint: { kind: 'solid', color }, width: 1.5, cap: 'round', join: 'round' },\n };\n}\n\n/** Where a menu finds the glyph a row's `icon` names: an icon registry, or anything answering as one. */\nexport type MenuIcons = Pick<IconRegistry, 'get' | 'getVersion'>;\n\n/** The DOM row draws its icon at 16px. */\nconst ICON_SIZE = 16;\n\n// The shadow `.surface` in ui's listbox.module.css gives the DOM panel.\nconst PANEL_SHADOW = 'var(--wzl-bevel-raised, 0 8px 24px var(--wzl-shadow))';\n\n/** What a panel's value rows hold now, and the text row being typed into. */\nexport interface MenuDrawValues {\n number(e: MenuNumberEntry): number | undefined;\n text(e: MenuTextEntry): string | undefined;\n editing?: HudTextEdit | null;\n /** The color a row draws as a swatch in its icon column, in place of its icon or check. */\n swatch?(e: MenuEntry): string | undefined;\n /** Width of a label, which places the caret in typed text. Defaults to {@link measureLabel}. */\n measure?(text: string, fontSize: number, fontFamily: string): number;\n}\n\n/** Each value row as it opened, with nothing being typed. */\nexport const OPENED_VALUES: MenuDrawValues = { number: (e) => e.value, text: (e) => e.value };\n\n/** One panel's commands: its rounded face and the DOM panel's box shadow, a highlight behind row\n * `highlight`, and every row, with the glyph `icons` holds for each row's icon. A value row shows what\n * `values` says it holds, by default what it opened with. */\nexport function drawPanel(\n ctx: HudDrawCtx, b: WidgetBounds, entries: readonly MenuEntry[], highlight: number | null, m: MenuMetrics,\n icons?: MenuIcons, values: MenuDrawValues = OPENED_VALUES,\n): DrawCommand[] {\n const t = ctx.tokens;\n const fg = t['--wzl-fg'];\n const muted = resolveCurrentColor(t['--wzl-fg-muted'], fg);\n const radius = tokenPx('--wzl-radius-md', t);\n const font = { fontFamily: ctx.defaultFont, fontSize: m.fontSize };\n const shadow = boxShadowCommands(b, radius, parseBoxShadow(expandVars(PANEL_SHADOW, t)), fg,\n { x: b.x + 1, y: b.y + 1, w: b.w - 2, h: b.h - 2 });\n const out: DrawCommand[] = [...shadow.under, {\n kind: 'path',\n path: roundRectPath(b.x, b.y, b.w, b.h, radius),\n fill: solid(t['--wzl-surface-popover']),\n stroke: { paint: { kind: 'solid', color: t['--wzl-border'] }, width: 1 },\n }, ...shadow.over];\n const rows = rowLayout(entries, m);\n const measure = values.measure ?? measureLabel;\n const selection = t['--wzl-accent-soft'] ?? t['--wzl-surface-pressed'] ?? muted;\n entries.forEach((e, i) => {\n const r = rows[i]!;\n if (e.kind === 'separator') {\n out.push(rect(b.x + m.padX, b.y + r.y + Math.floor(r.h / 2), b.w - m.padX * 2, 1, t['--wzl-border']));\n return;\n }\n if (i === highlight) out.push(rect(b.x + 2, b.y + r.y, b.w - 4, r.h, t['--wzl-surface-hover']));\n // A color row left a color row is one nothing writes (the widget makes the rest pickers), so it reads as disabled.\n const color = e.disabled || e.kind === 'color' ? muted : fg;\n out.push(textCommandFromRuns(\n b.x + m.padX + m.rowHeight, b.y + r.y,\n [{ text: e.label, fill: solid(color) }],\n font, undefined, r.h, 'center',\n ));\n const iconX = b.x + m.padX + m.rowHeight / 2;\n const iconY = b.y + r.y + r.h / 2;\n const ref = e.kind !== 'color' && typeof e.icon === 'string' ? toIconRef(e.icon) : undefined;\n const glyph = ref ? icons?.get(ref) : undefined;\n const swatch = values.swatch?.(e);\n if (swatch !== undefined) {\n const held = e.kind === 'item' && e.checked;\n out.push(swatchCommand(b, r, swatch, m, held ? fg : t['--wzl-border'], held ? 2 : 1));\n } else if (e.kind === 'item' && e.checked) out.push(check(iconX, iconY, color));\n else if (glyph) out.push(...glyphCommands(glyph, { x: iconX - ICON_SIZE / 2, y: iconY - ICON_SIZE / 2, size: ICON_SIZE, color }));\n const chip = shortcutOf(e);\n if (chip) {\n out.push(textCommandFromRuns(\n b.x + m.padX, b.y + r.y, [{ text: chip, fill: solid(muted) }],\n { ...font, align: 'right' }, undefined, r.h, 'center', undefined, b.w - m.padX * 2,\n ));\n }\n const ink = { fg, muted, border: t['--wzl-border'], font };\n if (e.kind === 'number') out.push(...numberCommands(b, r, e, values.number(e), m, ink));\n if (e.kind === 'color') out.push(...colorCommands(b, r, e, m, ink));\n if (e.kind === 'text') {\n const edit = values.editing?.entry === e ? values.editing : undefined;\n out.push(...(edit\n ? typingCommands(b, r, edit, m, ink, selection, (s) => measure(s, m.fontSize, ctx.defaultFont))\n : textCommands(b, r, values.text(e), m, ink, e.disabled ? 'off' : 'live')));\n }\n if (e.kind === 'submenu') out.push(caret(b.x + b.w - m.padX - m.rowHeight / 2, b.y + r.y + r.h / 2, color));\n });\n return out;\n}\n\n/** Index of the entry under panel-local `y`, or null. */\nexport function rowAt(entries: readonly MenuEntry[], m: MenuMetrics, y: number): number | null {\n const i = rowLayout(entries, m).findIndex((r) => y >= r.y && y < r.y + r.h);\n return i < 0 ? null : i;\n}\n","import { placeMenu, placeMenuUnder, placeSubmenu, type MenuController, type MenuEntry, type Rect } from '@weasel-js/menu';\nimport { faceGeneration } from '@weasel-js/font';\nimport { panelSize, rowLayout, type MenuMetrics } from './drawPanel';\nimport { estimateWidth } from './measureLabel';\n\ntype XY = { x: number; y: number };\n\n/** What placing needs: where the menu opened, the canvas, and how to measure. */\nexport interface PlaceOptions {\n anchor: XY;\n /** The button the menu hangs from, in canvas pixels; when set, `anchor` is not used. */\n under?: Rect;\n canvasSize(): { width: number; height: number };\n measure(text: string, fontSize: number, fontFamily: string): number;\n metrics: MenuMetrics;\n}\n\ninterface Placed {\n entries: readonly MenuEntry[];\n parentRow: number | null;\n rect: Rect;\n}\n\n/**\n * Places each open level once, when it opens: a level keeps its rect for as\n * long as its entries and the parent row it hangs from stay the same. A new\n * font family, or a face landing, re-measures everything. With no family yet\n * — the hud has not drawn — widths are estimated rather than measured in a\n * guessed family.\n */\nexport function createPlacer(opts: PlaceOptions): (c: MenuController, fontFamily: string | null) => Rect[] {\n let placed: Placed[] = [];\n let measured: { family: string | null; faces: number } | null = null;\n\n return (c, fontFamily) => {\n const faces = faceGeneration();\n if (measured?.family !== fontFamily || measured.faces !== faces) {\n placed = [];\n measured = { family: fontFamily, faces };\n }\n const { width, height } = opts.canvasSize();\n const bounds = { x: 0, y: 0, w: width, h: height };\n const m = opts.metrics;\n const stack = c.stack();\n const next: Placed[] = [];\n let kept = true;\n for (let level = 0; level < stack.length; level++) {\n const entries = c.entriesAt(level);\n const parentRow = level === 0 ? null : stack[level - 1] ?? null;\n const old = placed[level];\n if (kept && old && old.entries === entries && old.parentRow === parentRow) {\n next.push(old);\n continue;\n }\n kept = false;\n const size = panelSize(entries, m, (t, s) => (fontFamily === null ? estimateWidth(t, s) : opts.measure(t, s, fontFamily)));\n let at: XY;\n if (level === 0) {\n at = opts.under ? placeMenuUnder(size, opts.under, bounds) : placeMenu(size, opts.anchor, bounds);\n } else {\n const parent = next[level - 1]!.rect;\n const row = rowLayout(c.entriesAt(level - 1), m)[parentRow!]!;\n at = placeSubmenu(size, { x: parent.x, y: parent.y + row.y, w: parent.w, h: row.h }, bounds);\n }\n const rect = { x: at.x, y: at.y, w: size.w, h: size.h };\n next.push({ entries, parentRow, rect });\n c.setPanel(level, rect);\n }\n placed = next;\n return next.map((p) => p.rect);\n };\n}\n","import { tryNormalizeHex } from '@weasel-js/paint';\nimport type { MenuColorEntry, MenuController, MenuEntry, MenuTextEntry } from '@weasel-js/menu';\n\n/** The swatches a HUD menu's color row offers when given no palette. */\nexport const DEFAULT_MENU_PALETTE: readonly string[] = [\n '#000000', '#595959', '#a6a6a6', '#ffffff',\n '#e53935', '#fb8c00', '#fdd835', '#43a047',\n '#00acc1', '#1e88e5', '#8e24aa', '#d81b60',\n];\n\n/** Entries with each color row a HUD menu can write turned into a picker, and the color each row shows. */\nexport interface HudColorPickers {\n entries: MenuEntry[];\n /** The color drawn in `e`'s icon column: a picker's current color, or a swatch's own. */\n swatchOf(e: MenuEntry): string | undefined;\n}\n\n/** `text` as the `#rrggbb` (or with `alpha`, `#rrggbbaa`) a color row writes, or undefined when it is no hex color.\n * Without `alpha`, an alpha typed is dropped; with it, a color typed without one takes `keep`'s, else opaque. */\nexport function hexColor(text: string, alpha: boolean, keep?: string): string | undefined {\n const written = tryNormalizeHex(text);\n if (written === undefined) return undefined;\n if (!alpha) return written.slice(0, 7);\n if (written.length === 9) return written;\n return `${written}${(keep && tryNormalizeHex(keep, 'rgba')?.slice(7)) || 'ff'}`;\n}\n\n/**\n * `entries` with every color row that has a `set` and is not disabled made a submenu: one row per `palette` color,\n * drawn as its swatch, which writes that color, then a text row holding the hex, which writes what is typed into\n * it. Both leave the menu open. `c` is the controller the entries go to, read only once a row\n * is drawn or chosen.\n */\nexport function withColorPickers(\n entries: readonly MenuEntry[], palette: readonly string[], c: () => Pick<MenuController, 'colorValue' | 'setColor'>,\n): HudColorPickers {\n const swatches = new Map<MenuEntry, () => string | undefined>();\n const picker = (e: MenuColorEntry): MenuEntry => {\n const now = () => c().colorValue(e);\n const alpha = e.alpha === true;\n const rows: MenuEntry[] = palette.map((color) => {\n const value = hexColor(color, alpha, e.value) ?? color;\n const row: MenuEntry = {\n kind: 'item', key: `${e.key}/${color}`, label: color,\n keepOpen: true,\n get checked() { return hexColor(now() ?? '', alpha) === hexColor(value, alpha); },\n run: () => c().setColor(e, hexColor(color, alpha, now()) ?? color),\n };\n swatches.set(row, () => value);\n return row;\n });\n const hex: MenuTextEntry = {\n kind: 'text', key: `${e.key}/#`, label: 'Hex',\n get value() { return now(); },\n set: (text) => {\n const value = hexColor(text, alpha, now());\n if (value !== undefined) c().setColor(e, value);\n },\n };\n const sub: MenuEntry = {\n kind: 'submenu', key: e.key, label: e.label, ...(e.access ? { access: e.access } : {}),\n entries: [...rows, { kind: 'separator', key: `${e.key}/|` }, hex],\n };\n swatches.set(sub, now);\n return sub;\n };\n const walk = (es: readonly MenuEntry[]): MenuEntry[] => es.map((e) => {\n if (e.kind === 'submenu') return { ...e, entries: walk(e.entries) };\n if (e.kind === 'color' && e.set && !e.disabled) return picker(e);\n return e;\n });\n const out = walk(entries);\n return { entries: out, swatchOf: (e) => swatches.get(e)?.() };\n}\n","import { createStepRepeat, type StepRepeatOptions } from '@weasel-js/headless';\nimport { menuNumberCanStep, type MenuController, type MenuNumberEntry, type Rect } from '@weasel-js/menu';\nimport { rowAt, type MenuMetrics } from './drawPanel';\nimport { chipAt } from './valueRows';\n\n/** A number row's step chip: the row, and which way it steps. */\nexport interface MenuChip { entry: MenuNumberEntry; dir: 1 | -1 }\n\n/** The topmost of `panels` under (x, y), or -1. */\nexport function levelAt(panels: readonly Rect[], x: number, y: number): number {\n for (let i = panels.length - 1; i >= 0; i--) {\n const p = panels[i]!;\n if (x >= p.x && x < p.x + p.w && y >= p.y && y < p.y + p.h) return i;\n }\n return -1;\n}\n\n/** The step chip under (x, y) of a number row that takes input, or null. */\nexport function chipUnder(\n c: Pick<MenuController, 'entriesAt'>, panels: readonly Rect[], m: MenuMetrics, x: number, y: number,\n): MenuChip | null {\n const level = levelAt(panels, x, y);\n if (level < 0) return null;\n const p = panels[level]!, entries = c.entriesAt(level);\n const index = rowAt(entries, m, y - p.y);\n const entry = index === null ? undefined : entries[index];\n if (entry?.kind !== 'number' || entry.disabled) return null;\n const dir = chipAt(p.w, m, x - p.x);\n return dir === null ? null : { entry, dir };\n}\n\n/** A press on a number row's chips: {@link ChipHold.press}, then {@link ChipHold.follow} for each move and the release. */\nexport interface ChipHold {\n /** Step the chip under (x, y), if any, once now and then repeatedly while it is held. */\n press(x: number, y: number): void;\n /** The pointer is at (x, y), or released at null: the hold ends unless it is still on the held chip. */\n follow(at: { x: number; y: number } | null): void;\n stop(): void;\n}\n\n/** Hold-to-repeat on number rows' step chips, timed as a `@weasel-js/ui` number field's steppers are by default.\n * `under` finds the chip at a point. */\nexport function createChipHold(\n c: Pick<MenuController, 'spin' | 'numberValue'>, under: (x: number, y: number) => MenuChip | null,\n opts?: StepRepeatOptions,\n): ChipHold {\n const from = (e: MenuNumberEntry) => c.numberValue(e) ?? e.min ?? 0;\n const repeat = createStepRepeat<MenuChip>(\n ({ entry, dir }) => { c.spin(entry, dir > 0 ? 'ArrowUp' : 'ArrowDown'); },\n ({ entry, dir }) => entry.disabled === true || !menuNumberCanStep(entry, from(entry), dir),\n opts,\n );\n return {\n press(x, y) {\n const chip = under(x, y);\n if (chip) repeat.start(chip);\n },\n follow(at) {\n const held = repeat.held();\n if (!held) return;\n const chip = at && under(at.x, at.y);\n if (chip?.entry !== held.entry || chip.dir !== held.dir) repeat.stop();\n },\n stop: repeat.stop,\n };\n}\n","import { createMenuController, withLinks, type MenuController, type Rect } from '@weasel-js/menu';\nimport { faceGeneration } from '@weasel-js/font';\nimport type { ClaimableGesture, OpenMenu } from '@weasel-js/core';\nimport { createEmitter } from '@weasel-js/registry';\nimport { createRevision, type HudAccessibleTree, type HudTextInput, type HudKeyEvent, type HudPointerEvent, type Widget, type WidgetBounds } from '../widget';\nimport { accessibleMenu } from './accessibleMenu';\nimport { DEFAULT_MENU_METRICS, drawPanel, rowAt, rowLayout, type MenuIcons, type MenuMetrics } from './drawPanel';\nimport { measureLabel } from './measureLabel';\nimport { createPlacer } from './placePanels';\nimport { caretAt, caretX } from './valueRows';\nimport { createTextEditor, editMods } from './textEdit';\nimport { DEFAULT_MENU_PALETTE, withColorPickers } from './colorPicker';\nimport type { Point } from '@weasel-js/geom';\nimport type { StepRepeatOptions } from '@weasel-js/headless';\nimport { chipUnder, createChipHold, levelAt } from './chipRepeat';\n\nconst CLAIMS: readonly ClaimableGesture[] = ['pointer', 'doubleClick', 'contextMenu', 'longPress', 'wheel'];\n\n/** What {@link createMenuWidget} needs: the open menu, how to close it, and the canvas it draws on. */\nexport interface MenuWidgetOptions {\n open: OpenMenu;\n /** The menu is done: an item was chosen, or it was dismissed. */\n close(): void;\n /** Viewport point to canvas CSS pixels, for `open.client` and `open.under`. */\n toCanvas(client: Point): Point;\n canvasSize(): { width: number; height: number };\n /** Width of a label in the family the hud draws with. Defaults to the\n * registered face's own advances, which is what the text is laid out with. */\n measure?(text: string, fontSize: number, fontFamily: string): number;\n metrics?: MenuMetrics;\n /** Where a row's icon is looked up; without it no row draws one. */\n icons?: MenuIcons;\n /** The swatches a color row's picker offers, as `#rrggbb`. Default {@link DEFAULT_MENU_PALETTE}. */\n palette?: readonly string[];\n /** The timing of a held number chip. Defaults to `REPEAT_DELAY_MS` and `REPEAT_EVERY_MS` from `@weasel-js/headless`,\n * the defaults a `@weasel-js/ui` number field's steppers hold with. */\n repeat?: StepRepeatOptions;\n onChange(): void;\n}\n\nfunction underOnCanvas(r: Rect, toCanvas: (client: Point) => Point): Rect {\n const a = toCanvas({ x: r.x, y: r.y });\n const b = toCanvas({ x: r.x + r.w, y: r.y + r.h });\n return { x: a.x, y: a.y, w: b.x - a.x, h: b.y - a.y };\n}\n\n/** The box around every panel. */\nfunction union(panels: readonly Rect[]): WidgetBounds {\n const x0 = Math.min(...panels.map((p) => p.x));\n const y0 = Math.min(...panels.map((p) => p.y));\n const x1 = Math.max(...panels.map((p) => p.x + p.w));\n const y1 = Math.max(...panels.map((p) => p.y + p.h));\n return { x: x0, y: y0, w: x1 - x0, h: y1 - y0 };\n}\n\n/** The edit `typing` runs as a widget's text input: its caret's place on the canvas, read off `panels()`, and its\n * composition. `measure` gives the width of a run of a row's text. */\nfunction menuTextInput(\n c: Pick<MenuController, 'entriesAt'>, typing: ReturnType<typeof createTextEditor>, panels: () => readonly Rect[],\n m: MenuMetrics, measure: (text: string) => number, subscribe: HudTextInput['subscribe'],\n): HudTextInput {\n const read = () => {\n const edit = typing.current();\n const ps = panels();\n for (let level = 0; edit && level < ps.length; level++) {\n const entries = c.entriesAt(level);\n const i = entries.indexOf(edit.entry);\n if (i < 0) continue;\n const p = ps[level]!, r = rowLayout(entries, m)[i]!;\n const x = p.x + caretX(edit, p.w, m, measure);\n return { rect: { x, y: p.y + r.y, w: Math.max(1, p.x + p.w - x), h: r.h }, label: edit.entry.label };\n }\n return null;\n };\n return { read, subscribe, compose: typing.compose, insert: typing.insert };\n}\n\n/** A widget that draws `open` as one panel per open level, driven by a menu controller it owns. */\nexport function createMenuWidget(opts: MenuWidgetOptions): Widget {\n const m = opts.metrics ?? DEFAULT_MENU_METRICS;\n const measure = opts.measure ?? measureLabel;\n const edits = createEmitter();\n const rev = createRevision(() => { opts.onChange(); edits.emit(); });\n const pickers = withColorPickers(\n withLinks(opts.open.entries, (href) => window.location.assign(href)), opts.palette ?? DEFAULT_MENU_PALETTE, () => c,\n );\n const c = createMenuController({\n entries: pickers.entries, highlightFirst: opts.open.source === 'keyboard', onClose: opts.close,\n });\n const place = createPlacer({\n anchor: opts.toCanvas(opts.open.client),\n ...(opts.open.under ? { under: underOnCanvas(opts.open.under, opts.toCanvas) } : {}),\n canvasSize: opts.canvasSize,\n measure, metrics: m,\n });\n // The hud's font is known only once it draws.\n let family: string | null = null;\n let panels: Rect[] = place(c, family);\n let disposed = false;\n let armed = false;\n let hoverPanel: number | null = null;\n const typing = createTextEditor(c, rev.changed);\n const chips = createChipHold(c, (x, y) => chipUnder(c, panels, m, x, y), opts.repeat);\n c.subscribe(() => { panels = place(c, family); rev.changed(); });\n\n /** The pointer is now over `level` (null: no panel). Leaving a panel clears\n * its row, as the DOM menu's per-panel `pointerleave` does. */\n const enter = (level: number | null) => {\n if (hoverPanel !== null && hoverPanel !== level) c.hover(hoverPanel, null);\n hoverPanel = level;\n };\n\n const pointer = (evt: HudPointerEvent) => {\n if (evt.type === 'hoverleave') { enter(null); return; }\n if (evt.type === 'cancel') { armed = false; chips.stop(); return; }\n if (evt.type === 'down') {\n armed = true;\n // A number row's chips step it, since this menu has no field to type in: once on the press, then\n // repeating while held, as a number field's steppers do.\n chips.press(evt.x, evt.y);\n return;\n }\n if (evt.type !== 'hovermove' && evt.type !== 'move' && evt.type !== 'up') return;\n chips.follow(evt.type === 'up' ? null : evt);\n const level = levelAt(panels, evt.x, evt.y);\n // Only a release that follows a press here chooses: the release of the\n // right-click or long-press that opened the menu must not.\n const choose = evt.type === 'up' && armed;\n if (evt.type === 'up') armed = false;\n if (!choose) enter(level < 0 ? null : level);\n if (level < 0) return;\n const entries = c.entriesAt(level);\n const index = rowAt(entries, m, evt.y - panels[level]!.y);\n if (!choose) c.hover(level, index, { x: evt.x, y: evt.y });\n else if (index !== null) {\n typing.leave(entries[index]);\n c.press(level, index);\n typing.start(entries[index]);\n const e = entries[index];\n const { w } = panels[level]!, x = evt.x - panels[level]!.x;\n typing.place(e, (draft) => caretAt(draft, w, m, x, (s) => measure(s, m.fontSize, family ?? '')));\n }\n };\n\n const key = (evt: HudKeyEvent): boolean => {\n if (evt.type !== 'keydown') return false;\n if (typing.key(evt.key, editMods(evt))) return true;\n const level = c.stack().length - 1;\n const at = c.stack()[level];\n const row = at == null ? undefined : c.entriesAt(level)[at];\n if (evt.key === 'Enter' && row?.kind === 'text') typing.start(row);\n else if (!evt.ctrlKey && !evt.metaKey && !evt.altKey) c.key(evt.key);\n // Every key belongs to the open menu, so no canvas binding fires under it.\n return true;\n };\n\n const accessibleTree: HudAccessibleTree = { read: () => accessibleMenu(c, pickers.swatchOf), subscribe: c.subscribe };\n\n return {\n id: `weasel-menu-${opts.open.seq}`,\n get bounds() { return union(panels); },\n hidden: false,\n get disposed() { return disposed; },\n claims: CLAIMS,\n focusable: true,\n focusRing: false,\n accessibleName: 'Context menu',\n accessibleTree,\n textInput: menuTextInput(c, typing, () => panels, m, (s) => measure(s, m.fontSize, family ?? ''), edits.subscribe),\n deps: (ctx) => [...rev.deps(), ctx.defaultFont, faceGeneration(), opts.icons?.getVersion()],\n draw: (ctx) => {\n family = ctx.defaultFont;\n panels = place(c, family);\n const values = {\n number: c.numberValue, text: c.textValue, editing: typing.current(), swatch: pickers.swatchOf,\n measure,\n };\n return panels.flatMap((p, level) => drawPanel(ctx, p, c.entriesAt(level), c.stack()[level] ?? null, m, opts.icons, values));\n },\n hitTest: (x, y) => levelAt(panels, x, y) >= 0,\n cursorAt: () => 'default',\n onPointer: pointer,\n onKey: key,\n dispose() {\n // Dismissed mid-edit, the menu keeps what was typed, as the DOM menu's field does on blur.\n typing.leave();\n chips.stop();\n disposed = true;\n c.dispose();\n },\n };\n}\n","import type { MenuHost } from '@weasel-js/core';\nimport { attachMenuDismiss } from '@weasel-js/menu';\nimport type { Hud } from '../hud';\nimport type { Widget } from '../widget';\nimport { createMenuWidget, type MenuWidgetOptions } from './menuWidget';\n\n/** What {@link attachMenuHost} needs beyond the hud and host. */\nexport type AttachMenuHostOptions =\n Pick<MenuWidgetOptions, 'toCanvas' | 'canvasSize' | 'measure' | 'metrics' | 'icons' | 'palette' | 'repeat'>;\n\n/** Draw `host`'s open menu as a widget on `hud`, focused while open. A press\n * anywhere else takes focus from it, which closes the menu, as do a wheel\n * outside it, the window losing focus and a resize. Closing any other way\n * gives focus back to the widget that held it when the menu opened. Returns a detach. */\nexport function attachMenuHost(hud: Hud, host: MenuHost, opts: AttachMenuHostOptions): () => void {\n let widget: Widget | null = null;\n let returnTo: { widget: Widget | null; visible: boolean } = { widget: null, visible: false };\n\n // Cleared before removal: removing the focused widget blurs it, and that\n // blur must not read as a press elsewhere.\n const drop = () => {\n const w = widget;\n widget = null;\n if (!w) return;\n hud.remove(w);\n if (!w.disposed) w.dispose();\n };\n\n const giveBack = () => {\n const { widget: w, visible } = returnTo;\n returnTo = { widget: null, visible: false };\n if (w) hud.focus(w, { visible });\n };\n\n const sync = () => {\n const open = host.current();\n if (!widget) returnTo = { widget: hud.focused, visible: hud.focusVisible };\n const held = widget !== null && hud.focused === widget;\n drop();\n if (!open) {\n if (held) giveBack();\n return;\n }\n const w = createMenuWidget({\n ...opts, open,\n close: () => { if (host.current() === open) host.close(); },\n onChange: () => hud.markDirty(),\n });\n widget = w;\n hud.add(w);\n // A menu that cannot take focus could never be dismissed, so it does not open.\n if (!hud.focus(w)) { drop(); host.close(); }\n };\n\n const unsubscribe = host.subscribe(sync);\n const unfocus = hud.subscribeFocus((f) => { if (widget && f !== widget) host.close(); });\n // The focus subscription above is this host's press-outside.\n const undismiss = attachMenuDismiss<MouseEvent>(window, {\n press: false,\n outside: (e) => {\n if (!widget) return false;\n const p = opts.toCanvas({ x: e.clientX, y: e.clientY });\n return !widget.hitTest(p.x, p.y);\n },\n close: () => { if (widget) host.close(); },\n });\n sync();\n return () => {\n unsubscribe();\n unfocus();\n undismiss();\n drop();\n };\n}\n","import type { View } from '@weasel-js/core';\n\n/** Says whether what a lens reads from changed between one landed frame and the next. */\nexport interface ContentWatch {\n /** The camera the lens was just drawn through. */\n drew(view: View): void;\n /** Whether the content version or the camera differs from the last time this was asked. The first ask only\n * takes its bearings, and answers `false`. */\n changed(): boolean;\n}\n\n/**\n * Watches the two things that change the pixels under an aim that holds still: the content, through `version`\n * when the lens is given one, and the camera it is drawn through. A lens redrawing itself moves neither, which is\n * what lets it read the framebuffer again on a change without that read's own redraw asking for another.\n */\nexport function createContentWatch(version: (() => number) | undefined): ContentWatch {\n let camera = '';\n let seen: { version: number | undefined; camera: string } | null = null;\n return {\n drew(view) {\n camera = `${view.x},${view.y},${view.scale.x},${view.scale.y}`;\n },\n changed() {\n const now = { version: version?.(), camera };\n const moved = seen !== null && (seen.version !== now.version || seen.camera !== now.camera);\n seen = now;\n return moved;\n },\n };\n}\n","interface Point { x: number; y: number }\n\nconst POINTER_ENDS = ['pointerup', 'pointercancel', 'lostpointercapture'] as const;\n\n/**\n * Aims a lens from the pointer moving over `input`, in CSS px relative to it. A gesture that begins where\n * `holds` answers true freezes the aim until it ends: the lens camera follows the aim, so re-aiming mid-drag\n * would move the world under the pointer. Returns a detach.\n */\nexport function followPointer(\n input: HTMLElement,\n lens: { aimAt(p: Point): void; holds(p: Point): boolean },\n): () => void {\n let holding = false;\n const local = (evt: PointerEvent): Point => {\n const r = input.getBoundingClientRect();\n return { x: evt.clientX - r.left, y: evt.clientY - r.top };\n };\n const onPointerMove = (evt: PointerEvent) => {\n if (!holding) lens.aimAt(local(evt));\n };\n const onPointerDown = (evt: PointerEvent) => {\n if (lens.holds(local(evt))) holding = true;\n };\n const onPointerEnd = () => { holding = false; };\n\n input.addEventListener('pointermove', onPointerMove);\n input.addEventListener('pointerdown', onPointerDown);\n for (const type of POINTER_ENDS) input.addEventListener(type, onPointerEnd);\n return () => {\n input.removeEventListener('pointermove', onPointerMove);\n input.removeEventListener('pointerdown', onPointerDown);\n for (const type of POINTER_ENDS) input.removeEventListener(type, onPointerEnd);\n };\n}\n","import { clamp } from '@weasel-js/geom';\n\n/**\n * Read a `rw × rh` device-pixel region of the drawing buffer centered on\n * `pointer`, returned top-down. `pointer` is in CSS px relative to `target`,\n * the rect of the buffer the canvas paints into (device px, top-left origin),\n * and the read is clamped to stay inside that rect.\n *\n * GL reports rows bottom-up; every consumer here wants top-down, so both the\n * read origin and the returned rows are flipped.\n */\nexport function readbackRegion(\n gl: WebGL2RenderingContext,\n bufferHeight: number,\n target: { x: number; y: number; width: number; height: number },\n pointer: { x: number; y: number },\n dpr: number,\n rw: number,\n rh: number,\n): ImageData {\n const cx = target.x + Math.round(pointer.x * dpr);\n const cy = target.y + Math.round(pointer.y * dpr);\n const gx = clamp(cx - Math.floor(rw / 2), target.x, target.x + Math.max(0, target.width - rw));\n const gyTop = clamp(cy - Math.floor(rh / 2), target.y, target.y + Math.max(0, target.height - rh));\n const gy = bufferHeight - gyTop - rh;\n\n const raw = new Uint8Array(rw * rh * 4);\n gl.readPixels(gx, gy, rw, rh, gl.RGBA, gl.UNSIGNED_BYTE, raw);\n\n const flipped = new Uint8ClampedArray(rw * rh * 4);\n const stride = rw * 4;\n for (let row = 0; row < rh; row++) {\n const src = (rh - 1 - row) * stride;\n flipped.set(raw.subarray(src, src + stride), row * stride);\n }\n return new ImageData(flipped, rw, rh);\n}\n","import {\n createViewportLayer, screenToWorld, viewToTransform,\n type CanvasViewHandle, type RenderLayer, type SceneCanvasApi, type View, type ViewAt,\n} from '@weasel-js/core';\nimport { releaseImageSource, type DrawCommand } from '@weasel-js/core/renderer';\nimport {\n createLoupeModel, loupeInnerView,\n type LoupeMode, type LoupeModel, type LoupeSurface,\n} from '@weasel-js/loupe';\nimport type { Hud } from '../hud';\nimport type { WindowWidget } from '../widgets/window/window';\nimport type { HudContentCtx, WidgetBounds } from '../widget';\nimport { createContentWatch } from './contentWatch';\nimport { followPointer } from './pointerAim';\nimport { readbackRegion } from './readback';\n\nexport type { LoupeMode };\n\n/** Options for `createLoupe` shared by a plain lens and an interactive one. */\nexport interface LoupeBaseOptions {\n hud: Hud;\n /** The canvas pixel mode reads back from. Supplies the GL context and the\n * drawing-buffer dimensions. */\n canvas: HTMLCanvasElement;\n /** Where the aim comes from: the element pointer events are taken from and\n * the rect client coords are measured against. Defaults to `canvas`, which\n * is right whenever the canvas is also the thing under the pointer. */\n input?: HTMLElement;\n /** The rect of `canvas` the magnified picture occupies, in its CSS px — the\n * one the aim is relative to. Pass `CanvasExtensionApi.getSurfaceRect` for\n * a pane painted into a shared canvas. Defaults to `views.getSurfaceRect`\n * when the lens is a view, and to the whole canvas otherwise. */\n region?: () => { x: number; y: number; width: number; height: number };\n requestRedraw: () => void;\n /**\n * The version of what the canvas paints, read on every landed frame: when it moves, a lens whose aim has not\n * reads the framebuffer and the color under it again. Pass `CanvasExtensionApi.getPaintedVersion`. Defaults to\n * `views.getPaintedVersion` when the lens is a view. Without one the lens follows an edit under a parked aim\n * only in vector mode, or when told through `refresh()`; a camera move it follows either way.\n */\n contentVersion?: () => number;\n mode?: LoupeMode;\n factor?: number;\n bounds?: WidgetBounds;\n title?: string;\n /** Draw the window's titlebar and close box. Default `true`. Pass `false`\n * for a bare lens; the interior then doubles as the move handle, or, for an\n * `interactive` lens, a grip strip across its top does. */\n titlebar?: boolean;\n /** Called with the hex color under the aim point whenever it changes.\n * Sampled from the framebuffer in both modes — vector content is a\n * re-render whose edge colors differ from the screen's, so reading the\n * color off it would report something the user cannot see. */\n onColorChange?: (hex: string) => void;\n /** Fired when a click inside the lens picks a color — an eyedropper on the\n * magnified surface. Where the color goes is the consumer's: the loupe\n * reports the pick and nothing else. An `interactive` lens gives its clicks\n * to the canvas, so only `pick()` reaches this. */\n onPick?: (hex: string) => void;\n /** Fired by the window's close box. The window does not hide itself —\n * whoever owns the loupe's visibility decides what closing means. */\n onClose?: () => void;\n /** Backdrop painted behind the magnified content in both modes, so the\n * outer canvas does not show through where the lens is empty. Defaults to\n * the theme's surface color. */\n background?: string;\n}\n\n/** Options for `createLoupe`. */\nexport type LoupeOptions = LoupeBaseOptions & (\n | {\n /** Layers re-rendered through the magnified inner view in vector mode. */\n source: RenderLayer<unknown>[];\n views?: undefined;\n interactive?: false;\n }\n | {\n /**\n * The canvas, as a host for views. The lens becomes a view on it: vector\n * mode paints the canvas's own stack — scene and selection chrome — and\n * the lens can take input. It magnifies the camera of whatever view is\n * under its aim: aimed over a `<CanvasView>` panel, it shows and edits\n * that panel's world at the panel's zoom times its own factor, painting\n * and picking only the layers the panel does, and acting on the panel's\n * selection where it owns one. A host without `viewAt`\n * gets the canvas's camera and stack wherever it aims.\n */\n views: Pick<SceneCanvasApi, 'addView' | 'getSurfaceRect'> & Partial<Pick<SceneCanvasApi, 'getPaintedVersion' | 'viewAt'>>;\n /** Narrows what vector mode paints. Defaults to the canvas's stack. */\n source?: RenderLayer<unknown>[];\n /**\n * Route input inside the lens to what it shows: a press selects the node\n * magnified under the pointer, and a drag moves it by the pointer travel\n * divided by the magnification. Default `false` — the window keeps its\n * interior, and a click there picks a color.\n */\n interactive?: boolean;\n }\n);\n\nconst backdropOf = (ctx: HudContentCtx, color: string): DrawCommand => ({\n kind: 'path',\n path: { kind: 'rect', x: ctx.rect.x, y: ctx.rect.y, width: ctx.rect.w, height: ctx.rect.h },\n fill: { paint: { kind: 'solid', color } },\n});\n\n/** The id the lens's view takes on its canvas. */\nconst LENS_VIEW = 'weasel-loupe:lens';\n\n/** Where an interactive lens routes while its window is hidden: nowhere. */\nconst NO_RECT = { x: 0, y: 0, w: 0, h: 0 };\n\n/** The lens camera aimed at `aim`: magnifying the view under it, or the\n * canvas's own camera `outer` where no view is. */\nfunction lensCamera(\n aim: { x: number; y: number }, under: ViewAt | null, outer: View, rect: WidgetBounds, factor: number,\n): View {\n if (under && under.id !== null) {\n const world = {\n x: (aim.x - under.rect.x) / under.view.scale.x + under.view.x,\n y: (aim.y - under.rect.y) / under.view.scale.y + under.view.y,\n };\n return loupeInnerView(world, under.view, rect, factor);\n }\n const world = screenToWorld(aim.x, aim.y, viewToTransform(outer));\n return loupeInnerView({ x: world[0], y: world[1] }, outer, rect, factor);\n}\n\n/** Control surface for a live loupe: where it is aimed, how it magnifies,\n * what color it is over, and the window it lives in. */\nexport interface LoupeHandle {\n readonly window: WindowWidget;\n readonly mode: LoupeMode;\n readonly factor: number;\n /** Last aimed point, in screen-space CSS px relative to the canvas. */\n readonly aim: { x: number; y: number };\n /** Hex color under the aim point, read off the framebuffer on the first\n * frame to land after the aim. `null` until then, or when the GL context\n * is unavailable. */\n readonly color: string | null;\n setMode(mode: LoupeMode): void;\n setFactor(factor: number): void;\n /** Aim at a screen point. Ignored while the point is over the window —\n * that is the freeze rule that makes the borders reachable. */\n aimAt(p: { x: number; y: number }): void;\n /** Sample the color the lens is showing at `p` — a screen point inside the\n * lens — and report it to `onPick`. Omit `p` to pick at the aim point.\n * Returns the hex, or `null` when the framebuffer cannot answer for that\n * point, including before any frame has landed. Leaves the aim, and\n * `color`, alone. */\n pick(p?: { x: number; y: number }): string | null;\n /** Ask for a paint, and on the frame that lands read the picture and the color under the aim again: what is\n * under the aim changed in a way no `contentVersion` reports. */\n refresh(): void;\n dispose(): void;\n}\n\n/**\n * Build a magnifier: a HUD window whose interior shows the canvas around an\n * aim point, enlarged. Adds the window to the HUD and starts following the\n * pointer; `dispose` removes it again.\n */\nexport function createLoupe(opts: LoupeOptions): LoupeHandle {\n const { hud, canvas: element, requestRedraw } = opts;\n const host = opts.views;\n const interactive = host !== undefined && opts.interactive === true;\n const input = opts.input ?? element;\n let lens: CanvasViewHandle | null = null;\n let pixels: ImageBitmap | null = null;\n const dropPixels = () => {\n if (!pixels) return;\n releaseImageSource(pixels);\n pixels.close();\n pixels = null;\n };\n let pixelsPending = false;\n let refreshWanted = false;\n let disposed = false;\n // Until a paint lands, the context on a shared canvas may not exist yet, and\n // opening it here would give every tenant one with no stencil buffer.\n let landed = false;\n\n const b = opts.bounds ?? { x: 24, y: 24, w: 220, h: 200 };\n\n const watch = createContentWatch(opts.contentVersion ?? host?.getPaintedVersion);\n let refreshAsked = false;\n\n const content = (ctx: HudContentCtx): DrawCommand[] => {\n watch.drew(ctx.view);\n return model.mode === 'vector' ? drawVector(ctx) : drawPixels(ctx);\n };\n\n const backdropColor = (ctx: HudContentCtx): string =>\n opts.background ?? ctx.tokens['--wzl-surface'];\n const backdrop = (ctx: HudContentCtx): DrawCommand => backdropOf(ctx, backdropColor(ctx));\n\n const aimedView = () => host?.viewAt?.(model.aim, { except: LENS_VIEW }) ?? null;\n const innerView = (outer: View, rect: WidgetBounds): View => lensCamera(model.aim, aimedView(), outer, rect, model.factor);\n\n const drawVector = (ctx: HudContentCtx): DrawCommand[] => {\n if (host) return lens ? [backdrop(ctx), ...lens.draw(ctx.data, ctx.view, ctx.dims)] : [backdrop(ctx)];\n // A fresh lens per frame: CreateViewportLayerOpts.view is static, and the\n // inner view moves with the pointer.\n const picture = createViewportLayer<unknown>({\n id: `${win.id}:lens`,\n label: 'Loupe content',\n source: opts.source ?? [],\n view: innerView(ctx.view, ctx.rect),\n bounds: () => ctx.rect,\n background: backdropColor(ctx),\n });\n return picture.draw(ctx.data, ctx.view, ctx.dims);\n };\n\n const drawPixels = (ctx: HudContentCtx): DrawCommand[] => {\n // The backdrop paints even with a bitmap in hand: a readback of a\n // transparent framebuffer is transparent, and before the first one\n // settles there is nothing at all, either of which leaves the lens a\n // hole onto the unmagnified canvas.\n const out: DrawCommand[] = [backdrop(ctx)];\n if (pixels) {\n out.push({\n kind: 'image',\n image: pixels,\n x: ctx.rect.x, y: ctx.rect.y, w: ctx.rect.w, h: ctx.rect.h,\n sampling: 'nearest',\n });\n }\n return out;\n };\n\n // `gl.readPixels` outside a landed paint returns the *previous* frame, so an\n // aim only marks the lens dirty; the read itself happens in the frame\n // subscriber below, on the frame that painted.\n const scheduleRefresh = () => {\n if (disposed || model.mode !== 'pixel') return;\n refreshWanted = true;\n };\n\n /** Read device px of the loupe's region around `at`, sized for the\n * canvas's pixel ratio, or `null` when the framebuffer cannot answer. */\n const read = (\n at: { x: number; y: number },\n rw: (dpr: number) => number,\n rh: (dpr: number) => number,\n ): ImageData | null => {\n if (!landed) return null;\n const gl = element.getContext('webgl2');\n if (!gl) return null;\n const cssRect = element.getBoundingClientRect();\n if (cssRect.width === 0) return null;\n const dpr = element.width / cssRect.width;\n // A view-backed lens knows its canvas, so over a detached pane it reads\n // that pane's pixels without being told where the pane is.\n const r = (opts.region ?? host?.getSurfaceRect)?.();\n const target = r\n ? {\n x: Math.round(r.x * dpr), y: Math.round(r.y * dpr),\n width: Math.round(r.width * dpr), height: Math.round(r.height * dpr),\n }\n : { x: 0, y: 0, width: element.width, height: element.height };\n return readbackRegion(gl, element.height, target, at, dpr, rw(dpr), rh(dpr));\n };\n\n const refreshPixels = () => {\n if (disposed || model.mode !== 'pixel') return;\n const rect = win.contentRect;\n const data = read(\n model.aim,\n (dpr) => Math.max(1, Math.round((rect.w * dpr) / model.factor)),\n (dpr) => Math.max(1, Math.round((rect.h * dpr) / model.factor)),\n );\n if (!data) return;\n pixelsPending = true;\n createImageBitmap(data)\n .then((bmp) => {\n if (disposed) { bmp.close(); return; }\n dropPixels();\n pixels = bmp;\n pixelsPending = false;\n requestRedraw();\n })\n .catch(() => {\n pixelsPending = false;\n requestRedraw();\n });\n };\n\n const readHex = (at: { x: number; y: number }): string | null => {\n const px = read(at, () => 1, () => 1);\n if (!px || px.data[3] === 0) return null;\n return '#' + [px.data[0], px.data[1], px.data[2]]\n .map((c) => c.toString(16).padStart(2, '0')).join('');\n };\n\n const win = hud.window({\n id: 'weasel-loupe',\n x: b.x, y: b.y, w: b.w, h: b.h,\n title: opts.title ?? 'Loupe',\n titlebar: opts.titlebar,\n content,\n interior: interactive ? 'pass' : 'claim',\n onResize: () => { scheduleRefresh(); },\n ...(interactive ? {} : { onContentClick: (p: { x: number; y: number }) => { model.pick(p); } }),\n ...(opts.onClose ? { onClose: opts.onClose } : {}),\n });\n\n const surface: LoupeSurface = {\n lens: () => win.contentRect,\n covers: (p) => win.hitTest(p.x, p.y) || (win.passes?.(p.x, p.y) ?? false),\n sample: readHex,\n hidden: () => win.hidden,\n gone: () => win.disposed === true,\n changed: () => { scheduleRefresh(); requestRedraw(); },\n subscribeFrame: hud.subscribeFrame,\n };\n\n // Subscribed ahead of the model, so the frame that lands first is already\n // readable by the time the model samples on it.\n const unsubscribeFrame = hud.subscribeFrame(() => {\n landed = true;\n if (watch.changed() || refreshAsked) {\n refreshAsked = false;\n scheduleRefresh();\n model.resample();\n }\n // A refresh wanted while a bitmap is in flight is remembered rather than\n // dropped: the flag survives until a frame finds it settled, so the aim\n // the user ends a fast drag on is the one that gets read.\n if (!refreshWanted || pixelsPending) return;\n refreshWanted = false;\n refreshPixels();\n });\n\n const model: LoupeModel = createLoupeModel({\n surface,\n ...(opts.mode ? { mode: opts.mode } : {}),\n ...(opts.factor !== undefined ? { factor: opts.factor } : {}),\n ...(opts.onColorChange ? { onColorChange: opts.onColorChange } : {}),\n ...(opts.onPick ? { onPick: opts.onPick } : {}),\n onDispose: () => teardown(),\n });\n\n if (host) {\n lens = host.addView({\n id: LENS_VIEW,\n label: 'Loupe',\n bounds: () => (win.hidden ? NO_RECT : win.contentRect),\n view: (outer) => innerView(outer, win.contentRect),\n paint: false,\n interactive,\n follows: () => aimedView()?.id ?? null,\n ...(opts.source ? { layers: () => opts.source! } : {}),\n });\n }\n\n const unfollow = followPointer(input, {\n aimAt: (p) => model.aimAt(p),\n holds: (p) => interactive && surface.covers(p),\n });\n\n const teardown = () => {\n disposed = true;\n unsubscribeFrame();\n unfollow();\n lens?.remove();\n lens = null;\n dropPixels();\n };\n\n return {\n window: win,\n get mode() { return model.mode; },\n get factor() { return model.factor; },\n get aim() { return model.aim; },\n get color() { return model.color; },\n setMode: model.setMode,\n setFactor: model.setFactor,\n aimAt: model.aimAt,\n pick: model.pick,\n refresh() {\n if (disposed) return;\n refreshAsked = true;\n requestRedraw();\n },\n dispose() {\n model.dispose();\n win.dispose();\n },\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { Hud } from './hud';
2
+ import type { HudDrawCtx } from './widget';
3
+ /**
4
+ * The HUD layer's `deps`: one array, held for as long as every widget would
5
+ * draw what it drew last frame, so a canvas reuses the layer's commands and,
6
+ * past its retain policy's size, keeps its pixels instead of walking them.
7
+ *
8
+ * Unchanged means the same widgets in the same order, each with the same
9
+ * `hidden`, bounds and `deps`, under the same focus and canvas size; the theme
10
+ * and font are fixed for an attachment. A showing widget that declares no
11
+ * `deps`, or paints `content` from the scene, changes every frame.
12
+ */
13
+ export declare function createLayerDeps(hud: Hud): (ctx: HudDrawCtx) => readonly unknown[];
14
+ //# sourceMappingURL=layerDeps.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layerDeps.d.ts","sourceRoot":"","sources":["../src/layerDeps.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,KAAK,EAAE,UAAU,EAAU,MAAM,UAAU,CAAC;AAEnD;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,GAAG,GAAG,CAAC,GAAG,EAAE,UAAU,KAAK,SAAS,OAAO,EAAE,CAoCjF"}
@@ -70,8 +70,10 @@ export type LoupeOptions = LoupeBaseOptions & ({
70
70
  * mode paints the canvas's own stack — scene and selection chrome — and
71
71
  * the lens can take input. It magnifies the camera of whatever view is
72
72
  * under its aim: aimed over a `<CanvasView>` panel, it shows and edits
73
- * that panel's world at the panel's zoom times its own factor. A host
74
- * without `viewAt` gets the canvas's camera wherever it aims.
73
+ * that panel's world at the panel's zoom times its own factor, painting
74
+ * and picking only the layers the panel does, and acting on the panel's
75
+ * selection where it owns one. A host without `viewAt`
76
+ * gets the canvas's camera and stack wherever it aims.
75
77
  */
76
78
  views: Pick<SceneCanvasApi, 'addView' | 'getSurfaceRect'> & Partial<Pick<SceneCanvasApi, 'getPaintedVersion' | 'viewAt'>>;
77
79
  /** Narrows what vector mode paints. Defaults to the canvas's stack. */