carboncanvas 0.1.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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lib-CSrTsI4Y.js","sources":["../src/DesignCanvas/portalRoot.ts","../src/CommentLayer/hostScope.ts","../src/CommentLayer/ui.tsx","../src/entitlements/CommentsUpsell.tsx","../src/entitlements/useEntitlement.ts","../src/entitlements/lockState.ts","../src/CommentLayer/CommentLayer.tsx","../src/DesignCanvas/ModeBar.tsx","../src/DesignCanvas/fiberName.ts","../src/adapters/genericAdapter.ts","../src/adapters/index.ts","../src/DesignCanvas/DesignCanvas.tsx"],"sourcesContent":["// portalRoot — where DesignCanvas-family overlays (Inspector panel, comment\n// layer, focus overlay) portal to. Defaults to document.body, which is correct\n// when the canvas owns the page.\n//\n// A host that mounts the canvas inside its own max-z container (e.g. a modal /\n// fixed overlay ON TOP of the running app) can point the portal root at that\n// container via setPortalRoot(), so the chrome's z-indexes (100…2201) stay\n// inside the same stacking context instead of landing under the container.\n//\n// position:fixed children keep viewport-relative coordinates as long as the\n// container has no transform/filter — only z-order changes.\n\nlet portalRoot: HTMLElement | null = null;\n\n/** Point all DesignCanvas-family portals at `el` (null restores body). */\nexport function setPortalRoot(el: HTMLElement | null): void {\n portalRoot = el;\n}\n\nexport function getPortalRoot(): HTMLElement {\n return portalRoot && portalRoot.isConnected ? portalRoot : document.body;\n}\n","// hostScope — explicit canvas-id passthrough + dev-host classification.\n//\n// Extracted from networkClient.ts so the LIGHTWEIGHT comments shell (and the\n// entitlement check) can resolve the effective canvasId WITHOUT statically\n// importing networkClient — which would drag the whole socket.io/realtime runtime\n// into the free-install main bundle and defeat Workstream B's code-split. This\n// module depends on nothing but `window`, so it stays in the main chunk safely.\n//\n// networkClient re-exports `isLiveCommentsHost` from here for back-compat.\n\n/**\n * The explicit `canvasId` is ALWAYS authoritative — it's the permanent comment\n * partition the owner registered on the dashboard (an opaque `cnv_…` id) and\n * wired in via env. The library NEVER derives the id from the hostname.\n *\n * (Removed 2026-06-30: the embed-era auto-scoping that used the deployment\n * hostname AS the canvas id. With explicit registration it was actively wrong —\n * it silently repartitioned comments by deployment URL and overrode the id the\n * owner chose. Kept as a one-line chokepoint so the intent is obvious at the\n * call sites.)\n */\nexport function resolveCanvasId(explicitId: string): string {\n return explicitId;\n}\n\n/**\n * Is the app running on the developer's OWN COMPUTER (localhost / loopback)?\n * Used ONLY by the comment layer's WRITE gate: comments are automatically\n * read-only on localhost so building locally never pollutes the shared canvas\n * with throwaway / inaccurately-anchored comments. EVERY real URL — production\n * AND preview/staging links — allows comments, because those are the surfaces\n * you actually share for review.\n *\n * Deliberately localhost-ONLY (not LAN IPs): `localhost`/`127.0.0.1`/`::1` are\n * the one unambiguously-private case, whereas a network IP can be a real shared\n * internal tool. Fully decoupled from id resolution — the canvasId is honored\n * everywhere; only WRITES are gated, and only here. (Advanced escape: a\n * `?comments-write` URL flag re-enables writing on localhost when intentionally\n * testing; `unstableHostPatterns` can mark extra hosts read-only too.)\n */\nfunction isDevHost(host: string, unstableHostPatterns: RegExp[]): boolean {\n if (!host || host === 'localhost' || host === '127.0.0.1' || host === '::1') return true;\n if (unstableHostPatterns.some((re) => re.test(host))) return true; // opt-in extra read-only hosts\n return false;\n}\n\nexport function isLiveCommentsHost(unstableHostPatterns: RegExp[] = []): boolean {\n const host = typeof window !== 'undefined' ? window.location.hostname : '';\n return !isDevHost(host, unstableHostPatterns);\n}\n","import type { CSSProperties } from 'react';\nimport type { PublicUser } from './types';\n\nexport const FONT = 'system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif';\n\nexport const cardStyle: CSSProperties = {\n width: 300,\n background: '#fff',\n border: '1px solid #e4e4e7',\n borderRadius: 12,\n boxShadow: '0 8px 28px rgba(0,0,0,0.18)',\n fontFamily: FONT,\n fontSize: 13,\n color: '#1f1f23',\n overflow: 'hidden',\n};\n\nexport const textareaStyle: CSSProperties = {\n width: '100%',\n minHeight: 56,\n resize: 'vertical',\n border: '1px solid #e4e4e7',\n borderRadius: 8,\n padding: '8px 10px',\n font: 'inherit',\n outline: 'none',\n boxSizing: 'border-box',\n};\n\nexport const primaryBtn: CSSProperties = {\n font: 'inherit',\n fontWeight: 600,\n border: 'none',\n borderRadius: 8,\n padding: '7px 14px',\n background: 'linear-gradient(135deg,#cbd2de 0%,#868fa0 100%)',\n color: '#16181b',\n cursor: 'pointer',\n};\n\nexport const ghostBtn: CSSProperties = {\n font: 'inherit',\n fontWeight: 600,\n border: '1px solid #e4e4e7',\n borderRadius: 8,\n padding: '7px 12px',\n background: 'transparent',\n color: '#3c3c43',\n cursor: 'pointer',\n};\n\nexport const linkBtn: CSSProperties = {\n font: 'inherit',\n fontWeight: 600,\n border: 'none',\n background: 'transparent',\n color: '#9aa6bb',\n cursor: 'pointer',\n padding: 0,\n};\n\nfunction initials(name: string): string {\n const parts = name.trim().split(/\\s+/).filter(Boolean);\n if (parts.length === 0) return '?';\n if (parts.length === 1) return parts[0]!.slice(0, 2).toUpperCase();\n return (parts[0]![0]! + parts[parts.length - 1]![0]!).toUpperCase();\n}\n\nconst AVATAR_BG = ['#2D7FFF', '#7A3FF2', '#1C8B4B', '#C8841C', '#C8203A', '#0E8C8C'];\n\nexport function Avatar({ user, size = 24 }: { user: PublicUser | null; size?: number }) {\n const name = user?.displayName || user?.username || '?';\n const hash = [...name].reduce((a, c) => a + c.charCodeAt(0), 0);\n const bg = AVATAR_BG[hash % AVATAR_BG.length];\n if (user?.avatarUrl) {\n return (\n <img\n src={user.avatarUrl}\n alt={name}\n width={size}\n height={size}\n style={{ width: size, height: size, borderRadius: '50%', objectFit: 'cover', flex: '0 0 auto', alignSelf: 'flex-start' }}\n />\n );\n }\n return (\n <div\n style={{\n width: size,\n height: size,\n borderRadius: '50%',\n background: bg,\n color: '#fff',\n fontSize: size * 0.42,\n fontWeight: 700,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n flex: '0 0 auto',\n fontFamily: FONT,\n }}\n >\n {initials(name)}\n </div>\n );\n}\n\n/** Compact relative time: \"now\", \"5m\", \"3h\", \"2d\", else a short date. */\nexport function relativeTime(iso: string): string {\n const then = new Date(iso).getTime();\n if (Number.isNaN(then)) return '';\n const s = Math.max(0, Math.round((Date.now() - then) / 1000));\n if (s < 45) return 'now';\n const m = Math.round(s / 60);\n if (m < 60) return `${m}m`;\n const h = Math.round(m / 60);\n if (h < 24) return `${h}h`;\n const d = Math.round(h / 24);\n if (d < 7) return `${d}d`;\n return new Date(iso).toLocaleDateString(undefined, { month: 'short', day: 'numeric' });\n}\n","// CommentsUpsell — the ONE upsell surface every non-active lock state routes to\n// (Workstream B, plan §0.2/§4). The comments tab is ALWAYS present; when the\n// canvas owner isn't entitled this panel takes the place of the live runtime in\n// the same right-hand rail, so the affordance is identical whether you've paid\n// or not. Pay → key → the same tab lights up the real comments (no second\n// package, no different chrome).\n//\n// Presentation only — it renders nothing functional. The backend 402 is the real\n// lock (this panel is what the user sees while that lock is in force). Lightweight\n// by design: it pulls in NONE of the comments/realtime/socket.io runtime, so it\n// stays in the free-install main bundle while the heavy path is code-split away.\n//\n// The `locked` state (the common one — no canvas registered yet) is a two-step\n// GUIDE, not a one-click promise: comments live in the DEPLOYED bundle so the\n// whole team sees them, which means the durable switch is a code change the\n// user's coding agent makes. Step 1 gets them a canvasId from the dashboard;\n// step 2 hands that id to their agent with a copyable prompt. The Carbon Canvas\n// skill leads the agent through the actual wiring from there.\n\nimport { useState, type CSSProperties } from 'react';\nimport type { LockState } from './lockState';\nimport { FONT } from '../CommentLayer/ui';\n\nconst DARK = '#18191b'; // carbon panel bg (matches the canvas + all panels)\nconst PANEL_W = 340;\nconst PANEL_GAP = 16;\n\n/** Copy for the simple (non-locked) states: a title, body, and single CTA. */\nfunction simpleCopy(state: LockState): { title: string; body: string; cta: string } {\n switch (state) {\n case 'inactive':\n return {\n title: 'Comments are paused',\n body:\n 'This canvas’s plan no longer includes comments — they’re read-only until the subscription is renewed. Reviewers’ existing threads are safe.',\n cta: 'Renew to re-enable',\n };\n case 'unauthorized':\n default:\n // Reached only if a host opts to show the upsell on 401 instead of the\n // sign-in flow; the default routing mounts the runtime so reviewers sign in.\n return {\n title: 'Sign in to comment',\n body: 'Your session has expired or the access key is invalid. Sign in again to comment on this canvas.',\n cta: 'Manage access',\n };\n }\n}\n\n/**\n * The prompt we tell the user to hand their coding agent once they have an id.\n * It must be SELF-SUFFICIENT: an agent that receives only this paste needs the\n * backend URL and the skill URL to execute (P1.7). We bake both in from the\n * canvas's own `serviceUrl` so the agent can fetch `${serviceUrl}/skill.md` and\n * wire against the right backend with no further context.\n */\nfunction agentPrompt(serviceUrl?: string): string {\n const base =\n 'Enable Carbon Canvas comments on this project. My canvas ID is <paste-your-canvas-ID-here>.';\n if (serviceUrl) {\n return `${base} Backend: ${serviceUrl}. Follow the instructions at ${serviceUrl}/skill.md to wire it up.`;\n }\n return `${base} Follow the Carbon Canvas skill (served at <your-backend>/skill.md) to wire it up.`;\n}\n\nexport function CommentsUpsell({\n state,\n enableUrl,\n serviceUrl,\n onClose,\n}: {\n /** Which lock state we're presenting (drives copy). */\n state: LockState;\n /** Where the \"Create a canvas / Renew / Manage\" CTA points (dashboard/checkout). */\n enableUrl?: string;\n /** The canvas's comments backend origin — baked into the agent handoff prompt. */\n serviceUrl?: string;\n /** Close the panel (returns to cursor mode). */\n onClose?: () => void;\n}) {\n const href = enableUrl || '#';\n\n return (\n <div\n data-cl-ui\n data-cl-upsell\n style={{\n position: 'fixed',\n top: 16,\n right: PANEL_GAP,\n width: PANEL_W,\n zIndex: 2000,\n background: DARK,\n borderRadius: 10,\n boxShadow: '0 16px 48px rgba(0,0,0,0.4)',\n display: 'flex',\n flexDirection: 'column',\n fontFamily: FONT,\n color: '#f5f1e8',\n overflow: 'hidden',\n }}\n onPointerDown={(e) => e.stopPropagation()}\n >\n {/* Header — mirrors the live sidebar so the tab feels identical when locked. */}\n <div\n style={{\n padding: '12px 14px',\n borderBottom: '1px solid rgba(255,255,255,0.08)',\n display: 'flex',\n alignItems: 'center',\n gap: 8,\n }}\n >\n <span style={{ fontSize: 16, fontWeight: 600, color: '#fff', letterSpacing: -0.2 }}>\n Comments\n </span>\n <button\n type=\"button\"\n aria-label=\"Close comments\"\n onClick={onClose}\n style={{\n marginLeft: 'auto',\n border: 'none',\n background: 'transparent',\n color: 'rgba(245,241,232,0.7)',\n cursor: 'pointer',\n fontSize: 18,\n lineHeight: 1,\n padding: 0,\n }}\n >\n ×\n </button>\n </div>\n\n {state === 'locked' ? (\n <LockedSteps href={href} serviceUrl={serviceUrl} />\n ) : (\n <SimpleUpsell state={state} href={href} />\n )}\n </div>\n );\n}\n\n/** The two-step \"get a canvas → hand it to your agent\" guide (the `locked` state). */\nfunction LockedSteps({ href, serviceUrl }: { href: string; serviceUrl?: string }) {\n return (\n <div style={{ padding: '16px 16px 18px', display: 'flex', flexDirection: 'column', gap: 14 }}>\n <div>\n <div style={{ fontSize: 15, fontWeight: 600, color: '#fff' }}>Enable comments for your team</div>\n <div style={{ fontSize: 12.5, lineHeight: 1.5, color: 'rgba(245,241,232,0.6)', marginTop: 6 }}>\n Comments live on your deployed prototype so your whole team can review in place. Two quick steps:\n </div>\n </div>\n\n <Step n={1} title=\"Create a canvas\">\n <div style={{ fontSize: 12.5, lineHeight: 1.5, color: 'rgba(245,241,232,0.6)' }}>\n Sign in and create a canvas — you’ll get a canvas ID like <code style={codeInline}>cnv_…</code>.\n </div>\n <a\n href={href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{ ...ctaStyle, alignSelf: 'flex-start', marginTop: 8 }}\n onClick={(e) => {\n if (href === '#') e.preventDefault();\n }}\n >\n Sign in &amp; create a canvas →\n </a>\n </Step>\n\n <Step n={2} title=\"Give the ID to your coding agent\">\n <div style={{ fontSize: 12.5, lineHeight: 1.5, color: 'rgba(245,241,232,0.6)' }}>\n Paste this into Cursor, Claude Code, or whatever agent built this — with your ID dropped in:\n </div>\n <CopyPrompt text={agentPrompt(serviceUrl)} />\n </Step>\n\n <div style={{ fontSize: 11, lineHeight: 1.5, color: 'rgba(245,241,232,0.4)', borderTop: '1px solid rgba(255,255,255,0.06)', paddingTop: 12 }}>\n Your agent follows the Carbon Canvas skill to wire it in and redeploy — then the Comments tab turns on for\n everyone who opens the prototype. The canvas and inspector stay free either way.\n </div>\n </div>\n );\n}\n\n/** A numbered step row: a badge + a titled block of content. */\nfunction Step({ n, title, children }: { n: number; title: string; children: React.ReactNode }) {\n return (\n <div style={{ display: 'flex', gap: 12 }}>\n <div\n style={{\n flex: '0 0 auto',\n width: 22,\n height: 22,\n borderRadius: 11,\n background: 'rgba(154,166,187,0.15)',\n color: '#7aa8ff',\n fontSize: 12,\n fontWeight: 700,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n marginTop: 1,\n }}\n >\n {n}\n </div>\n <div style={{ display: 'flex', flexDirection: 'column', gap: 6, minWidth: 0, flex: 1 }}>\n <div style={{ fontSize: 13.5, fontWeight: 600, color: '#fff' }}>{title}</div>\n {children}\n </div>\n </div>\n );\n}\n\n/** A read-only prompt in a monospace box with a copy button + copied feedback. */\nfunction CopyPrompt({ text }: { text: string }) {\n const [copied, setCopied] = useState(false);\n return (\n <div style={{ marginTop: 8, position: 'relative' }}>\n <div\n style={{\n fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',\n fontSize: 11.5,\n lineHeight: 1.5,\n color: 'rgba(245,241,232,0.85)',\n background: 'rgba(0,0,0,0.35)',\n border: '1px solid rgba(255,255,255,0.08)',\n borderRadius: 8,\n padding: '10px 12px 34px',\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-word',\n }}\n >\n {text}\n </div>\n <button\n type=\"button\"\n onClick={() => {\n void navigator.clipboard?.writeText(text).then(\n () => {\n setCopied(true);\n window.setTimeout(() => setCopied(false), 1600);\n },\n () => {},\n );\n }}\n style={{\n position: 'absolute',\n right: 8,\n bottom: 8,\n border: '1px solid rgba(255,255,255,0.14)',\n background: copied ? 'rgba(154,166,187,0.25)' : 'rgba(255,255,255,0.06)',\n color: copied ? '#7aa8ff' : 'rgba(245,241,232,0.8)',\n borderRadius: 6,\n padding: '3px 9px',\n fontSize: 11,\n fontWeight: 600,\n fontFamily: FONT,\n cursor: 'pointer',\n }}\n >\n {copied ? 'Copied ✓' : 'Copy'}\n </button>\n </div>\n );\n}\n\n/** The simple single-CTA layout for the `inactive` / `unauthorized` states. */\nfunction SimpleUpsell({ state, href }: { state: LockState; href: string }) {\n const { title, body, cta } = simpleCopy(state);\n return (\n <div style={{ padding: '18px 16px', display: 'flex', flexDirection: 'column', gap: 12 }}>\n <div style={{ fontSize: 15, fontWeight: 600, color: '#fff' }}>{title}</div>\n <div style={{ fontSize: 13, lineHeight: 1.5, color: 'rgba(245,241,232,0.72)' }}>{body}</div>\n <a\n href={href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{ ...ctaStyle, alignSelf: 'flex-start' }}\n onClick={(e) => {\n if (href === '#') e.preventDefault();\n }}\n >\n {cta}\n </a>\n <div style={{ fontSize: 11, color: 'rgba(245,241,232,0.4)' }}>\n The canvas and inspector stay free — this only turns on team comments.\n </div>\n </div>\n );\n}\n\nconst ctaStyle: CSSProperties = {\n display: 'inline-block',\n padding: '9px 14px',\n borderRadius: 8,\n background: 'linear-gradient(135deg,#cbd2de 0%,#868fa0 100%)',\n color: '#16181b',\n fontSize: 13,\n fontWeight: 600,\n textDecoration: 'none',\n textAlign: 'center',\n};\n\nconst codeInline: CSSProperties = {\n fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',\n fontSize: 11.5,\n background: 'rgba(255,255,255,0.08)',\n borderRadius: 4,\n padding: '1px 5px',\n};\n","// useEntitlement — the thin client hook for the capability-flag gate\n// (Workstream C, DATA ONLY — no upsell / lock UI here; that's Workstream B).\n//\n// It fetches the backend's resolved entitlement for a canvas and exposes the\n// capability `features` blob the comments tab's lock-state machine will read.\n//\n// SOURCE OF TRUTH IS THE BACKEND. This hook NEVER decides entitlement itself —\n// it only mirrors what `GET /api/entitlements` returns. The real lock is the\n// server-side 402 from `requireCapability` (server/src/auth/entitlements.ts); a\n// client could lie about `features` and still get a 402 on the gated write. So\n// `features` here drives PRESENTATION (show the upsell vs the live tab), not\n// authorization. On any error (network / 401 / 5xx) the hook reports a LOCKED\n// (all-false) feature set — fail safe toward the upsell, never silently \"unlock\".\n//\n// Standalone by design (no imports from CommentLayer/*): it only needs the\n// backend base URL, the canvasId, and the reviewer/creator bearer token.\n\nimport { useCallback, useEffect, useState } from 'react';\n\n/** Capability names — mirror server/src/auth/entitlements.ts Capability. */\nexport type Capability = 'comments' | 'realtime' | 'createCanvas' | 'scans' | 'team';\n\nexport type EntitlementTier = 'free' | 'pro' | 'team' | 'enterprise';\nexport type EntitlementStatus = 'active' | 'past_due' | 'canceled' | 'trialing';\n\n/** Resolved capability flags. Partial<> because the server may add capabilities. */\nexport type EntitlementFeatures = Partial<Record<Capability, boolean>>;\n\n/** The wire shape of `GET /api/entitlements` (server EntitlementView). */\nexport interface EntitlementView {\n tier: EntitlementTier;\n status: EntitlementStatus;\n features: EntitlementFeatures;\n canvasLimit: number;\n currentPeriodEnd: string | null;\n}\n\nexport interface UseEntitlementOptions {\n /** Backend base URL (the comments service). '' = same-origin. */\n backend?: string;\n /**\n * Canvas to scope the entitlement to. With it, the server resolves the canvas\n * OWNER's entitlement (what actually gates comment write / realtime there) —\n * the right thing for a reviewer's comments tab. Without it, the server\n * resolves the requester's OWN account (dashboard use).\n */\n canvasId?: string;\n /**\n * Bearer token. If omitted, the hook best-effort reads the same per-origin\n * localStorage key the comments network client writes\n * (`quilt-comments-token:<serviceOrigin>`), so it works out of the box once\n * the reviewer/creator has signed in.\n */\n token?: string | null;\n /** Set false to skip fetching (e.g. comments disabled). Default true. */\n enabled?: boolean;\n}\n\nexport interface UseEntitlementResult {\n features: EntitlementFeatures;\n tier: EntitlementTier | null;\n status: EntitlementStatus | null;\n canvasLimit: number | null;\n loading: boolean;\n /** Machine-readable error code when the fetch failed, else null. */\n error: string | null;\n /** Convenience predicate over `features` (presentation only — see file header). */\n can: (capability: Capability) => boolean;\n /** Force a re-fetch (e.g. after sign-in or an unlock round-trip). */\n refresh: () => void;\n}\n\n/** The fail-safe LOCKED result — every capability off (drives the upsell). */\nconst LOCKED_FEATURES: EntitlementFeatures = {};\n\nfunction trimTrailingSlashes(s: string): string {\n return s.replace(/\\/+$/, '');\n}\n\n/** Read the comments network client's per-origin token from localStorage. */\nfunction readStoredToken(backend: string): string | null {\n try {\n const origin = backend ? new URL(backend).origin : window.location.origin;\n return window.localStorage.getItem(`quilt-comments-token:${origin}`);\n } catch {\n return null;\n }\n}\n\n/**\n * Fetch + expose the resolved entitlement for a canvas. Re-fetches when the\n * backend / canvasId / token / enabled inputs change, and on `refresh()`.\n */\nexport function useEntitlement(opts: UseEntitlementOptions = {}): UseEntitlementResult {\n const { backend = '', canvasId, enabled = true } = opts;\n const explicitToken = opts.token;\n\n const [view, setView] = useState<EntitlementView | null>(null);\n const [loading, setLoading] = useState<boolean>(enabled);\n const [error, setError] = useState<string | null>(null);\n // Bump to force a re-fetch without changing the real inputs.\n const [nonce, setNonce] = useState(0);\n\n const refresh = useCallback(() => setNonce((n) => n + 1), []);\n\n useEffect(() => {\n if (!enabled) {\n setLoading(false);\n setView(null);\n setError(null);\n return;\n }\n\n let cancelled = false;\n const controller = new AbortController();\n setLoading(true);\n setError(null);\n\n const base = trimTrailingSlashes(backend);\n const token = explicitToken ?? readStoredToken(base);\n const qs = canvasId ? `?canvasId=${encodeURIComponent(canvasId)}` : '';\n const headers: Record<string, string> = {};\n if (token) headers.Authorization = `Bearer ${token}`;\n\n fetch(`${base}/api/entitlements${qs}`, {\n headers,\n signal: controller.signal,\n // No credentials — bearer token only (matches networkClient.ts + open CORS).\n })\n .then(async (res) => {\n if (cancelled) return;\n if (!res.ok) {\n const data = (await res.json().catch(() => ({}))) as Record<string, unknown>;\n // Fail safe: locked feature set so the UI shows the upsell, not a crash.\n setView(null);\n setError((data.error as string) ?? `http_${res.status}`);\n return;\n }\n const data = (await res.json()) as EntitlementView;\n setView(data);\n })\n .catch((err: unknown) => {\n if (cancelled || (err as { name?: string })?.name === 'AbortError') return;\n setView(null);\n setError('network_error');\n })\n .finally(() => {\n if (!cancelled) setLoading(false);\n });\n\n return () => {\n cancelled = true;\n controller.abort();\n };\n }, [backend, canvasId, explicitToken, enabled, nonce]);\n\n const features = view?.features ?? LOCKED_FEATURES;\n\n const can = useCallback(\n (capability: Capability): boolean => features[capability] === true,\n [features],\n );\n\n return {\n features,\n tier: view?.tier ?? null,\n status: view?.status ?? null,\n canvasLimit: view?.canvasLimit ?? null,\n loading,\n error,\n can,\n refresh,\n };\n}\n","// lockState — the ONE comments lock-state machine (Workstream B).\n//\n// Pure, dependency-free derivation of the comments tab's gate state from the\n// `useEntitlement()` data hook (Workstream C) plus two local facts the hook\n// can't know: whether comments are even CONFIGURED to reach a backend, and\n// whether a write was just rejected with a 402 at the live gate.\n//\n// THE BACKEND IS THE SOURCE OF TRUTH. These states drive PRESENTATION only —\n// which surface the comments tab shows (the live runtime vs the upsell). A\n// client that lies its way to `active` still gets a 402 on the gated write,\n// which flips it straight to `inactive` (see `writeBlocked`). So this machine is\n// allowed to be optimistic where it can't know (`unauthorized`): it mounts the\n// real runtime and lets the server's 402 be the real lock.\n//\n// States (plan §4):\n// loading — entitlement fetch in flight; render nothing yet (don't flash\n// the upsell, and crucially don't load the heavy chunk).\n// locked — comments not configured to reach a backend (no serviceUrl /\n// no key). The generic \"Enable comments\" upsell.\n// unauthorized — the entitlement read 401'd (no/expired session). For the\n// accountless reviewer this just means \"not signed in yet\", so\n// we still mount the runtime (its sign-in prompt) and let the\n// write-time 402 be the real gate. Never a hard paywall.\n// inactive — a DEFINITIVE not-entitled signal: a 402 from the backend\n// (read or write), or a past_due / canceled subscription. The\n// renew/upgrade upsell.\n// active — the owner's tier grants comments → the real comments runtime.\n\nimport type { EntitlementStatus } from './useEntitlement';\n\nexport type LockState = 'loading' | 'locked' | 'unauthorized' | 'inactive' | 'active';\n\nexport interface LockStateInputs {\n /** True until the entitlement fetch resolves (skip while devMode/unconfigured). */\n loading: boolean;\n /** Machine-readable error from the entitlement read, or null. */\n error: string | null;\n /** features.comments === true (presentation hint, not authorization). */\n comments: boolean;\n /** Resolved subscription status, or null when unknown. */\n status: EntitlementStatus | null;\n /** Comments wired to a backend (serviceUrl present) OR the devMode mock. */\n configured: boolean;\n /** A write hit the live 402 gate — sticky until a refresh re-resolves. */\n writeBlocked: boolean;\n}\n\nexport function deriveLockState(i: LockStateInputs): LockState {\n // A live 402 outranks everything — the server has spoken (the real lock).\n if (i.writeBlocked) return 'inactive';\n // Nothing to talk to → the generic enable upsell, no fetch, no chunk.\n if (!i.configured) return 'locked';\n // Don't decide (or load the runtime) until the read resolves.\n if (i.loading) return 'loading';\n // The owner's tier grants comments → light up the real runtime.\n if (i.comments) return 'active';\n // Definitive paywall signals.\n if (i.error === 'payment_required' || i.status === 'past_due' || i.status === 'canceled') {\n return 'inactive';\n }\n // No session / expired token: not a paywall — let them sign in, gate on 402.\n if (i.error === 'unauthorized' || i.error === 'http_401') return 'unauthorized';\n // Fail safe toward the upsell for anything unexpected.\n return 'locked';\n}\n\n/**\n * Should the heavy comments runtime (networkClient + realtime + socket.io) be\n * mounted (and therefore its lazy chunk fetched)?\n *\n * `active` — entitled. `unauthorized` — optimistic: mount so the accountless\n * reviewer can sign in; the write-time 402 remains the real gate and flips us to\n * `inactive` if the owner truly isn't entitled. NEVER mount for `loading`\n * (would defeat zero-byte free installs), `locked`, or `inactive`.\n */\nexport function shouldMountRuntime(state: LockState): boolean {\n return state === 'active' || state === 'unauthorized';\n}\n\n/** Should the upsell panel be shown instead of the runtime? */\nexport function shouldShowUpsell(state: LockState): boolean {\n return state === 'locked' || state === 'inactive';\n}\n","import { Suspense, lazy, useEffect, useMemo, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { getPortalRoot } from '../DesignCanvas/portalRoot';\nimport { resolveCanvasId } from './hostScope';\nimport { CommentsUpsell } from '../entitlements/CommentsUpsell';\nimport { useEntitlement } from '../entitlements/useEntitlement';\nimport { deriveLockState, shouldMountRuntime, shouldShowUpsell } from '../entitlements/lockState';\nimport type { CommentsConfig } from './types';\nimport type { CanvasMode } from '../DesignCanvas/ModeBar';\n\n// CommentLayer — the LIGHTWEIGHT shell + gate (Workstream B).\n//\n// Mounted by DesignCanvas whenever the `comments` prop carries a canvasId, so\n// the comments TAB is ALWAYS present regardless of entitlement (the always-on\n// affordance from plan §0.2/§4 — the tab itself lives in the ModeBar, which\n// DesignCanvas renders off the same `hasComments`). This shell decides, per the\n// lock-state machine, whether that tab shows the real comments runtime or the\n// upsell:\n//\n// • active / unauthorized → lazy-load + mount CommentsRuntime (the heavy\n// networkClient + realtime + socket.io engine). It's behind a dynamic\n// import() so a free install that never unlocks ships ZERO of those bytes in\n// its main entry — they land in a separate chunk (vite.lib / dist-lib).\n// • locked / inactive → the single CommentsUpsell surface (no heavy chunk).\n// • loading → nothing yet (don't flash the upsell or eager-load).\n//\n// The BACKEND is the source of truth: `useEntitlement().features` drives only\n// which surface shows; a write that the server rejects with 402 flips us to the\n// inactive upsell via `onPaymentRequired` (the real, server-side lock).\n\n// Heavy comments/realtime engine — split into its own chunk, fetched on unlock.\nconst CommentsRuntime = lazy(() => import('./CommentsRuntime'));\n\nexport function CommentLayer({\n config,\n mode,\n setMode,\n activePageId = null,\n pages,\n onSwitchPage,\n onUnreadChange,\n}: {\n config: CommentsConfig;\n mode: CanvasMode;\n setMode: (m: CanvasMode) => void;\n /** Active DCPage id (null = unpaged canvas). Pins render only for this page. */\n activePageId?: string | null;\n /** All pages, for the sidebar's cross-page location labels + jumps. */\n pages?: { id: string; title: string }[];\n /** Switch the canvas to another page (used when a sidebar row is off-page). */\n onSwitchPage?: (id: string) => void;\n /** Reports the count of unread (unresolved) threads up to the ModeBar so the\n * Comment tab can show an unread dot when you're in another mode. */\n onUnreadChange?: (count: number) => void;\n}) {\n // devMode is the in-memory mock sandbox — always functional, no backend, no\n // entitlement (you can't pay your way into a mock). Otherwise comments must be\n // wired to a service to do anything; without one we're definitively \"locked\".\n const configured = !!config.devMode || !!config.serviceUrl;\n\n // Scope the entitlement read to the SAME canvas the server gates writes on —\n // the explicit canvasId, which is now authoritative everywhere. Presentation-only\n // (the write-time 402 is the real lock), but matching it keeps the upsell from\n // showing on the wrong canvas.\n const effectiveCanvasId = useMemo(() => resolveCanvasId(config.canvasId), [config.canvasId]);\n\n const ent = useEntitlement({\n backend: config.serviceUrl,\n canvasId: effectiveCanvasId,\n enabled: !config.devMode && configured,\n });\n\n // A write rejected with 402 (the live gate) — sticky until the entitlement\n // re-resolves as granting comments (e.g. after a renewal + refresh).\n const [writeBlocked, setWriteBlocked] = useState(false);\n useEffect(() => {\n if (ent.can('comments')) setWriteBlocked(false);\n }, [ent]);\n\n const lockState = config.devMode\n ? 'active'\n : deriveLockState({\n loading: ent.loading,\n error: ent.error,\n comments: ent.can('comments'),\n status: ent.status,\n configured,\n writeBlocked,\n });\n\n const mountRuntime = config.devMode || shouldMountRuntime(lockState);\n const showUpsell = !config.devMode && shouldShowUpsell(lockState);\n\n // When the runtime isn't mounted it can't report unread threads — make sure\n // the ModeBar's unread dot clears (don't leave a stale count from a prior\n // entitled state).\n useEffect(() => {\n if (!mountRuntime) onUnreadChange?.(0);\n }, [mountRuntime, onUnreadChange]);\n\n if (mountRuntime) {\n return (\n <Suspense fallback={null}>\n <CommentsRuntime\n config={config}\n mode={mode}\n setMode={setMode}\n activePageId={activePageId}\n pages={pages}\n onSwitchPage={onSwitchPage}\n onUnreadChange={onUnreadChange}\n onPaymentRequired={() => setWriteBlocked(true)}\n onAuthChanged={ent.refresh}\n />\n </Suspense>\n );\n }\n\n // Not entitled — the upsell takes the runtime's place in the right rail, but\n // only while the user is actually on the comments tab (comment mode). The tab\n // itself stays in the ModeBar regardless.\n if (showUpsell && mode === 'comment') {\n return createPortal(\n <CommentsUpsell\n state={lockState}\n enableUrl={config.enableUrl}\n serviceUrl={config.serviceUrl}\n onClose={() => setMode('cursor')}\n />,\n getPortalRoot(),\n );\n }\n\n return null;\n}\n","import { useEffect, useRef, useState } from 'react';\nimport type { CSSProperties, ReactNode } from 'react';\n\n/**\n * The canvas interaction mode. One bar, mutually-exclusive modes:\n * • cursor — normal pointer; play with the live prototypes, pan/zoom freely\n * • comment — drop pins + open the comments sidebar\n * • dev — click-to-inspect + the inspector panel\n *\n * Owned by DesignCanvas and threaded into the Inspector / CommentLayer so each\n * derives its `enabled` state from the shared mode rather than its own toggle.\n */\nexport type CanvasMode = 'cursor' | 'comment' | 'dev';\n\nconst FONT =\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", system-ui, sans-serif';\n\n// Cool-grey metallic gradient for filled highlights; solid #9aa6bb for strokes.\nconst ACCENT = 'linear-gradient(135deg,#cbd2de 0%,#868fa0 100%)';\n\nfunction Seg({\n active,\n disabled,\n title,\n onClick,\n icon,\n label,\n badge,\n}: {\n active?: boolean;\n disabled?: boolean;\n title: string;\n onClick?: () => void;\n icon: ReactNode;\n label: string;\n /** Show a blue unread dot on the icon. */\n badge?: boolean;\n}) {\n return (\n <button\n type=\"button\"\n disabled={disabled}\n onClick={onClick}\n title={title}\n // Toggle-button pattern: the visible label names it; aria-pressed carries\n // the active/inactive state to assistive tech.\n aria-pressed={active}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 7,\n border: 'none',\n borderRadius: 8,\n padding: '7px 11px',\n font: `600 12.5px ${FONT}`,\n cursor: disabled ? 'default' : 'pointer',\n color: active ? '#16181b' : disabled ? 'rgba(245,241,232,0.4)' : 'rgba(245,241,232,0.82)',\n background: active ? ACCENT : 'transparent',\n opacity: disabled ? 0.7 : 1,\n transition: 'background 120ms ease, color 120ms ease',\n whiteSpace: 'nowrap',\n }}\n >\n <span style={{ display: 'flex', flexShrink: 0, position: 'relative' }}>\n {icon}\n {badge && (\n <span\n style={{\n position: 'absolute',\n top: -3,\n right: -4,\n width: 7,\n height: 7,\n borderRadius: '50%',\n background: '#9aa6bb',\n boxShadow: '0 0 0 1.5px #18191b',\n }}\n />\n )}\n </span>\n {label}\n </button>\n );\n}\n\nconst Divider = () => (\n <span\n style={{\n width: 1,\n alignSelf: 'stretch',\n margin: '5px 3px',\n background: 'rgba(255,255,255,0.1)',\n flexShrink: 0,\n }}\n />\n);\n\nconst ICON = {\n page: (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\">\n <rect x=\"2\" y=\"1.5\" width=\"10\" height=\"11\" rx=\"1.6\" stroke=\"currentColor\" strokeWidth=\"1.3\" />\n <path d=\"M4.5 4.5h5M4.5 7h5M4.5 9.5h3\" stroke=\"currentColor\" strokeWidth=\"1.3\" strokeLinecap=\"round\" />\n </svg>\n ),\n cursor: (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\">\n <path\n d=\"M2.5 1.8l8.3 4-3.4 1.1-1.1 3.4-3.8-8.5z\"\n fill=\"currentColor\"\n stroke=\"currentColor\"\n strokeWidth=\"0.6\"\n strokeLinejoin=\"round\"\n />\n </svg>\n ),\n comment: (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\">\n <path\n d=\"M2 3.2A1.2 1.2 0 0 1 3.2 2h7.6A1.2 1.2 0 0 1 12 3.2v5A1.2 1.2 0 0 1 10.8 9.4H6l-2.8 2.3V9.4H3.2A1.2 1.2 0 0 1 2 8.2v-5z\"\n stroke=\"currentColor\"\n strokeWidth=\"1.3\"\n strokeLinejoin=\"round\"\n />\n </svg>\n ),\n dev: (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\">\n <path\n d=\"M6 1v3M6 8v3M1 6h3M8 6h3M6 6l5 5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.6\"\n strokeLinecap=\"round\"\n />\n </svg>\n ),\n};\n\nexport interface CanvasPage {\n id: string;\n title: string;\n}\n\n// Minimal shape of the imperative API DCViewport stashes on its DOM node.\ntype ViewportApi = {\n subscribe: (fn: (t: { x: number; y: number; scale: number }) => void) => () => void;\n getTransform: () => { x: number; y: number; scale: number };\n animateTransform: (next: { x: number; y: number; scale: number }, ms?: number) => void;\n};\n\n// Preset zoom levels (descending — the menu opens upward, so 100% sits on top).\nconst ZOOM_PRESETS = [1, 0.5, 0.25];\n\n/**\n * Live zoom readout + preset jump menu. Subscribes to the DCViewport transform\n * feed so the percentage tracks every pan/zoom to the nearest 1%; the dropdown\n * snaps to a preset, zooming about the viewport center and letting the viewport\n * clamp to its own min/max scale.\n */\nfunction ZoomControl() {\n const [open, setOpen] = useState(false);\n const [pct, setPct] = useState(100);\n const ref = useRef<HTMLDivElement>(null);\n const apiRef = useRef<ViewportApi | null>(null);\n\n // Locate the viewport API (set in a post-mount effect, so retry briefly) and\n // subscribe for live scale updates.\n useEffect(() => {\n let unsub: (() => void) | null = null;\n let tries = 0;\n let raf = 0;\n const attach = () => {\n const vp = document.querySelector('[data-dc-viewport]') as (HTMLElement & { __dcViewport?: ViewportApi }) | null;\n const api = vp?.__dcViewport ?? null;\n if (api) {\n apiRef.current = api;\n unsub = api.subscribe((t) => setPct(Math.round(t.scale * 100)));\n return;\n }\n if (tries++ < 60) raf = requestAnimationFrame(attach);\n };\n attach();\n return () => {\n if (raf) cancelAnimationFrame(raf);\n if (unsub) unsub();\n };\n }, []);\n\n useEffect(() => {\n if (!open) return;\n const onDown = (e: PointerEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false);\n };\n const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') setOpen(false); };\n document.addEventListener('pointerdown', onDown, true);\n document.addEventListener('keydown', onKey);\n return () => {\n document.removeEventListener('pointerdown', onDown, true);\n document.removeEventListener('keydown', onKey);\n };\n }, [open]);\n\n const zoomTo = (scale: number) => {\n const api = apiRef.current;\n const vp = document.querySelector('[data-dc-viewport]') as HTMLElement | null;\n if (!api || !vp) return;\n const r = vp.getBoundingClientRect();\n const cx = r.width / 2;\n const cy = r.height / 2;\n const t = api.getTransform();\n const k = scale / t.scale;\n // Keep the world point at the viewport center fixed (matches wheel-zoom math).\n api.animateTransform({ x: cx - (cx - t.x) * k, y: cy - (cy - t.y) * k, scale }, 200);\n setOpen(false);\n };\n\n return (\n <div ref={ref} style={{ position: 'relative', display: 'flex' }}>\n <button\n type=\"button\"\n onClick={() => setOpen((o) => !o)}\n title=\"Zoom\"\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 6,\n border: 'none',\n borderRadius: 8,\n padding: '7px 9px 7px 11px',\n font: `600 12.5px ${FONT}`,\n cursor: 'pointer',\n color: 'rgba(245,241,232,0.82)',\n background: open ? 'rgba(255,255,255,0.08)' : 'transparent',\n transition: 'background 120ms ease, color 120ms ease',\n whiteSpace: 'nowrap',\n fontVariantNumeric: 'tabular-nums',\n minWidth: 56,\n justifyContent: 'space-between',\n }}\n >\n <span>{pct}%</span>\n <svg width=\"9\" height=\"9\" viewBox=\"0 0 11 11\" fill=\"none\" stroke=\"currentColor\"\n strokeWidth=\"1.8\" strokeLinecap=\"round\" style={{ opacity: 0.6 }}>\n <path d={open ? 'M2 7l3.5-3.5L9 7' : 'M2 4l3.5 3.5L9 4'} />\n </svg>\n </button>\n {open && (\n <div\n style={{\n position: 'absolute',\n bottom: '100%',\n left: 0,\n marginBottom: 8,\n background: '#202123',\n borderRadius: 10,\n boxShadow: '0 10px 32px rgba(0,0,0,0.4)',\n padding: 4,\n minWidth: 120,\n zIndex: 10,\n }}\n >\n {ZOOM_PRESETS.map((z) => {\n const zp = Math.round(z * 100);\n const isActive = zp === pct;\n return (\n <button\n key={z}\n type=\"button\"\n onClick={() => zoomTo(z)}\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n width: '100%',\n textAlign: 'left',\n border: 'none',\n cursor: 'pointer',\n background: isActive ? 'rgba(255,255,255,0.1)' : 'transparent',\n color: '#fff',\n padding: '8px 10px',\n borderRadius: 6,\n font: `${isActive ? 600 : 400} 13px ${FONT}`,\n fontVariantNumeric: 'tabular-nums',\n }}\n onMouseEnter={(e) => { if (!isActive) e.currentTarget.style.background = 'rgba(255,255,255,0.05)'; }}\n onMouseLeave={(e) => { if (!isActive) e.currentTarget.style.background = 'transparent'; }}\n >\n {zp}%\n </button>\n );\n })}\n </div>\n )}\n </div>\n );\n}\n\n/**\n * Page chip + switcher. Inert chip when the canvas has ≤1 page; a clickable\n * dropdown (switch-only) once there are multiple `<DCPage>`s.\n */\nfunction PageSwitcher({\n pages,\n activePageId,\n setActivePage,\n fallbackName,\n}: {\n pages?: CanvasPage[];\n activePageId?: string | null;\n setActivePage?: (id: string) => void;\n fallbackName: string;\n}) {\n const [open, setOpen] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n const multi = !!(pages && pages.length > 1);\n const active = pages?.find((p) => p.id === activePageId);\n const label = active ? active.title : fallbackName;\n\n // Close on outside-click / Esc while open.\n useEffect(() => {\n if (!open) return;\n const onDown = (e: PointerEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false);\n };\n const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') setOpen(false); };\n document.addEventListener('pointerdown', onDown, true);\n document.addEventListener('keydown', onKey);\n return () => {\n document.removeEventListener('pointerdown', onDown, true);\n document.removeEventListener('keydown', onKey);\n };\n }, [open]);\n\n return (\n <div ref={ref} style={{ position: 'relative', display: 'flex' }}>\n <button\n type=\"button\"\n disabled={!multi}\n onClick={() => multi && setOpen((o) => !o)}\n title={multi ? 'Switch page' : `Page · ${label}`}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 7,\n border: 'none',\n borderRadius: 8,\n padding: '7px 11px',\n font: `600 12.5px ${FONT}`,\n cursor: multi ? 'pointer' : 'default',\n color: multi ? 'rgba(245,241,232,0.82)' : 'rgba(245,241,232,0.5)',\n background: open ? 'rgba(255,255,255,0.08)' : 'transparent',\n transition: 'background 120ms ease, color 120ms ease',\n whiteSpace: 'nowrap',\n }}\n >\n <span style={{ display: 'flex', flexShrink: 0 }}>{ICON.page}</span>\n {label}\n {multi && (\n <svg width=\"9\" height=\"9\" viewBox=\"0 0 11 11\" fill=\"none\" stroke=\"currentColor\"\n strokeWidth=\"1.8\" strokeLinecap=\"round\" style={{ opacity: 0.6, marginLeft: -1 }}>\n <path d={open ? 'M2 7l3.5-3.5L9 7' : 'M2 4l3.5 3.5L9 4'} />\n </svg>\n )}\n </button>\n {open && multi && pages && (\n <div\n style={{\n position: 'absolute',\n bottom: '100%',\n left: 0,\n marginBottom: 8,\n background: '#202123',\n borderRadius: 10,\n boxShadow: '0 10px 32px rgba(0,0,0,0.4)',\n padding: 4,\n minWidth: 180,\n zIndex: 10,\n }}\n >\n {pages.map((p) => {\n const isActive = p.id === activePageId;\n return (\n <button\n key={p.id}\n type=\"button\"\n onClick={() => { setActivePage?.(p.id); setOpen(false); }}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 8,\n width: '100%',\n textAlign: 'left',\n border: 'none',\n cursor: 'pointer',\n background: isActive ? 'rgba(255,255,255,0.1)' : 'transparent',\n color: '#fff',\n padding: '8px 10px',\n borderRadius: 6,\n font: `${isActive ? 600 : 400} 13px ${FONT}`,\n }}\n onMouseEnter={(e) => { if (!isActive) e.currentTarget.style.background = 'rgba(255,255,255,0.05)'; }}\n onMouseLeave={(e) => { if (!isActive) e.currentTarget.style.background = 'transparent'; }}\n >\n <span style={{ display: 'flex', flexShrink: 0, opacity: isActive ? 1 : 0.6 }}>{ICON.page}</span>\n {p.title}\n </button>\n );\n })}\n </div>\n )}\n </div>\n );\n}\n\n/**\n * Bottom-left mode switcher. Always shows the page chip + cursor mode; comment\n * and dev segments appear only when their capability is enabled on the canvas.\n */\nexport function ModeBar({\n mode,\n setMode,\n hasComments,\n hasInspector,\n commentUnread = 0,\n canvasLabel,\n pages,\n activePageId,\n setActivePage,\n}: {\n mode: CanvasMode;\n setMode: (m: CanvasMode) => void;\n hasComments?: boolean;\n hasInspector?: boolean;\n /** Unread comment count — shows a dot on the Comment tab when > 0 off-mode. */\n commentUnread?: number;\n canvasLabel?: string;\n pages?: CanvasPage[];\n activePageId?: string | null;\n setActivePage?: (id: string) => void;\n}) {\n // Short, human-ish page name from a `ns:project:page` canvasId — used as the\n // chip label for unpaged canvases.\n const pageName = canvasLabel ? canvasLabel.split(':').pop() || 'Canvas' : 'Canvas';\n\n const shell: CSSProperties = {\n position: 'fixed',\n left: 16,\n bottom: 16,\n zIndex: 2001,\n display: 'flex',\n alignItems: 'center',\n gap: 2,\n padding: 4,\n background: '#18191b',\n borderRadius: 12,\n border: '1px solid rgba(255,255,255,0.12)',\n boxShadow: '0 6px 22px rgba(0,0,0,0.32)',\n fontFamily: FONT,\n };\n\n return (\n <div data-dc-modebar style={shell} onPointerDown={(e) => e.stopPropagation()}>\n <ZoomControl />\n <Divider />\n <PageSwitcher\n pages={pages}\n activePageId={activePageId}\n setActivePage={setActivePage}\n fallbackName={pageName}\n />\n <Divider />\n <Seg\n title=\"Cursor — interact with the prototypes, pan & zoom\"\n active={mode === 'cursor'}\n onClick={() => setMode('cursor')}\n icon={ICON.cursor}\n label=\"Cursor\"\n />\n {hasComments && (\n <Seg\n title=\"Comment — drop pins and open the comments sidebar\"\n active={mode === 'comment'}\n onClick={() => setMode('comment')}\n icon={ICON.comment}\n label=\"Comment\"\n badge={commentUnread > 0 && mode !== 'comment'}\n />\n )}\n {hasInspector && (\n <Seg\n title=\"Dev — inspect components, tokens & accessibility\"\n active={mode === 'dev'}\n onClick={() => setMode('dev')}\n icon={ICON.dev}\n label=\"Dev\"\n />\n )}\n </div>\n );\n}\n","// Fiber display-name resolution, extracted from Inspector.tsx so design-system\n// adapters can import it without a circular dependency back through the\n// inspector. Mirrors React DevTools' name resolution: reads `displayName` /\n// function name off plain functions, and unwraps `forwardRef` / `memo`.\n//\n// In production builds React strips component names, so this returns minified\n// identifiers (or null) — which is exactly why a real design-system adapter\n// keeps its own export-name map keyed by component identity instead of relying\n// on this. The generic (no-DS) adapter falls back to this as its best effort.\n\nexport type FiberType = any;\n\nexport function getComponentName(type: FiberType): string | null {\n if (!type) return null;\n if (typeof type === 'string') return null;\n if (typeof type === 'function') return type.displayName || type.name || null;\n // forwardRef\n if (type.$$typeof && type.render) {\n return (\n type.displayName ||\n type.render.displayName ||\n type.render.name ||\n null\n );\n }\n // memo\n if (type.$$typeof && type.type) {\n return type.displayName || getComponentName(type.type);\n }\n return null;\n}\n","// genericAdapter — the no-design-system default. Compiles and runs with ZERO\n// Spring (or any other DS) dependency. Library detection is always false (no DS\n// is known), names fall back to fiber name resolution, and the token specs use\n// empty CSS-var prefixes so the reverse-lookup builders harvest nothing and the\n// inspector reports raw computed values instead of token labels.\n//\n// To light up real detection + token labels, write a per-DS adapter (see\n// examples/springAdapter.ts) and inject it via setDesignSystemAdapter().\n\nimport type { DesignSystemAdapter, AdapterFiber } from './types';\nimport { getComponentName } from '../DesignCanvas/fiberName';\n\nexport const genericAdapter: DesignSystemAdapter = {\n libraryLabel: 'Library',\n libraryShortLabel: 'Lib',\n\n // No design system connected → nothing is ever a library instance.\n isLibraryComponent(_type: any): boolean {\n return false;\n },\n\n componentName(type: any): string | null {\n return getComponentName(type);\n },\n\n classify(type: any): { kind: 'library' | 'user'; name: string | null } {\n // Without a DS, everything non-host is a user component.\n return { kind: 'user', name: getComponentName(type) };\n },\n\n // No icon library to match against.\n findIconName(_fiber: AdapterFiber | null): string | null {\n return null;\n },\n\n iconWrapperSize(_fiber: AdapterFiber | null): string | null {\n return null;\n },\n\n iconImportSnippet(name: string): string {\n // No known package — emit a neutral, still-useful reference line.\n return `import { ${name} } from 'icons';`;\n },\n iconLabel: 'Icon',\n\n tokens: {\n // Empty prefix → builders harvest no CSS vars → inspector shows raw values.\n color: { cssVarPrefix: '' },\n shadow: { cssVarPrefix: '' },\n spacing: { cssVarPrefix: '' },\n radius: { cssVarPrefix: '' },\n typography: {\n // No utility-class convention known → never matches a typography token.\n classMatcher: () => [],\n },\n // No utility-class convention known. Empty prefixes are guarded by the core\n // so they don't match every class.\n utilityClassPrefixes: {\n typography: '',\n text: '',\n bg: '',\n border: '',\n },\n },\n};\n","// Design-system adapter injection. Module-level singleton — matches the\n// existing module-level lazy token-map caches in Inspector.tsx (the inspector\n// is a single overlay, never two adapters at once on one page). Defaults to the\n// no-Spring genericAdapter so the core runs with zero design-system deps.\n//\n// To connect a design system, call setDesignSystemAdapter() once at app start\n// (before the Inspector mounts), e.g. from DesignCanvas's `adapter` prop:\n// import { springAdapter } from '../../examples/springAdapter';\n// setDesignSystemAdapter(springAdapter);\n\nimport type { DesignSystemAdapter } from './types';\nimport { genericAdapter } from './genericAdapter';\n\nlet activeAdapter: DesignSystemAdapter = genericAdapter;\n\n// Listeners fired on a genuine adapter change (P2.6). Kept as a registration\n// seam rather than a direct import so this module stays a dependency-free leaf:\n// the Inspector's token layer (tokens.ts) registers `resetTokenCaches` here at\n// load, so switching design systems invalidates the stale reverse-lookup maps\n// WITHOUT adapters/ importing the Inspector (which would be a cycle).\ntype AdapterChangeListener = (adapter: DesignSystemAdapter) => void;\nconst adapterChangeListeners: AdapterChangeListener[] = [];\nexport function onDesignSystemAdapterChange(fn: AdapterChangeListener): void {\n adapterChangeListeners.push(fn);\n}\n\nexport function setDesignSystemAdapter(adapter: DesignSystemAdapter): void {\n // Idempotent: re-installing the SAME adapter (the common case — the prop is\n // re-read on every DesignCanvas render) must not thrash the token caches.\n if (adapter === activeAdapter) return;\n // A DIFFERENT design system replacing an already-customized one means two\n // <DesignCanvas adapter=…> instances with different adapters on one page —\n // unsupported (the token caches + inspector are a single global). Warn in dev\n // so the mistake is visible; the caches are reset either way so at least the\n // most-recently-installed adapter reads correctly.\n const dev = (import.meta as unknown as { env?: { DEV?: boolean } }).env?.DEV;\n if (dev && activeAdapter !== genericAdapter) {\n // eslint-disable-next-line no-console\n console.warn(\n '[carboncanvas] a different design-system adapter was installed after the first one. ' +\n 'Two <DesignCanvas adapter=…> with different adapters on one page is unsupported; ' +\n 'the token caches were reset to the latest adapter.',\n );\n }\n activeAdapter = adapter;\n for (const fn of adapterChangeListeners) fn(adapter);\n}\n\nexport function getDesignSystemAdapter(): DesignSystemAdapter {\n return activeAdapter;\n}\n\n// Does the connected adapter actually carry a token vocabulary? True iff at\n// least one CSS-var token family declares a prefix to harvest. The genericAdapter\n// (no design system) leaves every prefix empty → false, so token-dependent\n// Inspector UI — the Tok/Var toggles, the \"off-token\" flags, the token-adherence\n// scan — hides itself and the inspector reports raw absolute values instead.\n// Connect a real adapter (non-empty prefixes) and all of it lights up. This is\n// the ONE capability signal those surfaces gate on (see the DS-scan plan doc).\nexport function adapterHasTokens(adapter: DesignSystemAdapter = activeAdapter): boolean {\n const t = adapter.tokens;\n return Boolean(\n t.color.cssVarPrefix || t.shadow.cssVarPrefix || t.spacing.cssVarPrefix || t.radius.cssVarPrefix,\n );\n}\n\nexport { genericAdapter };\nexport type {\n DesignSystemAdapter,\n AdapterFiber,\n ComponentKind,\n CssVarTokenSpec,\n TypographyTokenSpec,\n UtilityClassPrefixes,\n AdapterTokens,\n} from './types';\n","// DesignCanvas.tsx — Figma-ish design canvas wrapper\n// Warm gray grid bg + Sections + Artboards + PostIt notes.\n// Artboards are reorderable (grip-drag), labels/titles are inline-editable,\n// and any artboard can be opened in a fullscreen focus overlay (←/→/Esc).\n// No assets, no deps beyond React + ReactDOM.\n//\n// PERSISTENCE: this build has no persistence layer — renames and reorders\n// live for the current session only. To persist across reloads, plug a\n// writer into the `state.sections` effect inside DesignCanvas (localStorage,\n// fetch, or any host bridge).\n//\n// HEAVY CONTENT: artboards expose an `active` flag via the `useArtboardActive`\n// hook — `false` when the artboard is offscreen or zoomed below\n// `minActiveScale` (default 0.35). Heavy children (videos, canvases, iframes,\n// continuous animations) should gate on it so the canvas doesn't burn CPU\n// painting things the user can't see. Outside a DesignCanvas the hook returns\n// `true`, so the same component still works in fullscreen prototypes.\n//\n// Usage:\n// <DesignCanvas>\n// <DCSection id=\"onboarding\" title=\"Onboarding\" subtitle=\"First-run variants\">\n// <DCArtboard id=\"a\" label=\"A · Dusk\" width={260} height={480}>…</DCArtboard>\n// <DCArtboard id=\"b\" label=\"B · Minimal\" width={260} height={480}>…</DCArtboard>\n// </DCSection>\n// </DesignCanvas>\n\nimport React from 'react';\nimport type { CSSProperties, ReactElement, ReactNode } from 'react';\nimport { createPortal } from 'react-dom';\nimport { CommentLayer } from '../CommentLayer/CommentLayer';\nimport type { CommentsConfig } from '../CommentLayer/types';\nimport { ModeBar } from './ModeBar';\nimport type { CanvasMode } from './ModeBar';\nimport { getPortalRoot } from './portalRoot';\nimport { setDesignSystemAdapter } from '../adapters';\nimport type { DesignSystemAdapter } from '../adapters';\nimport type { DCTransform, DCViewportApi } from './viewportApi';\n\n// Inspector is dev-only and heavy (the overlay + XRay/Exploded + the split\n// submodules) — code-split it into its own chunk so a free-tier\n// `inspector={false}` install ships ZERO of those bytes. Mirrors the\n// CommentsRuntime lazy pattern (CommentLayer.tsx).\nconst Inspector = React.lazy(() => import('./Inspector'));\n\n// The viewport context value = the imperative handle plus the min-active-scale\n// threshold artboards read to self-deactivate. A superset of the DOM-stashed\n// DCViewportApi consumers outside the React tree see.\ntype DCViewportContext = DCViewportApi & { minActiveScale: number };\n\n// Per-section runtime state (ephemeral in this build — see header comment).\ntype SectionState = {\n order?: string[];\n title?: string;\n labels?: Record<string, string>;\n};\n\n// Canvas-wide runtime state owned by DesignCanvas.\ntype DCState = {\n sections: Record<string, SectionState>;\n focus: string | null;\n selected: string | null;\n};\n\n// The context API DesignCanvas exposes to DCSection / DCArtboardFrame / focus.\ntype DCApi = {\n state: DCState;\n section: (id: string) => SectionState;\n patchSection: (\n id: string,\n p: Partial<SectionState> | ((prev: SectionState) => Partial<SectionState>),\n ) => void;\n setFocus: (slotId: string | null) => void;\n setSelected: (slotId: string | null) => void;\n activePageId: string | null;\n};\n\n// A registered artboard slot (built synchronously each render from children).\ntype RegistryEntry = { sectionId: string; artboard: ReactElement<DCArtboardProps> };\n\nconst DC = {\n bg: '#18191b',\n grid: 'rgba(255,255,255,0.55)',\n label: 'rgba(233,234,237,0.6)',\n title: 'rgba(240,241,244,0.92)',\n subtitle: 'rgba(233,234,237,0.5)',\n postitBg: '#fef4a8',\n postitText: '#5a4a2a',\n font: '-apple-system, BlinkMacSystemFont, \"Segoe UI\", system-ui, sans-serif',\n};\n\n// One-time CSS injection (classes are dc-prefixed so they don't collide with\n// the hosted design's own styles). Called from DesignCanvas's render (a lazy\n// useState initializer, so it runs once, synchronously, before first paint) —\n// NOT at module scope: the package is `sideEffects: false`, and a top-level DOM\n// mutation on import both contradicts that and runs even for a consumer that\n// never renders a canvas. (P3.5)\nfunction ensureDcStyles() {\n if (typeof document === 'undefined' || document.getElementById('dc-styles')) return;\n const s = document.createElement('style');\n s.id = 'dc-styles';\n s.textContent = [\n '.dc-editable{cursor:text;outline:none;white-space:nowrap;border-radius:3px;padding:0 2px;margin:0 -2px}',\n '.dc-editable:focus{background:rgba(255,255,255,.1);color:#fff;box-shadow:0 0 0 1.5px #9aa6bb}',\n // Keyboard-only focus ring for hierarchy-tree rows (roving tabindex); no ring\n // on mouse focus so click-to-select stays visually unchanged.\n '[data-dc-treeitem]:focus{outline:none}',\n '[data-dc-treeitem]:focus-visible{outline:2px solid #9aa6bb;outline-offset:-2px}',\n // An ENGAGED artboard (clicked into; owns wheel/scroll until you click out)\n // gets a subtle accent ring so it is clear where scroll/zoom will land.\n '[data-dc-slot][data-dc-engaged] .dc-card{box-shadow:0 0 0 1.5px var(--quilt-accent,#9aa6bb),0 6px 24px rgba(154,166,187,.16)}',\n '.dc-card{transition:box-shadow .15s,transform .15s}',\n '.dc-card *{scrollbar-width:none}',\n '.dc-card *::-webkit-scrollbar{display:none}',\n '.dc-labelrow{display:flex;align-items:center;gap:4px;height:24px}',\n '.dc-labeltext{cursor:pointer;border-radius:4px;padding:3px 6px;display:flex;align-items:center;transition:background .12s}',\n '.dc-labeltext:hover{background:rgba(255,255,255,.08)}',\n '.dc-labeltext.dc-selected{background:rgba(154,166,187,.12)}',\n '.dc-share-pop{position:absolute;bottom:100%;left:-4px;margin-bottom:32px;z-index:5;display:flex;align-items:center;',\n ' background:#202123;color:#f5f1e8;border-radius:7px;padding:5px 6px;gap:2px;',\n ' box-shadow:0 6px 24px rgba(0,0,0,.28);white-space:nowrap}',\n '.dc-share-pop button{display:flex;align-items:center;gap:6px;border:none;background:transparent;color:inherit;',\n ' cursor:pointer;font:500 12px/1 -apple-system,BlinkMacSystemFont,\"Segoe UI\",system-ui,sans-serif;padding:5px 8px;border-radius:5px;transition:background .12s}',\n '.dc-share-pop button:hover{background:rgba(255,255,255,.12)}',\n '.dc-expand{position:absolute;bottom:100%;right:0;margin-bottom:5px;z-index:2;opacity:0;transition:opacity .12s,background .12s;',\n ' width:22px;height:22px;border-radius:5px;border:none;cursor:pointer;padding:0;',\n ' background:transparent;color:rgba(233,234,237,.55);display:flex;align-items:center;justify-content:center}',\n '.dc-expand:hover{background:rgba(255,255,255,.08);color:#fff}',\n '[data-dc-slot]:hover .dc-expand{opacity:1}',\n ].join('\\n');\n document.head.appendChild(s);\n}\n\nconst DCCtx = React.createContext<DCApi | null>(null);\n\n// Viewport ctx — lets artboards subscribe to pan/zoom transform updates so they\n// can self-deactivate when offscreen or zoomed too small. Default null means\n// \"no viewport in the tree\" (e.g. tests, focus overlay) and consumers should\n// treat their artboard as active.\nconst DCViewportCtx = React.createContext<DCViewportContext | null>(null);\n\n// Artboard active flag — read by heavy content (videos, canvases) to pause\n// work when its artboard isn't worth painting. Defaults to true so anything\n// rendered outside a DesignCanvas behaves normally.\nconst DCArtboardActiveCtx = React.createContext<boolean>(true);\nexport const useArtboardActive = (): boolean => React.useContext(DCArtboardActiveCtx);\n\n/**\n * Props for {@link DesignCanvas}.\n *\n * @remarks\n * **One `<DesignCanvas>` per page.** The canvas chrome (Inspector, ModeBar zoom,\n * comment pin/cursor panning) locates the active viewport via a global\n * `document.querySelector('[data-dc-viewport]')`, so two DesignCanvas instances\n * mounted on the same page cross-wire. Render at most one per route; nested\n * canvases-inside-an-artboard are supported (scoped by nearest-viewport), but two\n * sibling canvases are not.\n */\nexport interface DesignCanvasProps {\n children?: ReactNode;\n minScale?: number;\n maxScale?: number;\n /**\n * Artboards report `active = false` via `useArtboardActive()` when the\n * viewport scale drops below this threshold (or when the artboard scrolls\n * out of view). Heavy content (videos, canvases) should gate on it.\n * Defaults to 0.35.\n */\n minActiveScale?: number;\n style?: CSSProperties;\n /** Enables the click-to-inspect overlay (library component + props + className). */\n inspector?: boolean;\n /**\n * Connect a design system to the Inspector (token reverse-lookup, library\n * component + icon detection). Defaults to the no-design-system generic\n * adapter. See `../adapters` + `examples/springAdapter.ts`.\n */\n adapter?: DesignSystemAdapter;\n /**\n * Enables the comment layer (drop pins on artboard elements, thread, resolve).\n * Inert when omitted/false. `canvasId` namespaces the data in the\n * comments-service; `devMode` uses an in-memory mock store instead of the network.\n */\n comments?: false | CommentsConfig;\n}\n\n// ─────────────────────────────────────────────────────────────\n// DesignCanvas — stateful wrapper around the pan/zoom viewport.\n// Owns runtime state (per-section order, renamed titles/labels, focused\n// artboard). All state is ephemeral in this build — see header comment\n// for how to wire up persistence.\n// ─────────────────────────────────────────────────────────────\nexport function DesignCanvas({\n children,\n minScale,\n maxScale,\n minActiveScale,\n style,\n inspector = false,\n comments = false,\n adapter,\n}: DesignCanvasProps): ReactElement {\n // Connect a design system to the Inspector (token reverse-lookup, library\n // component + icon detection). Defaults to the no-design-system generic\n // adapter. Set ONCE via a lazy useState initializer — it runs synchronously\n // during the first render (before the Inspector child reads the adapter) but\n // NOT on every subsequent render. Writing the module singleton in render body\n // is a React anti-pattern and, now that setDesignSystemAdapter resets the\n // token caches (P2.6), doing it per-render would thrash them. StrictMode\n // double-invokes the initializer, but setDesignSystemAdapter is idempotent on\n // the same adapter, so the second call is a no-op.\n React.useState(() => {\n ensureDcStyles(); // inject the dc-* chrome CSS once, before first paint\n if (adapter) setDesignSystemAdapter(adapter);\n return null;\n });\n // A genuinely different `adapter` prop later (the unsupported two-canvas case)\n // is applied here — setDesignSystemAdapter dev-warns and invalidates the stale\n // token caches. No-op on mount (same adapter → idempotent guard).\n React.useEffect(() => {\n if (adapter) setDesignSystemAdapter(adapter);\n }, [adapter]);\n\n const [state, setState] = React.useState<DCState>({ sections: {}, focus: null, selected: null });\n\n // Shared canvas interaction mode ('cursor' | 'comment' | 'dev'), surfaced by\n // the bottom-left ModeBar and consumed by the Inspector + CommentLayer so each\n // derives its active state from one source of truth.\n const [mode, setMode] = React.useState<CanvasMode>('cursor');\n\n // Unread (unresolved) comment count, reported up by the CommentLayer so the\n // ModeBar's Comment tab can show a blue dot while you're in cursor/dev mode.\n const [commentUnread, setCommentUnread] = React.useState(0);\n\n // ── Pages ──────────────────────────────────────────────────────\n // Figma-style pages: direct `<DCPage>` children each hold their own\n // sections; only the active page renders. A canvas with no DCPage children\n // is unpaged and behaves exactly as before (one implicit page).\n const pages: { id: string; title: string; children: ReactNode }[] = [];\n React.Children.forEach(children, (p) => {\n if (!React.isValidElement(p) || p.type !== DCPage) return;\n const pp = p.props as DCPageProps;\n const pid = pp.id ?? pp.title;\n if (!pid) return;\n pages.push({ id: pid, title: pp.title ?? pid, children: pp.children });\n });\n const paged = pages.length > 0;\n\n // Active page id. Init from the `?page=` URL param if it names a real page,\n // else the first page. Unpaged canvases ignore this entirely.\n const [activePageId, setActivePageId] = React.useState<string | null>(() => {\n if (!paged) return null;\n const ids = pages.map((p) => p.id);\n let fromUrl: string | null = null;\n if (typeof window !== 'undefined') {\n fromUrl = new URLSearchParams(window.location.search).get('page');\n }\n return fromUrl && ids.includes(fromUrl) ? fromUrl : pages[0].id;\n });\n // If the page set changes (HMR/edit) and the active id no longer exists,\n // fall back to the first page so we never render a dead page.\n React.useEffect(() => {\n if (paged && !pages.some((p) => p.id === activePageId)) {\n setActivePageId(pages[0].id);\n }\n }, [paged, pages.map((p) => p.id).join('|'), activePageId]);\n\n const switchPage = React.useCallback((id: string) => {\n setActivePageId(id);\n setState((s) => ({ ...s, focus: null })); // focus targets are page-scoped\n if (typeof window !== 'undefined' && window.history) {\n const url = new URL(window.location.href);\n url.searchParams.set('page', id);\n window.history.replaceState(null, '', url);\n }\n }, []);\n\n const activePage = paged ? (pages.find((p) => p.id === activePageId) || pages[0]) : null;\n // Everything below (registry, viewport, focus) operates on the visible\n // page's children so focus navigation stays scoped to one page.\n const activeChildren = activePage ? activePage.children : children;\n\n // Comments are scoped to the whole canvas (one CommentLayer instance, one\n // fetch of every page) — NOT remounted per page. The sidebar lists comments\n // from all pages; the active page + a page switcher are passed down so pins\n // render only for the visible page and a row-click can jump to another page.\n // (This single canvas-wide subscription is also the seam realtime plugs into —\n // see CommentLayer/REALTIME.md.)\n const commentsConfig: CommentsConfig | null =\n comments && comments.canvasId ? comments : null;\n const hasComments = !!commentsConfig;\n const pageList = React.useMemo(\n () => (paged ? pages.map((p) => ({ id: p.id, title: p.title })) : undefined),\n [paged, pages],\n );\n\n // Build registries synchronously from the active page's children so\n // FocusOverlay can read them in the same render. Only direct\n // DCSection > DCArtboard children are walked — wrapping them in other\n // elements opts out of focus/reorder.\n const registry: Record<string, RegistryEntry> = {}; // slotId -> { sectionId, artboard }\n const sectionMeta: Record<string, { title?: string; subtitle?: string; slotIds: string[] }> = {}; // sectionId -> meta\n const sectionOrder: string[] = [];\n React.Children.forEach(activeChildren, (sec) => {\n if (!React.isValidElement(sec) || sec.type !== DCSection) return;\n const sp = sec.props as DCSectionProps;\n const sid = sp.id ?? sp.title;\n if (!sid) return;\n sectionOrder.push(sid);\n const persisted = state.sections[sid] || {};\n const srcIds: string[] = [];\n React.Children.forEach(sp.children, (ab) => {\n if (!React.isValidElement(ab) || ab.type !== DCArtboard) return;\n const abp = ab.props as DCArtboardProps;\n const aid = abp.id ?? abp.label;\n if (!aid) return;\n registry[`${sid}/${aid}`] = { sectionId: sid, artboard: ab as ReactElement<DCArtboardProps> };\n srcIds.push(aid);\n });\n const kept = (persisted.order || []).filter((k) => srcIds.includes(k));\n sectionMeta[sid] = {\n title: persisted.title ?? sp.title,\n subtitle: sp.subtitle,\n slotIds: [...kept, ...srcIds.filter((k) => !kept.includes(k))],\n };\n });\n\n const api = React.useMemo<DCApi>(() => ({\n state,\n section: (id) => state.sections[id] || {},\n patchSection: (id, p) => setState((s) => ({\n ...s,\n sections: { ...s.sections, [id]: { ...s.sections[id], ...(typeof p === 'function' ? p(s.sections[id] || {}) : p) } },\n })),\n setFocus: (slotId) => setState((s) => ({ ...s, focus: slotId })),\n setSelected: (slotId) => setState((s) => (s.selected === slotId ? s : { ...s, selected: slotId })),\n activePageId,\n }), [state, activePageId]);\n\n // Esc exits focus + clears the selection; any outside pointerdown commits an\n // in-progress rename and deselects (the label's own click re-selects after).\n React.useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') setState((s) => (s.focus || s.selected ? { ...s, focus: null, selected: null } : s));\n };\n const onPd = (e: PointerEvent) => {\n const ae = document.activeElement as HTMLElement | null;\n if (ae && ae.isContentEditable && !ae.contains(e.target as Node)) ae.blur();\n if (!(e.target instanceof Element) || !e.target.closest('.dc-labelrow, .dc-share-pop')) {\n setState((s) => (s.selected ? { ...s, selected: null } : s));\n }\n };\n document.addEventListener('keydown', onKey);\n document.addEventListener('pointerdown', onPd, true);\n return () => {\n document.removeEventListener('keydown', onKey);\n document.removeEventListener('pointerdown', onPd, true);\n };\n }, []);\n\n // Deeplink: `?artboard=<id>` (share-link counterpart of the comments' `?pin=`).\n // `?page=` has already picked the page above; once the slot mounts, pan/zoom\n // to it and select it so the recipient sees exactly what was shared.\n const artboardDeeplinkDone = React.useRef(false);\n React.useEffect(() => {\n if (artboardDeeplinkDone.current || typeof window === 'undefined') return;\n artboardDeeplinkDone.current = true;\n const aid = new URLSearchParams(window.location.search).get('artboard');\n if (!aid) return;\n let tries = 0;\n const tick = () => {\n const el = document.querySelector(`[data-dc-slot=\"${CSS.escape(aid)}\"]`);\n if (el) {\n panToSlot(el);\n const sec = el.closest('[data-dc-section]');\n if (sec) setState((s) => ({ ...s, selected: `${sec.getAttribute('data-dc-section')}/${aid}` }));\n return;\n }\n if (tries++ < 40) requestAnimationFrame(tick); // ~0.6s for the page to mount\n };\n requestAnimationFrame(tick);\n }, []);\n\n // An active page with no DCSection children shows a placeholder rather than\n // an empty grid — e.g. a page reserved for content authored later.\n const hasSections = React.Children.toArray(activeChildren).some(\n (c) => React.isValidElement(c) && c.type === DCSection,\n );\n\n return (\n <DCCtx.Provider value={api}>\n <DCViewport minScale={minScale} maxScale={maxScale} minActiveScale={minActiveScale} style={style} mode={mode} fitKey={paged ? activePageId : null}>\n {paged && !hasSections ? <DCEmptyPage title={activePage?.title} /> : activeChildren}\n </DCViewport>\n {state.focus && registry[state.focus] && (\n <DCFocusOverlay entry={registry[state.focus]} sectionMeta={sectionMeta} sectionOrder={sectionOrder} />\n )}\n {inspector && (\n <React.Suspense fallback={null}>\n <Inspector mode={mode} setMode={setMode} />\n </React.Suspense>\n )}\n {commentsConfig && (\n <CommentLayer\n config={commentsConfig}\n mode={mode}\n setMode={setMode}\n activePageId={paged ? activePageId : null}\n pages={pageList}\n onSwitchPage={switchPage}\n onUnreadChange={setCommentUnread}\n />\n )}\n {(inspector || hasComments) && (\n <ModeBar\n mode={mode}\n setMode={setMode}\n hasComments={hasComments}\n hasInspector={!!inspector}\n commentUnread={commentUnread}\n canvasLabel={commentsConfig ? commentsConfig.canvasId : undefined}\n pages={paged ? pages.map((p) => ({ id: p.id, title: p.title })) : undefined}\n activePageId={activePageId}\n setActivePage={switchPage}\n />\n )}\n </DCCtx.Provider>\n );\n}\n\nexport interface DCPageProps {\n /** Stable page id; also the `?page=` deep-link value. Defaults to `title`. */\n id?: string;\n title: string;\n children?: ReactNode;\n}\n// DCPage — marker; its children (DCSections) render only while it's the active\n// page. Read structurally by DesignCanvas; renders nothing itself.\n//\n// A Figma-style canvas page. Wrap groups of `DCSection`s in `DCPage`s and only\n// the active one renders; the bottom-left ModeBar gains a page switcher.\n// A canvas with no `DCPage` children is unpaged (today's single-surface behavior).\nexport function DCPage(_props: DCPageProps): ReactElement | null { return null; }\n\n// Pan/zoom the viewport so an artboard slot fills the screen comfortably.\n// Same __dcViewport handshake the CommentLayer's pin-pan uses.\nfunction panToSlot(slotEl: Element) {\n const vpEl = document.querySelector('[data-dc-viewport]') as\n | (HTMLElement & { __dcViewport?: DCViewportApi })\n | null;\n if (!vpEl) return;\n const api = vpEl.__dcViewport;\n if (!api) return;\n const vpRect = vpEl.getBoundingClientRect();\n const tf = api.getTransform();\n const r = slotEl.getBoundingClientRect();\n if (r.width === 0 && r.height === 0) return;\n const worldW = r.width / tf.scale;\n const worldH = r.height / tf.scale;\n const worldCx = (r.left + r.width / 2 - vpRect.left - tf.x) / tf.scale;\n const worldCy = (r.top + r.height / 2 - vpRect.top - tf.y) / tf.scale;\n const scale = Math.min(2, Math.max(0.15,\n Math.min((vpRect.width - 160) / worldW, (vpRect.height - 200) / worldH)));\n api.animateTransform({\n x: vpRect.width / 2 - worldCx * scale,\n y: vpRect.height / 2 - worldCy * scale,\n scale,\n }, 320);\n}\n\n// Centered placeholder for an active page that has no sections yet.\nfunction DCEmptyPage({ title }: { title?: string }) {\n return (\n <div style={{\n position: 'absolute', inset: 0, display: 'flex', flexDirection: 'column',\n alignItems: 'center', justifyContent: 'center', gap: 8, pointerEvents: 'none',\n fontFamily: DC.font, color: DC.subtitle,\n }}>\n <svg width=\"40\" height=\"40\" viewBox=\"0 0 24 24\" fill=\"none\" style={{ opacity: 0.5 }}>\n <rect x=\"4\" y=\"3\" width=\"16\" height=\"18\" rx=\"2\" stroke=\"currentColor\" strokeWidth=\"1.4\" />\n <path d=\"M8 8h8M8 12h8M8 16h4\" stroke=\"currentColor\" strokeWidth=\"1.4\" strokeLinecap=\"round\" />\n </svg>\n <div style={{ fontSize: 18, fontWeight: 600, color: DC.title }}>{title}</div>\n <div style={{ fontSize: 14 }}>Nothing here yet — add artboards in code.</div>\n </div>\n );\n}\n\n// ─────────────────────────────────────────────────────────────\n// DCViewport — transform-based pan/zoom (internal)\n//\n// Input mapping (Figma-style):\n// • trackpad pinch → zoom (ctrlKey wheel; Safari gesture* events)\n// • trackpad scroll → pan (two-finger)\n// • mouse wheel → zoom (notched; distinguished from trackpad scroll)\n// • middle-drag / primary-drag-on-bg → pan\n//\n// Transform state lives in a ref and is written straight to the DOM\n// (translate3d + will-change) so wheel ticks don't go through React —\n// keeps pans at 60fps on dense canvases.\n// ─────────────────────────────────────────────────────────────\nfunction DCViewport({\n children,\n minScale = 0.1,\n maxScale = 8,\n minActiveScale = 0.35,\n style = {},\n mode = 'cursor',\n fitKey = null,\n}: {\n children?: ReactNode;\n minScale?: number;\n maxScale?: number;\n minActiveScale?: number;\n style?: CSSProperties;\n mode?: CanvasMode;\n fitKey?: string | null;\n}) {\n const vpRef = React.useRef<HTMLDivElement | null>(null);\n const worldRef = React.useRef<HTMLDivElement | null>(null);\n const tf = React.useRef<DCTransform>({ x: 0, y: 0, scale: 1 });\n // Subscribers fire after every transform write — kept in a ref so apply()\n // stays a stable callback and wheel ticks don't go through React.\n const subsRef = React.useRef<Set<(t: DCTransform) => void>>(new Set());\n // The ENGAGED artboard slot element, or null. Set when the user clicks into\n // an artboard that has scrollable / zoomable content; that artboard then owns\n // wheel + scroll (a long form scrolls, a nested canvas zooms) until the user\n // clicks the canvas background or a non-scrollable tile. Default null → the\n // canvas owns the wheel everywhere (pan/zoom to cursor), the predictable\n // navigation default. Kept in a ref so wheel ticks never go through React.\n const engagedRef = React.useRef<HTMLElement | null>(null);\n\n const apply = React.useCallback(() => {\n const { x, y, scale } = tf.current;\n const el = worldRef.current;\n if (el) el.style.transform = `translate3d(${x}px, ${y}px, 0) scale(${scale})`;\n subsRef.current.forEach((fn) => fn(tf.current));\n }, []);\n\n // Imperative transform setter for external callers (e.g. the Inspector's\n // \"click a scan result to bring its element into view\" flow). Clamps scale\n // to the viewport's configured range and routes through apply() so the\n // subscriber set runs the same as any user-driven pan/zoom.\n const setTransform = React.useCallback((next: DCTransform) => {\n const t = tf.current;\n t.x = next.x;\n t.y = next.y;\n t.scale = Math.min(maxScale, Math.max(minScale, next.scale));\n apply();\n }, [apply, minScale, maxScale]);\n\n // Tweened version — 240ms ease-out. Cancels any in-flight tween via a\n // bumped token. Use this for \"bring into view\" gestures so the move reads\n // as intentional motion rather than a teleport.\n const tweenTokenRef = React.useRef(0);\n const animateTransform = React.useCallback((next: DCTransform, ms = 240) => {\n const start = { ...tf.current };\n const target = {\n x: next.x,\n y: next.y,\n scale: Math.min(maxScale, Math.max(minScale, next.scale)),\n };\n const token = ++tweenTokenRef.current;\n const t0 = performance.now();\n const step = (now: number) => {\n if (token !== tweenTokenRef.current) return; // cancelled\n const u = Math.min(1, (now - t0) / ms);\n const k = 1 - Math.pow(1 - u, 3); // ease-out cubic\n tf.current.x = start.x + (target.x - start.x) * k;\n tf.current.y = start.y + (target.y - start.y) * k;\n tf.current.scale = start.scale + (target.scale - start.scale) * k;\n apply();\n if (u < 1) requestAnimationFrame(step);\n };\n requestAnimationFrame(step);\n }, [apply, minScale, maxScale]);\n\n // Fit the active page's tiles into the viewport. Called on a page switch so a\n // newly-shown page's tiles are never stranded off-screen at the previous\n // page's pan/zoom. Scopes to slots THIS canvas owns (nearest\n // [data-dc-viewport] === vp, like slotForThisCanvas) so a nested canvas's\n // inner tiles don't inflate the bounds; inverts the live transform to get\n // world-local bounds, then centers + scales them to fit with a margin.\n const fitToContent = React.useCallback((ms = 260) => {\n const vp = vpRef.current;\n if (!vp) return;\n const vpRect = vp.getBoundingClientRect();\n if (!vpRect.width || !vpRect.height) return;\n const t = tf.current;\n const slots = Array.from(vp.querySelectorAll('[data-dc-slot]')).filter((el) => {\n const parent = el.parentElement;\n return !!(parent && parent.closest && parent.closest('[data-dc-viewport]') === vp);\n });\n if (!slots.length) return;\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const el of slots) {\n const r = el.getBoundingClientRect();\n // screen → world-local: world = (screen - vpOrigin - translate) / scale\n const x = (r.left - vpRect.left - t.x) / t.scale;\n const y = (r.top - vpRect.top - t.y) / t.scale;\n minX = Math.min(minX, x);\n minY = Math.min(minY, y);\n maxX = Math.max(maxX, x + r.width / t.scale);\n maxY = Math.max(maxY, y + r.height / t.scale);\n }\n const bw = maxX - minX, bh = maxY - minY;\n if (!(bw > 0) || !(bh > 0)) return;\n const margin = 0.88; // a little breathing room around the content\n // Never zoom IN past 100% on a switch — content stays at a readable size.\n const cap = Math.min(maxScale, 1);\n const scale = Math.min(cap, Math.max(minScale, Math.min(vpRect.width / bw, vpRect.height / bh) * margin));\n const cx = (minX + maxX) / 2, cy = (minY + maxY) / 2;\n animateTransform({ x: vpRect.width / 2 - cx * scale, y: vpRect.height / 2 - cy * scale, scale }, ms);\n }, [animateTransform, minScale, maxScale]);\n\n // Refit the viewport when the active page CHANGES (not on first mount — the\n // initial view is left as-is). Wait two frames so the new page's tiles have\n // laid out before we measure. Unpaged canvases (fitKey == null) never refit.\n const fitKeyRef = React.useRef<string | null>(null);\n React.useEffect(() => {\n if (fitKey == null) return;\n if (fitKeyRef.current === null) { fitKeyRef.current = fitKey; return; }\n if (fitKeyRef.current === fitKey) return;\n fitKeyRef.current = fitKey;\n let raf2 = 0;\n const raf1 = requestAnimationFrame(() => { raf2 = requestAnimationFrame(() => fitToContent()); });\n return () => { cancelAnimationFrame(raf1); if (raf2) cancelAnimationFrame(raf2); };\n }, [fitKey, fitToContent]);\n\n const viewportCtx = React.useMemo<DCViewportContext>(() => ({\n subscribe: (fn: (t: DCTransform) => void) => {\n subsRef.current.add(fn);\n // Fire once so subscribers can initialize with the current transform.\n fn(tf.current);\n return () => { subsRef.current.delete(fn); };\n },\n getTransform: () => tf.current,\n setTransform,\n animateTransform,\n minActiveScale,\n }), [minActiveScale, setTransform, animateTransform]);\n\n // Stash the viewport API on the DOM node so siblings outside the React\n // context (the Inspector portal) can find it via querySelector.\n React.useEffect(() => {\n const vp = vpRef.current as (HTMLDivElement & { __dcViewport?: DCViewportContext }) | null;\n if (!vp) return;\n vp.__dcViewport = viewportCtx;\n return () => { if (vp.__dcViewport === viewportCtx) delete vp.__dcViewport; };\n }, [viewportCtx]);\n\n React.useEffect(() => {\n const vp = vpRef.current;\n if (!vp) return;\n\n const zoomAt = (cx: number, cy: number, factor: number) => {\n const r = vp.getBoundingClientRect();\n const px = cx - r.left, py = cy - r.top;\n const t = tf.current;\n const next = Math.min(maxScale, Math.max(minScale, t.scale * factor));\n const k = next / t.scale;\n // keep the world point under the cursor fixed\n t.x = px - (px - t.x) * k;\n t.y = py - (py - t.y) * k;\n t.scale = next;\n apply();\n };\n\n // Tag the viewport with [data-dc-interacting] whenever a pan/zoom is in\n // flight (drag, native gesture, or a recent wheel). The Inspector reads\n // this to suppress its hover-preview state updates during interaction —\n // without it, mousemoves fire ~60×/sec, each one re-renders the panel,\n // and the renders queue faster than they finish.\n const interacting = { drag: false, gesture: false };\n let wheelTimer: ReturnType<typeof setTimeout> | null = null;\n const syncInteractingAttr = () => {\n const active = interacting.drag || interacting.gesture || wheelTimer !== null;\n if (active) vp.setAttribute('data-dc-interacting', 'true');\n else vp.removeAttribute('data-dc-interacting');\n };\n const pulseWheelInteracting = () => {\n if (wheelTimer) clearTimeout(wheelTimer);\n wheelTimer = setTimeout(() => { wheelTimer = null; syncInteractingAttr(); }, 150);\n syncInteractingAttr();\n };\n\n // Mouse-wheel vs trackpad-scroll heuristic. A physical wheel sends\n // line-mode deltas (Firefox) or large integer pixel deltas with no X\n // component (Chrome/Safari, typically multiples of 100/120). Trackpad\n // two-finger scroll sends small/fractional pixel deltas, often with\n // non-zero deltaX. ctrlKey is set by the browser for trackpad pinch.\n const isMouseWheel = (e: WheelEvent) =>\n e.deltaMode !== 0 ||\n (e.deltaX === 0 && Number.isInteger(e.deltaY) && Math.abs(e.deltaY) >= 40);\n\n // Opt-in escape hatch: if the wheel originates inside an element marked\n // [data-dc-allow-scroll] and that element can actually scroll in the\n // wheel's direction, let native scroll happen instead of pan/zoom. Pinch\n // (ctrlKey) and notched mouse wheel still zoom the canvas as before.\n const canNativelyScroll = (e: WheelEvent) => {\n if (e.ctrlKey || isMouseWheel(e)) return false;\n const target = e.target as Element | null;\n if (!target || !target.closest) return false;\n let el: Element | null = target.closest('[data-dc-allow-scroll]');\n while (el) {\n const cs = getComputedStyle(el);\n const overY = cs.overflowY;\n const scrollableY =\n (overY === 'auto' || overY === 'scroll') &&\n el.scrollHeight > el.clientHeight;\n if (scrollableY) {\n const dy = e.deltaY;\n const atTop = el.scrollTop <= 0 && dy < 0;\n const atBottom =\n el.scrollTop + el.clientHeight >= el.scrollHeight - 1 && dy > 0;\n if (!atTop && !atBottom) return true;\n }\n el = el.parentElement\n ? el.parentElement.closest('[data-dc-allow-scroll]')\n : null;\n }\n return false;\n };\n\n // Can `el` itself consume this wheel — i.e. is it scroll-able in the\n // wheel's direction and not already pinned at that edge?\n const isScrollableInDir = (el: Element | null, e: WheelEvent) => {\n if (!el || el === vp || !el.getBoundingClientRect) return false;\n const cs = getComputedStyle(el);\n const dy = e.deltaY, dx = e.deltaX;\n if (dy !== 0 && (cs.overflowY === 'auto' || cs.overflowY === 'scroll') && el.scrollHeight > el.clientHeight) {\n const atTop = el.scrollTop <= 0 && dy < 0;\n const atBottom = el.scrollTop + el.clientHeight >= el.scrollHeight - 1 && dy > 0;\n if (!atTop && !atBottom) return true;\n }\n if (dx !== 0 && (cs.overflowX === 'auto' || cs.overflowX === 'scroll') && el.scrollWidth > el.clientWidth) {\n const atLeft = el.scrollLeft <= 0 && dx < 0;\n const atRight = el.scrollLeft + el.clientWidth >= el.scrollWidth - 1 && dx > 0;\n if (!atLeft && !atRight) return true;\n }\n return false;\n };\n\n // Would this wheel be consumed by something INSIDE `root` (the engaged\n // artboard) under the cursor — a nested canvas, or a scrollable element\n // with room to move? Walks target→root. If yes, the canvas yields.\n const wheelConsumableWithin = (root: HTMLElement, e: WheelEvent) => {\n let el = e.target as Element | null;\n while (el && el.nodeType === 1) {\n if (el.matches && el.matches('[data-dc-viewport]') && el !== vp) return true; // a nested canvas\n if (el !== root && isScrollableInDir(el, e)) return true;\n if (el === root) break;\n el = el.parentElement;\n }\n return false;\n };\n\n const onWheel = (e: WheelEvent) => {\n if (canNativelyScroll(e)) return; // marked chrome ([data-dc-allow-scroll]) keeps its scroll\n // Engagement routing: if the user has clicked into an artboard with\n // scrollable/zoomable content and this wheel lands on something there\n // that can consume it, let the artboard have it (capture phase means we\n // run before any nested handler, so returning lets the event flow down).\n const eng = engagedRef.current;\n if (eng && eng.isConnected && eng.contains(e.target as Node) && wheelConsumableWithin(eng, e)) return;\n // Otherwise the canvas owns the wheel. stopPropagation so a nested canvas\n // (or any inner wheel handler) can't ALSO act on the same tick.\n e.preventDefault();\n e.stopPropagation();\n if (isGesturing) return; // Safari: gesture* owns the pinch — discard concurrent wheels\n if (e.ctrlKey) {\n // trackpad pinch (or explicit ctrl+wheel)\n zoomAt(e.clientX, e.clientY, Math.exp(-e.deltaY * 0.01));\n } else if (isMouseWheel(e)) {\n // notched mouse wheel — fixed-ratio step per click\n zoomAt(e.clientX, e.clientY, Math.exp(-Math.sign(e.deltaY) * 0.18));\n } else {\n // trackpad two-finger scroll — pan\n tf.current.x -= e.deltaX;\n tf.current.y -= e.deltaY;\n apply();\n }\n pulseWheelInteracting();\n };\n\n // Safari sends native gesture* events for trackpad pinch with a smooth\n // e.scale; preferring these over the ctrl+wheel fallback gives a much\n // better feel there. No-ops on other browsers. Safari also fires\n // ctrlKey wheel events during the same pinch — isGesturing makes\n // onWheel drop those entirely so they neither zoom nor pan.\n let gsBase = 1;\n let isGesturing = false;\n // Safari-only gesture events aren't in the standard DOM lib; model the\n // fields we read (scale + client coords) structurally.\n type GestureEvt = Event & { scale: number; clientX: number; clientY: number };\n const onGestureStart = (e: Event) => {\n e.preventDefault();\n isGesturing = true;\n gsBase = tf.current.scale;\n interacting.gesture = true;\n syncInteractingAttr();\n };\n const onGestureChange = (e: Event) => {\n e.preventDefault();\n const g = e as GestureEvt;\n zoomAt(g.clientX, g.clientY, (gsBase * g.scale) / tf.current.scale);\n };\n const onGestureEnd = (e: Event) => {\n e.preventDefault();\n isGesturing = false;\n interacting.gesture = false;\n syncInteractingAttr();\n };\n\n // Drag-pan: middle button anywhere, or primary button on canvas\n // background (anything that isn't an artboard or an inline editor).\n let drag: { id: number; lx: number; ly: number } | null = null;\n const onPointerDown = (e: PointerEvent) => {\n const onBg = !(e.target as Element).closest('[data-dc-slot], .dc-editable');\n if (!(e.button === 1 || (e.button === 0 && onBg))) return;\n e.preventDefault();\n vp.setPointerCapture(e.pointerId);\n drag = { id: e.pointerId, lx: e.clientX, ly: e.clientY };\n vp.style.cursor = 'grabbing';\n interacting.drag = true;\n syncInteractingAttr();\n };\n const onPointerMove = (e: PointerEvent) => {\n if (!drag || e.pointerId !== drag.id) return;\n tf.current.x += e.clientX - drag.lx;\n tf.current.y += e.clientY - drag.ly;\n drag.lx = e.clientX; drag.ly = e.clientY;\n apply();\n };\n const onPointerUp = (e: PointerEvent) => {\n if (!drag || e.pointerId !== drag.id) return;\n vp.releasePointerCapture(e.pointerId);\n drag = null;\n vp.style.cursor = '';\n interacting.drag = false;\n syncInteractingAttr();\n };\n\n // Engagement tracking. A click into an artboard that has scroll/zoom\n // content engages it (it then owns the wheel — see onWheel); a click on the\n // background or a non-scrollable tile releases. Runs in the CAPTURE phase so\n // it sees the click even though composed artboards let the click pass\n // through to the prototype underneath (zero-click interaction is preserved —\n // we never preventDefault here).\n const slotConsumable = (slot: HTMLElement | null) => {\n if (!slot) return false;\n if (slot.querySelector('[data-dc-viewport]')) return true; // a nested canvas\n for (const el of Array.from(slot.querySelectorAll('*'))) {\n // Cheap layout reads gate the expensive getComputedStyle: an element\n // that doesn't overflow can never be scroll-consumable, so skip the\n // style read entirely (the common case for most nodes in a subtree).\n const overflowsY = el.scrollHeight > el.clientHeight;\n const overflowsX = el.scrollWidth > el.clientWidth;\n if (!overflowsY && !overflowsX) continue;\n const cs = getComputedStyle(el);\n if (overflowsY && (cs.overflowY === 'auto' || cs.overflowY === 'scroll')) return true;\n if (overflowsX && (cs.overflowX === 'auto' || cs.overflowX === 'scroll')) return true;\n }\n return false;\n };\n const setEngaged = (slot: HTMLElement | null) => {\n const next = slot && slotConsumable(slot) ? slot : null;\n if (next === engagedRef.current) return;\n if (engagedRef.current) engagedRef.current.removeAttribute('data-dc-engaged');\n engagedRef.current = next;\n if (next) next.setAttribute('data-dc-engaged', '');\n };\n // The artboard slot belonging to THIS canvas under `target` — the slot whose\n // nearest [data-dc-viewport] ancestor is our own vp. (A plain closest() would\n // return a nested canvas's inner artboard when clicking a canvas-in-an-\n // artboard; we want the outer tile this canvas owns.)\n const slotForThisCanvas = (target: EventTarget | null) => {\n let el = target as Element | null;\n while (el && el !== vp && el.nodeType === 1) {\n if (el.matches && el.matches('[data-dc-slot]')) {\n const parent: Element | null = el.parentElement;\n const nearestVp: Element | null = parent && parent.closest ? parent.closest('[data-dc-viewport]') : null;\n if (nearestVp === vp) return el as HTMLElement;\n }\n el = el.parentElement;\n }\n return null;\n };\n const onEngageDown = (e: PointerEvent) => {\n setEngaged(slotForThisCanvas(e.target));\n };\n\n vp.addEventListener('wheel', onWheel, { passive: false, capture: true });\n vp.addEventListener('pointerdown', onEngageDown, true);\n vp.addEventListener('gesturestart', onGestureStart, { passive: false });\n vp.addEventListener('gesturechange', onGestureChange, { passive: false });\n vp.addEventListener('gestureend', onGestureEnd, { passive: false });\n vp.addEventListener('pointerdown', onPointerDown);\n vp.addEventListener('pointermove', onPointerMove);\n vp.addEventListener('pointerup', onPointerUp);\n vp.addEventListener('pointercancel', onPointerUp);\n return () => {\n vp.removeEventListener('wheel', onWheel, { capture: true });\n vp.removeEventListener('pointerdown', onEngageDown, true);\n vp.removeEventListener('gesturestart', onGestureStart);\n vp.removeEventListener('gesturechange', onGestureChange);\n vp.removeEventListener('gestureend', onGestureEnd);\n vp.removeEventListener('pointerdown', onPointerDown);\n vp.removeEventListener('pointermove', onPointerMove);\n vp.removeEventListener('pointerup', onPointerUp);\n vp.removeEventListener('pointercancel', onPointerUp);\n if (engagedRef.current) { engagedRef.current.removeAttribute('data-dc-engaged'); engagedRef.current = null; }\n if (wheelTimer) { clearTimeout(wheelTimer); wheelTimer = null; }\n vp.removeAttribute('data-dc-interacting');\n };\n }, [apply, minScale, maxScale]);\n\n // A field of small \"+\" marks — one centered in each 80px cell.\n const gridSvg = `url(\"data:image/svg+xml,%3Csvg width='80' height='80' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M37 40h6M40 37v6' fill='none' stroke='${encodeURIComponent(DC.grid)}' stroke-width='0.75'/%3E%3C/svg%3E\")`;\n return (\n <div\n ref={vpRef}\n className=\"design-canvas\"\n data-dc-viewport\n /* The shared interaction mode, readable from the DOM — live route tiles\n (in-app canvas mode) observe this attribute to decide whether their\n event-catching overlay must be present (comment/dev) or whether the\n frame may be interacted with directly (cursor). */\n data-dc-mode={mode}\n style={{\n height: '100vh', width: '100vw',\n background: DC.bg,\n overflow: 'hidden',\n overscrollBehavior: 'none',\n touchAction: 'none',\n position: 'relative',\n fontFamily: DC.font,\n boxSizing: 'border-box',\n ...style,\n }}\n >\n <div\n ref={worldRef}\n style={{\n position: 'absolute', top: 0, left: 0,\n transformOrigin: '0 0',\n willChange: 'transform',\n width: 'max-content', minWidth: '100%',\n minHeight: '100%',\n padding: '60px 0 80px',\n }}\n >\n <div style={{ position: 'absolute', inset: -6000, backgroundImage: gridSvg, backgroundSize: '80px 80px', pointerEvents: 'none', zIndex: -1 }} />\n <DCViewportCtx.Provider value={viewportCtx}>{children}</DCViewportCtx.Provider>\n </div>\n </div>\n );\n}\n\nexport interface DCSectionProps {\n id?: string;\n title: string;\n subtitle?: string;\n children?: ReactNode;\n gap?: number;\n}\n// ─────────────────────────────────────────────────────────────\n// DCSection — editable title + h-row of artboards in persisted order\n// ─────────────────────────────────────────────────────────────\nexport function DCSection({ id, title, subtitle, children, gap = 48 }: DCSectionProps): ReactElement {\n const ctx = React.useContext(DCCtx);\n const sid = id ?? title;\n const all = React.Children.toArray(children);\n const artboards = all.filter(\n (c): c is ReactElement<DCArtboardProps> => React.isValidElement(c) && c.type === DCArtboard,\n );\n const rest = all.filter((c) => !(React.isValidElement(c) && c.type === DCArtboard));\n const srcOrder = artboards.map((a) => a.props.id ?? a.props.label);\n const sec: SectionState = (ctx && sid ? ctx.section(sid) : undefined) || {};\n\n const order = React.useMemo(() => {\n const kept = (sec.order || []).filter((k) => srcOrder.includes(k));\n return [...kept, ...srcOrder.filter((k) => !kept.includes(k))];\n }, [sec.order, srcOrder.join('|')]);\n\n const byId = Object.fromEntries(\n artboards.map((a): [string, ReactElement<DCArtboardProps>] => [a.props.id ?? a.props.label, a]),\n );\n\n return (\n <div data-dc-section={sid} style={{ marginBottom: 80, position: 'relative' }}>\n <div style={{ padding: '0 60px 56px' }}>\n {/* Section/row title is display-only — not user-editable. The title\n still reflects programmatic renames (ctx.patchSection), so an AI\n agent can rename a row; users just can't click/edit it inline. */}\n <div style={{ fontSize: 28, fontWeight: 600, color: DC.title, letterSpacing: -0.4, marginBottom: 6, display: 'inline-block' }}>\n {sec.title ?? title}\n </div>\n {subtitle && <div style={{ fontSize: 16, color: DC.subtitle }}>{subtitle}</div>}\n </div>\n <div style={{ display: 'flex', gap, padding: '0 60px', alignItems: 'flex-start', width: 'max-content' }}>\n {order.map((k) => (\n <DCArtboardFrame key={k} sectionId={sid} artboard={byId[k]}\n label={(sec.labels || {})[k] ?? byId[k].props.label}\n selected={!!ctx && ctx.state.selected === `${sid}/${k}`}\n onSelect={() => { if (ctx) ctx.setSelected(`${sid}/${k}`); }}\n activePageId={ctx ? ctx.activePageId : null}\n onRename={(v) => { if (ctx) ctx.patchSection(sid, (x) => ({ labels: { ...x.labels, [k]: v } })); }}\n onFocus={() => { if (ctx) ctx.setFocus(`${sid}/${k}`); }} />\n ))}\n </div>\n {rest}\n </div>\n );\n}\n\nexport interface DCArtboardProps {\n id?: string;\n label: string;\n width?: number;\n height?: number;\n style?: CSSProperties;\n /**\n * Make the artboard card a containing block for `position:fixed` descendants\n * (adds `contain:layout`), so a host app's fixed portals — modals, drawer\n * sheets, menus — clip to the tile instead of escaping to the transformed\n * canvas. Used by composed live artboards (wave 10). Off by default.\n */\n contain?: boolean;\n children?: ReactNode;\n}\n// DCArtboard — marker; rendered by DCArtboardFrame via DCSection.\nexport function DCArtboard(_props: DCArtboardProps): ReactElement | null { return null; }\n\nfunction DCArtboardFrame({ sectionId: _sectionId, artboard, label, selected, onSelect, activePageId, onRename, onFocus }: {\n sectionId: string;\n artboard: ReactElement<DCArtboardProps>;\n label: string;\n selected: boolean;\n onSelect: () => void;\n activePageId: string | null;\n onRename: (v: string) => void;\n onFocus: () => void;\n}) {\n const { id: rawId, label: rawLabel, width = 260, height = 480, children, style = {}, contain = false } = artboard.props;\n const id = rawId ?? rawLabel;\n const ref = React.useRef<HTMLDivElement | null>(null);\n\n // Pause heavy content (videos etc.) when this artboard is offscreen or zoomed\n // out beyond minActiveScale. Recomputes on every transform tick + window\n // resize, but only re-renders when the boolean flips.\n const viewport = React.useContext(DCViewportCtx);\n const [active, setActive] = React.useState(true);\n React.useEffect(() => {\n if (!viewport) return;\n let last = true;\n const check = (t: DCTransform) => {\n const el = ref.current;\n if (!el) return;\n const tooSmall = t.scale < viewport.minActiveScale;\n // 400px margin so artboards re-mount slightly before they scroll in,\n // hiding the mount-time flash of any heavy content.\n const r = el.getBoundingClientRect();\n const m = 400;\n const inView =\n r.right > -m && r.left < window.innerWidth + m &&\n r.bottom > -m && r.top < window.innerHeight + m;\n const next = inView && !tooSmall;\n if (next !== last) { last = next; setActive(next); }\n };\n const unsub = viewport.subscribe(check);\n const onResize = () => check(viewport.getTransform());\n window.addEventListener('resize', onResize);\n return () => { unsub(); window.removeEventListener('resize', onResize); };\n }, [viewport]);\n\n // Single click on the label selects the artboard (ring + share popover);\n // double click renames; the hover expand button still opens focus mode.\n const [editing, setEditing] = React.useState(false);\n const labelRef = React.useRef<HTMLSpanElement | null>(null);\n const startRename = () => {\n setEditing(true);\n requestAnimationFrame(() => {\n const el = labelRef.current;\n if (!el) return;\n el.focus();\n const range = document.createRange();\n range.selectNodeContents(el);\n const sel = window.getSelection();\n sel?.removeAllRanges();\n sel?.addRange(range);\n });\n };\n const commitRename = () => {\n setEditing(false);\n if (labelRef.current) onRename(labelRef.current.textContent ?? '');\n };\n\n // Share link: current URL with `?artboard=<id>` (+ the active page when\n // paged), minus any `?pin=` — the artboard twin of a comment permalink.\n const [copied, setCopied] = React.useState(false);\n const copyShareLink = () => {\n const url = new URL(window.location.href);\n url.searchParams.delete('pin');\n if (activePageId) url.searchParams.set('page', activePageId);\n url.searchParams.set('artboard', id);\n navigator.clipboard?.writeText(url.toString());\n setCopied(true);\n setTimeout(() => setCopied(false), 1500);\n };\n React.useEffect(() => { if (!selected) setCopied(false); }, [selected]);\n\n return (\n <div ref={ref} data-dc-slot={id} style={{ position: 'relative', flexShrink: 0 }}>\n <div className=\"dc-labelrow\" style={{ position: 'absolute', bottom: '100%', left: -4, marginBottom: 4, color: DC.label }}>\n <div className={`dc-labeltext${selected ? ' dc-selected' : ''}`}\n onClick={() => !editing && onSelect()} onDoubleClick={startRename}\n title={editing ? undefined : 'Click to select · double-click to rename'}>\n <span ref={labelRef} className=\"dc-editable\" contentEditable={editing} suppressContentEditableWarning\n onPointerDown={(e) => { if (editing) e.stopPropagation(); }}\n onBlur={() => editing && commitRename()}\n onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); e.currentTarget.blur(); } }}\n style={{ fontSize: 15, fontWeight: 500, color: selected ? '#9aa6bb' : DC.label, lineHeight: 1, cursor: editing ? 'text' : 'pointer' }}>\n {label}\n </span>\n </div>\n </div>\n {selected && (\n <div className=\"dc-share-pop\" onPointerDown={(e) => e.stopPropagation()}>\n <button onClick={copyShareLink}>\n {copied ? (\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" stroke=\"#7ed3a0\" strokeWidth=\"1.8\" strokeLinecap=\"round\" strokeLinejoin=\"round\"><path d=\"M2 6.5L4.8 9.2 10 3.5\"/></svg>\n ) : (\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.4\" strokeLinecap=\"round\"><path d=\"M5 7a2.4 2.4 0 0 0 3.4.2l1.8-1.8a2.4 2.4 0 0 0-3.4-3.4l-1 1\"/><path d=\"M7 5a2.4 2.4 0 0 0-3.4-.2L1.8 6.6A2.4 2.4 0 0 0 5.2 10l1-1\"/></svg>\n )}\n {copied ? 'Link copied' : 'Copy link to artboard'}\n </button>\n </div>\n )}\n <button className=\"dc-expand\" onClick={onFocus} onPointerDown={(e) => e.stopPropagation()} title=\"Focus\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.6\" strokeLinecap=\"round\"><path d=\"M7 1h4v4M5 11H1V7M11 1L7.5 4.5M1 11l3.5-3.5\"/></svg>\n </button>\n <div className=\"dc-card\"\n // `contain` (wave 10, composed artboards): `contain:layout` makes the\n // card a containing block for position:fixed descendants, so the host\n // app's fixed portals (modals, drawer sheets, menus) clip to the tile\n // instead of escaping to the transformed canvas — no per-project hack\n // (the built-in upgrade over RC's per-kit data-vt-window). `overflow:\n // hidden` (always on) does the actual clipping. Harmless on iframe/\n // snapshot tiles, so it's just a prop, not a mode.\n data-vt-window={contain ? '' : undefined}\n style={{ borderRadius: 2, boxShadow: '0 1px 3px rgba(0,0,0,.08),0 4px 16px rgba(0,0,0,.06)', overflow: 'hidden', width, height, background: '#fff', ...(contain ? { contain: 'layout' } : {}), ...style,\n ...(selected ? { outline: '2px solid #9aa6bb', outlineOffset: 2 } : null) }}>\n <DCArtboardActiveCtx.Provider value={active}>\n {children || <div style={{ height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#bbb', fontSize: 13, fontFamily: DC.font }}>{id}</div>}\n </DCArtboardActiveCtx.Provider>\n </div>\n </div>\n );\n}\n\n// ─────────────────────────────────────────────────────────────\n// Focus mode — overlay one artboard; ←/→ within section, ↑/↓ across\n// sections, Esc or backdrop click to exit.\n// ─────────────────────────────────────────────────────────────\nfunction DCFocusOverlay({ entry, sectionMeta, sectionOrder }: {\n entry: RegistryEntry;\n sectionMeta: Record<string, { title?: string; subtitle?: string; slotIds: string[] }>;\n sectionOrder: string[];\n}) {\n // Always rendered inside DCCtx.Provider, so the context is non-null.\n const ctx = React.useContext(DCCtx)!;\n const { sectionId, artboard } = entry;\n const sec = ctx.section(sectionId);\n const meta = sectionMeta[sectionId];\n const peers = meta.slotIds;\n const aid = artboard.props.id ?? artboard.props.label;\n const idx = peers.indexOf(aid);\n const secIdx = sectionOrder.indexOf(sectionId);\n\n const go = (d: number) => { const n = peers[(idx + d + peers.length) % peers.length]; if (n) ctx.setFocus(`${sectionId}/${n}`); };\n const goSection = (d: number) => {\n const ns = sectionOrder[(secIdx + d + sectionOrder.length) % sectionOrder.length];\n const first = sectionMeta[ns] && sectionMeta[ns].slotIds[0];\n if (first) ctx.setFocus(`${ns}/${first}`);\n };\n\n React.useEffect(() => {\n const k = (e: KeyboardEvent) => {\n if (e.key === 'ArrowLeft') { e.preventDefault(); go(-1); }\n if (e.key === 'ArrowRight') { e.preventDefault(); go(1); }\n if (e.key === 'ArrowUp') { e.preventDefault(); goSection(-1); }\n if (e.key === 'ArrowDown') { e.preventDefault(); goSection(1); }\n };\n document.addEventListener('keydown', k);\n return () => document.removeEventListener('keydown', k);\n });\n\n const { width = 260, height = 480, children } = artboard.props;\n const [vp, setVp] = React.useState({ w: window.innerWidth, h: window.innerHeight });\n React.useEffect(() => { const r = () => setVp({ w: window.innerWidth, h: window.innerHeight }); window.addEventListener('resize', r); return () => window.removeEventListener('resize', r); }, []);\n const scale = Math.max(0.1, Math.min((vp.w - 200) / width, (vp.h - 260) / height, 2));\n\n const [ddOpen, setDd] = React.useState(false);\n const Arrow = ({ dir, onClick }: { dir: 'left' | 'right'; onClick: () => void }) => (\n <button onClick={(e) => { e.stopPropagation(); onClick(); }}\n style={{ position: 'absolute', top: '50%', [dir]: 28, transform: 'translateY(-50%)',\n border: 'none', background: 'rgba(255,255,255,.08)', color: 'rgba(255,255,255,.9)',\n width: 44, height: 44, borderRadius: 22, fontSize: 18, cursor: 'pointer',\n display: 'flex', alignItems: 'center', justifyContent: 'center', transition: 'background .15s' } as CSSProperties}\n onMouseEnter={(e) => (e.currentTarget.style.background = 'rgba(255,255,255,.18)')}\n onMouseLeave={(e) => (e.currentTarget.style.background = 'rgba(255,255,255,.08)')}>\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 18 18\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\">\n <path d={dir === 'left' ? 'M11 3L5 9l6 6' : 'M7 3l6 6-6 6'} /></svg>\n </button>\n );\n\n // Portal to body so position:fixed is the real viewport regardless of any\n // transform on DesignCanvas's ancestors (including the canvas zoom itself).\n return createPortal(\n <div onClick={() => ctx.setFocus(null)}\n onWheel={(e) => e.preventDefault()}\n style={{ position: 'fixed', inset: 0, zIndex: 100, background: 'rgba(24,25,27,.6)', backdropFilter: 'blur(14px)',\n fontFamily: DC.font, color: '#fff' }}>\n\n {/* top bar: section dropdown (left) · close (right) */}\n <div onClick={(e) => e.stopPropagation()}\n style={{ position: 'absolute', top: 0, left: 0, right: 0, height: 72, display: 'flex', alignItems: 'flex-start', padding: '16px 20px 0', gap: 16 }}>\n <div style={{ position: 'relative' }}>\n <button onClick={() => setDd((o) => !o)}\n style={{ border: 'none', background: 'transparent', color: '#fff', cursor: 'pointer', padding: '6px 8px',\n borderRadius: 6, textAlign: 'left', fontFamily: 'inherit' }}>\n <span style={{ display: 'flex', alignItems: 'center', gap: 8 }}>\n <span style={{ fontSize: 18, fontWeight: 600, letterSpacing: -0.3 }}>{meta.title}</span>\n <svg width=\"11\" height=\"11\" viewBox=\"0 0 11 11\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.8\" strokeLinecap=\"round\" style={{ opacity: .7 }}><path d=\"M2 4l3.5 3.5L9 4\"/></svg>\n </span>\n {meta.subtitle && <span style={{ display: 'block', fontSize: 13, opacity: .6, fontWeight: 400, marginTop: 2 }}>{meta.subtitle}</span>}\n </button>\n {ddOpen && (\n <div style={{ position: 'absolute', top: '100%', left: 0, marginTop: 4, background: '#202123', borderRadius: 8,\n boxShadow: '0 8px 32px rgba(0,0,0,.4)', padding: 4, minWidth: 200, zIndex: 10 }}>\n {sectionOrder.map((sid) => (\n <button key={sid} onClick={() => { setDd(false); const f = sectionMeta[sid].slotIds[0]; if (f) ctx.setFocus(`${sid}/${f}`); }}\n style={{ display: 'block', width: '100%', textAlign: 'left', border: 'none', cursor: 'pointer',\n background: sid === sectionId ? 'rgba(255,255,255,.1)' : 'transparent', color: '#fff',\n padding: '8px 12px', borderRadius: 5, fontSize: 14, fontWeight: sid === sectionId ? 600 : 400, fontFamily: 'inherit' }}>\n {sectionMeta[sid].title}\n </button>\n ))}\n </div>\n )}\n </div>\n <div style={{ flex: 1 }} />\n <button onClick={() => ctx.setFocus(null)}\n onMouseEnter={(e) => (e.currentTarget.style.background = 'rgba(255,255,255,.12)')}\n onMouseLeave={(e) => (e.currentTarget.style.background = 'transparent')}\n style={{ border: 'none', background: 'transparent', color: 'rgba(255,255,255,.7)', width: 32, height: 32,\n borderRadius: 16, fontSize: 20, cursor: 'pointer', lineHeight: 1, transition: 'background .12s' }}>×</button>\n </div>\n\n {/* card centered, label + index below — only the card itself stops\n propagation so any backdrop click (including the margins around\n the card) exits focus */}\n <div\n style={{ position: 'absolute', top: 64, bottom: 56, left: 100, right: 100, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 16 }}>\n <div onClick={(e) => e.stopPropagation()} style={{ width: width * scale, height: height * scale, position: 'relative' }}>\n <div style={{ width, height, transform: `scale(${scale})`, transformOrigin: 'top left', background: '#fff', borderRadius: 2, overflow: 'hidden',\n boxShadow: '0 20px 80px rgba(0,0,0,.4)' }}>\n {children || <div style={{ height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#bbb' }}>{aid}</div>}\n </div>\n </div>\n <div onClick={(e) => e.stopPropagation()} style={{ fontSize: 14, fontWeight: 500, opacity: .85, textAlign: 'center' }}>\n {(sec.labels || {})[aid] ?? artboard.props.label}\n <span style={{ opacity: .5, marginLeft: 10, fontVariantNumeric: 'tabular-nums' }}>{idx + 1} / {peers.length}</span>\n </div>\n </div>\n\n <Arrow dir=\"left\" onClick={() => go(-1)} />\n <Arrow dir=\"right\" onClick={() => go(1)} />\n\n {/* dots */}\n <div onClick={(e) => e.stopPropagation()}\n style={{ position: 'absolute', bottom: 20, left: '50%', transform: 'translateX(-50%)', display: 'flex', gap: 8 }}>\n {peers.map((p, i) => (\n <button key={p} onClick={() => ctx.setFocus(`${sectionId}/${p}`)}\n style={{ border: 'none', padding: 0, cursor: 'pointer', width: 6, height: 6, borderRadius: 3,\n background: i === idx ? '#fff' : 'rgba(255,255,255,.3)' }} />\n ))}\n </div>\n </div>,\n getPortalRoot(),\n );\n}\n\nexport interface DCPostItProps {\n children?: ReactNode;\n top?: number | string;\n left?: number | string;\n right?: number | string;\n bottom?: number | string;\n rotate?: number;\n width?: number;\n}\n// ─────────────────────────────────────────────────────────────\n// Post-it — absolute-positioned sticky note\n// ─────────────────────────────────────────────────────────────\nexport function DCPostIt({ children, top, left, right, bottom, rotate = -2, width = 180 }: DCPostItProps): ReactElement {\n return (\n <div style={{\n position: 'absolute', top, left, right, bottom, width,\n background: DC.postitBg, padding: '14px 16px',\n fontFamily: '\"Comic Sans MS\", \"Marker Felt\", \"Segoe Print\", cursive',\n fontSize: 14, lineHeight: 1.4, color: DC.postitText,\n boxShadow: '0 2px 8px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.08)',\n transform: `rotate(${rotate}deg)`,\n zIndex: 5,\n }}>{children}</div>\n );\n}\n"],"names":["FONT","data","_a"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "carboncanvas",
3
+ "version": "0.1.0",
4
+ "description": "Carbon Canvas — a JSX spatial review canvas + click-to-inspect Inspector, with a design-system adapter seam. The free, open client for the Carbon Canvas comments/realtime backend.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "author": "Alex Roitch",
8
+ "homepage": "https://carboncanvas.design",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/rollsroych/quilt.git",
12
+ "directory": "packaging"
13
+ },
14
+ "bugs": {
15
+ "url": "https://github.com/rollsroych/quilt/issues"
16
+ },
17
+ "sideEffects": false,
18
+ "main": "./index.js",
19
+ "module": "./index.js",
20
+ "types": "./index.d.ts",
21
+ "exports": {
22
+ ".": {
23
+ "types": "./index.d.ts",
24
+ "import": "./index.js"
25
+ },
26
+ "./vite": {
27
+ "types": "./vite.d.ts",
28
+ "default": "./vite.js"
29
+ },
30
+ "./babel-plugin-data-anchor": {
31
+ "types": "./tools/babel-plugin-data-anchor.d.ts",
32
+ "default": "./tools/babel-plugin-data-anchor.js"
33
+ },
34
+ "./package.json": "./package.json"
35
+ },
36
+ "files": [
37
+ "*.js",
38
+ "*.js.map",
39
+ "index.d.ts",
40
+ "vite.js",
41
+ "vite.d.ts",
42
+ "tools/babel-plugin-data-anchor.js",
43
+ "tools/babel-plugin-data-anchor.d.ts",
44
+ "README.md",
45
+ "LICENSE"
46
+ ],
47
+ "peerDependencies": {
48
+ "react": "^18 || ^19",
49
+ "react-dom": "^18 || ^19"
50
+ },
51
+ "keywords": [
52
+ "react",
53
+ "canvas",
54
+ "design-review",
55
+ "inspector",
56
+ "comments",
57
+ "prototype"
58
+ ],
59
+ "engines": {
60
+ "node": ">=18"
61
+ },
62
+ "publishConfig": {
63
+ "access": "public"
64
+ }
65
+ }
@@ -0,0 +1,6 @@
1
+ // Type stub for the data-anchor Babel plugin (shipped in the `carboncanvas`
2
+ // tarball as the `carboncanvas/babel-plugin-data-anchor` subpath export). The
3
+ // plugin itself is plain JS; this declaration keeps consumer vite.config.ts /
4
+ // babel configs from erroring with TS7016 ("could not find a declaration file").
5
+ declare const plugin: (babel: any) => any;
6
+ export default plugin;
@@ -0,0 +1,64 @@
1
+ import path from 'path';
2
+
3
+ // Babel plugin: stamp `data-anchor="<relPath>:<line>:<col>"` on every JSX *host*
4
+ // element (lowercase intrinsic tags like <div>, <button>), at build time.
5
+ //
6
+ // Why build-time + deterministic-from-source (not a runtime random id): our
7
+ // prototypes evolve by editing JSX, which is React unmount/remount — a runtime
8
+ // id is regenerated on every mount and dies on the exact edit it's meant to
9
+ // survive. A source-derived attribute is identical render-to-render, so it
10
+ // survives re-render/HMR; it only shifts when the element moves file/line.
11
+ //
12
+ // The coordinate intentionally mirrors what @babel/plugin-transform-react-jsx-source
13
+ // writes into the fiber's `_debugSource` (line, column+1), so the DOM attribute
14
+ // and the fiber's source location are the SAME join key — usable by CommentLayer
15
+ // pin anchoring, Inspector selection, and the figma-bridge code↔design map.
16
+ //
17
+ // Scope: @vitejs/plugin-react only runs Babel over project source, so node_modules
18
+ // (Spring UI internals) are untouched — consistent with `_debugSource`, which is
19
+ // also absent for compiled library JSX. Component call sites (<Button/>) are not
20
+ // host elements and are skipped; the host DOM they render gets stamped from its
21
+ // own JSX inside the component (when that component is in project source).
22
+
23
+ export default function dataAnchorPlugin({ types: t }) {
24
+ return {
25
+ name: 'data-anchor',
26
+ visitor: {
27
+ JSXOpeningElement(nodePath, state) {
28
+ const nameNode = nodePath.node.name;
29
+
30
+ // Only intrinsic host tags: a plain lowercase JSXIdentifier (`div`,
31
+ // `button`). Uppercase = component, member (`Foo.Bar`) / namespaced
32
+ // (`svg:use`) names aren't DOM hosts → skip.
33
+ if (!t.isJSXIdentifier(nameNode)) return;
34
+ const tag = nameNode.name;
35
+ if (!/^[a-z]/.test(tag)) return;
36
+
37
+ // Idempotent + respect a hand-authored anchor.
38
+ const hasAnchor = nodePath.node.attributes.some(
39
+ (attr) =>
40
+ t.isJSXAttribute(attr) &&
41
+ t.isJSXIdentifier(attr.name) &&
42
+ attr.name.name === 'data-anchor',
43
+ );
44
+ if (hasAnchor) return;
45
+
46
+ const loc = nodePath.node.loc;
47
+ if (!loc) return;
48
+
49
+ const filename = state.file.opts.filename;
50
+ if (!filename) return;
51
+ // Relative to cwd (vite runs from the project dir) → stable, readable,
52
+ // machine-independent: `src/components/Foo.tsx`.
53
+ const relPath = path.relative(process.cwd(), filename).split(path.sep).join('/');
54
+
55
+ // column+1 to match jsx-source's 1-based columnNumber in `_debugSource`.
56
+ const value = `${relPath}:${loc.start.line}:${loc.start.column + 1}`;
57
+
58
+ nodePath.node.attributes.push(
59
+ t.jsxAttribute(t.jsxIdentifier('data-anchor'), t.stringLiteral(value)),
60
+ );
61
+ },
62
+ },
63
+ };
64
+ }