@loworbitstudio/visor 1.35.0 → 1.36.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.
- package/dist/CHANGELOG.json +1 -1
- package/dist/registry.json +5 -5
- package/dist/visor-manifest.json +15 -2
- package/package.json +2 -2
package/dist/CHANGELOG.json
CHANGED
package/dist/registry.json
CHANGED
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
{
|
|
47
47
|
"path": "components/ui/heading/heading.module.css",
|
|
48
48
|
"type": "registry:ui",
|
|
49
|
-
"content": "/* Heading base styles */\n.base {\n font-family: var(--font-heading, ui-sans-serif, system-ui, sans-serif);\n color: var(--text-primary, #111827);\n line-height: var(--line-height-tight, 1.25);\n margin: 0;\n}\n\n/* Sizes */\n.sizeXs {\n font-size: var(--font-size-sm, 0.875rem);\n}\n\n.sizeSm {\n font-size: var(--font-size-base, 1rem);\n}\n\n.sizeMd {\n font-size: var(--font-size-lg, 1.125rem);\n}\n\n.sizeLg {\n font-size: var(--font-size-xl, 1.25rem);\n}\n\n.sizeXl {\n font-size: var(--font-size-2xl, 1.5rem);\n}\n\n.size2xl {\n font-size: var(--font-size-4xl, 2.25rem);\n}\n\n/* Weights */\n\n/*\n * VI-639: the theme's own heading weight. `--font-weight-heading` carries what\n * this theme says headings weigh; `--font-weight-semibold` is a step on the\n * named ramp and no longer doubles as that channel. Falls back through semibold\n * so a consumer on an older tokens package keeps the previous resolution.\n */\n.weightHeading {\n font-weight: var(--font-weight-heading, var(--font-weight-semibold, 600));\n}\n\n.weightNormal {\n font-weight: var(--font-weight-normal, 400);\n}\n\n.weightMedium {\n font-weight: var(--font-weight-medium, 500);\n}\n\n.weightSemibold {\n font-weight: var(--font-weight-semibold, 600);\n}\n\n.weightBold {\n font-weight: var(--font-weight-bold, 700);\n}\n"
|
|
49
|
+
"content": "/* Heading base styles */\n.base {\n font-family: var(--font-heading, ui-sans-serif, system-ui, sans-serif);\n color: var(--text-primary, #111827);\n line-height: var(--line-height-tight, 1.25);\n /* VI-687: theme-set heading casing; inherit (the CSS default) when unset. */\n text-transform: var(--font-heading-text-transform, inherit);\n margin: 0;\n}\n\n/* Sizes */\n.sizeXs {\n font-size: var(--font-size-sm, 0.875rem);\n}\n\n.sizeSm {\n font-size: var(--font-size-base, 1rem);\n}\n\n.sizeMd {\n font-size: var(--font-size-lg, 1.125rem);\n}\n\n.sizeLg {\n font-size: var(--font-size-xl, 1.25rem);\n}\n\n.sizeXl {\n font-size: var(--font-size-2xl, 1.5rem);\n}\n\n.size2xl {\n font-size: var(--font-size-4xl, 2.25rem);\n}\n\n/* Weights */\n\n/*\n * VI-639: the theme's own heading weight. `--font-weight-heading` carries what\n * this theme says headings weigh; `--font-weight-semibold` is a step on the\n * named ramp and no longer doubles as that channel. Falls back through semibold\n * so a consumer on an older tokens package keeps the previous resolution.\n */\n.weightHeading {\n font-weight: var(--font-weight-heading, var(--font-weight-semibold, 600));\n}\n\n.weightNormal {\n font-weight: var(--font-weight-normal, 400);\n}\n\n.weightMedium {\n font-weight: var(--font-weight-medium, 500);\n}\n\n.weightSemibold {\n font-weight: var(--font-weight-semibold, 600);\n}\n\n.weightBold {\n font-weight: var(--font-weight-bold, 700);\n}\n"
|
|
50
50
|
}
|
|
51
51
|
]
|
|
52
52
|
},
|
|
@@ -322,7 +322,7 @@
|
|
|
322
322
|
{
|
|
323
323
|
"path": "components/ui/select/select.tsx",
|
|
324
324
|
"type": "registry:ui",
|
|
325
|
-
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as SelectPrimitive from \"@radix-ui/react-select\"\nimport { CaretDownIcon, CaretUpIcon, CheckIcon } from \"@phosphor-icons/react\"\nimport { cn } from \"../../../lib/utils\"\nimport styles from \"./select.module.css\"\n\nconst Select = SelectPrimitive.Root\n\nconst SelectGroup = SelectPrimitive.Group\n\nconst SelectValue = SelectPrimitive.Value\n\nconst SelectTrigger = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger> & {\n size?: \"sm\" | \"md\" | \"lg\"\n /**\n * Visual variant of the closed trigger. `\"default\"` keeps the 1px border on\n * the standard control surface. `\"borderless\"` drops the border and sits on\n * `--field-control-bg`, matching a borderless Input inside an in-dialog form\n * context (one that sets `--field-control-bg: var(--surface-subtle)`).\n * Opt-in — default is unchanged.\n */\n variant?: \"default\" | \"borderless\"\n }\n>(({ className, size = \"md\", variant = \"default\", children, ...props }, ref) => {\n const sizeClass = {\n sm: styles.triggerSizeSm,\n md: styles.triggerSizeMd,\n lg: styles.triggerSizeLg,\n }[size]\n\n return (\n <SelectPrimitive.Trigger\n data-slot=\"select-trigger\"\n data-size={size}\n data-variant={variant}\n className={cn(\n styles.trigger,\n sizeClass,\n variant === \"borderless\" && styles.triggerBorderless,\n className\n )}\n ref={ref}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <CaretDownIcon className={styles.triggerIcon} />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n )\n})\nSelectTrigger.displayName = SelectPrimitive.Trigger.displayName\n\nconst SelectContent = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Content>,\n
|
|
325
|
+
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as SelectPrimitive from \"@radix-ui/react-select\"\nimport { CaretDownIcon, CaretUpIcon, CheckIcon } from \"@phosphor-icons/react\"\nimport { cn } from \"../../../lib/utils\"\nimport styles from \"./select.module.css\"\n\nconst Select = SelectPrimitive.Root\n\nconst SelectGroup = SelectPrimitive.Group\n\nconst SelectValue = SelectPrimitive.Value\n\nconst SelectTrigger = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger> & {\n size?: \"sm\" | \"md\" | \"lg\"\n /**\n * Visual variant of the closed trigger. `\"default\"` keeps the 1px border on\n * the standard control surface. `\"borderless\"` drops the border and sits on\n * `--field-control-bg`, matching a borderless Input inside an in-dialog form\n * context (one that sets `--field-control-bg: var(--surface-subtle)`).\n * Opt-in — default is unchanged.\n */\n variant?: \"default\" | \"borderless\"\n }\n>(({ className, size = \"md\", variant = \"default\", children, ...props }, ref) => {\n const sizeClass = {\n sm: styles.triggerSizeSm,\n md: styles.triggerSizeMd,\n lg: styles.triggerSizeLg,\n }[size]\n\n return (\n <SelectPrimitive.Trigger\n data-slot=\"select-trigger\"\n data-size={size}\n data-variant={variant}\n className={cn(\n styles.trigger,\n sizeClass,\n variant === \"borderless\" && styles.triggerBorderless,\n className\n )}\n ref={ref}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <CaretDownIcon className={styles.triggerIcon} />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n )\n})\nSelectTrigger.displayName = SelectPrimitive.Trigger.displayName\n\ninterface SelectContentProps\n extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content> {\n /**\n * Element the menu portals into. Defaults to `document.body`. Pass the root\n * of a class-scoped theme so the menu inherits that theme's tokens.\n */\n container?: React.ComponentPropsWithoutRef<typeof SelectPrimitive.Portal>[\"container\"]\n}\n\nconst SelectContent = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Content>,\n SelectContentProps\n>(({ className, children, position = \"popper\", container, ...props }, ref) => {\n return (\n <SelectPrimitive.Portal container={container}>\n <SelectPrimitive.Content\n data-slot=\"select-content\"\n className={cn(styles.content, className)}\n position={position}\n ref={ref}\n {...props}\n >\n <SelectScrollUpButton />\n <SelectPrimitive.Viewport\n className={cn(\n styles.viewport,\n position === \"popper\" && styles.viewportPopper\n )}\n >\n {children}\n </SelectPrimitive.Viewport>\n <SelectScrollDownButton />\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n )\n})\nSelectContent.displayName = SelectPrimitive.Content.displayName\n\nconst SelectLabel = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>\n>(({ className, ...props }, ref) => {\n return (\n <SelectPrimitive.Label\n data-slot=\"select-label\"\n className={cn(styles.label, className)}\n ref={ref}\n {...props}\n />\n )\n})\nSelectLabel.displayName = SelectPrimitive.Label.displayName\n\nconst SelectItem = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>\n>(({ className, children, ...props }, ref) => {\n return (\n <SelectPrimitive.Item\n data-slot=\"select-item\"\n className={cn(styles.item, className)}\n ref={ref}\n {...props}\n >\n <span className={styles.itemIndicatorWrapper}>\n <SelectPrimitive.ItemIndicator>\n <CheckIcon className={styles.itemIndicatorIcon} />\n </SelectPrimitive.ItemIndicator>\n </span>\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n </SelectPrimitive.Item>\n )\n})\nSelectItem.displayName = SelectPrimitive.Item.displayName\n\nconst SelectSeparator = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>\n>(({ className, ...props }, ref) => {\n return (\n <SelectPrimitive.Separator\n data-slot=\"select-separator\"\n className={cn(styles.separator, className)}\n ref={ref}\n {...props}\n />\n )\n})\nSelectSeparator.displayName = SelectPrimitive.Separator.displayName\n\nconst SelectScrollUpButton = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>\n>(({ className, ...props }, ref) => {\n return (\n <SelectPrimitive.ScrollUpButton\n data-slot=\"select-scroll-up-button\"\n className={cn(styles.scrollButton, className)}\n ref={ref}\n {...props}\n >\n <CaretUpIcon className={styles.scrollButtonIcon} />\n </SelectPrimitive.ScrollUpButton>\n )\n})\nSelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName\n\nconst SelectScrollDownButton = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>\n>(({ className, ...props }, ref) => {\n return (\n <SelectPrimitive.ScrollDownButton\n data-slot=\"select-scroll-down-button\"\n className={cn(styles.scrollButton, className)}\n ref={ref}\n {...props}\n >\n <CaretDownIcon className={styles.scrollButtonIcon} />\n </SelectPrimitive.ScrollDownButton>\n )\n})\nSelectScrollDownButton.displayName =\n SelectPrimitive.ScrollDownButton.displayName\n\nexport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectScrollDownButton,\n SelectScrollUpButton,\n SelectSeparator,\n SelectTrigger,\n SelectValue,\n}\nexport type { SelectContentProps }\n"
|
|
326
326
|
},
|
|
327
327
|
{
|
|
328
328
|
"path": "components/ui/select/select.module.css",
|
|
@@ -353,7 +353,7 @@
|
|
|
353
353
|
{
|
|
354
354
|
"path": "components/ui/switch/switch.module.css",
|
|
355
355
|
"type": "registry:ui",
|
|
356
|
-
"content": "/* Switch root styles */\n.root {\n position: relative;\n display: inline-flex;\n flex-shrink: 0;\n align-items: center;\n border-radius: 9999px;\n /* VI-655: the border only holds box geometry. The track's resting edge is an\n inset outline on the shared --control-edge-* tokens; it is transparent\n unless a theme sets --switch-edge-color, and --control-edge-width: 0\n removes it with every other control's edge. */\n border: 1px solid transparent;\n background-color: var(--switch-track-bg, var(--border-default, #e5e7eb));\n transition: background-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out), outline-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out), box-shadow var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n outline: var(--control-edge-width, 1px) var(--control-edge-style, solid) var(--switch-edge-color, transparent);\n outline-offset: calc(-1 * var(--control-edge-width, 1px));\n cursor: pointer;\n}\n\n@media (hover: hover) {\n .root:hover:not(:focus-visible):not(:disabled):not([aria-invalid=\"true\"]) {\n background-color: var(--border-strong, #d1d5db);\n }\n}\n\n/* Focus and invalid draw at --control-state-edge-width, which the edge switch\n does not touch. */\n.root:focus-visible {\n outline: var(--control-state-edge-width, 1px) solid var(--border-focus, #111827);\n outline-offset: calc(-1 * var(--control-state-edge-width, 1px));\n box-shadow: 0 0 0 var(--focus-ring-width, 2px) color-mix(in srgb, var(--border-focus, #111827) 15%, transparent);\n}\n\n.root:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n.root[aria-invalid=\"true\"] {\n outline: var(--control-state-edge-width, 1px) solid var(--border-error, #ef4444);\n outline-offset: calc(-1 * var(--control-state-edge-width, 1px));\n box-shadow: 0 0 0 var(--focus-ring-width, 2px) color-mix(in srgb, var(--border-error, #ef4444) 15%, transparent);\n}\n\n.root[data-state=\"checked\"] {\n background-color: var(--interactive-primary-bg, var(--primary, #111827));\n}\n\n/* Size variants\n The default size takes its dimensions from the theme (VI-656):\n --switch-track-width / -height, and --switch-knob-inset, the gap between the\n knob and the track's outer edge on every side. The private properties below\n exist only while --switch-knob-inset is set; unset, they are invalid, so the\n knob falls back to its shipped 1rem size and position and the track keeps\n whatever inline padding it had (revert-layer). Set, the track's inline\n padding goes to 0 so the inset alone places the knob. The 1px is the\n geometry border (see .root), which the inset is measured across. */\n.sizeDefault {\n height: var(--switch-track-height, 1.15rem);\n width: var(--switch-track-width, 2rem);\n --_switch-pad: calc(var(--switch-knob-inset) * 0);\n --_switch-knob-size: calc(var(--switch-track-height, 1.15rem) - 2 * var(--switch-knob-inset));\n --_switch-knob-start: calc(var(--switch-knob-inset) - 1px);\n}\n\n/* In visor-base so an unset inset leaves the track's padding to whatever reset\n or browser default applies, and a set inset zeroes it only where no consumer\n rule speaks. */\n@layer visor-base {\n .sizeDefault {\n padding-inline: var(--_switch-pad, revert-layer);\n }\n}\n\n.sizeSm {\n height: 0.875rem;\n width: 1.5rem;\n}\n\n/* Thumb */\n.thumb {\n display: block;\n border-radius: 9999px;\n background-color: var(--surface-page, #ffffff);\n box-shadow: var(--shadow-sm);\n transition: transform var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n pointer-events: none;\n}\n\n/* Thumb size — derived from parent via CSS nesting */\n.sizeDefault .thumb {\n width: var(--_switch-knob-size, 1rem);\n height: var(--_switch-knob-size, 1rem);\n}\n\n.sizeSm .thumb {\n width: 0.75rem;\n height: 0.75rem;\n}\n\n.root[data-state=\"unchecked\"] .thumb {\n transform: translateX(0);\n}\n\n.sizeDefault[data-state=\"unchecked\"] .thumb {\n transform: translateX(var(--_switch-knob-start, 0));\n}\n\n/* The knob's right edge sits the same distance from the track's right edge as\n its left edge does from the left: flush inside the 1px geometry border by\n default (2rem - 1rem - 2px, the shipped 100% - 2px), or the inset when set. */\n.sizeDefault[data-state=\"checked\"] .thumb {\n transform: translateX(calc(var(--switch-track-width, 2rem) - 100% - 2px - var(--_switch-knob-start, 0px)));\n}\n\n.sizeSm[data-state=\"checked\"] .thumb {\n transform: translateX(calc(100% - 2px));\n}\n"
|
|
356
|
+
"content": "/* Switch root styles */\n.root {\n position: relative;\n display: inline-flex;\n flex-shrink: 0;\n align-items: center;\n border-radius: 9999px;\n /* VI-655: the border only holds box geometry. The track's resting edge is an\n inset outline on the shared --control-edge-* tokens; it is transparent\n unless a theme sets --switch-edge-color, and --control-edge-width: 0\n removes it with every other control's edge. */\n border: 1px solid transparent;\n background-color: var(--switch-track-bg, var(--border-default, #e5e7eb));\n transition: background-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out), outline-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out), box-shadow var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n outline: var(--control-edge-width, 1px) var(--control-edge-style, solid) var(--switch-edge-color, transparent);\n outline-offset: calc(-1 * var(--control-edge-width, 1px));\n cursor: pointer;\n}\n\n/* VI-693: hover reads its own keys, so a borderless theme (border-strong set\n transparent) keeps a visible track under the pointer. Unset, both states\n repaint with --border-strong, as they always have. The checked rule is one\n class more specific, so it wins over the unchecked one. */\n@media (hover: hover) {\n .root:hover:not(:focus-visible):not(:disabled):not([aria-invalid=\"true\"]) {\n background-color: var(--switch-track-hover-bg, var(--border-strong, #d1d5db));\n }\n\n .root[data-state=\"checked\"]:hover:not(:focus-visible):not(:disabled):not([aria-invalid=\"true\"]) {\n background-color: var(--switch-track-hover-bg-checked, var(--border-strong, #d1d5db));\n }\n}\n\n/* Focus and invalid draw at --control-state-edge-width, which the edge switch\n does not touch. */\n.root:focus-visible {\n outline: var(--control-state-edge-width, 1px) solid var(--border-focus, #111827);\n outline-offset: calc(-1 * var(--control-state-edge-width, 1px));\n box-shadow: 0 0 0 var(--focus-ring-width, 2px) color-mix(in srgb, var(--border-focus, #111827) 15%, transparent);\n}\n\n.root:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n.root[aria-invalid=\"true\"] {\n outline: var(--control-state-edge-width, 1px) solid var(--border-error, #ef4444);\n outline-offset: calc(-1 * var(--control-state-edge-width, 1px));\n box-shadow: 0 0 0 var(--focus-ring-width, 2px) color-mix(in srgb, var(--border-error, #ef4444) 15%, transparent);\n}\n\n.root[data-state=\"checked\"] {\n background-color: var(--interactive-primary-bg, var(--primary, #111827));\n}\n\n/* Size variants\n The default size takes its dimensions from the theme (VI-656):\n --switch-track-width / -height, and --switch-knob-inset, the gap between the\n knob and the track's outer edge on every side. The private properties below\n exist only while --switch-knob-inset is set; unset, they are invalid, so the\n knob falls back to its shipped 1rem size and position and the track keeps\n whatever inline padding it had (revert-layer). Set, the track's inline\n padding goes to 0 so the inset alone places the knob. The 1px is the\n geometry border (see .root), which the inset is measured across. */\n.sizeDefault {\n height: var(--switch-track-height, 1.15rem);\n width: var(--switch-track-width, 2rem);\n --_switch-pad: calc(var(--switch-knob-inset) * 0);\n --_switch-knob-size: calc(var(--switch-track-height, 1.15rem) - 2 * var(--switch-knob-inset));\n --_switch-knob-start: calc(var(--switch-knob-inset) - 1px);\n}\n\n/* In visor-base so an unset inset leaves the track's padding to whatever reset\n or browser default applies, and a set inset zeroes it only where no consumer\n rule speaks. */\n@layer visor-base {\n .sizeDefault {\n padding-inline: var(--_switch-pad, revert-layer);\n }\n}\n\n.sizeSm {\n height: 0.875rem;\n width: 1.5rem;\n}\n\n/* Thumb */\n.thumb {\n display: block;\n border-radius: 9999px;\n background-color: var(--switch-knob-bg, var(--surface-page, #ffffff));\n box-shadow: var(--shadow-sm);\n transition: transform var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n pointer-events: none;\n}\n\n/* Thumb size — derived from parent via CSS nesting */\n.sizeDefault .thumb {\n width: var(--_switch-knob-size, 1rem);\n height: var(--_switch-knob-size, 1rem);\n}\n\n.sizeSm .thumb {\n width: 0.75rem;\n height: 0.75rem;\n}\n\n/* VI-693: the knob has a key per state. A dark theme's page colour is a black\n knob, which an unchecked track cannot hold at 3:1 (WCAG 1.4.11). */\n.root[data-state=\"checked\"] .thumb {\n background-color: var(--switch-knob-bg-checked, var(--surface-page, #ffffff));\n}\n\n.root[data-state=\"unchecked\"] .thumb {\n transform: translateX(0);\n}\n\n.sizeDefault[data-state=\"unchecked\"] .thumb {\n transform: translateX(var(--_switch-knob-start, 0));\n}\n\n/* The knob's right edge sits the same distance from the track's right edge as\n its left edge does from the left: flush inside the 1px geometry border by\n default (2rem - 1rem - 2px, the shipped 100% - 2px), or the inset when set. */\n.sizeDefault[data-state=\"checked\"] .thumb {\n transform: translateX(calc(var(--switch-track-width, 2rem) - 100% - 2px - var(--_switch-knob-start, 0px)));\n}\n\n.sizeSm[data-state=\"checked\"] .thumb {\n transform: translateX(calc(100% - 2px));\n}\n"
|
|
357
357
|
}
|
|
358
358
|
]
|
|
359
359
|
},
|
|
@@ -2904,7 +2904,7 @@
|
|
|
2904
2904
|
{
|
|
2905
2905
|
"path": "components/ui/page-header/page-header.module.css",
|
|
2906
2906
|
"type": "registry:ui",
|
|
2907
|
-
"content": "/* Page Header base: container query wrapper.\n\n VI-625: `--page-header-title-size` / `-title-family` used to be *declared*\n here. An element-level declaration outranks anything a theme emits into a\n cascade layer on :root, so the documented \"themes can set these\" was never\n actually true — the component shadowed the theme. Both use sites already\n carry the identical fallback inline, so dropping the declarations is\n value-preserving (`var(--x, 3.5rem)` with no --x resolves to 3.5rem, exactly\n as it did when --x was declared as 3.5rem) and makes the hooks genuinely\n theme-bindable. `--page-header-title-leading` was already unset for the same\n reason: the title falls back to its per-rule default line-height (tight for\n the standard title, `1` for the marquee scale); the `leading` prop sets it. */\n.base {\n display: flex;\n flex-direction: column;\n width: 100%;\n min-width: 0;\n gap: var(--page-header-gap, var(--spacing-4, 1rem));\n container-type: inline-size;\n container-name: page-header;\n color: var(--page-header-text-color, var(--text-primary, #111827));\n}\n\n/* Size variants control vertical rhythm */\n.sizeSm {\n gap: var(--spacing-3, 0.75rem);\n}\n\n.sizeMd {\n gap: var(--spacing-4, 1rem);\n}\n\n.sizeLg {\n gap: var(--spacing-5, 1.25rem);\n}\n\n/* Breadcrumb slot sits above the title row */\n.breadcrumb {\n display: flex;\n align-items: center;\n min-width: 0;\n}\n\n/* Main row: text block on the left, actions on the right */\n.row {\n display: flex;\n align-items: flex-end;\n justify-content: space-between;\n gap: var(--spacing-6, 1.5rem);\n min-width: 0;\n}\n\n/* When a leading media/identity slot is present, the row forms an identity\n lockup: the media sits before the text stack a tight gap from it. Scoped to\n `data-has-leading` so the default (text|actions) row is untouched for\n consumers that don't pass `leading`. The expanding text block keeps actions\n pinned right via the inherited `justify-content: space-between`. */\n.row[data-has-leading] {\n align-items: center;\n gap: var(--page-header-leading-gap, var(--spacing-3, 0.75rem));\n}\n\n/* Leading media/identity slot: sits before the text block, vertically\n centered against the title/description stack, never shrinks. (Reverts the\n VI-539 top-align, which assumed a different slot — the blessed admin\n identity lockup centers the media. Superseded per the admin-editorial\n reconcile plan.) */\n.leading {\n display: flex;\n align-items: center;\n flex: 0 0 auto;\n}\n\n/* Text block: eyebrow, title, description stacked */\n.text {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-2, 0.5rem);\n min-width: 0;\n flex: 1 1 auto;\n}\n\n.sizeSm .text {\n gap: var(--spacing-1, 0.25rem);\n}\n\n.sizeLg .text {\n gap: var(--spacing-3, 0.75rem);\n}\n\n/* Eyebrow: small uppercase label above the title */\n.eyebrow {\n font-size: var(--page-header-eyebrow-font-size, var(--font-size-xs, 0.75rem));\n font-weight: var(--page-header-eyebrow-font-weight, var(--font-weight-semibold, 600));\n letter-spacing: var(--page-header-eyebrow-letter-spacing, var(--letter-spacing-wide, 0.05em));\n text-transform: var(--page-header-eyebrow-text-transform, uppercase);\n color: var(--page-header-eyebrow-color, var(--text-tertiary, #6b7280));\n line-height: var(--line-height-tight, 1.25);\n}\n\n/* Title */\n.title {\n margin: 0;\n font-family: var(--font-family-heading, inherit);\n font-size: var(--page-header-title-font-size, var(--font-size-2xl, 1.5rem));\n font-weight: var(--page-header-title-font-weight, var(--font-weight-semibold, 600));\n line-height: var(--page-header-title-leading, var(--line-height-tight, 1.2));\n color: var(--page-header-title-color, var(--text-primary, #111827));\n letter-spacing: var(--page-header-title-letter-spacing, var(--letter-spacing-tight, -0.01em));\n}\n\n.sizeSm .title {\n font-size: var(--font-size-xl, 1.25rem);\n}\n\n.sizeLg .title {\n font-size: var(--font-size-3xl, 1.875rem);\n}\n\n/* Title typography overrides (orthogonal to size variants).\n `data-title-size=\"marquee\"` pulls the title up to a hero scale via the\n `--page-header-title-size` custom property. Raw-string consumers pass an\n inline `--page-header-title-size` and rely on the same rule. */\n.title[data-title-size=\"marquee\"] {\n font-size: var(--page-header-title-size, 3.5rem);\n line-height: var(--page-header-title-leading, 1);\n letter-spacing: var(--letter-spacing-tight, -0.01em);\n}\n\n/* `data-title-family=\"display\"` switches to the display family with a\n graceful fallback to the heading family when no display font is themed.\n VI-625: `--admin-ui-marquee-family` sits in the chain so the admin-ui\n pattern's marquee role drives the hero title when a theme binds it. */\n.title[data-title-family=\"display\"] {\n font-family: var(--page-header-title-family, var(--admin-ui-marquee-family, var(--font-display, var(--font-family-heading, inherit))));\n}\n\n/* Description */\n.description {\n margin: 0;\n font-size: var(--page-header-description-font-size, var(--font-size-sm, 0.875rem));\n line-height: var(--line-height-relaxed, 1.6);\n color: var(--page-header-description-color, var(--text-secondary, #6b7280));\n max-width: 65ch;\n}\n\n.sizeLg .description {\n font-size: var(--font-size-base, 1rem);\n}\n\n/* Actions slot: cluster on the right */\n.actions {\n display: flex;\n align-items: center;\n gap: var(--page-header-actions-gap, var(--spacing-2, 0.5rem));\n flex: 0 0 auto;\n flex-wrap: wrap;\n justify-content: flex-end;\n}\n\n/* Container query: stack to column below a small container width */\n@container page-header (max-width: 480px) {\n .row {\n flex-direction: column;\n align-items: flex-start;\n gap: var(--spacing-4, 1rem);\n }\n\n .actions {\n width: 100%;\n justify-content: flex-start;\n }\n}\n"
|
|
2907
|
+
"content": "/* Page Header base: container query wrapper.\n\n VI-625: `--page-header-title-size` / `-title-family` used to be *declared*\n here. An element-level declaration outranks anything a theme emits into a\n cascade layer on :root, so the documented \"themes can set these\" was never\n actually true — the component shadowed the theme. Both use sites already\n carry the identical fallback inline, so dropping the declarations is\n value-preserving (`var(--x, 3.5rem)` with no --x resolves to 3.5rem, exactly\n as it did when --x was declared as 3.5rem) and makes the hooks genuinely\n theme-bindable. `--page-header-title-leading` was already unset for the same\n reason: the title falls back to its per-rule default line-height (tight for\n the standard title, `1` for the marquee scale); the `leading` prop sets it. */\n.base {\n display: flex;\n flex-direction: column;\n width: 100%;\n min-width: 0;\n gap: var(--page-header-gap, var(--spacing-4, 1rem));\n container-type: inline-size;\n container-name: page-header;\n color: var(--page-header-text-color, var(--text-primary, #111827));\n}\n\n/* Size variants control vertical rhythm */\n.sizeSm {\n gap: var(--spacing-3, 0.75rem);\n}\n\n.sizeMd {\n gap: var(--spacing-4, 1rem);\n}\n\n.sizeLg {\n gap: var(--spacing-5, 1.25rem);\n}\n\n/* Breadcrumb slot sits above the title row */\n.breadcrumb {\n display: flex;\n align-items: center;\n min-width: 0;\n}\n\n/* Main row: text block on the left, actions on the right */\n.row {\n display: flex;\n align-items: flex-end;\n justify-content: space-between;\n gap: var(--spacing-6, 1.5rem);\n min-width: 0;\n}\n\n/* When a leading media/identity slot is present, the row forms an identity\n lockup: the media sits before the text stack a tight gap from it. Scoped to\n `data-has-leading` so the default (text|actions) row is untouched for\n consumers that don't pass `leading`. The expanding text block keeps actions\n pinned right via the inherited `justify-content: space-between`. */\n.row[data-has-leading] {\n align-items: center;\n gap: var(--page-header-leading-gap, var(--spacing-3, 0.75rem));\n}\n\n/* Leading media/identity slot: sits before the text block, vertically\n centered against the title/description stack, never shrinks. (Reverts the\n VI-539 top-align, which assumed a different slot — the blessed admin\n identity lockup centers the media. Superseded per the admin-editorial\n reconcile plan.) */\n.leading {\n display: flex;\n align-items: center;\n flex: 0 0 auto;\n}\n\n/* Text block: eyebrow, title, description stacked */\n.text {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-2, 0.5rem);\n min-width: 0;\n flex: 1 1 auto;\n}\n\n.sizeSm .text {\n gap: var(--spacing-1, 0.25rem);\n}\n\n.sizeLg .text {\n gap: var(--spacing-3, 0.75rem);\n}\n\n/* Eyebrow: small uppercase label above the title */\n.eyebrow {\n font-size: var(--page-header-eyebrow-font-size, var(--font-size-xs, 0.75rem));\n font-weight: var(--page-header-eyebrow-font-weight, var(--font-weight-semibold, 600));\n letter-spacing: var(--page-header-eyebrow-letter-spacing, var(--letter-spacing-wide, 0.05em));\n text-transform: var(--page-header-eyebrow-text-transform, uppercase);\n color: var(--page-header-eyebrow-color, var(--text-tertiary, #6b7280));\n line-height: var(--line-height-tight, 1.25);\n}\n\n/* Title */\n.title {\n margin: 0;\n font-family: var(--font-family-heading, inherit);\n font-size: var(--page-header-title-font-size, var(--font-size-2xl, 1.5rem));\n font-weight: var(--page-header-title-font-weight, var(--font-weight-semibold, 600));\n line-height: var(--page-header-title-leading, var(--line-height-tight, 1.2));\n color: var(--page-header-title-color, var(--text-primary, #111827));\n letter-spacing: var(--page-header-title-letter-spacing, var(--letter-spacing-tight, -0.01em));\n}\n\n.sizeSm .title {\n font-size: var(--font-size-xl, 1.25rem);\n}\n\n.sizeLg .title {\n font-size: var(--font-size-3xl, 1.875rem);\n}\n\n/* Title typography overrides (orthogonal to size variants).\n `data-title-size=\"marquee\"` pulls the title up to a hero scale via the\n `--page-header-title-size` custom property. Raw-string consumers pass an\n inline `--page-header-title-size` and rely on the same rule. */\n.title[data-title-size=\"marquee\"] {\n font-size: var(--page-header-title-size, 3.5rem);\n line-height: var(--page-header-title-leading, 1);\n letter-spacing: var(--letter-spacing-tight, -0.01em);\n}\n\n/* `data-title-family=\"display\"` switches to the display family with a\n graceful fallback to the heading family when no display font is themed.\n VI-625: `--admin-ui-marquee-family` sits in the chain so the admin-ui\n pattern's marquee role drives the hero title when a theme binds it. */\n.title[data-title-family=\"display\"] {\n font-family: var(--page-header-title-family, var(--admin-ui-marquee-family, var(--font-display, var(--font-family-heading, inherit))));\n /* VI-687: theme-set display casing; inherit when unset. */\n text-transform: var(--font-display-text-transform, inherit);\n}\n\n/* Description */\n.description {\n margin: 0;\n font-size: var(--page-header-description-font-size, var(--font-size-sm, 0.875rem));\n line-height: var(--line-height-relaxed, 1.6);\n color: var(--page-header-description-color, var(--text-secondary, #6b7280));\n max-width: 65ch;\n}\n\n.sizeLg .description {\n font-size: var(--font-size-base, 1rem);\n}\n\n/* Actions slot: cluster on the right */\n.actions {\n display: flex;\n align-items: center;\n gap: var(--page-header-actions-gap, var(--spacing-2, 0.5rem));\n flex: 0 0 auto;\n flex-wrap: wrap;\n justify-content: flex-end;\n}\n\n/* Container query: stack to column below a small container width */\n@container page-header (max-width: 480px) {\n .row {\n flex-direction: column;\n align-items: flex-start;\n gap: var(--spacing-4, 1rem);\n }\n\n .actions {\n width: 100%;\n justify-content: flex-start;\n }\n}\n"
|
|
2908
2908
|
}
|
|
2909
2909
|
]
|
|
2910
2910
|
},
|
|
@@ -2977,7 +2977,7 @@
|
|
|
2977
2977
|
{
|
|
2978
2978
|
"path": "components/ui/section-intro/section-intro.module.css",
|
|
2979
2979
|
"type": "registry:ui",
|
|
2980
|
-
"content": "/* SectionIntro — marketing eyebrow + display heading + optional lede\n *\n * The eyebrow color is intentionally driven through a CSS custom property\n * (`--section-intro-eyebrow-color`) so that consumers can override it at\n * any ancestor level and have it track a live-rewritten brand accent var\n * (for example a keyed `--color-acid` that swaps between artist palette entries).\n * Default fallback chain: --section-intro-eyebrow-color → --accent-default\n * → --interactive-primary-bg → #111827 (Tailwind Gray-900).\n *\n * Alignment is controlled by data-align on the root (set by the `align`\n * prop). Both \"left\" and \"center\" are defined here.\n */\n\n.root {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-4, 1rem);\n width: 100%;\n min-width: 0;\n}\n\n/* ── Alignment variants ─────────────────────────────────────────────────── */\n\n.root[data-align=\"left\"] {\n align-items: flex-start;\n text-align: left;\n}\n\n.root[data-align=\"center\"] {\n align-items: center;\n text-align: center;\n}\n\n/* ── Eyebrow ────────────────────────────────────────────────────────────── */\n\n.eyebrow {\n margin: 0;\n font-family: var(--font-mono, ui-monospace, monospace);\n font-size: var(--font-size-xs, 0.6875rem);\n font-weight: var(--font-weight-medium, 500);\n letter-spacing: var(--letter-spacing-widest, 0.2em);\n text-transform: uppercase;\n line-height: var(--line-height-tight, 1.25);\n /*\n * Live-rewriteable eyebrow color. Override --section-intro-eyebrow-color\n * at any ancestor (for example on the <section> that contains this component) to\n * track a keyed brand accent that changes at runtime.\n */\n color: var(\n --section-intro-eyebrow-color,\n var(--accent-default, var(--interactive-primary-bg, #111827))\n );\n}\n\n/* ── Heading ────────────────────────────────────────────────────────────── */\n\n.heading {\n margin: 0;\n font-family: var(--font-display, var(--font-family-heading, inherit));\n font-size: clamp(2.5rem, 6vw, 4rem);\n font-weight: var(--font-weight-medium, 500);\n line-height: var(--line-height-none, 1.05);\n letter-spacing: var(--letter-spacing-tight, -0.02em);\n color: var(--text-primary, #111827);\n text-wrap: balance;\n max-width: 18ch;\n}\n\n.root[data-align=\"center\"] .heading {\n max-width: 22ch;\n}\n\n/* ── Lede ───────────────────────────────────────────────────────────────── */\n\n.lede {\n margin: 0;\n font-size: var(--font-size-base, 1rem);\n line-height: var(--line-height-relaxed, 1.6);\n font-weight: var(--font-weight-light, 300);\n color: var(--text-secondary, #6b7280);\n max-width: 54ch;\n}\n\n.root[data-align=\"center\"] .lede {\n max-width: 60ch;\n}\n"
|
|
2980
|
+
"content": "/* SectionIntro — marketing eyebrow + display heading + optional lede\n *\n * The eyebrow color is intentionally driven through a CSS custom property\n * (`--section-intro-eyebrow-color`) so that consumers can override it at\n * any ancestor level and have it track a live-rewritten brand accent var\n * (for example a keyed `--color-acid` that swaps between artist palette entries).\n * Default fallback chain: --section-intro-eyebrow-color → --accent-default\n * → --interactive-primary-bg → #111827 (Tailwind Gray-900).\n *\n * Alignment is controlled by data-align on the root (set by the `align`\n * prop). Both \"left\" and \"center\" are defined here.\n */\n\n.root {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-4, 1rem);\n width: 100%;\n min-width: 0;\n}\n\n/* ── Alignment variants ─────────────────────────────────────────────────── */\n\n.root[data-align=\"left\"] {\n align-items: flex-start;\n text-align: left;\n}\n\n.root[data-align=\"center\"] {\n align-items: center;\n text-align: center;\n}\n\n/* ── Eyebrow ────────────────────────────────────────────────────────────── */\n\n.eyebrow {\n margin: 0;\n font-family: var(--font-mono, ui-monospace, monospace);\n font-size: var(--font-size-xs, 0.6875rem);\n font-weight: var(--font-weight-medium, 500);\n letter-spacing: var(--letter-spacing-widest, 0.2em);\n text-transform: uppercase;\n line-height: var(--line-height-tight, 1.25);\n /*\n * Live-rewriteable eyebrow color. Override --section-intro-eyebrow-color\n * at any ancestor (for example on the <section> that contains this component) to\n * track a keyed brand accent that changes at runtime.\n */\n color: var(\n --section-intro-eyebrow-color,\n var(--accent-default, var(--interactive-primary-bg, #111827))\n );\n}\n\n/* ── Heading ────────────────────────────────────────────────────────────── */\n\n.heading {\n margin: 0;\n font-family: var(--font-display, var(--font-family-heading, inherit));\n /* VI-687: theme-set display casing; inherit when unset. */\n text-transform: var(--font-display-text-transform, inherit);\n font-size: clamp(2.5rem, 6vw, 4rem);\n font-weight: var(--font-weight-medium, 500);\n line-height: var(--line-height-none, 1.05);\n letter-spacing: var(--letter-spacing-tight, -0.02em);\n color: var(--text-primary, #111827);\n text-wrap: balance;\n max-width: 18ch;\n}\n\n.root[data-align=\"center\"] .heading {\n max-width: 22ch;\n}\n\n/* ── Lede ───────────────────────────────────────────────────────────────── */\n\n.lede {\n margin: 0;\n font-size: var(--font-size-base, 1rem);\n line-height: var(--line-height-relaxed, 1.6);\n font-weight: var(--font-weight-light, 300);\n color: var(--text-secondary, #6b7280);\n max-width: 54ch;\n}\n\n.root[data-align=\"center\"] .lede {\n max-width: 60ch;\n}\n"
|
|
2981
2981
|
}
|
|
2982
2982
|
]
|
|
2983
2983
|
},
|
package/dist/visor-manifest.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": "0.4.0",
|
|
3
|
-
"generated_at": "2026-10-
|
|
3
|
+
"generated_at": "2026-10-04T22:55:53.108Z",
|
|
4
4
|
"components": {
|
|
5
5
|
"accessibility-specimen": {
|
|
6
6
|
"category": "specimen",
|
|
@@ -5314,6 +5314,7 @@
|
|
|
5314
5314
|
],
|
|
5315
5315
|
"tokens_used": [
|
|
5316
5316
|
"--font-heading",
|
|
5317
|
+
"--font-heading-text-transform",
|
|
5317
5318
|
"--font-size-2xl",
|
|
5318
5319
|
"--font-size-4xl",
|
|
5319
5320
|
"--font-size-base",
|
|
@@ -6979,6 +6980,7 @@
|
|
|
6979
6980
|
"tokens_used": [
|
|
6980
6981
|
"--admin-ui-marquee-family",
|
|
6981
6982
|
"--font-display",
|
|
6983
|
+
"--font-display-text-transform",
|
|
6982
6984
|
"--font-family-heading",
|
|
6983
6985
|
"--font-size-2xl",
|
|
6984
6986
|
"--font-size-3xl",
|
|
@@ -8070,6 +8072,7 @@
|
|
|
8070
8072
|
"tokens_used": [
|
|
8071
8073
|
"--accent-default",
|
|
8072
8074
|
"--font-display",
|
|
8075
|
+
"--font-display-text-transform",
|
|
8073
8076
|
"--font-family-heading",
|
|
8074
8077
|
"--font-mono",
|
|
8075
8078
|
"--font-size-base",
|
|
@@ -8368,6 +8371,12 @@
|
|
|
8368
8371
|
"name": "placeholder",
|
|
8369
8372
|
"type": "string",
|
|
8370
8373
|
"description": "Shown via SelectValue when no value is selected"
|
|
8374
|
+
},
|
|
8375
|
+
{
|
|
8376
|
+
"name": "container",
|
|
8377
|
+
"type": "HTMLElement | null",
|
|
8378
|
+
"default": "document.body",
|
|
8379
|
+
"description": "SelectContent only. Element the menu portals into. Pass the root of a class-scoped theme so the menu reads that theme's tokens instead of the page's.\n"
|
|
8371
8380
|
}
|
|
8372
8381
|
],
|
|
8373
8382
|
"sub_components": [
|
|
@@ -8381,7 +8390,7 @@
|
|
|
8381
8390
|
},
|
|
8382
8391
|
{
|
|
8383
8392
|
"name": "SelectContent",
|
|
8384
|
-
"description": "The dropdown container with scroll buttons and portal positioning."
|
|
8393
|
+
"description": "The dropdown container with scroll buttons and portal positioning (document.body unless `container` is set)."
|
|
8385
8394
|
},
|
|
8386
8395
|
{
|
|
8387
8396
|
"name": "SelectItem",
|
|
@@ -10300,9 +10309,13 @@
|
|
|
10300
10309
|
"--shadow-sm",
|
|
10301
10310
|
"--surface-page",
|
|
10302
10311
|
"--switch-edge-color",
|
|
10312
|
+
"--switch-knob-bg",
|
|
10313
|
+
"--switch-knob-bg-checked",
|
|
10303
10314
|
"--switch-knob-inset",
|
|
10304
10315
|
"--switch-track-bg",
|
|
10305
10316
|
"--switch-track-height",
|
|
10317
|
+
"--switch-track-hover-bg",
|
|
10318
|
+
"--switch-track-hover-bg-checked",
|
|
10306
10319
|
"--switch-track-width"
|
|
10307
10320
|
],
|
|
10308
10321
|
"example": "<div style={{ display: \"flex\", alignItems: \"center\", gap: \"0.5rem\" }}>\n <Switch id=\"notifications\" />\n <Label htmlFor=\"notifications\">Enable notifications</Label>\n</div>\n"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loworbitstudio/visor",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.36.0",
|
|
4
4
|
"description": "CLI for the Visor design system — add components, hooks, and utilities to your project.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@aws-sdk/client-s3": "^3.1021.0",
|
|
48
48
|
"@babel/parser": "^7.26.0",
|
|
49
|
-
"@loworbitstudio/visor-theme-engine": "^0.
|
|
49
|
+
"@loworbitstudio/visor-theme-engine": "^0.29.0",
|
|
50
50
|
"commander": "^13.1.0",
|
|
51
51
|
"diff": "^8.0.4",
|
|
52
52
|
"picocolors": "^1.1.1",
|