feat(collab): dev-time presence style tuner (VITE_PRESENCE_TUNER=1)

Parametrizes every visual knob of the presence overlay so we can pick the
shipped look live, then wire the winners into the defaults:
- collab_presence_style.h: shared STYLE struct + drawing (now used by BOTH
  editor TUs — no more duplicated overlay code): selection shape (rect /
  corner brackets / underline / rounded rect / filled-only), border width +
  alpha, infill alpha, padding, corner radius; name tag show/size/chip-
  background/inside-outside/top-bottom/start-end-center/offset; cursor shape
  (cross / pointer / circle+dot), size/width/alpha + label knobs; fixed-color
  and palette-by-name-hash overrides (try palettes without changing what
  senders publish); pin radius/ring/alphas. Defaults == shipped look.
- kicadCollabSetStyle(json) live-patch export + kicadCollabTestListItems(n)
  (real KIIDs for synthetic previews); merged dispatch; pins now carry the
  author name so palette overrides recolor them consistently.
- PresenceTuner.tsx: floating dev panel (env-gated, tree-shaken otherwise) —
  grouped sliders/selects, demo peers+pins injection for SOLO tuning,
  localStorage persistence across reloads, Copy JSON export, reset.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CvqUd4QsJSGHN28aunJRTq
This commit is contained in:
Gergő Törcsvári 2026-07-06 19:10:40 +02:00
commit ce99773af4
No known key found for this signature in database
GPG key ID: 8E75F2CDE64E5322
8 changed files with 907 additions and 77 deletions

View file

@ -181,6 +181,14 @@ export function presenceUser(): PresenceUser {
return { id: slug, name: slug, color: colorForUser(slug) };
}
/**
* DEV-TIME presence style tuner (collab-presence): VITE_PRESENCE_TUNER=1 mounts
* a floating panel that live-patches the wasm overlay style
* (kicadCollabSetStyle) — shapes, widths, alphas, label placement, palettes —
* so we can pick the shipped look. Off (and tree-shaken) in normal builds.
*/
export const PRESENCE_TUNER_ENABLED = import.meta.env.VITE_PRESENCE_TUNER === "1";
/**
* The active scope (first URL segment) for API calls. Mirrors how `userSlug()`
* reads the URL, so the source layer scopes requests without threading scope