@loworbitstudio/visor 1.24.0 → 1.24.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 +1 -1
- package/dist/registry.json +1 -1
- package/dist/visor-manifest.json +1 -1
- package/package.json +1 -1
package/dist/CHANGELOG.json
CHANGED
package/dist/registry.json
CHANGED
|
@@ -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