@loworbitstudio/visor 1.18.0 → 1.18.1
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.
- package/dist/CHANGELOG.json +7 -1
- package/dist/index.js +91 -0
- package/dist/registry.json +27 -2
- package/dist/visor-manifest.json +136 -1
- package/package.json +1 -1
package/dist/CHANGELOG.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": "0.4.0",
|
|
3
|
-
"generated_at": "2026-07-
|
|
3
|
+
"generated_at": "2026-07-15T17:44:38.986Z",
|
|
4
4
|
"components": {
|
|
5
5
|
"accessibility-specimen": {
|
|
6
6
|
"changeType": "current",
|
|
@@ -266,6 +266,12 @@
|
|
|
266
266
|
"breakingChange": false,
|
|
267
267
|
"migrationNote": null
|
|
268
268
|
},
|
|
269
|
+
"fidelity-mirror": {
|
|
270
|
+
"changeType": "current",
|
|
271
|
+
"files": [],
|
|
272
|
+
"breakingChange": false,
|
|
273
|
+
"migrationNote": null
|
|
274
|
+
},
|
|
269
275
|
"field": {
|
|
270
276
|
"changeType": "current",
|
|
271
277
|
"files": [],
|
package/dist/index.js
CHANGED
|
@@ -8205,6 +8205,97 @@ var FIXTURES = {
|
|
|
8205
8205
|
}`
|
|
8206
8206
|
}
|
|
8207
8207
|
},
|
|
8208
|
+
"fidelity-mirror": {
|
|
8209
|
+
default: {
|
|
8210
|
+
export: "FidelityMirror",
|
|
8211
|
+
interactiveTarget: '[data-slot="fidelity-mirror-overlay"]',
|
|
8212
|
+
// Mirrors the approved spec's Example A — the web split DRIFT compare of a
|
|
8213
|
+
// doc-nav cluster (design-left / built-right), so the rendered diff is
|
|
8214
|
+
// meaningful for the render-vs-design self-check. Captures are lightweight
|
|
8215
|
+
// inline nodes (React is in scope in the fixture) — no external assets.
|
|
8216
|
+
props: `(function () {
|
|
8217
|
+
var cluster = function (drift) {
|
|
8218
|
+
return React.createElement(
|
|
8219
|
+
"div",
|
|
8220
|
+
{
|
|
8221
|
+
style: {
|
|
8222
|
+
display: "flex", flexDirection: "column", gap: "10px",
|
|
8223
|
+
fontFamily: "var(--font-sans)",
|
|
8224
|
+
},
|
|
8225
|
+
},
|
|
8226
|
+
React.createElement(
|
|
8227
|
+
"div",
|
|
8228
|
+
{ style: { display: "flex", alignItems: "center", gap: "var(--spacing-2)" } },
|
|
8229
|
+
React.createElement("span", {
|
|
8230
|
+
style: {
|
|
8231
|
+
width: "20px", height: "20px", borderRadius: "6px",
|
|
8232
|
+
display: "grid", placeItems: "center",
|
|
8233
|
+
background: "var(--primary)", color: "var(--color-white)",
|
|
8234
|
+
fontFamily: "var(--font-mono)", fontSize: "10px", fontWeight: 700,
|
|
8235
|
+
},
|
|
8236
|
+
}, "V"),
|
|
8237
|
+
React.createElement("span", {
|
|
8238
|
+
style: { fontFamily: "var(--font-mono)", fontWeight: 700, fontSize: "14px", color: "var(--text-primary)" },
|
|
8239
|
+
}, "Visor")
|
|
8240
|
+
),
|
|
8241
|
+
React.createElement(
|
|
8242
|
+
"div",
|
|
8243
|
+
{
|
|
8244
|
+
style: {
|
|
8245
|
+
display: "inline-flex", flexDirection: "column", gap: "var(--spacing-2)",
|
|
8246
|
+
padding: "var(--spacing-2)",
|
|
8247
|
+
border: "1px solid var(--hairline)",
|
|
8248
|
+
borderRadius: drift ? "22px" : "12px",
|
|
8249
|
+
background: "var(--surface-card)",
|
|
8250
|
+
},
|
|
8251
|
+
},
|
|
8252
|
+
React.createElement("span", {
|
|
8253
|
+
style: {
|
|
8254
|
+
fontFamily: "var(--font-mono)", fontSize: "9px", fontWeight: 700,
|
|
8255
|
+
letterSpacing: drift ? "0" : "0.14em",
|
|
8256
|
+
textTransform: drift ? "none" : "uppercase",
|
|
8257
|
+
color: "var(--text-secondary)",
|
|
8258
|
+
},
|
|
8259
|
+
}, "Shared"),
|
|
8260
|
+
React.createElement(
|
|
8261
|
+
"div",
|
|
8262
|
+
{ style: { display: "flex", gap: "var(--spacing-1)" } },
|
|
8263
|
+
["Overview", "Tokens", "Themes"].map(function (label, i) {
|
|
8264
|
+
return React.createElement("span", {
|
|
8265
|
+
key: label,
|
|
8266
|
+
style: {
|
|
8267
|
+
padding: "5px 9px", borderRadius: "9999px",
|
|
8268
|
+
border: "1px solid transparent",
|
|
8269
|
+
background: drift
|
|
8270
|
+
? "var(--surface-subtle)"
|
|
8271
|
+
: "color-mix(in srgb, var(--surface-card), var(--color-neutral-950) 22%)",
|
|
8272
|
+
fontFamily: "var(--font-mono)", fontSize: "9px", fontWeight: 500,
|
|
8273
|
+
letterSpacing: "0.05em", textTransform: "uppercase",
|
|
8274
|
+
color: "var(--text-secondary)",
|
|
8275
|
+
},
|
|
8276
|
+
}, label)
|
|
8277
|
+
})
|
|
8278
|
+
)
|
|
8279
|
+
)
|
|
8280
|
+
)
|
|
8281
|
+
}
|
|
8282
|
+
return {
|
|
8283
|
+
title: "DocNav",
|
|
8284
|
+
subtitle: "Fidelity Mirror \xB7 VI-611",
|
|
8285
|
+
platform: "web",
|
|
8286
|
+
verdict: "drift",
|
|
8287
|
+
score: "3 deltas",
|
|
8288
|
+
design: { content: cluster(false), meta: "index.html" },
|
|
8289
|
+
built: { content: cluster(true), meta: "route \xB7 /doc-nav" },
|
|
8290
|
+
deltas: [
|
|
8291
|
+
{ class: "radius", description: "Group cluster corners 22px -> 12px.", position: { top: "34px", left: "12px" } },
|
|
8292
|
+
{ class: "color", description: "Resting pills read --surface-subtle.", position: { top: "52px", left: "96px" } },
|
|
8293
|
+
{ class: "type", description: "Group labels are title-case.", position: { top: "34px", right: "12px" } },
|
|
8294
|
+
],
|
|
8295
|
+
}
|
|
8296
|
+
})()`
|
|
8297
|
+
}
|
|
8298
|
+
},
|
|
8208
8299
|
button: {
|
|
8209
8300
|
default: {
|
|
8210
8301
|
export: "Button",
|
package/dist/registry.json
CHANGED
|
@@ -2842,7 +2842,32 @@
|
|
|
2842
2842
|
{
|
|
2843
2843
|
"path": "components/ui/doc-frame/doc-frame.module.css",
|
|
2844
2844
|
"type": "registry:ui",
|
|
2845
|
-
"content": "/* DocFrame — the themed doc-page shell that wraps DocNav.\n *\n * A sticky header (a flexible brand/logo slot + an OVERVIEW home pill + a\n * right-aligned meta slot, then the DocNav slot) above a content wrapper (the\n * doc as children). The header sticks to the page scroll so the brand + nav\n * never leave view. Theme-agnostic: every value references a CSS custom property\n * token, so the shell adopts the active project theme.\n *\n * No ancestor sets overflow: hidden/auto — that would create a scroll container\n * and break the viewport-anchored sticky header.\n */\n\n/* Shell root — a centered, max-width column. */\n.frame {\n /* A tight, controlled glyph radius the frame owns — NOT the theme `--radius-*`\n * scale, which decorative themes inflate far past what a 24px brand chip wants\n * (Strata inflates `--radius-md` to 10px, `--radius-xl` to 32px). Overridable\n * by a consumer/theme via this variable. */\n --doc-frame-glyph-radius: 0.375rem;\n display: flex;\n flex-direction: column;\n min-height: 100%;\n max-width: var(--doc-frame-max-width, 75rem);\n margin-inline: auto;\n background: var(--surface-page, #ffffff);\n color: var(--text-primary, #111827);\n}\n\n/* Sticky chrome — the header row + nav row. The page surface (opaque, so\n * scrolled content never bleeds through) sits below the card-surfaced nav\n * groups + chips, which read lighter on top. Sticks to the nearest scroll\n * ancestor (the page/viewport). */\n.chrome {\n position: sticky;\n top: 0;\n z-index: 10;\n display: flex;\n flex-direction: column;\n background: var(--surface-page, #ffffff);\n border-bottom: var(--stroke-width-thin, 1px) solid\n var(--hairline, var(--border-default, #e5e7eb));\n}\n\n/* Header row — brand/logo slot, then the OVERVIEW home pill, a flexible spacer,\n * and the right-aligned meta slot. A hairline rule separates it from the nav. */\n.headerRow {\n display: flex;\n align-items: center;\n gap: var(--spacing-3, 0.75rem) var(--spacing-4, 1rem);\n flex-wrap: wrap;\n padding: var(--spacing-3, 0.75rem) var(--spacing-5, 1.25rem);\n border-bottom: var(--stroke-width-thin, 1px) solid\n var(--hairline, var(--border-default, #e5e7eb));\n}\n\n.brandSlot {\n display: inline-flex;\n align-items: center;\n min-width: 0;\n}\n\n.spacer {\n flex: 1 1 auto;\n}\n\n/* Nav row — holds the DocNav slot. */\n.navRow {\n display: flex;\n min-width: 0;\n padding: var(--spacing-3, 0.75rem) var(--spacing-5, 1.25rem);\n}\n\n/* Content wrapper — the doc, as children. */\n.content {\n flex: 1 1 auto;\n padding: var(--spacing-6, 1.5rem) var(--spacing-5, 1.25rem)\n var(--spacing-8, 2rem);\n}\n\n/* ─── brand slot ─────────────────────────────────────────────────────────── */\n\n/* Wraps the theme-logo layer + the text wordmark. */\n.brand {\n position: relative;\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n min-width: 0;\n}\n\n/* Text wordmark — the resting/fallback brand (a leading glyph chip + the name).\n * Mode-adaptive via --text-primary. */\n.wordmark {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n font-size: var(--font-size-lg, 1.125rem);\n font-weight: var(--font-weight-bold, 700);\n letter-spacing: -0.01em;\n line-height: 1.1;\n color: var(--text-primary, #111827);\n}\n\n/* Brand glyph — a single-letter mark in the theme's primary brand color, its\n * guaranteed-contrasting on-primary text. A controlled small radius (see\n * `--doc-frame-glyph-radius`), not the ballooning theme radius scale. */\n.glyph {\n display: grid;\n place-items: center;\n flex-shrink: 0;\n width: var(--spacing-6, 1.5rem);\n height: var(--spacing-6, 1.5rem);\n border-radius: var(--doc-frame-glyph-radius, 0.375rem);\n background: var(--primary, #111827);\n color: var(--primary-text, #ffffff);\n font-size: var(--font-size-xs, 0.75rem);\n font-weight: var(--font-weight-bold, 700);\n line-height: 1;\n}\n\n/* Theme-logo layer — the active theme's brand logo SVG (mode-aware via the\n * --brand-logo custom property). Hidden until the client effect confirms the\n * theme ships one AND it loads, so the resting state is always the visible\n * wordmark and a failed load never leaves an empty slot. */\n.themeLogo {\n display: none;\n height: var(--doc-frame-logo-height, var(--spacing-5, 1.25rem));\n /* An explicit min-width keeps a masked/tinted mark from collapsing to a\n * zero-width box on themes that ship no --brand-logo-aspect-ratio. */\n min-width: var(--spacing-8, 2rem);\n aspect-ratio: var(--brand-logo-aspect-ratio, 3 / 1);\n background-image: var(--brand-logo);\n background-repeat: no-repeat;\n background-position: left center;\n background-size: contain;\n}\n\n/* When the theme provides --brand-logo, show the image and drop the wordmark. */\n.brand[data-theme-logo] .themeLogo {\n display: inline-block;\n}\n\n.brand[data-theme-logo] .wordmark {\n display: none;\n}\n\n/* ─── header chrome — home pill + meta ───────────────────────────────────── */\n\n/* OVERVIEW / home pill — a bordered mono chip with a leading compass glyph. */\n.home {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n flex-shrink: 0;\n /* ~6px 12px — a compact chip that clears the mono caps. */\n padding: calc(var(--spacing-1, 0.25rem) * 1.5) var(--spacing-3, 0.75rem);\n border: var(--stroke-width-thin, 1px) solid\n var(--hairline, var(--border-default, #e5e7eb));\n border-radius: var(--radius-full, 9999px);\n background: var(--surface-card, #ffffff);\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: var(--font-size-2xs, 0.6875rem);\n font-weight: var(--font-weight-medium, 500);\n letter-spacing: 0.06em;\n /* Collapse the line box to the glyph height so the all-caps label optically\n * centers against the compass icon. */\n line-height: 1;\n text-transform: uppercase;\n color: var(--text-tertiary, #9ca3af);\n text-decoration: none;\n white-space: nowrap;\n transition: color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease),\n border-color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease);\n}\n\n.home:hover {\n color: var(--text-primary, #111827);\n border-color: var(--hairline-strong, var(--border-default, #d1d5db));\n}\n\n.home:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--border-focus, currentColor);\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n/* Compass glyph — a hair larger than the caps (the design's 13px vs 11px);\n * inherits the pill color via currentColor. */\n.homeIcon {\n flex-shrink: 0;\n width: var(--font-size-sm, 0.875rem);\n height: var(--font-size-sm, 0.875rem);\n}\n\n/* Meta slot — a right-aligned breadcrumb/status line, mono UPPERCASE, tertiary. */\n.meta {\n flex-shrink: 0;\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: var(--font-size-2xs, 0.6875rem);\n font-weight: var(--font-weight-medium, 500);\n letter-spacing: 0.12em;\n line-height: 1;\n text-transform: uppercase;\n color: var(--text-tertiary, #9ca3af);\n white-space: nowrap;\n}\n\n/* ─── mobile ─────────────────────────────────────────────────────────────── */\n\n@media (max-width: 640px) {\n .headerRow {\n padding: var(--spacing-3, 0.75rem) var(--spacing-4, 1rem);\n }\n\n .navRow {\n padding: var(--spacing-3, 0.75rem) var(--spacing-4, 1rem);\n }\n\n .content {\n padding: var(--spacing-5, 1.25rem) var(--spacing-4, 1rem)\n var(--spacing-6, 1.5rem);\n }\n}\n"
|
|
2845
|
+
"content": "/* DocFrame — the themed doc-page shell that wraps DocNav.\n *\n * A sticky header (a flexible brand/logo slot + an OVERVIEW home pill + a\n * right-aligned meta slot, then the DocNav slot) above a content wrapper (the\n * doc as children). The header sticks to the page scroll so the brand + nav\n * never leave view. Theme-agnostic: every value references a CSS custom property\n * token, so the shell adopts the active project theme.\n *\n * No ancestor sets overflow: hidden/auto — that would create a scroll container\n * and break the viewport-anchored sticky header.\n */\n\n/* Shell root — a centered, max-width column. */\n.frame {\n /* A tight, controlled glyph radius the frame owns — NOT the theme `--radius-*`\n * scale, which decorative themes inflate far past what a 24px brand chip wants\n * (Strata inflates `--radius-md` to 10px, `--radius-xl` to 32px). Overridable\n * by a consumer/theme via this variable. */\n --doc-frame-glyph-radius: 0.375rem;\n display: flex;\n flex-direction: column;\n min-height: 100%;\n max-width: var(--doc-frame-max-width, 75rem);\n margin-inline: auto;\n background: var(--surface-page, #ffffff);\n color: var(--text-primary, #111827);\n}\n\n/* Sticky chrome — the header row + nav row. The page surface (opaque, so\n * scrolled content never bleeds through) sits below the card-surfaced nav\n * groups + chips, which read lighter on top. Sticks to the nearest scroll\n * ancestor (the page/viewport). */\n.chrome {\n position: sticky;\n top: 0;\n z-index: 10;\n display: flex;\n flex-direction: column;\n background: var(--surface-page, #ffffff);\n border-bottom: var(--stroke-width-thin, 1px) solid\n var(--hairline, var(--border-default, #e5e7eb));\n}\n\n/* Header row — brand/logo slot, then the OVERVIEW home pill, a flexible spacer,\n * and the right-aligned meta slot. A hairline rule separates it from the nav. */\n.headerRow {\n display: flex;\n align-items: center;\n gap: var(--spacing-3, 0.75rem) var(--spacing-4, 1rem);\n flex-wrap: wrap;\n padding: var(--spacing-3, 0.75rem) var(--spacing-5, 1.25rem);\n border-bottom: var(--stroke-width-thin, 1px) solid\n var(--hairline, var(--border-default, #e5e7eb));\n}\n\n.brandSlot {\n display: inline-flex;\n align-items: center;\n min-width: 0;\n}\n\n.spacer {\n flex: 1 1 auto;\n}\n\n/* Nav row — holds the DocNav slot. */\n.navRow {\n display: flex;\n min-width: 0;\n padding: var(--spacing-3, 0.75rem) var(--spacing-5, 1.25rem);\n}\n\n/* Content wrapper — the doc, as children. */\n.content {\n flex: 1 1 auto;\n padding: var(--spacing-6, 1.5rem) var(--spacing-5, 1.25rem)\n var(--spacing-8, 2rem);\n}\n\n/* ─── brand slot ─────────────────────────────────────────────────────────── */\n\n/* Wraps the theme-logo layer + the text wordmark. */\n.brand {\n position: relative;\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n min-width: 0;\n}\n\n/* Text wordmark — the resting/fallback brand (a leading glyph chip + the name).\n * Mode-adaptive via --text-primary. Set in the theme's display face so a text\n * wordmark carries the theme's brand character (say, Animal's condensed\n * \"Sequel 100 Black 95\" rather than the body \"Ratio\"); degrades to the heading\n * face, then the ambient sans, on themes that ship no --font-display — matching\n * the display-font convention in stat-card / page-header / section-intro. */\n.wordmark {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n font-family: var(--font-display, var(--font-family-heading, inherit));\n font-size: var(--font-size-lg, 1.125rem);\n font-weight: var(--font-weight-bold, 700);\n letter-spacing: -0.01em;\n line-height: 1.1;\n color: var(--text-primary, #111827);\n}\n\n/* Brand glyph — a single-letter mark in the theme's primary brand color, its\n * guaranteed-contrasting on-primary text. A controlled small radius (see\n * `--doc-frame-glyph-radius`), not the ballooning theme radius scale. */\n.glyph {\n display: grid;\n place-items: center;\n flex-shrink: 0;\n width: var(--spacing-6, 1.5rem);\n height: var(--spacing-6, 1.5rem);\n border-radius: var(--doc-frame-glyph-radius, 0.375rem);\n background: var(--primary, #111827);\n color: var(--primary-text, #ffffff);\n font-size: var(--font-size-xs, 0.75rem);\n font-weight: var(--font-weight-bold, 700);\n line-height: 1;\n}\n\n/* Theme-logo layer — the active theme's brand logo SVG (mode-aware via the\n * --brand-logo custom property). Hidden until the client effect confirms the\n * theme ships one AND it loads, so the resting state is always the visible\n * wordmark and a failed load never leaves an empty slot. */\n.themeLogo {\n display: none;\n height: var(--doc-frame-logo-height, var(--spacing-5, 1.25rem));\n /* An explicit min-width keeps a masked/tinted mark from collapsing to a\n * zero-width box on themes that ship no --brand-logo-aspect-ratio. */\n min-width: var(--spacing-8, 2rem);\n aspect-ratio: var(--brand-logo-aspect-ratio, 3 / 1);\n background-image: var(--brand-logo);\n background-repeat: no-repeat;\n background-position: left center;\n background-size: contain;\n}\n\n/* When the theme provides --brand-logo, show the image and drop the wordmark. */\n.brand[data-theme-logo] .themeLogo {\n display: inline-block;\n}\n\n.brand[data-theme-logo] .wordmark {\n display: none;\n}\n\n/* ─── header chrome — home pill + meta ───────────────────────────────────── */\n\n/* OVERVIEW / home pill — a bordered mono chip with a leading compass glyph. */\n.home {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n flex-shrink: 0;\n /* ~6px 12px — a compact chip that clears the mono caps. */\n padding: calc(var(--spacing-1, 0.25rem) * 1.5) var(--spacing-3, 0.75rem);\n border: var(--stroke-width-thin, 1px) solid\n var(--hairline, var(--border-default, #e5e7eb));\n border-radius: var(--radius-full, 9999px);\n background: var(--surface-card, #ffffff);\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: var(--font-size-2xs, 0.6875rem);\n font-weight: var(--font-weight-medium, 500);\n letter-spacing: 0.06em;\n /* Collapse the line box to the glyph height so the all-caps label optically\n * centers against the compass icon. */\n line-height: 1;\n text-transform: uppercase;\n color: var(--text-tertiary, #9ca3af);\n text-decoration: none;\n white-space: nowrap;\n transition: color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease),\n border-color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease);\n}\n\n.home:hover {\n color: var(--text-primary, #111827);\n border-color: var(--hairline-strong, var(--border-default, #d1d5db));\n}\n\n.home:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--border-focus, currentColor);\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n/* Compass glyph — a hair larger than the caps (the design's 13px vs 11px);\n * inherits the pill color via currentColor. */\n.homeIcon {\n flex-shrink: 0;\n width: var(--font-size-sm, 0.875rem);\n height: var(--font-size-sm, 0.875rem);\n}\n\n/* Meta slot — a right-aligned breadcrumb/status line, mono UPPERCASE, tertiary. */\n.meta {\n flex-shrink: 0;\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: var(--font-size-2xs, 0.6875rem);\n font-weight: var(--font-weight-medium, 500);\n letter-spacing: 0.12em;\n line-height: 1;\n text-transform: uppercase;\n color: var(--text-tertiary, #9ca3af);\n white-space: nowrap;\n}\n\n/* ─── mobile ─────────────────────────────────────────────────────────────── */\n\n@media (max-width: 640px) {\n .headerRow {\n padding: var(--spacing-3, 0.75rem) var(--spacing-4, 1rem);\n }\n\n .navRow {\n padding: var(--spacing-3, 0.75rem) var(--spacing-4, 1rem);\n }\n\n .content {\n padding: var(--spacing-5, 1.25rem) var(--spacing-4, 1rem)\n var(--spacing-6, 1.5rem);\n }\n}\n"
|
|
2846
|
+
}
|
|
2847
|
+
]
|
|
2848
|
+
},
|
|
2849
|
+
{
|
|
2850
|
+
"name": "fidelity-mirror",
|
|
2851
|
+
"type": "registry:ui",
|
|
2852
|
+
"description": "The design-left / built-right comparison surface — renders a pure-HTML design source beside its Visor-TSX render (or a native/Flutter device-framed screenshot, or an external artifact) in recessed capture wells, with a verdict diff indicator, numbered delta callouts, a classed delta legend, and a drag-to-reveal overlay mode. Composes inside DocFrame's content and goes full-bleed on widescreen so each pane is ~50vw. The fidelity DISPLAY (the screenshot-diff GATE is a separate verification concern).",
|
|
2853
|
+
"category": "data-display",
|
|
2854
|
+
"dependencies": [
|
|
2855
|
+
"@phosphor-icons/react",
|
|
2856
|
+
"@loworbitstudio/visor-core"
|
|
2857
|
+
],
|
|
2858
|
+
"registryDependencies": [
|
|
2859
|
+
"utils"
|
|
2860
|
+
],
|
|
2861
|
+
"files": [
|
|
2862
|
+
{
|
|
2863
|
+
"path": "components/ui/fidelity-mirror/fidelity-mirror.tsx",
|
|
2864
|
+
"type": "registry:ui",
|
|
2865
|
+
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport {\n ColumnsIcon,\n SquareHalfIcon,\n DeviceMobileIcon,\n BrowserIcon,\n ArrowsHorizontalIcon,\n} from \"@phosphor-icons/react\"\nimport { cn } from \"../../../lib/utils\"\nimport styles from \"./fidelity-mirror.module.css\"\n\n/**\n * FidelityMirror (VI-610) — the design-left / built-right comparison surface.\n *\n * PL-2139 shipped the fidelity GATE (screenshot-diff verification). This is the\n * fidelity DISPLAY: the side-by-side viewer that renders the Fidelity Mirror doc\n * type inside DocFrame's content. Gate VERIFIES; component DISPLAYS.\n *\n * REAL compare semantics (operator refinement): the LEFT pane is the *pure HTML\n * design* source, the RIGHT pane is the *Visor-ified TSX* render — never a\n * synthetically recolored side. The scope-dot hues carry SOURCE identity\n * (`--info` for the design, `--accent` for the built render), not decoration.\n *\n * The compare goes full-bleed on widescreen (`bleed`, default on) so each pane\n * is ~50vw with the center gutter equal to the outer padding. Under 768px the\n * panes stack design-over-built — never a sideways scroll strip.\n */\n\n// ─── types ─────────────────────────────────────────────────────────────────────\n\n/** The platform of the built surface — drives the built-side renderer + chip. */\nexport type FidelityPlatform = \"web\" | \"native\" | \"flutter\" | \"external\"\n\n/** Compare presentation: `split` (design-left / built-right) or `overlay` (slider). */\nexport type FidelityCompareMode = \"split\" | \"overlay\"\n\n/** The diff indicator's verdict — tints the status pill. */\nexport type FidelityVerdict = \"match\" | \"drift\" | \"fail\"\n\n/** The drift class a delta belongs to — classes the legend tag. */\nexport type FidelityDeltaClass = \"radius\" | \"color\" | \"spacing\" | \"type\" | \"align\"\n\n/** A single enumerated drift — a numbered callout on the built side + a legend row. */\nexport interface FidelityDelta {\n /** The drift class (mirrors the render-vs-design self-check taxonomy). */\n class: FidelityDeltaClass\n /** Short legend tag (defaults to the title-cased `class`). */\n label?: string\n /** The legend row copy (any node — supports inline `<b>`/`<code>`). */\n description: React.ReactNode\n /** Callout position over the built pane, as CSS inset values. Omit → no marker. */\n position?: { top?: string; left?: string; right?: string; bottom?: string }\n}\n\n/**\n * A captured surface for one side of the compare. `content` (an arbitrary node)\n * wins when present; otherwise the side renders from `src` per `kind` — an\n * `<img>` (image), or a live-route / external `<iframe>`.\n */\nexport interface FidelitySource {\n /** Renderer. Defaults by platform: web → route, external → external, else image. */\n kind?: \"image\" | \"route\" | \"external\" | \"node\"\n /** Image URL or iframe src. */\n src?: string\n /** Alt text (image) / iframe title (route/external). */\n title?: string\n /** Arbitrary rendered content — wins over `src` when present. */\n content?: React.ReactNode\n /** Pane label override (defaults per side + platform). */\n label?: string\n /** Right-aligned pane meta (mono) — e.g. `index.html`, `route · /doc-nav`. */\n meta?: string\n}\n\nexport interface FidelityMirrorProps\n extends Omit<React.ComponentProps<\"section\">, \"title\"> {\n /** The compared surface's name — the header title (e.g. a component/screen). */\n title: string\n /** Header subtitle under the title (e.g. `Fidelity Mirror · VI-611`). */\n subtitle?: string\n /** Platform of the built surface. Default `web`. */\n platform?: FidelityPlatform\n /** The DESIGN source — the pure-HTML design (left pane). */\n design: FidelitySource\n /** The BUILT source — the Visor-TSX render (right pane). */\n built: FidelitySource\n /** Initial compare mode. Default `split`. The header toggle switches in place. */\n mode?: FidelityCompareMode\n /** The diff verdict — the status pill. */\n verdict: FidelityVerdict\n /** Optional score/summary string on the pill (e.g. `99.4%`, `3 deltas`). */\n score?: string\n /** Enumerated drifts — numbered callouts + the classed legend. Omit → none. */\n deltas?: FidelityDelta[]\n /** Widescreen full-bleed layout (panes ~50vw). Default `true`. */\n bleed?: boolean\n /** Initial overlay reveal position, 0–100. Default `55`. */\n overlayPosition?: number\n /** Notified when the compare mode toggles. */\n onModeChange?: (mode: FidelityCompareMode) => void\n}\n\n// ─── constants ─────────────────────────────────────────────────────────────────\n\nconst DELTA_LABELS: Record<FidelityDeltaClass, string> = {\n radius: \"Radius\",\n color: \"Color\",\n spacing: \"Spacing\",\n type: \"Type\",\n align: \"Align\",\n}\n\n// ─── helpers ───────────────────────────────────────────────────────────────────\n\n/** The default renderer kind for a side, given the platform. */\nfunction defaultKind(platform: FidelityPlatform): FidelitySource[\"kind\"] {\n if (platform === \"web\") return \"route\"\n if (platform === \"external\") return \"external\"\n return \"image\"\n}\n\n/** Whether a platform frames its captures in a device bezel. */\nfunction isDeviceFramed(platform: FidelityPlatform): boolean {\n return platform === \"native\" || platform === \"flutter\"\n}\n\n/** Default pane label for a side, honoring the web HTML/TSX source identity. */\nfunction defaultLabel(\n side: \"design\" | \"built\",\n platform: FidelityPlatform\n): string {\n if (platform === \"web\") {\n return side === \"design\" ? \"Design · HTML\" : \"Built · Visor TSX\"\n }\n return side === \"design\" ? \"Design\" : \"Built\"\n}\n\n/** Overlay ribbon label — the web ribbons read \"HTML Design\" / \"Visor TSX\". */\nfunction ribbonLabel(\n side: \"design\" | \"built\",\n platform: FidelityPlatform\n): string {\n if (platform === \"web\") {\n return side === \"design\" ? \"HTML Design\" : \"Visor TSX\"\n }\n return side === \"design\" ? \"Design\" : \"Built\"\n}\n\n// ─── capture renderer ──────────────────────────────────────────────────────────\n\nfunction Capture({\n source,\n platform,\n}: {\n source: FidelitySource\n platform: FidelityPlatform\n}) {\n const framed = isDeviceFramed(platform)\n const kind = source.content ? \"node\" : source.kind ?? defaultKind(platform)\n\n let media: React.ReactNode\n if (kind === \"node\" || source.content) {\n media = source.content\n } else if (kind === \"image\") {\n media = (\n <img className={styles.media} src={source.src} alt={source.title ?? \"\"} />\n )\n } else {\n // route | external → a live iframe of the built/design surface.\n media = (\n <iframe\n className={styles.media}\n src={source.src}\n title={source.title ?? \"Captured surface\"}\n loading=\"lazy\"\n />\n )\n }\n\n return framed ? <div className={styles.bezel}>{media}</div> : <>{media}</>\n}\n\n// ─── FidelityMirror ────────────────────────────────────────────────────────────\n\nconst FidelityMirror = React.forwardRef<HTMLElement, FidelityMirrorProps>(\n (\n {\n title,\n subtitle,\n platform = \"web\",\n design,\n built,\n mode = \"split\",\n verdict,\n score,\n deltas,\n bleed = true,\n overlayPosition = 55,\n onModeChange,\n className,\n \"aria-label\": ariaLabel,\n ...props\n },\n ref\n ) => {\n const [activeMode, setActiveMode] = React.useState<FidelityCompareMode>(mode)\n const [split, setSplit] = React.useState<number>(overlayPosition)\n\n const setMode = (next: FidelityCompareMode) => {\n setActiveMode(next)\n onModeChange?.(next)\n }\n\n const hasDeltas = Array.isArray(deltas) && deltas.length > 0\n const designLabel = design.label ?? defaultLabel(\"design\", platform)\n const builtLabel = built.label ?? defaultLabel(\"built\", platform)\n\n return (\n <section\n ref={ref}\n data-slot=\"fidelity-mirror\"\n data-platform={platform}\n data-mode={activeMode}\n data-verdict={verdict}\n aria-label={ariaLabel ?? `Fidelity comparison: ${title}`}\n className={cn(styles.root, bleed && styles.bleed, className)}\n {...props}\n >\n {/* ── Header bar ── */}\n <div className={styles.bar}>\n <span className={styles.titleWrap}>\n <span className={styles.title}>{title}</span>\n {subtitle ? <span className={styles.subtitle}>{subtitle}</span> : null}\n </span>\n\n <PlatformChip platform={platform} />\n\n <span className={styles.spacer} aria-hidden=\"true\" />\n\n <span className={styles.status} data-verdict={verdict}>\n <span className={styles.statusGlyph} aria-hidden=\"true\" />\n {verdict}\n {score ? <span className={styles.score}>· {score}</span> : null}\n </span>\n\n <div className={styles.seg} role=\"group\" aria-label=\"Compare mode\">\n <button\n type=\"button\"\n className={styles.segBtn}\n data-slot=\"fidelity-mirror-split\"\n aria-pressed={activeMode === \"split\"}\n onClick={() => setMode(\"split\")}\n >\n <ColumnsIcon\n className={styles.segIcon}\n weight=\"bold\"\n aria-hidden=\"true\"\n />\n Split\n </button>\n <button\n type=\"button\"\n className={styles.segBtn}\n data-slot=\"fidelity-mirror-overlay\"\n aria-pressed={activeMode === \"overlay\"}\n onClick={() => setMode(\"overlay\")}\n >\n <SquareHalfIcon\n className={styles.segIcon}\n weight=\"bold\"\n aria-hidden=\"true\"\n />\n Overlay\n </button>\n </div>\n </div>\n\n {/* ── Body: split panes or overlay slider ── */}\n {activeMode === \"split\" ? (\n <div className={styles.panes} data-slot=\"fidelity-mirror-panes\">\n <div className={styles.pane} data-side=\"design\">\n <span className={styles.paneLabel}>\n <span className={styles.scopeDot} aria-hidden=\"true\" />\n {designLabel}\n {design.meta ? (\n <span className={styles.paneMeta}>{design.meta}</span>\n ) : null}\n </span>\n <div className={styles.well}>\n <Capture source={design} platform={platform} />\n </div>\n </div>\n\n <div className={styles.pane} data-side=\"built\">\n <span className={styles.paneLabel}>\n <span className={styles.scopeDot} aria-hidden=\"true\" />\n {builtLabel}\n {built.meta ? (\n <span className={styles.paneMeta}>{built.meta}</span>\n ) : null}\n </span>\n <div className={styles.well}>\n {hasDeltas\n ? deltas\n .filter((d) => d.position)\n .map((d, i) => (\n <span\n key={`${d.class}-${i}`}\n className={styles.delta}\n style={d.position}\n aria-hidden=\"true\"\n >\n {i + 1}\n </span>\n ))\n : null}\n <Capture source={built} platform={platform} />\n </div>\n </div>\n </div>\n ) : (\n <div className={styles.overlay} data-slot=\"fidelity-mirror-overlay-view\">\n <div\n className={styles.overlayFrame}\n style={{ \"--fm-split\": `${split}%` } as React.CSSProperties}\n >\n <span className={styles.ribbon} data-side=\"built\">\n {ribbonLabel(\"built\", platform)}\n </span>\n {/* Base layer: built render. */}\n <div className={styles.layer}>\n <Capture source={built} platform={platform} />\n </div>\n {/* Top layer: design, clipped to the reveal position. */}\n <div className={cn(styles.layer, styles.layerTop)}>\n <span className={styles.ribbon} data-side=\"design\">\n {ribbonLabel(\"design\", platform)}\n </span>\n <Capture source={design} platform={platform} />\n </div>\n <div className={styles.handle} aria-hidden=\"true\">\n <span className={styles.grip}>\n <ArrowsHorizontalIcon\n className={styles.gripIcon}\n weight=\"bold\"\n aria-hidden=\"true\"\n />\n </span>\n </div>\n </div>\n <input\n className={styles.range}\n type=\"range\"\n min={0}\n max={100}\n value={split}\n aria-label=\"Reveal position\"\n onChange={(e) => setSplit(Number(e.target.value))}\n />\n </div>\n )}\n\n {/* ── Delta legend ── */}\n {hasDeltas ? (\n <div className={styles.legend} data-slot=\"fidelity-mirror-legend\">\n <span className={styles.legendHead}>Deltas — built vs design</span>\n {deltas.map((d, i) => (\n <div className={styles.legendRow} key={`${d.class}-legend-${i}`}>\n <span className={styles.legendNum}>{i + 1}</span>\n <span className={styles.tag} data-class={d.class}>\n {d.label ?? DELTA_LABELS[d.class]}\n </span>\n <span className={styles.legendText}>{d.description}</span>\n </div>\n ))}\n </div>\n ) : null}\n </section>\n )\n }\n)\nFidelityMirror.displayName = \"FidelityMirror\"\n\n// ─── PlatformChip (internal) ────────────────────────────────────────────────────\n\nfunction PlatformChip({ platform }: { platform: FidelityPlatform }) {\n if (platform === \"web\") {\n return (\n <span className={styles.chip} data-slot=\"fidelity-mirror-chip\">\n <span className={styles.chipDot} aria-hidden=\"true\" />\n Web · Live Route\n </span>\n )\n }\n if (platform === \"native\") {\n return (\n <span className={styles.chip} data-slot=\"fidelity-mirror-chip\">\n <DeviceMobileIcon className={styles.chipIcon} aria-hidden=\"true\" />\n iOS · SwiftUI\n </span>\n )\n }\n if (platform === \"flutter\") {\n return (\n <span className={styles.chip} data-slot=\"fidelity-mirror-chip\">\n <DeviceMobileIcon className={styles.chipIcon} aria-hidden=\"true\" />\n Flutter\n </span>\n )\n }\n return (\n <span className={styles.chip} data-slot=\"fidelity-mirror-chip\">\n <BrowserIcon className={styles.chipIcon} aria-hidden=\"true\" />\n External\n </span>\n )\n}\n\nexport { FidelityMirror }\n"
|
|
2866
|
+
},
|
|
2867
|
+
{
|
|
2868
|
+
"path": "components/ui/fidelity-mirror/fidelity-mirror.module.css",
|
|
2869
|
+
"type": "registry:ui",
|
|
2870
|
+
"content": "/* FidelityMirror — the design-left / built-right comparison surface.\n *\n * Renders the pure DESIGN source (left) beside the BUILT render (right) in\n * recessed capture wells, with a verdict/diff indicator, numbered delta\n * callouts, a classed delta legend, and a drag-to-reveal overlay mode. Composes\n * inside DocFrame's content, and goes full-bleed on widescreen so each pane is\n * ~50vw (the compare is meant for fullscreen monitors).\n *\n * Theme-agnostic: every value references a Visor token. The card/cluster radius\n * and the recessed well fill are component-OWNED (fixed) tokens, NOT the theme\n * `--radius-*` scale or a bare `--surface-*` token — decorative themes inflate\n * `--radius-xl` to 32px and lift `--surface-subtle` ABOVE the card in dark mode,\n * which is precisely the drift this component exists to surface.\n */\n\n/* Root — the framed compare. */\n.root {\n /* Fixed cluster radius the component OWNS — NOT the theme `--radius-*` scale,\n * which decorative themes inflate far past what a dense compare cluster wants\n * (Space inflates `--radius-xl` to 32px). Overridable by a consumer/theme. */\n --fm-radius: 0.75rem;\n --fm-well-radius: 0.625rem;\n /* Widescreen gutter/padding — the outer left/right padding AND the center\n * gutter resolve to the SAME value, so each pane is ~50vw: (100vw - 3*pad)/2. */\n --fm-pad: clamp(1.25rem, 3.2vw, 3.5rem);\n /* Recessed well fill — darker than `--surface-card` in BOTH modes (the DocNav\n * pill-bg convention). The surface ramp inverts light<->dark, so a single\n * surface token can't stay \"below\" the card; mixing the card toward\n * neutral-950 darkens it directionally in either mode. Overridable. */\n --fm-well: color-mix(\n in srgb,\n var(--surface-card, #111827),\n var(--color-neutral-950, #030712) 22%\n );\n /* Source identity hues (kept across split + overlay): design = info, built =\n * accent. These carry SOURCE identity, not decoration — do not retint. */\n --fm-design-hue: var(--info, #0ea5e9);\n --fm-built-hue: var(--accent, #2563eb);\n\n display: flex;\n flex-direction: column;\n border: var(--stroke-width-thin, 1px) solid var(--hairline, #e5e7eb);\n border-radius: var(--fm-radius);\n background: var(--surface-card, #ffffff);\n box-shadow: var(--shadow-md);\n overflow: hidden;\n font-family: var(--font-sans, system-ui, sans-serif);\n}\n\n/* Widescreen full-bleed — escape DocFrame's centered column and span the\n * viewport. Header + legend align to the panes' outer edge via `--fm-pad`; the\n * panes grid uses `gap: var(--fm-pad)` so each column resolves to ~50vw. */\n.bleed {\n width: 100vw;\n margin-left: calc(50% - 50vw);\n border-radius: 0;\n border-inline: 0;\n}\n.bleed .bar {\n padding-inline: var(--fm-pad);\n}\n.bleed .panes {\n padding-inline: var(--fm-pad);\n gap: var(--fm-pad);\n}\n.bleed .legend {\n padding-inline: var(--fm-pad);\n}\n.bleed .overlay {\n padding-inline: var(--fm-pad);\n}\n\n/* ── Header bar ──────────────────────────────────────────────────────────── */\n.bar {\n display: flex;\n align-items: center;\n gap: var(--spacing-3, 0.75rem);\n flex-wrap: wrap;\n padding: var(--spacing-3, 0.75rem) var(--spacing-4, 1rem);\n border-bottom: var(--stroke-width-thin, 1px) solid var(--hairline, #e5e7eb);\n}\n.titleWrap {\n display: inline-flex;\n flex-direction: column;\n gap: calc(var(--spacing-1, 0.25rem) * 1.5);\n min-width: 0;\n}\n.title {\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: var(--font-size-sm, 0.8125rem);\n font-weight: var(--font-weight-bold, 700);\n letter-spacing: 0.02em;\n line-height: 1;\n color: var(--text-primary, #111827);\n}\n.subtitle {\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: var(--font-size-2xs, 0.6875rem);\n font-weight: var(--font-weight-medium, 500);\n letter-spacing: 0.12em;\n text-transform: uppercase;\n line-height: 1;\n color: var(--text-tertiary, #9ca3af);\n}\n\n/* Spacer — pushes the status + toggle to the right edge. */\n.spacer {\n flex: 1 1 auto;\n}\n\n/* Platform chip — mono caps pill, hairline, card bg. */\n.chip {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n padding: calc(var(--spacing-1, 0.25rem) * 1.25) var(--spacing-3, 0.75rem);\n border: var(--stroke-width-thin, 1px) solid var(--hairline, #e5e7eb);\n border-radius: var(--radius-full, 9999px);\n background: var(--surface-card, #ffffff);\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: var(--font-size-2xs, 0.6875rem);\n font-weight: var(--font-weight-medium, 500);\n letter-spacing: 0.06em;\n line-height: 1;\n text-transform: uppercase;\n white-space: nowrap;\n color: var(--text-secondary, #4b5563);\n}\n.chipDot {\n width: 0.375rem;\n height: 0.375rem;\n border-radius: var(--radius-full, 9999px);\n background: var(--success, #22c55e);\n box-shadow: 0 0 0.375rem color-mix(in srgb, var(--success, #22c55e) 70%, transparent);\n}\n.chipIcon {\n width: 0.75rem;\n height: 0.75rem;\n color: var(--text-tertiary, #9ca3af);\n}\n\n/* Status pill — the diff indicator, tinted by verdict. */\n.status {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n padding: calc(var(--spacing-1, 0.25rem) * 1.25) var(--spacing-3, 0.75rem);\n border: var(--stroke-width-thin, 1px) solid transparent;\n border-radius: var(--radius-full, 9999px);\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: var(--font-size-2xs, 0.6875rem);\n font-weight: var(--font-weight-bold, 700);\n letter-spacing: 0.08em;\n line-height: 1;\n text-transform: uppercase;\n white-space: nowrap;\n}\n.status[data-verdict=\"match\"] {\n color: var(--success, #22c55e);\n border-color: color-mix(in srgb, var(--success, #22c55e) 40%, transparent);\n background: color-mix(in srgb, var(--success, #22c55e) 12%, var(--surface-card, #ffffff));\n}\n.status[data-verdict=\"drift\"] {\n color: var(--warning, #f59e0b);\n border-color: color-mix(in srgb, var(--warning, #f59e0b) 42%, transparent);\n background: color-mix(in srgb, var(--warning, #f59e0b) 12%, var(--surface-card, #ffffff));\n}\n.status[data-verdict=\"fail\"] {\n color: var(--destructive, #ef4444);\n border-color: color-mix(in srgb, var(--destructive, #ef4444) 42%, transparent);\n background: color-mix(in srgb, var(--destructive, #ef4444) 12%, var(--surface-card, #ffffff));\n}\n.statusGlyph {\n width: 0.625rem;\n height: 0.625rem;\n border-radius: var(--radius-full, 9999px);\n background: currentColor;\n box-shadow: 0 0 0.4375rem currentColor;\n}\n.score {\n font-variant-numeric: tabular-nums;\n letter-spacing: 0.02em;\n opacity: var(--opacity-80, 0.85);\n}\n\n/* Segmented compare-mode toggle — split / overlay. */\n.seg {\n display: inline-flex;\n gap: calc(var(--spacing-1, 0.25rem) * 0.5);\n padding: calc(var(--spacing-1, 0.25rem) * 0.75);\n border: var(--stroke-width-thin, 1px) solid var(--hairline, #e5e7eb);\n border-radius: var(--radius-full, 9999px);\n background: var(--fm-well);\n}\n.segBtn {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n padding: calc(var(--spacing-1, 0.25rem) * 1.25) calc(var(--spacing-1, 0.25rem) * 2.5);\n border: 0;\n border-radius: var(--radius-full, 9999px);\n background: transparent;\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: var(--font-size-2xs, 0.6875rem);\n font-weight: var(--font-weight-medium, 500);\n letter-spacing: 0.06em;\n text-transform: uppercase;\n line-height: 1;\n color: var(--text-tertiary, #9ca3af);\n cursor: pointer;\n transition: color var(--motion-duration-fast, 150ms) var(--motion-easing-standard, ease),\n background-color var(--motion-duration-fast, 150ms) var(--motion-easing-standard, ease);\n}\n.segIcon {\n width: 0.8125rem;\n height: 0.8125rem;\n}\n.segBtn[aria-pressed=\"true\"] {\n color: var(--text-primary, #111827);\n background: var(--surface-card, #ffffff);\n box-shadow: var(--shadow-md);\n}\n.segBtn:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--border-focus, currentColor);\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n/* ── Panes: side-by-side ─────────────────────────────────────────────────── */\n.panes {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: var(--spacing-4, 1rem);\n padding: var(--spacing-4, 1rem);\n align-items: start;\n}\n.pane {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-2, 0.5rem);\n min-width: 0;\n}\n.paneLabel {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: var(--font-size-2xs, 0.6875rem);\n font-weight: var(--font-weight-bold, 700);\n letter-spacing: 0.14em;\n text-transform: uppercase;\n line-height: 1;\n color: var(--text-secondary, #4b5563);\n}\n.scopeDot {\n width: 0.5rem;\n height: 0.5rem;\n flex-shrink: 0;\n border-radius: var(--radius-full, 9999px);\n background: currentColor;\n box-shadow: 0 0 0.5rem color-mix(in srgb, currentColor 60%, transparent);\n}\n.pane[data-side=\"design\"] .scopeDot {\n color: var(--fm-design-hue);\n}\n.pane[data-side=\"built\"] .scopeDot {\n color: var(--fm-built-hue);\n}\n.paneMeta {\n margin-left: auto;\n color: var(--text-tertiary, #9ca3af);\n letter-spacing: 0.1em;\n font-weight: var(--font-weight-medium, 500);\n}\n\n/* Capture well — the recessed frame that holds a captured surface. */\n.well {\n position: relative;\n border: var(--stroke-width-thin, 1px) solid var(--hairline, #e5e7eb);\n border-radius: var(--fm-well-radius);\n background: var(--fm-well);\n padding: var(--spacing-3, 0.75rem);\n overflow: hidden;\n}\n.pane[data-side=\"built\"] .well {\n box-shadow: inset 0 0 0 var(--stroke-width-thin, 1px)\n color-mix(in srgb, var(--fm-built-hue) 22%, transparent);\n}\n\n/* Captured media — an image or a live-route/external iframe fills the well. */\n.media {\n display: block;\n width: 100%;\n height: auto;\n border: 0;\n border-radius: calc(var(--fm-well-radius) - 0.25rem);\n}\n\n/* Device bezel — native / flutter screenshots read inside a subtle frame. */\n.bezel {\n width: 10.5rem;\n margin: 0 auto;\n border: 0.375rem solid color-mix(in srgb, var(--text-primary, #111827) 78%, transparent);\n border-radius: 1.625rem;\n overflow: hidden;\n background: var(--surface-page, #ffffff);\n box-shadow: var(--shadow-lg);\n}\n.bezel .media {\n border-radius: 0;\n}\n\n/* Delta callout marker — a numbered accent dot pinned over a drift location. */\n.delta {\n position: absolute;\n z-index: 3;\n display: grid;\n place-items: center;\n width: 1.25rem;\n height: 1.25rem;\n border-radius: var(--radius-full, 9999px);\n background: var(--warning, #f59e0b);\n color: var(--color-neutral-950, #030712);\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: var(--font-size-2xs, 0.6875rem);\n font-weight: var(--font-weight-bold, 700);\n line-height: 1;\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--warning, #f59e0b) 30%, transparent),\n var(--shadow-md);\n}\n\n/* ── Overlay / slider mode ───────────────────────────────────────────────── */\n.overlay {\n position: relative;\n padding: var(--spacing-4, 1rem);\n}\n.overlayFrame {\n position: relative;\n border: var(--stroke-width-thin, 1px) solid var(--hairline, #e5e7eb);\n border-radius: var(--fm-well-radius);\n background: var(--fm-well);\n overflow: hidden;\n}\n.layer {\n padding: var(--spacing-3, 0.75rem);\n}\n/* Clear space below the corner ribbons so they never collide with content. */\n.overlayFrame .layer {\n padding-top: var(--spacing-10, 2.5rem);\n}\n.layerTop {\n position: absolute;\n inset: 0;\n /* Revealed portion driven by `--fm-split` (design shows on the left). */\n clip-path: inset(0 calc(100% - var(--fm-split, 55%)) 0 0);\n}\n.handle {\n position: absolute;\n top: 0;\n bottom: 0;\n left: var(--fm-split, 55%);\n width: 2px;\n background: var(--accent, #2563eb);\n box-shadow: 0 0 0.625rem color-mix(in srgb, var(--accent, #2563eb) 70%, transparent);\n z-index: 4;\n}\n.grip {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n display: grid;\n place-items: center;\n width: 1.75rem;\n height: 1.75rem;\n border-radius: var(--radius-full, 9999px);\n background: var(--accent, #2563eb);\n color: var(--color-white, #ffffff);\n box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent, #2563eb) 26%, transparent),\n var(--shadow-md);\n}\n.gripIcon {\n width: 0.9375rem;\n height: 0.9375rem;\n}\n.ribbon {\n position: absolute;\n z-index: 5;\n top: var(--spacing-3, 0.75rem);\n padding: var(--spacing-1, 0.25rem) var(--spacing-2, 0.5rem);\n border-radius: var(--radius-full, 9999px);\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: calc(var(--font-size-2xs, 0.6875rem) * 0.9);\n font-weight: var(--font-weight-bold, 700);\n letter-spacing: 0.12em;\n text-transform: uppercase;\n line-height: 1;\n color: var(--color-white, #ffffff);\n}\n.ribbon[data-side=\"design\"] {\n left: var(--spacing-3, 0.75rem);\n background: color-mix(in srgb, var(--fm-design-hue) 85%, var(--color-neutral-950, #030712));\n}\n.ribbon[data-side=\"built\"] {\n right: var(--spacing-3, 0.75rem);\n background: color-mix(in srgb, var(--fm-built-hue) 85%, var(--color-neutral-950, #030712));\n}\n.range {\n width: 100%;\n margin-top: var(--spacing-3, 0.75rem);\n accent-color: var(--accent, #2563eb);\n cursor: ew-resize;\n}\n.range:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--border-focus, currentColor);\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n/* ── Delta legend ────────────────────────────────────────────────────────── */\n.legend {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-2, 0.5rem);\n padding: var(--spacing-3, 0.75rem) var(--spacing-4, 1rem);\n border-top: var(--stroke-width-thin, 1px) solid var(--hairline, #e5e7eb);\n}\n.legendHead {\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: var(--font-size-2xs, 0.6875rem);\n font-weight: var(--font-weight-bold, 700);\n letter-spacing: 0.14em;\n text-transform: uppercase;\n color: var(--text-tertiary, #9ca3af);\n}\n.legendRow {\n display: flex;\n align-items: center;\n gap: var(--spacing-3, 0.75rem);\n}\n.legendNum {\n flex-shrink: 0;\n display: grid;\n place-items: center;\n width: 1.125rem;\n height: 1.125rem;\n border-radius: var(--radius-full, 9999px);\n background: var(--warning, #f59e0b);\n color: var(--color-neutral-950, #030712);\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: calc(var(--font-size-2xs, 0.6875rem) * 0.9);\n font-weight: var(--font-weight-bold, 700);\n}\n.tag {\n flex-shrink: 0;\n padding: calc(var(--spacing-1, 0.25rem) * 0.75) var(--spacing-2, 0.5rem);\n border: var(--stroke-width-thin, 1px) solid var(--hairline, #e5e7eb);\n border-radius: var(--radius-sm, 0.25rem);\n background: var(--surface-subtle, #f3f4f6);\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: calc(var(--font-size-2xs, 0.6875rem) * 0.9);\n font-weight: var(--font-weight-bold, 700);\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--text-secondary, #4b5563);\n}\n.legendText {\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: var(--font-size-sm, 0.8125rem);\n color: var(--text-secondary, #4b5563);\n}\n.legendText b {\n color: var(--text-primary, #111827);\n font-weight: var(--font-weight-bold, 700);\n}\n\n/* Visually-hidden text for assistive technology. */\n.srOnly {\n position: absolute;\n width: var(--stroke-width-thin, 1px);\n height: var(--stroke-width-thin, 1px);\n padding: 0;\n margin: calc(-1 * var(--stroke-width-thin, 1px));\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n\n/* Responsive: panes stack under 768px (design over built) — NEVER a sideways\n * scroll strip (the defect the doc-set surfaces exist to kill). */\n@media (max-width: 767px) {\n .panes {\n grid-template-columns: 1fr;\n }\n .bar {\n gap: var(--spacing-2, 0.5rem);\n }\n}\n"
|
|
2846
2871
|
}
|
|
2847
2872
|
]
|
|
2848
2873
|
},
|
|
@@ -5088,7 +5113,7 @@
|
|
|
5088
5113
|
{
|
|
5089
5114
|
"path": "components/devtools/source-inspector/visor-component-names.generated.ts",
|
|
5090
5115
|
"type": "registry:devtool",
|
|
5091
|
-
"content": "// THIS FILE IS GENERATED BY scripts/generate-visor-component-names.ts.\n// Do not edit by hand. Re-run `npm run generate:component-names` after\n// adding, removing, or renaming a Visor component.\n//\n// Source of truth: registry/registry-{ui,blocks,deck,visual,devtools}.ts\n// Used by: components/devtools/source-inspector/* (VI-311)\n\nexport const VISOR_COMPONENT_NAMES: ReadonlySet<string> = new Set([\n \"AccessibilitySection\",\n \"AccessibilitySlide\",\n \"AccessibilitySpecimen\",\n \"Accordion\",\n \"AccordionContent\",\n \"AccordionItem\",\n \"AccordionTrigger\",\n \"ActivityFeed\",\n \"ActivityFeedContext\",\n \"ActivityFeedItem\",\n \"ActivityFeedRoot\",\n \"AdminDashboard\",\n \"AdminDetail\",\n \"AdminDetailDrawer\",\n \"AdminListPage\",\n \"AdminListPageInner\",\n \"AdminSettingsPage\",\n \"AdminShell\",\n \"AdminTabbedEditor\",\n \"AdminWizard\",\n \"Alert\",\n \"AlertActions\",\n \"AlertDescription\",\n \"AlertTitle\",\n \"AmbientGlow\",\n \"Avatar\",\n \"AvatarFallback\",\n \"AvatarImage\",\n \"AvatarStack\",\n \"Badge\",\n \"Banner\",\n \"BannerAction\",\n \"BannerDescription\",\n \"BannerTitle\",\n \"BentoGrid\",\n \"BentoTile\",\n \"BentoTileBody\",\n \"BentoTileDescription\",\n \"BentoTileFigure\",\n \"BentoTileHeadline\",\n \"BentoTileMedia\",\n \"BentoTileMeta\",\n \"BentoTileTitle\",\n \"Box\",\n \"Breadcrumb\",\n \"BreadcrumbEllipsis\",\n \"BreadcrumbItem\",\n \"BreadcrumbLink\",\n \"BreadcrumbList\",\n \"BreadcrumbPage\",\n \"BreadcrumbSeparator\",\n \"BrowserFrame\",\n \"BulkActionBar\",\n \"Button\",\n \"ButtonSpecimenSection\",\n \"ButtonSpecimenSlide\",\n \"Calendar\",\n \"Card\",\n \"CardContent\",\n \"CardDescription\",\n \"CardFooter\",\n \"CardGrid\",\n \"CardHeader\",\n \"CardLift\",\n \"CardTitle\",\n \"Carousel\",\n \"CarouselContent\",\n \"CarouselContext\",\n \"CarouselGallery\",\n \"CarouselItem\",\n \"CarouselNext\",\n \"CarouselPrevious\",\n \"ChallengeCard\",\n \"ChallengeCardAction\",\n \"ChallengeCardActions\",\n \"ChallengeCardBody\",\n \"ChallengeCardGate\",\n \"ChallengeCardHeader\",\n \"ChartContainer\",\n \"ChartContext\",\n \"ChartLegend\",\n \"ChartLegendContent\",\n \"ChartStyle\",\n \"ChartTooltip\",\n \"ChartTooltipContent\",\n \"Checkbox\",\n \"CheckGroup\",\n \"CheckRow\",\n \"Chip\",\n \"ChipGroup\",\n \"ChipGroupContext\",\n \"ChipGroupItem\",\n \"ChoiceChip\",\n \"ChromeButton\",\n \"ClosingSlide\",\n \"CodeBlock\",\n \"Collapsible\",\n \"CollapsibleContent\",\n \"CollapsibleTrigger\",\n \"ColorBar\",\n \"ColorPaletteSection\",\n \"ColorPicker\",\n \"ColorPickerSurface\",\n \"ColorSwatch\",\n \"ColorSwatchGrid\",\n \"Combobox\",\n \"ComboboxContent\",\n \"ComboboxContext\",\n \"ComboboxEmpty\",\n \"ComboboxGroup\",\n \"ComboboxInput\",\n \"ComboboxItem\",\n \"ComboboxSeparator\",\n \"Command\",\n \"CommandDialog\",\n \"CommandEmpty\",\n \"CommandGroup\",\n \"CommandInput\",\n \"CommandItem\",\n \"CommandList\",\n \"CommandLoading\",\n \"CommandSeparator\",\n \"CommandShortcut\",\n \"ComponentShowcaseContent\",\n \"ComponentShowcaseSection\",\n \"ComponentShowcaseSlide\",\n \"Composer\",\n \"ComposerContext\",\n \"ComposerField\",\n \"ComposerSend\",\n \"ComposerSpacer\",\n \"ComposerToolbar\",\n \"ComposerToolButton\",\n \"ConceptSlide\",\n \"ConfigurationPanel\",\n \"ConfirmDialog\",\n \"ConflictBanner\",\n \"Container\",\n \"ContextMenu\",\n \"ContextMenuCheckboxItem\",\n \"ContextMenuContent\",\n \"ContextMenuGroup\",\n \"ContextMenuItem\",\n \"ContextMenuLabel\",\n \"ContextMenuPortal\",\n \"ContextMenuRadioGroup\",\n \"ContextMenuRadioItem\",\n \"ContextMenuSeparator\",\n \"ContextMenuShortcut\",\n \"ContextMenuSub\",\n \"ContextMenuSubContent\",\n \"ContextMenuSubTrigger\",\n \"ContextMenuTrigger\",\n \"Controls\",\n \"CtaSection\",\n \"DataTable\",\n \"DataTableInner\",\n \"DatePicker\",\n \"DateRangePicker\",\n \"DeckContext\",\n \"DeckFooter\",\n \"DeckLayout\",\n \"DeckProvider\",\n \"DeckRenderer\",\n \"DesignSystemDeck\",\n \"DesignSystemSpecimen\",\n \"Dialog\",\n \"DialogClose\",\n \"DialogContent\",\n \"DialogDescription\",\n \"DialogFooter\",\n \"DialogHeader\",\n \"DialogOverlay\",\n \"DialogPortal\",\n \"DialogTitle\",\n \"DialogTrigger\",\n \"DocFrame\",\n \"DocFrameBrand\",\n \"DocNav\",\n \"DocNavGroup\",\n \"DocNavPill\",\n \"DotNav\",\n \"DropdownMenu\",\n \"DropdownMenuCheckboxItem\",\n \"DropdownMenuContent\",\n \"DropdownMenuGroup\",\n \"DropdownMenuItem\",\n \"DropdownMenuLabel\",\n \"DropdownMenuPortal\",\n \"DropdownMenuRadioGroup\",\n \"DropdownMenuRadioItem\",\n \"DropdownMenuSeparator\",\n \"DropdownMenuShortcut\",\n \"DropdownMenuSub\",\n \"DropdownMenuSubContent\",\n \"DropdownMenuSubTrigger\",\n \"DropdownMenuTrigger\",\n \"EditableBlock\",\n \"ElevationCard\",\n \"ElevationSlide\",\n \"EmptyState\",\n \"ErrorPlacard\",\n \"ExportMenu\",\n \"FeaturesGrid\",\n \"Field\",\n \"FieldDescription\",\n \"FieldError\",\n \"FieldLabel\",\n \"Fieldset\",\n \"FieldsetLegend\",\n \"FileUpload\",\n \"FilterBar\",\n \"FilterChip\",\n \"FontShowcase\",\n \"FontShowcaseGrid\",\n \"Footer\",\n \"FooterSection\",\n \"Form\",\n \"FormError\",\n \"FormErrorDescription\",\n \"FormErrorTitle\",\n \"FormField\",\n \"FormSpecimenSection\",\n \"FormSpecimenSlide\",\n \"FullscreenOverlay\",\n \"FullscreenOverlayContent\",\n \"FullscreenOverlayTrigger\",\n \"GrainOverlay\",\n \"Grid\",\n \"Header\",\n \"Heading\",\n \"HeroGlow\",\n \"HeroSection\",\n \"HeroSlide\",\n \"HoverCard\",\n \"HoverCardContent\",\n \"HoverCardTrigger\",\n \"IconGrid\",\n \"IconGridSection\",\n \"IconSizeRow\",\n \"IconsSlide\",\n \"Image\",\n \"InfographicBar\",\n \"Inline\",\n \"Input\",\n \"Kbd\",\n \"KeyValueList\",\n \"Label\",\n \"Landing\",\n \"Lightbox\",\n \"LightboxContent\",\n \"LightboxContext\",\n \"LightboxTrigger\",\n \"LoginForm\",\n \"Marquee\",\n \"MarqueeBandRenderer\",\n \"MatrixCell\",\n \"MatrixTable\",\n \"MatrixTableInner\",\n \"Menubar\",\n \"MenubarCheckboxItem\",\n \"MenubarContent\",\n \"MenubarGroup\",\n \"MenubarItem\",\n \"MenubarLabel\",\n \"MenubarMenu\",\n \"MenubarRadioGroup\",\n \"MenubarRadioItem\",\n \"MenubarSeparator\",\n \"MenubarShortcut\",\n \"MenubarSub\",\n \"MenubarSubContent\",\n \"MenubarSubTrigger\",\n \"MenubarTrigger\",\n \"MonthCalendar\",\n \"MotionDuration\",\n \"MotionDurationSection\",\n \"MotionEasing\",\n \"MotionEasingSection\",\n \"MotionSlide\",\n \"NameRoster\",\n \"NameRosterItem\",\n \"Navbar\",\n \"NavbarBrand\",\n \"NavbarContent\",\n \"NavbarItem\",\n \"NavbarLink\",\n \"NavbarToggle\",\n \"NumberInput\",\n \"OfflineBanner\",\n \"OpacityBar\",\n \"OpacitySlide\",\n \"OTPInput\",\n \"PageHeader\",\n \"Pagination\",\n \"PaginationContent\",\n \"PaginationEllipsis\",\n \"PaginationItem\",\n \"PaginationLink\",\n \"PaginationNext\",\n \"PaginationPrevious\",\n \"PasswordInput\",\n \"PhoneInput\",\n \"Popover\",\n \"PopoverAnchor\",\n \"PopoverContent\",\n \"PopoverFooter\",\n \"PopoverSelectionItem\",\n \"PopoverSelectionLabel\",\n \"PopoverSelectionList\",\n \"PopoverTrigger\",\n \"PricingSection\",\n \"ProfileMenu\",\n \"Progress\",\n \"PrototypeReview\",\n \"QuickActions\",\n \"RadioGroup\",\n \"RadioGroupItem\",\n \"RadiusScale\",\n \"RadiusSection\",\n \"RadiusSlide\",\n \"RecordSection\",\n \"RightRailList\",\n \"ScoreIndicator\",\n \"ScrollArea\",\n \"ScrollBar\",\n \"SearchInput\",\n \"SectionHeader\",\n \"SectionIntro\",\n \"SectionNav\",\n \"SectionNavItem\",\n \"SegmentedProgress\",\n \"Select\",\n \"SelectContent\",\n \"SelectGroup\",\n \"SelectionListContext\",\n \"SelectItem\",\n \"SelectLabel\",\n \"SelectScrollDownButton\",\n \"SelectScrollUpButton\",\n \"SelectSeparator\",\n \"SelectTrigger\",\n \"SelectValue\",\n \"SemanticColorGrid\",\n \"SemanticColorItem\",\n \"SemanticTokensSlide\",\n \"SensitivePanel\",\n \"Separator\",\n \"SessionTimeout\",\n \"ShadowSection\",\n \"Sheet\",\n \"SheetClose\",\n \"SheetContent\",\n \"SheetDescription\",\n \"SheetFooter\",\n \"SheetHeader\",\n \"SheetOverlay\",\n \"SheetPortal\",\n \"SheetTitle\",\n \"SheetTrigger\",\n \"Sidebar\",\n \"SidebarContent\",\n \"SidebarContext\",\n \"SidebarFooter\",\n \"SidebarGroup\",\n \"SidebarGroupAction\",\n \"SidebarGroupContent\",\n \"SidebarGroupLabel\",\n \"SidebarHeader\",\n \"SidebarInset\",\n \"SidebarMenu\",\n \"SidebarMenuAction\",\n \"SidebarMenuBadge\",\n \"SidebarMenuButton\",\n \"SidebarMenuItem\",\n \"SidebarMenuSub\",\n \"SidebarMenuSubButton\",\n \"SidebarMenuSubItem\",\n \"SidebarProvider\",\n \"SidebarRail\",\n \"SidebarSeparator\",\n \"SidebarTrigger\",\n \"Skeleton\",\n \"SkeletonDetail\",\n \"SkeletonList\",\n \"SkeletonTable\",\n \"Slide\",\n \"SlideHeader\",\n \"Slider\",\n \"SliderControl\",\n \"SlideThemeContext\",\n \"SlideThemeProvider\",\n \"SlowNetworkBar\",\n \"SourceInspector\",\n \"SourceInspectorContext\",\n \"SourceInspectorDevImpl\",\n \"SourceInspectorProvider\",\n \"SourceInspectorRunner\",\n \"SourceInspectorToggle\",\n \"SpacingScale\",\n \"SpacingSection\",\n \"SpacingSlide\",\n \"Sparkline\",\n \"SpecimenCard\",\n \"SpecimenCardFooter\",\n \"Sphere\",\n \"SpherePlayground\",\n \"Spinner\",\n \"Stack\",\n \"Stage\",\n \"StatCard\",\n \"StatHero\",\n \"StationSpectrum\",\n \"StatusBadge\",\n \"StatusColorsSlide\",\n \"StatusDot\",\n \"Stepper\",\n \"StepperContext\",\n \"StepperDescription\",\n \"StepperItem\",\n \"StepperSeparator\",\n \"StepperTitle\",\n \"StepperTrigger\",\n \"StepsSection\",\n \"StructuredPrompt\",\n \"StructuredPromptBody\",\n \"StructuredPromptHeader\",\n \"StructuredPromptHint\",\n \"StructuredPromptSlot\",\n \"SuccessLiveRegion\",\n \"SurfaceRow\",\n \"SurfaceScaleStack\",\n \"SurfaceSection\",\n \"Switch\",\n \"Table\",\n \"TableBody\",\n \"TableCaption\",\n \"TableCell\",\n \"TableFooter\",\n \"TableHead\",\n \"TableHeader\",\n \"TableRow\",\n \"Tabs\",\n \"TabsContent\",\n \"TabsList\",\n \"TabsTrigger\",\n \"TagInput\",\n \"TestimonialAttribution\",\n \"TestimonialSection\",\n \"Text\",\n \"Textarea\",\n \"ThemeArchitectureSlide\",\n \"ThemeColorsSlide\",\n \"ThemeSwitcher\",\n \"Timeline\",\n \"TimelineContent\",\n \"TimelineDescription\",\n \"TimelineIcon\",\n \"TimelineItem\",\n \"TimelineTimestamp\",\n \"TimelineTitle\",\n \"TitleSlide\",\n \"ToastCard\",\n \"ToastCardStack\",\n \"Toaster\",\n \"TOCSlide\",\n \"ToggleButton\",\n \"ToggleDevImpl\",\n \"ToggleGroup\",\n \"ToggleGroupContext\",\n \"ToggleGroupItem\",\n \"Tooltip\",\n \"TooltipContent\",\n \"TooltipProvider\",\n \"TooltipTrigger\",\n \"TypeBodySlide\",\n \"TypeDisplaySlide\",\n \"TypeScaleStack\",\n \"TypeSpecimen\",\n \"TypographySection\",\n \"Vignette\",\n \"WorkspaceSwitcher\",\n])\n"
|
|
5116
|
+
"content": "// THIS FILE IS GENERATED BY scripts/generate-visor-component-names.ts.\n// Do not edit by hand. Re-run `npm run generate:component-names` after\n// adding, removing, or renaming a Visor component.\n//\n// Source of truth: registry/registry-{ui,blocks,deck,visual,devtools}.ts\n// Used by: components/devtools/source-inspector/* (VI-311)\n\nexport const VISOR_COMPONENT_NAMES: ReadonlySet<string> = new Set([\n \"AccessibilitySection\",\n \"AccessibilitySlide\",\n \"AccessibilitySpecimen\",\n \"Accordion\",\n \"AccordionContent\",\n \"AccordionItem\",\n \"AccordionTrigger\",\n \"ActivityFeed\",\n \"ActivityFeedContext\",\n \"ActivityFeedItem\",\n \"ActivityFeedRoot\",\n \"AdminDashboard\",\n \"AdminDetail\",\n \"AdminDetailDrawer\",\n \"AdminListPage\",\n \"AdminListPageInner\",\n \"AdminSettingsPage\",\n \"AdminShell\",\n \"AdminTabbedEditor\",\n \"AdminWizard\",\n \"Alert\",\n \"AlertActions\",\n \"AlertDescription\",\n \"AlertTitle\",\n \"AmbientGlow\",\n \"Avatar\",\n \"AvatarFallback\",\n \"AvatarImage\",\n \"AvatarStack\",\n \"Badge\",\n \"Banner\",\n \"BannerAction\",\n \"BannerDescription\",\n \"BannerTitle\",\n \"BentoGrid\",\n \"BentoTile\",\n \"BentoTileBody\",\n \"BentoTileDescription\",\n \"BentoTileFigure\",\n \"BentoTileHeadline\",\n \"BentoTileMedia\",\n \"BentoTileMeta\",\n \"BentoTileTitle\",\n \"Box\",\n \"Breadcrumb\",\n \"BreadcrumbEllipsis\",\n \"BreadcrumbItem\",\n \"BreadcrumbLink\",\n \"BreadcrumbList\",\n \"BreadcrumbPage\",\n \"BreadcrumbSeparator\",\n \"BrowserFrame\",\n \"BulkActionBar\",\n \"Button\",\n \"ButtonSpecimenSection\",\n \"ButtonSpecimenSlide\",\n \"Calendar\",\n \"Capture\",\n \"Card\",\n \"CardContent\",\n \"CardDescription\",\n \"CardFooter\",\n \"CardGrid\",\n \"CardHeader\",\n \"CardLift\",\n \"CardTitle\",\n \"Carousel\",\n \"CarouselContent\",\n \"CarouselContext\",\n \"CarouselGallery\",\n \"CarouselItem\",\n \"CarouselNext\",\n \"CarouselPrevious\",\n \"ChallengeCard\",\n \"ChallengeCardAction\",\n \"ChallengeCardActions\",\n \"ChallengeCardBody\",\n \"ChallengeCardGate\",\n \"ChallengeCardHeader\",\n \"ChartContainer\",\n \"ChartContext\",\n \"ChartLegend\",\n \"ChartLegendContent\",\n \"ChartStyle\",\n \"ChartTooltip\",\n \"ChartTooltipContent\",\n \"Checkbox\",\n \"CheckGroup\",\n \"CheckRow\",\n \"Chip\",\n \"ChipGroup\",\n \"ChipGroupContext\",\n \"ChipGroupItem\",\n \"ChoiceChip\",\n \"ChromeButton\",\n \"ClosingSlide\",\n \"CodeBlock\",\n \"Collapsible\",\n \"CollapsibleContent\",\n \"CollapsibleTrigger\",\n \"ColorBar\",\n \"ColorPaletteSection\",\n \"ColorPicker\",\n \"ColorPickerSurface\",\n \"ColorSwatch\",\n \"ColorSwatchGrid\",\n \"Combobox\",\n \"ComboboxContent\",\n \"ComboboxContext\",\n \"ComboboxEmpty\",\n \"ComboboxGroup\",\n \"ComboboxInput\",\n \"ComboboxItem\",\n \"ComboboxSeparator\",\n \"Command\",\n \"CommandDialog\",\n \"CommandEmpty\",\n \"CommandGroup\",\n \"CommandInput\",\n \"CommandItem\",\n \"CommandList\",\n \"CommandLoading\",\n \"CommandSeparator\",\n \"CommandShortcut\",\n \"ComponentShowcaseContent\",\n \"ComponentShowcaseSection\",\n \"ComponentShowcaseSlide\",\n \"Composer\",\n \"ComposerContext\",\n \"ComposerField\",\n \"ComposerSend\",\n \"ComposerSpacer\",\n \"ComposerToolbar\",\n \"ComposerToolButton\",\n \"ConceptSlide\",\n \"ConfigurationPanel\",\n \"ConfirmDialog\",\n \"ConflictBanner\",\n \"Container\",\n \"ContextMenu\",\n \"ContextMenuCheckboxItem\",\n \"ContextMenuContent\",\n \"ContextMenuGroup\",\n \"ContextMenuItem\",\n \"ContextMenuLabel\",\n \"ContextMenuPortal\",\n \"ContextMenuRadioGroup\",\n \"ContextMenuRadioItem\",\n \"ContextMenuSeparator\",\n \"ContextMenuShortcut\",\n \"ContextMenuSub\",\n \"ContextMenuSubContent\",\n \"ContextMenuSubTrigger\",\n \"ContextMenuTrigger\",\n \"Controls\",\n \"CtaSection\",\n \"DataTable\",\n \"DataTableInner\",\n \"DatePicker\",\n \"DateRangePicker\",\n \"DeckContext\",\n \"DeckFooter\",\n \"DeckLayout\",\n \"DeckProvider\",\n \"DeckRenderer\",\n \"DesignSystemDeck\",\n \"DesignSystemSpecimen\",\n \"Dialog\",\n \"DialogClose\",\n \"DialogContent\",\n \"DialogDescription\",\n \"DialogFooter\",\n \"DialogHeader\",\n \"DialogOverlay\",\n \"DialogPortal\",\n \"DialogTitle\",\n \"DialogTrigger\",\n \"DocFrame\",\n \"DocFrameBrand\",\n \"DocNav\",\n \"DocNavGroup\",\n \"DocNavPill\",\n \"DotNav\",\n \"DropdownMenu\",\n \"DropdownMenuCheckboxItem\",\n \"DropdownMenuContent\",\n \"DropdownMenuGroup\",\n \"DropdownMenuItem\",\n \"DropdownMenuLabel\",\n \"DropdownMenuPortal\",\n \"DropdownMenuRadioGroup\",\n \"DropdownMenuRadioItem\",\n \"DropdownMenuSeparator\",\n \"DropdownMenuShortcut\",\n \"DropdownMenuSub\",\n \"DropdownMenuSubContent\",\n \"DropdownMenuSubTrigger\",\n \"DropdownMenuTrigger\",\n \"EditableBlock\",\n \"ElevationCard\",\n \"ElevationSlide\",\n \"EmptyState\",\n \"ErrorPlacard\",\n \"ExportMenu\",\n \"FeaturesGrid\",\n \"FidelityMirror\",\n \"Field\",\n \"FieldDescription\",\n \"FieldError\",\n \"FieldLabel\",\n \"Fieldset\",\n \"FieldsetLegend\",\n \"FileUpload\",\n \"FilterBar\",\n \"FilterChip\",\n \"FontShowcase\",\n \"FontShowcaseGrid\",\n \"Footer\",\n \"FooterSection\",\n \"Form\",\n \"FormError\",\n \"FormErrorDescription\",\n \"FormErrorTitle\",\n \"FormField\",\n \"FormSpecimenSection\",\n \"FormSpecimenSlide\",\n \"FullscreenOverlay\",\n \"FullscreenOverlayContent\",\n \"FullscreenOverlayTrigger\",\n \"GrainOverlay\",\n \"Grid\",\n \"Header\",\n \"Heading\",\n \"HeroGlow\",\n \"HeroSection\",\n \"HeroSlide\",\n \"HoverCard\",\n \"HoverCardContent\",\n \"HoverCardTrigger\",\n \"IconGrid\",\n \"IconGridSection\",\n \"IconSizeRow\",\n \"IconsSlide\",\n \"Image\",\n \"InfographicBar\",\n \"Inline\",\n \"Input\",\n \"Kbd\",\n \"KeyValueList\",\n \"Label\",\n \"Landing\",\n \"Lightbox\",\n \"LightboxContent\",\n \"LightboxContext\",\n \"LightboxTrigger\",\n \"LoginForm\",\n \"Marquee\",\n \"MarqueeBandRenderer\",\n \"MatrixCell\",\n \"MatrixTable\",\n \"MatrixTableInner\",\n \"Menubar\",\n \"MenubarCheckboxItem\",\n \"MenubarContent\",\n \"MenubarGroup\",\n \"MenubarItem\",\n \"MenubarLabel\",\n \"MenubarMenu\",\n \"MenubarRadioGroup\",\n \"MenubarRadioItem\",\n \"MenubarSeparator\",\n \"MenubarShortcut\",\n \"MenubarSub\",\n \"MenubarSubContent\",\n \"MenubarSubTrigger\",\n \"MenubarTrigger\",\n \"MonthCalendar\",\n \"MotionDuration\",\n \"MotionDurationSection\",\n \"MotionEasing\",\n \"MotionEasingSection\",\n \"MotionSlide\",\n \"NameRoster\",\n \"NameRosterItem\",\n \"Navbar\",\n \"NavbarBrand\",\n \"NavbarContent\",\n \"NavbarItem\",\n \"NavbarLink\",\n \"NavbarToggle\",\n \"NumberInput\",\n \"OfflineBanner\",\n \"OpacityBar\",\n \"OpacitySlide\",\n \"OTPInput\",\n \"PageHeader\",\n \"Pagination\",\n \"PaginationContent\",\n \"PaginationEllipsis\",\n \"PaginationItem\",\n \"PaginationLink\",\n \"PaginationNext\",\n \"PaginationPrevious\",\n \"PasswordInput\",\n \"PhoneInput\",\n \"PlatformChip\",\n \"Popover\",\n \"PopoverAnchor\",\n \"PopoverContent\",\n \"PopoverFooter\",\n \"PopoverSelectionItem\",\n \"PopoverSelectionLabel\",\n \"PopoverSelectionList\",\n \"PopoverTrigger\",\n \"PricingSection\",\n \"ProfileMenu\",\n \"Progress\",\n \"PrototypeReview\",\n \"QuickActions\",\n \"RadioGroup\",\n \"RadioGroupItem\",\n \"RadiusScale\",\n \"RadiusSection\",\n \"RadiusSlide\",\n \"RecordSection\",\n \"RightRailList\",\n \"ScoreIndicator\",\n \"ScrollArea\",\n \"ScrollBar\",\n \"SearchInput\",\n \"SectionHeader\",\n \"SectionIntro\",\n \"SectionNav\",\n \"SectionNavItem\",\n \"SegmentedProgress\",\n \"Select\",\n \"SelectContent\",\n \"SelectGroup\",\n \"SelectionListContext\",\n \"SelectItem\",\n \"SelectLabel\",\n \"SelectScrollDownButton\",\n \"SelectScrollUpButton\",\n \"SelectSeparator\",\n \"SelectTrigger\",\n \"SelectValue\",\n \"SemanticColorGrid\",\n \"SemanticColorItem\",\n \"SemanticTokensSlide\",\n \"SensitivePanel\",\n \"Separator\",\n \"SessionTimeout\",\n \"ShadowSection\",\n \"Sheet\",\n \"SheetClose\",\n \"SheetContent\",\n \"SheetDescription\",\n \"SheetFooter\",\n \"SheetHeader\",\n \"SheetOverlay\",\n \"SheetPortal\",\n \"SheetTitle\",\n \"SheetTrigger\",\n \"Sidebar\",\n \"SidebarContent\",\n \"SidebarContext\",\n \"SidebarFooter\",\n \"SidebarGroup\",\n \"SidebarGroupAction\",\n \"SidebarGroupContent\",\n \"SidebarGroupLabel\",\n \"SidebarHeader\",\n \"SidebarInset\",\n \"SidebarMenu\",\n \"SidebarMenuAction\",\n \"SidebarMenuBadge\",\n \"SidebarMenuButton\",\n \"SidebarMenuItem\",\n \"SidebarMenuSub\",\n \"SidebarMenuSubButton\",\n \"SidebarMenuSubItem\",\n \"SidebarProvider\",\n \"SidebarRail\",\n \"SidebarSeparator\",\n \"SidebarTrigger\",\n \"Skeleton\",\n \"SkeletonDetail\",\n \"SkeletonList\",\n \"SkeletonTable\",\n \"Slide\",\n \"SlideHeader\",\n \"Slider\",\n \"SliderControl\",\n \"SlideThemeContext\",\n \"SlideThemeProvider\",\n \"SlowNetworkBar\",\n \"SourceInspector\",\n \"SourceInspectorContext\",\n \"SourceInspectorDevImpl\",\n \"SourceInspectorProvider\",\n \"SourceInspectorRunner\",\n \"SourceInspectorToggle\",\n \"SpacingScale\",\n \"SpacingSection\",\n \"SpacingSlide\",\n \"Sparkline\",\n \"SpecimenCard\",\n \"SpecimenCardFooter\",\n \"Sphere\",\n \"SpherePlayground\",\n \"Spinner\",\n \"Stack\",\n \"Stage\",\n \"StatCard\",\n \"StatHero\",\n \"StationSpectrum\",\n \"StatusBadge\",\n \"StatusColorsSlide\",\n \"StatusDot\",\n \"Stepper\",\n \"StepperContext\",\n \"StepperDescription\",\n \"StepperItem\",\n \"StepperSeparator\",\n \"StepperTitle\",\n \"StepperTrigger\",\n \"StepsSection\",\n \"StructuredPrompt\",\n \"StructuredPromptBody\",\n \"StructuredPromptHeader\",\n \"StructuredPromptHint\",\n \"StructuredPromptSlot\",\n \"SuccessLiveRegion\",\n \"SurfaceRow\",\n \"SurfaceScaleStack\",\n \"SurfaceSection\",\n \"Switch\",\n \"Table\",\n \"TableBody\",\n \"TableCaption\",\n \"TableCell\",\n \"TableFooter\",\n \"TableHead\",\n \"TableHeader\",\n \"TableRow\",\n \"Tabs\",\n \"TabsContent\",\n \"TabsList\",\n \"TabsTrigger\",\n \"TagInput\",\n \"TestimonialAttribution\",\n \"TestimonialSection\",\n \"Text\",\n \"Textarea\",\n \"ThemeArchitectureSlide\",\n \"ThemeColorsSlide\",\n \"ThemeSwitcher\",\n \"Timeline\",\n \"TimelineContent\",\n \"TimelineDescription\",\n \"TimelineIcon\",\n \"TimelineItem\",\n \"TimelineTimestamp\",\n \"TimelineTitle\",\n \"TitleSlide\",\n \"ToastCard\",\n \"ToastCardStack\",\n \"Toaster\",\n \"TOCSlide\",\n \"ToggleButton\",\n \"ToggleDevImpl\",\n \"ToggleGroup\",\n \"ToggleGroupContext\",\n \"ToggleGroupItem\",\n \"Tooltip\",\n \"TooltipContent\",\n \"TooltipProvider\",\n \"TooltipTrigger\",\n \"TypeBodySlide\",\n \"TypeDisplaySlide\",\n \"TypeScaleStack\",\n \"TypeSpecimen\",\n \"TypographySection\",\n \"Vignette\",\n \"WorkspaceSwitcher\",\n])\n"
|
|
5092
5117
|
}
|
|
5093
5118
|
]
|
|
5094
5119
|
},
|
package/dist/visor-manifest.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": "0.4.0",
|
|
3
|
-
"generated_at": "2026-07-
|
|
3
|
+
"generated_at": "2026-07-15T17:44:38.978Z",
|
|
4
4
|
"components": {
|
|
5
5
|
"accessibility-specimen": {
|
|
6
6
|
"category": "specimen",
|
|
@@ -3513,6 +3513,8 @@
|
|
|
3513
3513
|
"--doc-frame-max-width",
|
|
3514
3514
|
"--focus-ring-offset",
|
|
3515
3515
|
"--focus-ring-width",
|
|
3516
|
+
"--font-display",
|
|
3517
|
+
"--font-family-heading",
|
|
3516
3518
|
"--font-mono",
|
|
3517
3519
|
"--font-size-2xs",
|
|
3518
3520
|
"--font-size-lg",
|
|
@@ -4100,6 +4102,138 @@
|
|
|
4100
4102
|
],
|
|
4101
4103
|
"example": "import { WarningCircle } from '@phosphor-icons/react';\n\n<ErrorPlacard\n icon={<WarningCircle weight=\"fill\" />}\n title=\"Could not load members\"\n body=\"The request timed out. Check your connection and try again.\"\n actions={\n <>\n <Button variant=\"ghost\" size=\"sm\">Dismiss</Button>\n <Button variant=\"outline\" size=\"sm\">Retry</Button>\n </>\n }\n/>\n"
|
|
4102
4104
|
},
|
|
4105
|
+
"fidelity-mirror": {
|
|
4106
|
+
"category": "data-display",
|
|
4107
|
+
"description": "The design-left / built-right comparison surface — renders a pure-HTML design source beside its Visor-TSX render (or a native/Flutter device-framed screenshot set, or an external artifact) in recessed capture wells, with a verdict diff indicator, numbered delta callouts, a classed delta legend, and a drag-to-reveal overlay mode. Composes inside DocFrame's content and goes full-bleed on widescreen so each pane is ~50vw. This is the Fidelity Mirror DISPLAY; the screenshot-diff GATE (PL-2139) is a separate verification concern.",
|
|
4108
|
+
"when_to_use": [
|
|
4109
|
+
"A Fidelity Mirror doc surface that renders a design-vs-built comparison inside DocFrame, so the doc type is Borealis-native rather than hand-rolled per project",
|
|
4110
|
+
"Showing the pure HTML design (left) against the Visor-ified TSX render (right) with a diff verdict and enumerated, classed deltas",
|
|
4111
|
+
"Comparing a native (SwiftUI) or Flutter screen against its design inside a device bezel, or an external claude.ai artifact against its source",
|
|
4112
|
+
"A widescreen full-bleed compare where each pane spans ~50vw for pixel-level review on a fullscreen monitor"
|
|
4113
|
+
],
|
|
4114
|
+
"when_not_to_use": [
|
|
4115
|
+
"The fidelity GATE — screenshot-diff verification that a build matches its design (that is PL-2139 / Gate 16, a verification concern, not a display one)",
|
|
4116
|
+
"The themed doc-page shell / sticky header / brand slot (use DocFrame — VI-609)",
|
|
4117
|
+
"The grouped, collapsible doc navigation (use DocNav — VI-608)",
|
|
4118
|
+
"A generic two-up media comparison with no design-fidelity semantics (use a plain grid or Carousel)"
|
|
4119
|
+
],
|
|
4120
|
+
"variants": {},
|
|
4121
|
+
"props": [
|
|
4122
|
+
{
|
|
4123
|
+
"name": "title",
|
|
4124
|
+
"type": "string",
|
|
4125
|
+
"required": true,
|
|
4126
|
+
"description": "The compared surface's name — the header title (e.g. a component or screen name)."
|
|
4127
|
+
},
|
|
4128
|
+
{
|
|
4129
|
+
"name": "design",
|
|
4130
|
+
"type": "FidelitySource",
|
|
4131
|
+
"required": true,
|
|
4132
|
+
"description": "The DESIGN source (left pane) — the pure-HTML design. Renders `content` when present, else an `<img>` (image) or a live-route/external `<iframe>` from `src`. Carries an optional pane `label` + mono `meta`."
|
|
4133
|
+
},
|
|
4134
|
+
{
|
|
4135
|
+
"name": "built",
|
|
4136
|
+
"type": "FidelitySource",
|
|
4137
|
+
"required": true,
|
|
4138
|
+
"description": "The BUILT source (right pane) — the Visor-TSX render, or a device-framed screenshot for native/flutter. Same shape as `design`; the built pane also draws the numbered delta callouts."
|
|
4139
|
+
},
|
|
4140
|
+
{
|
|
4141
|
+
"name": "verdict",
|
|
4142
|
+
"type": "'match' | 'drift' | 'fail'",
|
|
4143
|
+
"required": true,
|
|
4144
|
+
"description": "The diff verdict — tints the status pill (the diff indicator). match → success, drift → warning, fail → destructive."
|
|
4145
|
+
},
|
|
4146
|
+
{
|
|
4147
|
+
"name": "platform",
|
|
4148
|
+
"type": "'web' | 'native' | 'flutter' | 'external'",
|
|
4149
|
+
"default": "'web'",
|
|
4150
|
+
"description": "Platform of the built surface. Drives the built-side renderer and the header chip — web → live-route iframe + \"Web · Live Route\"; native → SwiftUI screenshot in a device bezel + \"iOS · SwiftUI\"; flutter → device-framed image + \"Flutter\"; external → external artifact + \"External\"."
|
|
4151
|
+
},
|
|
4152
|
+
{
|
|
4153
|
+
"name": "mode",
|
|
4154
|
+
"type": "'split' | 'overlay'",
|
|
4155
|
+
"default": "'split'",
|
|
4156
|
+
"description": "Initial compare presentation — split (design-left / built-right in recessed wells) or overlay (drag-to-reveal slider seam). The header segmented toggle switches in place."
|
|
4157
|
+
},
|
|
4158
|
+
{
|
|
4159
|
+
"name": "score",
|
|
4160
|
+
"type": "string",
|
|
4161
|
+
"description": "Optional score/summary string on the status pill (e.g. \"99.4%\", \"3 deltas\")."
|
|
4162
|
+
},
|
|
4163
|
+
{
|
|
4164
|
+
"name": "deltas",
|
|
4165
|
+
"type": "FidelityDelta[]",
|
|
4166
|
+
"description": "Enumerated drifts — each renders a numbered callout on the built side (when it carries a `position`) and a classed legend row. Classes mirror the render-vs-design self-check taxonomy (radius | color | spacing | type | align). Omit → no callouts or legend (e.g. a MATCH case)."
|
|
4167
|
+
},
|
|
4168
|
+
{
|
|
4169
|
+
"name": "bleed",
|
|
4170
|
+
"type": "boolean",
|
|
4171
|
+
"default": "true",
|
|
4172
|
+
"description": "Widescreen full-bleed layout — the compare escapes DocFrame's centered column and spans the viewport so each pane is ~50vw with the center gutter equal to the outer padding. Under 768px the panes stack design-over-built."
|
|
4173
|
+
},
|
|
4174
|
+
{
|
|
4175
|
+
"name": "overlayPosition",
|
|
4176
|
+
"type": "number",
|
|
4177
|
+
"default": "55",
|
|
4178
|
+
"description": "Initial overlay reveal position (0–100), the percent of the design source shown from the left before the slider seam."
|
|
4179
|
+
},
|
|
4180
|
+
{
|
|
4181
|
+
"name": "onModeChange",
|
|
4182
|
+
"type": "(mode: 'split' | 'overlay') => void",
|
|
4183
|
+
"description": "Notified when the compare mode toggles via the header segmented control."
|
|
4184
|
+
}
|
|
4185
|
+
],
|
|
4186
|
+
"dependencies": [
|
|
4187
|
+
"@phosphor-icons/react",
|
|
4188
|
+
"@loworbitstudio/visor-core"
|
|
4189
|
+
],
|
|
4190
|
+
"tokens_used": [
|
|
4191
|
+
"--accent",
|
|
4192
|
+
"--border-focus",
|
|
4193
|
+
"--color-neutral-950",
|
|
4194
|
+
"--color-white",
|
|
4195
|
+
"--destructive",
|
|
4196
|
+
"--fm-built-hue",
|
|
4197
|
+
"--fm-design-hue",
|
|
4198
|
+
"--fm-pad",
|
|
4199
|
+
"--fm-radius",
|
|
4200
|
+
"--fm-split",
|
|
4201
|
+
"--fm-well",
|
|
4202
|
+
"--fm-well-radius",
|
|
4203
|
+
"--focus-ring-offset",
|
|
4204
|
+
"--focus-ring-width",
|
|
4205
|
+
"--font-mono",
|
|
4206
|
+
"--font-sans",
|
|
4207
|
+
"--font-size-2xs",
|
|
4208
|
+
"--font-size-sm",
|
|
4209
|
+
"--font-weight-bold",
|
|
4210
|
+
"--font-weight-medium",
|
|
4211
|
+
"--hairline",
|
|
4212
|
+
"--info",
|
|
4213
|
+
"--motion-duration-fast",
|
|
4214
|
+
"--motion-easing-standard",
|
|
4215
|
+
"--opacity-80",
|
|
4216
|
+
"--radius-full",
|
|
4217
|
+
"--radius-sm",
|
|
4218
|
+
"--shadow-lg",
|
|
4219
|
+
"--shadow-md",
|
|
4220
|
+
"--spacing-1",
|
|
4221
|
+
"--spacing-10",
|
|
4222
|
+
"--spacing-2",
|
|
4223
|
+
"--spacing-3",
|
|
4224
|
+
"--spacing-4",
|
|
4225
|
+
"--stroke-width-thin",
|
|
4226
|
+
"--success",
|
|
4227
|
+
"--surface-card",
|
|
4228
|
+
"--surface-page",
|
|
4229
|
+
"--surface-subtle",
|
|
4230
|
+
"--text-primary",
|
|
4231
|
+
"--text-secondary",
|
|
4232
|
+
"--text-tertiary",
|
|
4233
|
+
"--warning"
|
|
4234
|
+
],
|
|
4235
|
+
"example": "import { FidelityMirror } from '@/components/ui/fidelity-mirror/fidelity-mirror'\n\nexport function DocNavMirror() {\n return (\n <FidelityMirror\n title=\"DocNav\"\n subtitle=\"Fidelity Mirror · VI-611\"\n platform=\"web\"\n verdict=\"drift\"\n score=\"3 deltas\"\n design={{ content: <DesignCapture />, meta: 'index.html' }}\n built={{ content: <BuiltCapture />, meta: 'route · /doc-nav' }}\n deltas={[\n { class: 'radius', description: <>Group cluster corners <b>22px → 12px</b>.</>, position: { top: '34px', left: '12px' } },\n { class: 'color', description: <>Resting pills read <b>--surface-subtle</b> — should be a recessed well.</>, position: { top: '52px', left: '96px' } },\n { class: 'type', description: <>Group labels are <b>title-case</b> — should be all-caps mono.</>, position: { top: '34px', right: '12px' } },\n ]}\n />\n )\n}\n"
|
|
4236
|
+
},
|
|
4103
4237
|
"field": {
|
|
4104
4238
|
"category": "form",
|
|
4105
4239
|
"description": "A form field wrapper composing label, description, and error components.",
|
|
@@ -12260,6 +12394,7 @@
|
|
|
12260
12394
|
"bento-grid",
|
|
12261
12395
|
"card",
|
|
12262
12396
|
"chart",
|
|
12397
|
+
"fidelity-mirror",
|
|
12263
12398
|
"key-value-list",
|
|
12264
12399
|
"marquee",
|
|
12265
12400
|
"name-roster",
|