@loworbitstudio/visor 1.24.0 → 1.25.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 +3 -3
- package/dist/visor-manifest.json +32 -8
- package/package.json +1 -1
package/dist/CHANGELOG.json
CHANGED
package/dist/registry.json
CHANGED
|
@@ -41,12 +41,12 @@
|
|
|
41
41
|
{
|
|
42
42
|
"path": "components/ui/heading/heading.tsx",
|
|
43
43
|
"type": "registry:ui",
|
|
44
|
-
"content": "import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { cn } from \"../../../lib/utils\"\nimport styles from \"./heading.module.css\"\n\nconst headingVariants = cva(styles.base, {\n variants: {\n size: {\n xs: styles.sizeXs,\n sm: styles.sizeSm,\n md: styles.sizeMd,\n lg: styles.sizeLg,\n xl: styles.sizeXl,\n \"2xl\": styles.size2xl,\n },\n weight: {\n normal: styles.weightNormal,\n medium: styles.weightMedium,\n semibold: styles.weightSemibold,\n bold: styles.weightBold,\n },\n },\n defaultVariants: {\n weight: \"
|
|
44
|
+
"content": "import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { cn } from \"../../../lib/utils\"\nimport styles from \"./heading.module.css\"\n\nconst headingVariants = cva(styles.base, {\n variants: {\n size: {\n xs: styles.sizeXs,\n sm: styles.sizeSm,\n md: styles.sizeMd,\n lg: styles.sizeLg,\n xl: styles.sizeXl,\n \"2xl\": styles.size2xl,\n },\n weight: {\n // `heading` follows the theme's declared heading weight; the other four\n // are steps on the named ramp. Before VI-639 these were the same thing —\n // `--font-weight-semibold` was emitted as the theme's heading weight, so\n // the default below silently meant \"heading\" on every theme.\n heading: styles.weightHeading,\n normal: styles.weightNormal,\n medium: styles.weightMedium,\n semibold: styles.weightSemibold,\n bold: styles.weightBold,\n },\n },\n defaultVariants: {\n weight: \"heading\",\n },\n})\n\nconst levelSizeMap: Record<number, \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\" | \"2xl\"> = {\n 1: \"2xl\",\n 2: \"xl\",\n 3: \"lg\",\n 4: \"md\",\n 5: \"sm\",\n 6: \"xs\",\n}\n\nexport interface HeadingProps\n extends React.HTMLAttributes<HTMLHeadingElement>,\n VariantProps<typeof headingVariants> {\n level?: 1 | 2 | 3 | 4 | 5 | 6\n}\n\nconst Heading = React.forwardRef<HTMLHeadingElement, HeadingProps>(\n ({ className, level = 2, size, weight, ...props }, ref) => {\n const Tag = `h${level}` as const\n const resolvedSize = size ?? levelSizeMap[level]\n\n return (\n <Tag\n ref={ref}\n data-slot=\"heading\"\n data-level={level}\n className={cn(headingVariants({ size: resolvedSize, weight }), className)}\n {...props}\n />\n )\n }\n)\nHeading.displayName = \"Heading\"\n\nexport { Heading, headingVariants }\n"
|
|
45
45
|
},
|
|
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.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 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
|
},
|
|
@@ -1944,7 +1944,7 @@
|
|
|
1944
1944
|
{
|
|
1945
1945
|
"path": "components/ui/phone-input/phone-input.tsx",
|
|
1946
1946
|
"type": "registry:ui",
|
|
1947
|
-
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport IntlTelInput from \"@intl-tel-input/react\"\nimport type { IntlTelInputRef } from \"@intl-tel-input/react\"\nimport type { CountrySelectorMode, Iso2, ValidationError } from \"intl-tel-input\"\nimport \"intl-tel-input/styles\"\nimport { cn } from \"../../../lib/utils\"\n\n// Password managers mangle tel fields. Typed through `input` props because the\n// library's `inputProps` surface does not model arbitrary data attributes.\nconst PASSWORD_MANAGER_OPT_OUT = {\n \"data-1p-ignore\": true,\n \"data-lpignore\": \"true\",\n \"data-bwignore\": true,\n \"data-form-type\": \"other\",\n} as React.ComponentPropsWithoutRef<\"input\">\n\nexport interface PhoneInputPortal {\n /** Element the country selector is portaled into. */\n container: HTMLElement\n /**\n * Theme-scoping class applied to the portaled country selector. Required —\n * a selector portaled out of the tree escapes the consumer's theme class,\n * so the scope has to travel with it.\n */\n scopeClassName: string\n}\n\nexport interface PhoneInputProps {\n /** HTML id attribute */\n id?: string\n /** HTML name attribute */\n name?: string\n /** Phone number in E.164 (e.g. \"+14155551234\"). Displayed formatted for the detected country. */\n value?: string | null\n /** Placeholder text */\n placeholder?: string\n /** Whether the field is required */\n required?: boolean\n /** Whether the field is disabled */\n disabled?: boolean\n /** Whether the field is read-only. Pair with `countrySelectorMode=\"OFF\"` to also close off the country dropdown. */\n readOnly?: boolean\n /** Country selector behaviour. `\"OFF\"` renders the selected country as a non-interactive element. */\n countrySelectorMode?: CountrySelectorMode\n /** ISO 3166-1 alpha-2 country selected on mount. */\n initialCountry?: Iso2\n /** Size variant — matches Input component sizes */\n size?: \"sm\" | \"md\" | \"lg\"\n /** Additional CSS classes applied to the wrapper */\n className?: string\n /**\n * Portal the country selector out of the input's DOM position. All-or-nothing:\n * the scoping class is not separable from the container, so the selector can\n * never escape its theme. Omit for the default inline selector.\n */\n portal?: PhoneInputPortal\n /**\n * Called with the E.164 number and its validity. `e164` is `null` for anything\n * that is not a complete, valid number — a partial is never emitted.\n */\n onChange?: (e164: string | null, isValid: boolean) => void\n /** Called on blur with the validation error for a non-empty, invalid number (otherwise `null`). */\n onBlur?: (error: ValidationError | null) => void\n}\n\nconst PhoneInput = React.forwardRef<IntlTelInputRef, PhoneInputProps>(\n (\n {\n id,\n name,\n value,\n placeholder,\n required = false,\n disabled = false,\n readOnly = false,\n countrySelectorMode,\n initialCountry = \"us\",\n size = \"md\",\n className,\n portal,\n onChange,\n onBlur,\n },\n ref\n ) => {\n const itiRef = React.useRef<IntlTelInputRef>(null)\n // `undefined` until the first emission — an initial `{ null, false }` would be\n // indistinguishable from the first partial the user types and would swallow it.\n const lastEmitted = React.useRef<\n { e164: string | null; isValid: boolean } | undefined\n >(undefined)\n\n React.useImperativeHandle(ref, () => ({\n getInstance: () => itiRef.current?.getInstance() ?? null,\n getInput: () => itiRef.current?.getInput() ?? null,\n }))\n\n // `emit` must be identity-stable. The wrapper derives its internal `update`\n // from the onChange* props and keys its value-writeback effect on\n // `[value, update]`; a new `emit` each render re-runs that effect, and while\n // the field is unfocused and holding a partial (so the controlled value is\n // null) it calls setNumber(\"\") and erases what the user typed. Reading the\n // consumer's callback from a ref keeps the effect keyed on `value` alone.\n const onChangeRef = React.useRef(onChange)\n onChangeRef.current = onChange\n\n // The library's own `onChangeNumber` emits `getNumber()` verbatim, which for a\n // partial is a `+<dial code>` prefix glued to the formatted national string\n // (typing \"21337\" yields \"+1213-37\"). Derive the value at emit time instead so\n // a malformed number can never reach the consumer.\n const emit = React.useCallback(() => {\n const iti = itiRef.current?.getInstance()\n const isValid = iti?.isValidNumber() ?? false\n const e164 = isValid ? iti!.getNumber() : null\n const last = lastEmitted.current\n if (last && last.e164 === e164 && last.isValid === isValid) return\n lastEmitted.current = { e164, isValid }\n onChangeRef.current?.(e164, isValid)\n }, [])\n\n const handleBlur = React.useCallback(() => {\n const iti = itiRef.current?.getInstance()\n const input = itiRef.current?.getInput()\n // The error callback never fires while a number is still partial, so read the\n // error directly — a visibly-present partial that saves as nothing is silent\n // data loss. Gate on validity: getValidationError() reports \"IS_POSSIBLE\" for\n // a number that is fine, which is not an error.\n const error =\n iti && input?.value && !iti.isValidNumber()\n ? (iti.getValidationError() ?? null)\n : null\n onBlur?.(error)\n }, [onBlur])\n\n return (\n <div data-slot=\"phone-input\" data-size={size} className={cn(className)}>\n <IntlTelInput\n ref={itiRef}\n value={value}\n disabled={disabled}\n readOnly={readOnly}\n onChangeNumber={emit}\n onChangeCountry={emit}\n onChangeValidity={emit}\n initialCountry={initialCountry}\n initialCountryLookup={null}\n
|
|
1947
|
+
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport IntlTelInput from \"@intl-tel-input/react\"\nimport type { IntlTelInputRef } from \"@intl-tel-input/react\"\nimport type { CountrySelectorMode, Iso2, ValidationError } from \"intl-tel-input\"\nimport \"intl-tel-input/styles\"\nimport { cn } from \"../../../lib/utils\"\n\n// Password managers mangle tel fields. Typed through `input` props because the\n// library's `inputProps` surface does not model arbitrary data attributes.\nconst PASSWORD_MANAGER_OPT_OUT = {\n \"data-1p-ignore\": true,\n \"data-lpignore\": \"true\",\n \"data-bwignore\": true,\n \"data-form-type\": \"other\",\n} as React.ComponentPropsWithoutRef<\"input\">\n\nexport interface PhoneInputPortal {\n /** Element the country selector is portaled into. */\n container: HTMLElement\n /**\n * Theme-scoping class applied to the portaled country selector. Required —\n * a selector portaled out of the tree escapes the consumer's theme class,\n * so the scope has to travel with it.\n */\n scopeClassName: string\n}\n\nexport interface PhoneInputProps {\n /** HTML id attribute */\n id?: string\n /** HTML name attribute */\n name?: string\n /** Phone number in E.164 (e.g. \"+14155551234\"). Displayed formatted for the detected country. */\n value?: string | null\n /** Placeholder text */\n placeholder?: string\n /** Whether the field is required */\n required?: boolean\n /** Whether the field is disabled */\n disabled?: boolean\n /** Whether the field is read-only. Pair with `countrySelectorMode=\"OFF\"` to also close off the country dropdown. */\n readOnly?: boolean\n /** Country selector behaviour. `\"OFF\"` renders the selected country as a non-interactive element. */\n countrySelectorMode?: CountrySelectorMode\n /** ISO 3166-1 alpha-2 country selected on mount. */\n initialCountry?: Iso2\n /** Size variant — matches Input component sizes */\n size?: \"sm\" | \"md\" | \"lg\"\n /** Additional CSS classes applied to the wrapper */\n className?: string\n /**\n * Portal the country selector out of the input's DOM position. All-or-nothing:\n * the scoping class is not separable from the container, so the selector can\n * never escape its theme. Omit for the default inline selector.\n */\n portal?: PhoneInputPortal\n /**\n * Called with the E.164 number and its validity. `e164` is `null` for anything\n * that is not a complete, valid number — a partial is never emitted.\n */\n onChange?: (e164: string | null, isValid: boolean) => void\n /** Called on blur with the validation error for a non-empty, invalid number (otherwise `null`). */\n onBlur?: (error: ValidationError | null) => void\n}\n\nconst PhoneInput = React.forwardRef<IntlTelInputRef, PhoneInputProps>(\n (\n {\n id,\n name,\n value,\n placeholder,\n required = false,\n disabled = false,\n readOnly = false,\n countrySelectorMode,\n initialCountry = \"us\",\n size = \"md\",\n className,\n portal,\n onChange,\n onBlur,\n },\n ref\n ) => {\n const itiRef = React.useRef<IntlTelInputRef>(null)\n // `undefined` until the first emission — an initial `{ null, false }` would be\n // indistinguishable from the first partial the user types and would swallow it.\n const lastEmitted = React.useRef<\n { e164: string | null; isValid: boolean } | undefined\n >(undefined)\n\n React.useImperativeHandle(ref, () => ({\n getInstance: () => itiRef.current?.getInstance() ?? null,\n getInput: () => itiRef.current?.getInput() ?? null,\n }))\n\n // `emit` must be identity-stable. The wrapper derives its internal `update`\n // from the onChange* props and keys its value-writeback effect on\n // `[value, update]`; a new `emit` each render re-runs that effect, and while\n // the field is unfocused and holding a partial (so the controlled value is\n // null) it calls setNumber(\"\") and erases what the user typed. Reading the\n // consumer's callback from a ref keeps the effect keyed on `value` alone.\n const onChangeRef = React.useRef(onChange)\n onChangeRef.current = onChange\n\n // The library's own `onChangeNumber` emits `getNumber()` verbatim, which for a\n // partial is a `+<dial code>` prefix glued to the formatted national string\n // (typing \"21337\" yields \"+1213-37\"). Derive the value at emit time instead so\n // a malformed number can never reach the consumer.\n const emit = React.useCallback(() => {\n const iti = itiRef.current?.getInstance()\n const isValid = iti?.isValidNumber() ?? false\n const e164 = isValid ? iti!.getNumber() : null\n const last = lastEmitted.current\n if (last && last.e164 === e164 && last.isValid === isValid) return\n lastEmitted.current = { e164, isValid }\n onChangeRef.current?.(e164, isValid)\n }, [])\n\n const handleBlur = React.useCallback(() => {\n const iti = itiRef.current?.getInstance()\n const input = itiRef.current?.getInput()\n // The error callback never fires while a number is still partial, so read the\n // error directly — a visibly-present partial that saves as nothing is silent\n // data loss. Gate on validity: getValidationError() reports \"IS_POSSIBLE\" for\n // a number that is fine, which is not an error.\n const error =\n iti && input?.value && !iti.isValidNumber()\n ? (iti.getValidationError() ?? null)\n : null\n onBlur?.(error)\n }, [onBlur])\n\n // The library validates every option key it is handed, and a key explicitly\n // set to `undefined` is still an own key — so spreading an unset optional\n // prop makes it warn (\"must be ...; got undefined. Ignoring.\") on every\n // mount. Carry each key only when the consumer actually set one; there is no\n // correct default to invent for either.\n const optional = {\n ...(countrySelectorMode !== undefined && { countrySelectorMode }),\n ...(portal && {\n classNames: { countrySelectorContainer: portal.scopeClassName },\n }),\n }\n\n return (\n <div data-slot=\"phone-input\" data-size={size} className={cn(className)}>\n <IntlTelInput\n ref={itiRef}\n {...optional}\n value={value}\n disabled={disabled}\n readOnly={readOnly}\n onChangeNumber={emit}\n onChangeCountry={emit}\n onChangeValidity={emit}\n initialCountry={initialCountry}\n initialCountryLookup={null}\n separateDialCode\n formatAsYouType\n strictMode\n countrySearch\n loadUtils={() => import(\"intl-tel-input/utils\")}\n dropdownParent={portal?.container ?? null}\n inputProps={{\n id,\n name,\n placeholder,\n required,\n autoComplete: \"tel\",\n onBlur: handleBlur,\n ...PASSWORD_MANAGER_OPT_OUT,\n }}\n />\n </div>\n )\n }\n)\nPhoneInput.displayName = \"PhoneInput\"\n\nexport { PhoneInput }\n"
|
|
1948
1948
|
},
|
|
1949
1949
|
{
|
|
1950
1950
|
"path": "components/ui/phone-input/phone-input.css",
|
package/dist/visor-manifest.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": "0.4.0",
|
|
3
|
-
"generated_at": "2026-09-
|
|
3
|
+
"generated_at": "2026-09-18T04:27:52.346Z",
|
|
4
4
|
"components": {
|
|
5
5
|
"accessibility-specimen": {
|
|
6
6
|
"category": "specimen",
|
|
@@ -4937,6 +4937,7 @@
|
|
|
4937
4937
|
"2xl"
|
|
4938
4938
|
],
|
|
4939
4939
|
"weight": [
|
|
4940
|
+
"heading",
|
|
4940
4941
|
"normal",
|
|
4941
4942
|
"medium",
|
|
4942
4943
|
"semibold",
|
|
@@ -4957,8 +4958,9 @@
|
|
|
4957
4958
|
},
|
|
4958
4959
|
{
|
|
4959
4960
|
"name": "weight",
|
|
4960
|
-
"type": "'normal' | 'medium' | 'semibold' | 'bold'",
|
|
4961
|
-
"default": "'
|
|
4961
|
+
"type": "'heading' | 'normal' | 'medium' | 'semibold' | 'bold'",
|
|
4962
|
+
"default": "'heading'",
|
|
4963
|
+
"description": "Visual weight. 'heading' follows the theme's declared heading weight (--weight-heading); the rest are steps on the named ramp."
|
|
4962
4964
|
}
|
|
4963
4965
|
],
|
|
4964
4966
|
"dependencies": [
|
|
@@ -4973,6 +4975,7 @@
|
|
|
4973
4975
|
"--font-size-sm",
|
|
4974
4976
|
"--font-size-xl",
|
|
4975
4977
|
"--font-weight-bold",
|
|
4978
|
+
"--font-weight-heading",
|
|
4976
4979
|
"--font-weight-medium",
|
|
4977
4980
|
"--font-weight-normal",
|
|
4978
4981
|
"--font-weight-semibold",
|
|
@@ -13650,6 +13653,27 @@
|
|
|
13650
13653
|
"defaultLight": "700",
|
|
13651
13654
|
"defaultDark": "700"
|
|
13652
13655
|
},
|
|
13656
|
+
{
|
|
13657
|
+
"name": "--font-weight-heading",
|
|
13658
|
+
"tier": "primitive",
|
|
13659
|
+
"description": "Primitive font weight: 600",
|
|
13660
|
+
"defaultLight": "600",
|
|
13661
|
+
"defaultDark": "600"
|
|
13662
|
+
},
|
|
13663
|
+
{
|
|
13664
|
+
"name": "--font-weight-body",
|
|
13665
|
+
"tier": "primitive",
|
|
13666
|
+
"description": "Primitive font weight: 400",
|
|
13667
|
+
"defaultLight": "400",
|
|
13668
|
+
"defaultDark": "400"
|
|
13669
|
+
},
|
|
13670
|
+
{
|
|
13671
|
+
"name": "--font-weight-display",
|
|
13672
|
+
"tier": "primitive",
|
|
13673
|
+
"description": "Primitive font weight: 400",
|
|
13674
|
+
"defaultLight": "400",
|
|
13675
|
+
"defaultDark": "400"
|
|
13676
|
+
},
|
|
13653
13677
|
{
|
|
13654
13678
|
"name": "--line-height-none",
|
|
13655
13679
|
"tier": "primitive",
|
|
@@ -14552,8 +14576,8 @@
|
|
|
14552
14576
|
"name": "--weight-body",
|
|
14553
14577
|
"tier": "semantic",
|
|
14554
14578
|
"description": "Semantic typography: weight-body",
|
|
14555
|
-
"defaultLight": "var(--font-weight-
|
|
14556
|
-
"defaultDark": "var(--font-weight-
|
|
14579
|
+
"defaultLight": "var(--font-weight-body)",
|
|
14580
|
+
"defaultDark": "var(--font-weight-body)"
|
|
14557
14581
|
},
|
|
14558
14582
|
{
|
|
14559
14583
|
"name": "--weight-label",
|
|
@@ -14566,8 +14590,8 @@
|
|
|
14566
14590
|
"name": "--weight-heading",
|
|
14567
14591
|
"tier": "semantic",
|
|
14568
14592
|
"description": "Semantic typography: weight-heading",
|
|
14569
|
-
"defaultLight": "var(--font-weight-
|
|
14570
|
-
"defaultDark": "var(--font-weight-
|
|
14593
|
+
"defaultLight": "var(--font-weight-heading)",
|
|
14594
|
+
"defaultDark": "var(--font-weight-heading)"
|
|
14571
14595
|
},
|
|
14572
14596
|
{
|
|
14573
14597
|
"name": "--weight-strong",
|
|
@@ -15245,7 +15269,7 @@
|
|
|
15245
15269
|
}
|
|
15246
15270
|
],
|
|
15247
15271
|
"summary": {
|
|
15248
|
-
"total":
|
|
15272
|
+
"total": 317
|
|
15249
15273
|
}
|
|
15250
15274
|
}
|
|
15251
15275
|
}
|