@xploreu/components 0.3.0 → 0.3.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.
@@ -0,0 +1,2 @@
1
+ import {c,d as d$1,p,u,w,A}from'./chunk-JFJU2DLY.js';import {a}from'./chunk-XXHHZYH6.js';import*as t from'react';import*as C from'react-phone-number-input';import q from'react-phone-number-input/flags';import {cn}from'@xploreu/lib/cn';import {Combobox}from'@base-ui/react/combobox';import {ChevronsUpDownIcon}from'lucide-react';import {jsx,jsxs}from'react/jsx-runtime';var x=({country:l,countryName:o})=>{let s=l?q[l]:void 0;return jsx("span",{className:"flex h-4 w-6 shrink-0 overflow-hidden rounded-sm bg-fg-quaternary/20 [&_svg:not([class*='size-'])]:size-full",children:s&&jsx(s,{title:o})})},d=44,V=288,k=6;function D({disabled:l,value:o,options:s,onChange:i}){let[c$1,r]=t.useState(false),[b,I]=t.useState(""),[y,N]=t.useState(0),R=t.useRef(null),m=t.useMemo(()=>s.filter(e=>!!e.value),[s]),u$1=t.useMemo(()=>{let e=b.trim().toLowerCase();return e?m.filter(a=>{let f=C.getCountryCallingCode(a.value);return a.label.toLowerCase().includes(e)||a.value.toLowerCase().includes(e)||f.includes(e.replace(/^\+/,""))}):m},[b,m]),L=t.useMemo(()=>m.find(e=>e.value===o)??null,[m,o]);t.useEffect(()=>{N(0),R.current&&(R.current.scrollTop=0);},[b]);let z=Math.min(u$1.length*d,V),g=t.useMemo(()=>{let e=Math.floor(y/d),a=Math.max(0,e-k),f=Math.ceil(V/d),P=Math.min(u$1.length,e+f+k);return {startIndex:a,endIndex:P,items:u$1.slice(a,P)}},[u$1,y]),_=g.startIndex*d,F=Math.max(0,(u$1.length-g.endIndex)*d),U=t.useCallback(e=>{e?.value&&(i(e.value),I(""),r(false));},[i]);return jsxs(c,{behavior:"default",disabled:l,inputValue:b,items:u$1,open:c$1,value:L,virtualized:true,filter:null,isItemEqualToValue:(e,a)=>e.value===a.value,openOnInputClick:false,onValueChange:U,onInputValueChange:I,onOpenChange:e=>{r(e),e||I("");},children:[jsx(d$1,{render:jsxs("button",{type:"button",className:cn(a(),"h-11 w-18 shrink-0 justify-between gap-1 rounded-r-none border-r-0 px-3","hover:bg-bg-primary-hover focus-visible:z-10 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand","disabled:pointer-events-none disabled:opacity-50"),disabled:l,children:[jsxs("span",{className:"flex items-center gap-1.5 overflow-hidden",children:[jsx(x,{country:o,countryName:o}),o&&jsx("span",{className:"text-body-medium-3 text-text-primary",children:o})]}),jsx(ChevronsUpDownIcon,{className:"size-3.5 shrink-0 text-fg-quaternary"})]})}),jsxs(p,{className:"w-[300px] p-1.5",align:"start",sideOffset:4,collisionPadding:8,children:[jsx(Combobox.Input,{className:cn(a({size:"sm"}),"mb-1"),placeholder:"Search country...","aria-label":"Search country"}),jsx(u,{status:u$1.length===0?"empty":null}),jsx(w,{ref:R,className:"relative gap-0",style:{height:z},onScroll:e=>N(e.currentTarget.scrollTop),children:jsx("div",{className:"flex w-full shrink-0 flex-col",style:{paddingTop:_,paddingBottom:F},children:g.items.map((e,a)=>{let f=g.startIndex+a;return jsx(A,{index:f,value:e,children:jsxs("div",{className:"flex items-center gap-2 w-full min-w-0",children:[jsx(x,{country:e.value,countryName:e.label}),jsx("span",{className:"flex-1 text-sm truncate",children:e.label}),jsxs("span",{className:"text-sm text-text-tertiary shrink-0",children:["+",C.getCountryCallingCode(e.value)]})]})},e.value)})})})]})]})}var H=t.forwardRef(({className:l,onChange:o,...s},i)=>{let c=t.useCallback(r=>{r.currentTarget.value==="+"&&(r.currentTarget.value=""),o?.(r);},[o]);return jsx("input",{className:cn(a(),"h-11 flex-1 rounded-l-none text-body-regular-2",l),ref:i,type:"tel",onChange:c,...s})});H.displayName="InputComponent";var G=t.forwardRef(({className:l,onChange:o,value:s,...i},c)=>jsx(C.default,{ref:c,className:cn("flex w-full min-w-0 items-center",l),flagComponent:x,countrySelectComponent:D,inputComponent:H,smartCaret:false,value:s||void 0,onChange:r=>o?.(r||""),...i}));G.displayName="PhoneInput";export{G as a};//# sourceMappingURL=chunk-UFNEGKVA.js.map
2
+ //# sourceMappingURL=chunk-UFNEGKVA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/composites/phone-input.tsx"],"names":["FlagComponent","country","countryName","Flag","flags","jsx","COUNTRY_ROW_HEIGHT","COUNTRY_LIST_HEIGHT","COUNTRY_OVERSCAN","CountrySelect","disabled","selectedCountry","countryList","onChange","open","setOpen","inputValue","setInputValue","scrollTop","setScrollTop","listRef","items","item","filteredItems","search","callingCode","value","listHeight","virtualRange","visibleStartIndex","startIndex","visibleCount","endIndex","paddingTop","paddingBottom","handleValueChange","jsxs","Combobox","a","b","ComboboxTrigger","cn","inputVariants","ChevronsUpDownIcon","ComboboxContent","ComboboxPrimitive","ComboboxStatus","ComboboxList","event","virtualIndex","index","ComboboxItem","InputComponent","className","props","ref","handleChange","PhoneInput"],"mappings":"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","file":"chunk-UFNEGKVA.js","sourcesContent":["\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport * as RPNInput from \"react-phone-number-input\"\r\nimport flags from \"react-phone-number-input/flags\"\r\n\r\nimport { cn } from \"@xploreu/lib/cn\"\r\nimport { Combobox as ComboboxPrimitive } from \"@base-ui/react/combobox\"\r\nimport {\r\n Combobox,\r\n ComboboxContent,\r\n ComboboxItem,\r\n ComboboxList,\r\n ComboboxStatus,\r\n ComboboxTrigger,\r\n} from \"../ui/combobox\"\r\nimport { inputVariants } from \"../ui/input\"\r\nimport { ChevronsUpDownIcon } from \"lucide-react\"\r\n\r\n// ---------------------------------------------------------------------------\r\n// Types\r\n// ---------------------------------------------------------------------------\r\n\r\ntype PhoneInputProps = Omit<\r\n React.ComponentProps<\"input\">,\r\n \"onChange\" | \"value\" | \"ref\"\r\n> &\r\n Omit<RPNInput.Props<typeof RPNInput.default>, \"onChange\"> & {\r\n onChange?: (value: RPNInput.Value) => void\r\n }\r\n\r\n// ---------------------------------------------------------------------------\r\n// Flag\r\n// ---------------------------------------------------------------------------\r\n\r\nconst FlagComponent = ({ country, countryName }: RPNInput.FlagProps) => {\r\n const Flag = country ? flags[country] : undefined\r\n\r\n return (\r\n <span className=\"flex h-4 w-6 shrink-0 overflow-hidden rounded-sm bg-fg-quaternary/20 [&_svg:not([class*='size-'])]:size-full\">\r\n {Flag && <Flag title={countryName} />}\r\n </span>\r\n )\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Country Select — uses base-ui Combobox\r\n// ---------------------------------------------------------------------------\r\n\r\ntype CountryEntry = { label: string; value: RPNInput.Country | undefined }\r\ntype CountryItem = { label: string; value: RPNInput.Country }\r\n\r\nconst COUNTRY_ROW_HEIGHT = 44\r\nconst COUNTRY_LIST_HEIGHT = 288\r\nconst COUNTRY_OVERSCAN = 6\r\n\r\ntype CountrySelectProps = {\r\n disabled?: boolean\r\n value: RPNInput.Country\r\n options: CountryEntry[]\r\n onChange: (country: RPNInput.Country) => void\r\n}\r\n\r\nfunction CountrySelect({\r\n disabled,\r\n value: selectedCountry,\r\n options: countryList,\r\n onChange,\r\n}: CountrySelectProps) {\r\n const [open, setOpen] = React.useState(false)\r\n const [inputValue, setInputValue] = React.useState(\"\")\r\n const [scrollTop, setScrollTop] = React.useState(0)\r\n const listRef = React.useRef<HTMLDivElement>(null)\r\n\r\n const items = React.useMemo(\r\n () => countryList.filter((item): item is CountryItem => Boolean(item.value)),\r\n [countryList]\r\n )\r\n\r\n const filteredItems = React.useMemo(() => {\r\n const search = inputValue.trim().toLowerCase()\r\n\r\n if (!search) return items\r\n\r\n return items.filter((item) => {\r\n const callingCode = RPNInput.getCountryCallingCode(item.value)\r\n\r\n return item.label.toLowerCase().includes(search)\r\n || item.value.toLowerCase().includes(search)\r\n || callingCode.includes(search.replace(/^\\+/, \"\"))\r\n })\r\n }, [inputValue, items])\r\n\r\n const value = React.useMemo(\r\n () => items.find((item) => item.value === selectedCountry) ?? null,\r\n [items, selectedCountry]\r\n )\r\n\r\n React.useEffect(() => {\r\n setScrollTop(0)\r\n if (listRef.current) listRef.current.scrollTop = 0\r\n }, [inputValue])\r\n\r\n const listHeight = Math.min(\r\n filteredItems.length * COUNTRY_ROW_HEIGHT,\r\n COUNTRY_LIST_HEIGHT\r\n )\r\n\r\n const virtualRange = React.useMemo(() => {\r\n const visibleStartIndex = Math.floor(scrollTop / COUNTRY_ROW_HEIGHT)\r\n const startIndex = Math.max(\r\n 0,\r\n visibleStartIndex - COUNTRY_OVERSCAN\r\n )\r\n const visibleCount = Math.ceil(COUNTRY_LIST_HEIGHT / COUNTRY_ROW_HEIGHT)\r\n const endIndex = Math.min(\r\n filteredItems.length,\r\n visibleStartIndex + visibleCount + COUNTRY_OVERSCAN\r\n )\r\n\r\n return {\r\n startIndex,\r\n endIndex,\r\n items: filteredItems.slice(startIndex, endIndex),\r\n }\r\n }, [filteredItems, scrollTop])\r\n\r\n const paddingTop = virtualRange.startIndex * COUNTRY_ROW_HEIGHT\r\n const paddingBottom = Math.max(\r\n 0,\r\n (filteredItems.length - virtualRange.endIndex) * COUNTRY_ROW_HEIGHT\r\n )\r\n\r\n const handleValueChange = React.useCallback(\r\n (item: CountryItem | null) => {\r\n if (!item?.value) return\r\n\r\n onChange(item.value)\r\n setInputValue(\"\")\r\n setOpen(false)\r\n },\r\n [onChange]\r\n )\r\n\r\n return (\r\n <Combobox\r\n behavior=\"default\"\r\n disabled={disabled}\r\n inputValue={inputValue}\r\n items={filteredItems}\r\n open={open}\r\n value={value}\r\n virtualized\r\n filter={null}\r\n isItemEqualToValue={(a, b) => a.value === b.value}\r\n openOnInputClick={false}\r\n onValueChange={handleValueChange}\r\n onInputValueChange={setInputValue}\r\n onOpenChange={(open) => {\r\n setOpen(open)\r\n if (!open) setInputValue(\"\")\r\n }}\r\n >\r\n {/* Visible trigger button styled as part of the input */}\r\n <ComboboxTrigger\r\n render={\r\n <button\r\n type=\"button\"\r\n className={cn(\r\n inputVariants(),\r\n \"h-11 w-18 shrink-0 justify-between gap-1 rounded-r-none border-r-0 px-3\",\r\n \"hover:bg-bg-primary-hover focus-visible:z-10 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand\",\r\n \"disabled:pointer-events-none disabled:opacity-50\"\r\n )}\r\n disabled={disabled}\r\n >\r\n <span className=\"flex items-center gap-1.5 overflow-hidden\">\r\n <FlagComponent\r\n country={selectedCountry}\r\n countryName={selectedCountry}\r\n />\r\n {selectedCountry && (\r\n <span className=\"text-body-medium-3 text-text-primary\">\r\n {selectedCountry}\r\n </span>\r\n )}\r\n </span>\r\n <ChevronsUpDownIcon className=\"size-3.5 shrink-0 text-fg-quaternary\" />\r\n </button>\r\n }\r\n />\r\n\r\n {/* Dropdown content */}\r\n <ComboboxContent\r\n className=\"w-[300px] p-1.5\"\r\n align=\"start\"\r\n sideOffset={4}\r\n collisionPadding={8}\r\n >\r\n <ComboboxPrimitive.Input\r\n className={cn(inputVariants({ size: \"sm\" }), \"mb-1\")}\r\n placeholder=\"Search country...\"\r\n aria-label=\"Search country\"\r\n />\r\n <ComboboxStatus status={filteredItems.length === 0 ? \"empty\" : null} />\r\n <ComboboxList\r\n ref={listRef}\r\n className=\"relative gap-0\"\r\n style={{ height: listHeight }}\r\n onScroll={(event) => setScrollTop(event.currentTarget.scrollTop)}\r\n >\r\n <div\r\n className=\"flex w-full shrink-0 flex-col\"\r\n style={{ paddingTop, paddingBottom }}\r\n >\r\n {virtualRange.items.map((item, virtualIndex) => {\r\n const index = virtualRange.startIndex + virtualIndex\r\n\r\n return (\r\n <ComboboxItem\r\n key={item.value}\r\n index={index}\r\n value={item}\r\n >\r\n <div className=\"flex items-center gap-2 w-full min-w-0\">\r\n <FlagComponent country={item.value} countryName={item.label} />\r\n <span className=\"flex-1 text-sm truncate\">{item.label}</span>\r\n <span className=\"text-sm text-text-tertiary shrink-0\">\r\n +{RPNInput.getCountryCallingCode(item.value)}\r\n </span>\r\n </div>\r\n </ComboboxItem>\r\n )\r\n })}\r\n </div>\r\n </ComboboxList>\r\n </ComboboxContent>\r\n </Combobox>\r\n )\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Input Component\r\n// ---------------------------------------------------------------------------\r\n\r\nconst InputComponent = React.forwardRef<\r\n HTMLInputElement,\r\n React.ComponentProps<\"input\">\r\n>(({ className, onChange, ...props }, ref) => {\r\n const handleChange = React.useCallback(\r\n (event: React.ChangeEvent<HTMLInputElement>) => {\r\n if (event.currentTarget.value === \"+\") {\r\n event.currentTarget.value = \"\"\r\n }\r\n\r\n onChange?.(event)\r\n },\r\n [onChange]\r\n )\r\n\r\n return (\r\n <input\r\n className={cn(\r\n inputVariants(),\r\n \"h-11 flex-1 rounded-l-none text-body-regular-2\",\r\n className\r\n )}\r\n ref={ref}\r\n type=\"tel\"\r\n onChange={handleChange}\r\n {...props}\r\n />\r\n )\r\n})\r\nInputComponent.displayName = \"InputComponent\"\r\n\r\n// ---------------------------------------------------------------------------\r\n// Phone Input\r\n// ---------------------------------------------------------------------------\r\n\r\nconst PhoneInput: React.ForwardRefExoticComponent<PhoneInputProps> =\r\n React.forwardRef<\r\n React.ElementRef<typeof RPNInput.default>,\r\n PhoneInputProps\r\n >(({\r\n className,\r\n onChange,\r\n value,\r\n ...props\r\n }, ref) => {\r\n return (\r\n <RPNInput.default\r\n ref={ref}\r\n className={cn(\r\n \"flex w-full min-w-0 items-center\",\r\n className\r\n )}\r\n flagComponent={FlagComponent}\r\n countrySelectComponent={CountrySelect}\r\n inputComponent={InputComponent}\r\n smartCaret={false}\r\n value={value || undefined}\r\n onChange={(value) => onChange?.(value || (\"\" as RPNInput.Value))}\r\n {...props}\r\n />\r\n )\r\n })\r\nPhoneInput.displayName = \"PhoneInput\"\r\n\r\nexport { PhoneInput, type PhoneInputProps }\r\n"]}
@@ -1,6 +1,7 @@
1
1
  export { ComboboxChipOutside } from './combobox-chip-outside.js';
2
2
  import * as React from 'react';
3
3
  import { ComboboxProps, ComboboxPortal, ComboboxInfiniteScroll } from '../ui/combobox.js';
4
+ export { PhoneInput } from './phone-input.js';
4
5
  import '@base-ui/react/combobox';
5
6
  import 'motion/react';
6
7
  import '../effects/highlight.js';
@@ -8,6 +9,7 @@ import '../ui/infinite-scroll.js';
8
9
  import '../ui/input.js';
9
10
  import 'class-variance-authority/types';
10
11
  import 'class-variance-authority';
12
+ import 'react-phone-number-input';
11
13
 
12
14
  type ComboboxChipProps<Value> = Omit<ComboboxProps<Value, true>, "multiple"> & {
13
15
  multiple?: boolean;
@@ -1,2 +1,2 @@
1
- export{a as ComboboxChipOutside}from'../chunk-7ASZFFFB.js';import'../chunk-ZQTWDSKK.js';import'../chunk-XRBBTMGF.js';import {c,a,l,k,m,n,b,p,u,w,A,H as H$1}from'../chunk-JFJU2DLY.js';import'../chunk-4YATKUEK.js';import'../chunk-52U7K5UV.js';import'../chunk-5YDJTHDG.js';import'../chunk-TED2PUK6.js';import {a as a$1}from'../chunk-XXHHZYH6.js';import'../chunk-WIUYDPXB.js';import'../chunk-MMCL4HWD.js';import'../chunk-ZVME3JB3.js';import'../chunk-2TUGHMFW.js';import'../chunk-KYD4ATTG.js';import*as r from'react';import {cn}from'@xploreu/lib/cn';import {useControlledState}from'@xploreu/hooks/use-controlled-state';import {jsxs,jsx,Fragment}from'react/jsx-runtime';function H({multiple:z=true,inputPlaceholder:E="Search...",container:G,items:s,infiniteScroll:O,isPending:T,taggable:c$1=false,maxVisible:i,...m$1}){let[j,q]=useControlledState({value:m$1?.inputValue?.toString(),defaultValue:m$1?.defaultInputValue?.toString(),onChange:m$1?.onInputValueChange}),[b$1,h]=useControlledState({value:m$1?.value??[],defaultValue:m$1?.defaultValue??[],onChange:m$1?.onValueChange}),[g,V]=r.useState([]),C=r.useRef(new Set);r.useEffect(()=>{let e=new Set(b$1.map(n=>n.value));V(n=>{let l=n.filter(o=>e.has(o.value));return l.length===n.length?n:(C.current=new Set(l.map(o=>o.value)),l)});},[b$1]);let a$2=j?.toString().trim()??"",A$1=r.useMemo(()=>a$2?b$1.some(e=>e.value.toLowerCase()===a$2.toLowerCase()):false,[a$2,b$1]),p$1=r.useMemo(()=>!c$1||!a$2?false:!s?.some(e=>e.label.toLowerCase()===a$2.toLowerCase()),[c$1,a$2,s]),B=r.useMemo(()=>{let e=[...s??[],...g];return p$1?[...e,{label:a$2,value:a$2,tag:true}]:e},[s,g,p$1,a$2]);return jsxs(c,{...m$1,behavior:"chip-outside",multiple:true,items:c$1?B:s,isItemEqualToValue:(e,n)=>e.value===n.value,onValueChange:(e,n)=>{if(c$1){let l=e.filter(o=>o?.tag===true&&!C.current.has(o.value));if(l.length>0){for(let o of l)C.current.add(o.value);V(o=>[...o,...l]);}}h(z?e:[e[e.length-1]],n);},onInputValueChange:q,children:[jsxs(a,{className:cn(a$1(),"h-auto min-h-13 flex flex-wrap items-center gap-1.5 px-3 py-1.5 cursor-text"),children:[jsx(l,{className:cn("contents",i!==void 0&&"flex-nowrap overflow-hidden"),children:jsx(k,{children:e=>{let n$1=i!==void 0?e.slice(0,i):e,l=i!==void 0?e.length-i:0;return jsxs(Fragment,{children:[n$1?.map(o=>jsxs(m,{className:cn(i!==void 0&&"min-w-0 shrink"),children:[o?.image&&jsx("img",{src:o.image,alt:o?.label||"",className:"size-4 rounded-full object-cover shrink-0 mr-1"}),i!==void 0?jsx("span",{className:"truncate",children:o?.label||""}):o?.label||"",jsx(n,{})]},o?.value||"")),l>0&&jsxs(m,{className:"shrink-0",children:["+",l]})]})}})}),jsx(b,{render:jsx("input",{className:"flex-1 min-w-[80px] bg-transparent outline-none text-body-regular-1 text-text-primary placeholder:text-text-placeholder",placeholder:b$1.length===0?E:void 0})})]}),jsxs(p,{container:G,children:[jsx(u,{status:T||s===void 0?"pending":s?.length===0&&!p$1?"empty":null}),jsxs(w,{children:[s?.map(e=>jsx(A,{value:e,children:jsxs("div",{className:"flex items-center gap-2 w-full min-w-0",children:[e.image&&jsx("img",{src:e.image,alt:e.label,className:"size-6 rounded-full object-cover shrink-0"}),jsx("span",{className:"truncate",children:e.label})]})},e.value)),p$1&&jsx(A,{value:{label:a$2,value:a$2,tag:true},children:jsxs("div",{className:"flex items-center gap-1.5 w-full min-w-0",children:[!A$1&&jsx("span",{className:"text-text-secondary",children:"Create:"}),jsx("span",{className:"font-medium text-text-primary truncate",children:a$2})]})}),jsx(H$1,{...O})]})]})]})}export{H as ComboboxChip};//# sourceMappingURL=index.js.map
1
+ export{a as ComboboxChipOutside}from'../chunk-7ASZFFFB.js';export{a as PhoneInput}from'../chunk-UFNEGKVA.js';import'../chunk-ZQTWDSKK.js';import'../chunk-XRBBTMGF.js';import {c,a,l,k,m,n,b,p,u,w,A,H}from'../chunk-JFJU2DLY.js';import'../chunk-4YATKUEK.js';import'../chunk-52U7K5UV.js';import'../chunk-5YDJTHDG.js';import'../chunk-TED2PUK6.js';import {a as a$1}from'../chunk-XXHHZYH6.js';import'../chunk-WIUYDPXB.js';import'../chunk-MMCL4HWD.js';import'../chunk-ZVME3JB3.js';import'../chunk-2TUGHMFW.js';import'../chunk-KYD4ATTG.js';import*as r from'react';import {cn}from'@xploreu/lib/cn';import {useControlledState}from'@xploreu/hooks/use-controlled-state';import {jsxs,jsx,Fragment}from'react/jsx-runtime';function J({multiple:z=true,inputPlaceholder:E="Search...",container:G,items:s,infiniteScroll:O,isPending:T,taggable:c$1=false,maxVisible:m$1,...i}){let[j,q]=useControlledState({value:i?.inputValue?.toString(),defaultValue:i?.defaultInputValue?.toString(),onChange:i?.onInputValueChange}),[b$1,h]=useControlledState({value:i?.value??[],defaultValue:i?.defaultValue??[],onChange:i?.onValueChange}),[g,V]=r.useState([]),C=r.useRef(new Set);r.useEffect(()=>{let e=new Set(b$1.map(a=>a.value));V(a=>{let l=a.filter(o=>e.has(o.value));return l.length===a.length?a:(C.current=new Set(l.map(o=>o.value)),l)});},[b$1]);let n$1=j?.toString().trim()??"",A$1=r.useMemo(()=>n$1?b$1.some(e=>e.value.toLowerCase()===n$1.toLowerCase()):false,[n$1,b$1]),p$1=r.useMemo(()=>!c$1||!n$1?false:!s?.some(e=>e.label.toLowerCase()===n$1.toLowerCase()),[c$1,n$1,s]),B=r.useMemo(()=>{let e=[...s??[],...g];return p$1?[...e,{label:n$1,value:n$1,tag:true}]:e},[s,g,p$1,n$1]);return jsxs(c,{...i,behavior:"chip-outside",multiple:true,items:c$1?B:s,isItemEqualToValue:(e,a)=>e.value===a.value,onValueChange:(e,a)=>{if(c$1){let l=e.filter(o=>o?.tag===true&&!C.current.has(o.value));if(l.length>0){for(let o of l)C.current.add(o.value);V(o=>[...o,...l]);}}h(z?e:[e[e.length-1]],a);},onInputValueChange:q,children:[jsxs(a,{className:cn(a$1(),"h-auto min-h-13 flex flex-wrap items-center gap-1.5 px-3 py-1.5 cursor-text"),children:[jsx(l,{className:cn("contents",m$1!==void 0&&"flex-nowrap overflow-hidden"),children:jsx(k,{children:e=>{let a=m$1!==void 0?e.slice(0,m$1):e,l=m$1!==void 0?e.length-m$1:0;return jsxs(Fragment,{children:[a?.map(o=>jsxs(m,{className:cn(m$1!==void 0&&"min-w-0 shrink"),children:[o?.image&&jsx("img",{src:o.image,alt:o?.label||"",className:"size-4 rounded-full object-cover shrink-0 mr-1"}),m$1!==void 0?jsx("span",{className:"truncate",children:o?.label||""}):o?.label||"",jsx(n,{})]},o?.value||"")),l>0&&jsxs(m,{className:"shrink-0",children:["+",l]})]})}})}),jsx(b,{render:jsx("input",{className:"flex-1 min-w-[80px] bg-transparent outline-none text-body-regular-1 text-text-primary placeholder:text-text-placeholder",placeholder:b$1.length===0?E:void 0})})]}),jsxs(p,{container:G,children:[jsx(u,{status:T||s===void 0?"pending":s?.length===0&&!p$1?"empty":null}),jsxs(w,{children:[s?.map(e=>jsx(A,{value:e,children:jsxs("div",{className:"flex items-center gap-2 w-full min-w-0",children:[e.image&&jsx("img",{src:e.image,alt:e.label,className:"size-6 rounded-full object-cover shrink-0"}),jsx("span",{className:"truncate",children:e.label})]})},e.value)),p$1&&jsx(A,{value:{label:n$1,value:n$1,tag:true},children:jsxs("div",{className:"flex items-center gap-1.5 w-full min-w-0",children:[!A$1&&jsx("span",{className:"text-text-secondary",children:"Create:"}),jsx("span",{className:"font-medium text-text-primary truncate",children:n$1})]})}),jsx(H,{...O})]})]})]})}export{J as ComboboxChip};//# sourceMappingURL=index.js.map
2
2
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/composites/combobox-chip.tsx"],"names":["ComboboxChip","multiple","inputPlaceholder","container","items","infiniteScroll","isPending","taggable","maxVisible","props","inputValue","setInputValue","useControlledState","value","setValue","createdItems","setCreatedItems","createdValuesRef","currentValues","v","prev","next","item","trimmedInput","isInputSelected","isCreatingItem","combinedItems","base","jsxs","Combobox","a","b","eventDetails","newTags","tag","ComboboxInputGroup","cn","inputVariants","jsx","ComboboxChips","ComboboxValue","visible","overflow","Fragment","ComboboxChipRemove","ComboboxInput","ComboboxContent","ComboboxStatus","ComboboxList","ComboboxItem","ComboboxInfiniteScroll"],"mappings":"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","file":"index.js","sourcesContent":["import * as React from \"react\"\r\n\r\nimport { cn } from \"@xploreu/lib/cn\"\r\nimport {\r\n ComboboxInput as ComboboxInputPrimitive,\r\n ComboboxInputGroup,\r\n} from \"../primitives/combobox\"\r\nimport {\r\n Combobox,\r\n ComboboxChip as ComboboxChipUI,\r\n ComboboxChipRemove,\r\n ComboboxChips,\r\n ComboboxContent,\r\n ComboboxInfiniteScroll,\r\n ComboboxItem,\r\n ComboboxList,\r\n ComboboxPortal,\r\n ComboboxStatus,\r\n ComboboxValue,\r\n type ComboboxProps\r\n} from \"../ui/combobox\"\r\nimport { useControlledState } from \"@xploreu/hooks/use-controlled-state\"\r\nimport { inputVariants } from \"../ui/input\"\r\n\r\ntype ComboboxChipProps<Value> = Omit<ComboboxProps<Value, true>, \"multiple\"> & {\r\n multiple?: boolean\r\n inputPlaceholder?: string\r\n container?: React.ComponentProps<typeof ComboboxPortal>[\"container\"]\r\n items: ({ label: string; value: string; image?: string }[]) | undefined\r\n infiniteScroll?: React.ComponentProps<typeof ComboboxInfiniteScroll>\r\n isPending?: boolean\r\n /**\r\n * When true, enables creatable / taggable mode.\r\n * If the typed value has no exact match in the current item list,\r\n * a \"Create \\\"…\\\"\" option is shown at the top of the dropdown.\r\n * Created items are appended to the value with `{ label, value, tag: true }`.\r\n */\r\n taggable?: boolean\r\n /**\r\n * Maximum number of chips to show before collapsing the rest into a \"+N\" chip.\r\n * When undefined, all chips are shown.\r\n */\r\n maxVisible?: number\r\n}\r\n\r\nfunction ComboboxChip<Value extends { label: string; value: string; image?: string; tag?: true }>({\r\n multiple = true,\r\n inputPlaceholder = \"Search...\",\r\n container,\r\n items,\r\n infiniteScroll,\r\n isPending,\r\n taggable = false,\r\n maxVisible,\r\n ...props\r\n}: ComboboxChipProps<Value>) {\r\n const [inputValue, setInputValue] = useControlledState({\r\n value: props?.inputValue?.toString(),\r\n defaultValue: props?.defaultInputValue?.toString(),\r\n onChange: props?.onInputValueChange,\r\n })\r\n\r\n const [value, setValue] = useControlledState({\r\n value: props?.value ?? [],\r\n defaultValue: props?.defaultValue ?? [],\r\n onChange: props?.onValueChange,\r\n })\r\n\r\n // Track items created via taggable mode\r\n // Sync with value to avoid stale tags when controlled value is reset from outside\r\n const [createdItems, setCreatedItems] = React.useState<Value[]>([])\r\n const createdValuesRef = React.useRef<Set<string>>(new Set())\r\n\r\n React.useEffect(() => {\r\n const currentValues = new Set(value.map((v) => v.value))\r\n setCreatedItems((prev) => {\r\n const next = prev.filter((item) => currentValues.has(item.value))\r\n if (next.length === prev.length) return prev\r\n createdValuesRef.current = new Set(next.map((v) => v.value))\r\n return next\r\n })\r\n }, [value])\r\n\r\n const trimmedInput = inputValue?.toString().trim() ?? \"\"\r\n const isInputSelected = React.useMemo(() => {\r\n if (!trimmedInput) return false\r\n return value.some(\r\n (item) => item.value.toLowerCase() === trimmedInput.toLowerCase()\r\n )\r\n }, [trimmedInput, value])\r\n\r\n // true = show the taggable item in dropdown (either as \"Create:\" or as checked item)\r\n const isCreatingItem = React.useMemo(() => {\r\n if (!taggable || !trimmedInput) return false\r\n return !items?.some(\r\n (item) => item.label.toLowerCase() === trimmedInput.toLowerCase()\r\n )\r\n }, [taggable, trimmedInput, items])\r\n\r\n // Merge server items with locally created tags + the \"Create\" placeholder\r\n const combinedItems = React.useMemo(() => {\r\n const base: Value[] = [\r\n ...items ?? [],\r\n ...createdItems,\r\n ]\r\n\r\n if (isCreatingItem) {\r\n return [...base, { label: trimmedInput, value: trimmedInput, tag: true } as unknown as Value]\r\n }\r\n\r\n return base\r\n }, [items, createdItems, isCreatingItem, trimmedInput])\r\n\r\n const handleValueChange: ComboboxProps<Value, true>[\"onValueChange\"] = (value, eventDetails) => {\r\n if (taggable) {\r\n const newTags = value.filter(\r\n (v) => v?.tag === true && !createdValuesRef.current.has(v.value)\r\n )\r\n if (newTags.length > 0) {\r\n for (const tag of newTags) {\r\n createdValuesRef.current.add(tag.value)\r\n }\r\n setCreatedItems((prev) => [...prev, ...newTags])\r\n }\r\n }\r\n\r\n if (!multiple) {\r\n setValue([value[value.length - 1]], eventDetails)\r\n } else {\r\n setValue(value, eventDetails)\r\n }\r\n }\r\n\r\n return (\r\n <Combobox\r\n {...props}\r\n behavior=\"chip-outside\"\r\n multiple\r\n items={taggable ? combinedItems : items}\r\n isItemEqualToValue={(a, b) => a.value === b.value}\r\n onValueChange={handleValueChange}\r\n onInputValueChange={setInputValue}\r\n >\r\n {/* Input box with chips inside */}\r\n <ComboboxInputGroup\r\n className={cn(\r\n inputVariants(),\r\n \"h-auto min-h-13 flex flex-wrap items-center gap-1.5 px-3 py-1.5 cursor-text\"\r\n )}\r\n >\r\n {/* Chips inside the input box */}\r\n <ComboboxChips\r\n className={cn(\r\n \"contents\",\r\n maxVisible !== undefined && \"flex-nowrap overflow-hidden\"\r\n )}\r\n >\r\n <ComboboxValue>\r\n {(value: Value[]) => {\r\n const visible = maxVisible !== undefined ? value.slice(0, maxVisible) : value\r\n const overflow = maxVisible !== undefined ? value.length - maxVisible : 0\r\n return (\r\n <>\r\n {visible?.map((item) => (\r\n <ComboboxChipUI\r\n key={item?.value || \"\"}\r\n className={cn(maxVisible !== undefined && \"min-w-0 shrink\")}\r\n >\r\n {item?.image && (\r\n <img\r\n src={item.image}\r\n alt={item?.label || \"\"}\r\n className=\"size-4 rounded-full object-cover shrink-0 mr-1\"\r\n />\r\n )}\r\n {maxVisible !== undefined\r\n ? <span className=\"truncate\">{item?.label || \"\"}</span>\r\n : (item?.label || \"\")\r\n }\r\n <ComboboxChipRemove />\r\n </ComboboxChipUI>\r\n ))}\r\n {overflow > 0 && (\r\n <ComboboxChipUI className=\"shrink-0\">\r\n +{overflow}\r\n </ComboboxChipUI>\r\n )}\r\n </>\r\n )\r\n }}\r\n </ComboboxValue>\r\n </ComboboxChips>\r\n\r\n {/* Text input — shrinks to fit remaining space */}\r\n <ComboboxInputPrimitive\r\n render={\r\n <input\r\n className=\"flex-1 min-w-[80px] bg-transparent outline-none text-body-regular-1 text-text-primary placeholder:text-text-placeholder\"\r\n placeholder={value.length === 0 ? inputPlaceholder : undefined}\r\n />\r\n }\r\n />\r\n </ComboboxInputGroup>\r\n\r\n <ComboboxContent container={container}>\r\n <ComboboxStatus\r\n status={\r\n isPending || items === undefined\r\n ? \"pending\"\r\n : items?.length === 0 && !isCreatingItem\r\n ? \"empty\"\r\n : null\r\n }\r\n />\r\n <ComboboxList>\r\n {items?.map((item) => (\r\n <ComboboxItem\r\n key={item.value}\r\n value={item as Value}\r\n >\r\n <div className=\"flex items-center gap-2 w-full min-w-0\">\r\n {item.image && (\r\n <img\r\n src={item.image}\r\n alt={item.label}\r\n className=\"size-6 rounded-full object-cover shrink-0\"\r\n />\r\n )}\r\n <span className=\"truncate\">{item.label}</span>\r\n </div>\r\n </ComboboxItem>\r\n ))}\r\n {isCreatingItem && (\r\n <ComboboxItem\r\n value={{ label: trimmedInput, value: trimmedInput, tag: true }}\r\n >\r\n <div className=\"flex items-center gap-1.5 w-full min-w-0\">\r\n {!isInputSelected && (\r\n <span className=\"text-text-secondary\">Create:</span>\r\n )}\r\n <span className=\"font-medium text-text-primary truncate\">\r\n {trimmedInput}\r\n </span>\r\n </div>\r\n </ComboboxItem>\r\n )}\r\n <ComboboxInfiniteScroll {...infiniteScroll} />\r\n </ComboboxList>\r\n </ComboboxContent>\r\n </Combobox>\r\n )\r\n}\r\n\r\nexport { ComboboxChip }\r\nexport type { ComboboxChipProps }\r\n"]}
1
+ {"version":3,"sources":["../../src/composites/combobox-chip.tsx"],"names":["ComboboxChip","multiple","inputPlaceholder","container","items","infiniteScroll","isPending","taggable","maxVisible","props","inputValue","setInputValue","useControlledState","value","setValue","createdItems","setCreatedItems","createdValuesRef","currentValues","v","prev","next","item","trimmedInput","isInputSelected","isCreatingItem","combinedItems","base","jsxs","Combobox","a","b","eventDetails","newTags","tag","ComboboxInputGroup","cn","inputVariants","jsx","ComboboxChips","ComboboxValue","visible","overflow","Fragment","ComboboxChipRemove","ComboboxInput","ComboboxContent","ComboboxStatus","ComboboxList","ComboboxItem","ComboboxInfiniteScroll"],"mappings":"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","file":"index.js","sourcesContent":["import * as React from \"react\"\r\n\r\nimport { cn } from \"@xploreu/lib/cn\"\r\nimport {\r\n ComboboxInput as ComboboxInputPrimitive,\r\n ComboboxInputGroup,\r\n} from \"../primitives/combobox\"\r\nimport {\r\n Combobox,\r\n ComboboxChip as ComboboxChipUI,\r\n ComboboxChipRemove,\r\n ComboboxChips,\r\n ComboboxContent,\r\n ComboboxInfiniteScroll,\r\n ComboboxItem,\r\n ComboboxList,\r\n ComboboxPortal,\r\n ComboboxStatus,\r\n ComboboxValue,\r\n type ComboboxProps\r\n} from \"../ui/combobox\"\r\nimport { useControlledState } from \"@xploreu/hooks/use-controlled-state\"\r\nimport { inputVariants } from \"../ui/input\"\r\n\r\ntype ComboboxChipProps<Value> = Omit<ComboboxProps<Value, true>, \"multiple\"> & {\r\n multiple?: boolean\r\n inputPlaceholder?: string\r\n container?: React.ComponentProps<typeof ComboboxPortal>[\"container\"]\r\n items: ({ label: string; value: string; image?: string }[]) | undefined\r\n infiniteScroll?: React.ComponentProps<typeof ComboboxInfiniteScroll>\r\n isPending?: boolean\r\n /**\r\n * When true, enables creatable / taggable mode.\r\n * If the typed value has no exact match in the current item list,\r\n * a \"Create \\\"…\\\"\" option is shown at the top of the dropdown.\r\n * Created items are appended to the value with `{ label, value, tag: true }`.\r\n */\r\n taggable?: boolean\r\n /**\r\n * Maximum number of chips to show before collapsing the rest into a \"+N\" chip.\r\n * When undefined, all chips are shown.\r\n */\r\n maxVisible?: number\r\n}\r\n\r\nfunction ComboboxChip<Value extends { label: string; value: string; image?: string; tag?: true }>({\r\n multiple = true,\r\n inputPlaceholder = \"Search...\",\r\n container,\r\n items,\r\n infiniteScroll,\r\n isPending,\r\n taggable = false,\r\n maxVisible,\r\n ...props\r\n}: ComboboxChipProps<Value>) {\r\n const [inputValue, setInputValue] = useControlledState({\r\n value: props?.inputValue?.toString(),\r\n defaultValue: props?.defaultInputValue?.toString(),\r\n onChange: props?.onInputValueChange,\r\n })\r\n\r\n const [value, setValue] = useControlledState({\r\n value: props?.value ?? [],\r\n defaultValue: props?.defaultValue ?? [],\r\n onChange: props?.onValueChange,\r\n })\r\n\r\n // Track items created via taggable mode\r\n // Sync with value to avoid stale tags when controlled value is reset from outside\r\n const [createdItems, setCreatedItems] = React.useState<Value[]>([])\r\n const createdValuesRef = React.useRef<Set<string>>(new Set())\r\n\r\n React.useEffect(() => {\r\n const currentValues = new Set(value.map((v) => v.value))\r\n setCreatedItems((prev) => {\r\n const next = prev.filter((item) => currentValues.has(item.value))\r\n if (next.length === prev.length) return prev\r\n createdValuesRef.current = new Set(next.map((v) => v.value))\r\n return next\r\n })\r\n }, [value])\r\n\r\n const trimmedInput = inputValue?.toString().trim() ?? \"\"\r\n const isInputSelected = React.useMemo(() => {\r\n if (!trimmedInput) return false\r\n return value.some(\r\n (item) => item.value.toLowerCase() === trimmedInput.toLowerCase()\r\n )\r\n }, [trimmedInput, value])\r\n\r\n // true = show the taggable item in dropdown (either as \"Create:\" or as checked item)\r\n const isCreatingItem = React.useMemo(() => {\r\n if (!taggable || !trimmedInput) return false\r\n return !items?.some(\r\n (item) => item.label.toLowerCase() === trimmedInput.toLowerCase()\r\n )\r\n }, [taggable, trimmedInput, items])\r\n\r\n // Merge server items with locally created tags + the \"Create\" placeholder\r\n const combinedItems = React.useMemo(() => {\r\n const base: Value[] = [\r\n ...items ?? [],\r\n ...createdItems,\r\n ]\r\n\r\n if (isCreatingItem) {\r\n return [...base, { label: trimmedInput, value: trimmedInput, tag: true } as unknown as Value]\r\n }\r\n\r\n return base\r\n }, [items, createdItems, isCreatingItem, trimmedInput])\r\n\r\n const handleValueChange: ComboboxProps<Value, true>[\"onValueChange\"] = (value, eventDetails) => {\r\n if (taggable) {\r\n const newTags = value.filter(\r\n (v) => v?.tag === true && !createdValuesRef.current.has(v.value)\r\n )\r\n if (newTags.length > 0) {\r\n for (const tag of newTags) {\r\n createdValuesRef.current.add(tag.value)\r\n }\r\n setCreatedItems((prev) => [...prev, ...newTags])\r\n }\r\n }\r\n\r\n if (!multiple) {\r\n setValue([value[value.length - 1]], eventDetails)\r\n } else {\r\n setValue(value, eventDetails)\r\n }\r\n }\r\n\r\n return (\r\n <Combobox\r\n {...props}\r\n behavior=\"chip-outside\"\r\n multiple\r\n items={taggable ? combinedItems : items}\r\n isItemEqualToValue={(a, b) => a.value === b.value}\r\n onValueChange={handleValueChange}\r\n onInputValueChange={setInputValue}\r\n >\r\n {/* Input box with chips inside */}\r\n <ComboboxInputGroup\r\n className={cn(\r\n inputVariants(),\r\n \"h-auto min-h-13 flex flex-wrap items-center gap-1.5 px-3 py-1.5 cursor-text\"\r\n )}\r\n >\r\n {/* Chips inside the input box */}\r\n <ComboboxChips\r\n className={cn(\r\n \"contents\",\r\n maxVisible !== undefined && \"flex-nowrap overflow-hidden\"\r\n )}\r\n >\r\n <ComboboxValue>\r\n {(value: Value[]) => {\r\n const visible = maxVisible !== undefined ? value.slice(0, maxVisible) : value\r\n const overflow = maxVisible !== undefined ? value.length - maxVisible : 0\r\n return (\r\n <>\r\n {visible?.map((item) => (\r\n <ComboboxChipUI\r\n key={item?.value || \"\"}\r\n className={cn(maxVisible !== undefined && \"min-w-0 shrink\")}\r\n >\r\n {item?.image && (\r\n <img\r\n src={item.image}\r\n alt={item?.label || \"\"}\r\n className=\"size-4 rounded-full object-cover shrink-0 mr-1\"\r\n />\r\n )}\r\n {maxVisible !== undefined\r\n ? <span className=\"truncate\">{item?.label || \"\"}</span>\r\n : (item?.label || \"\")\r\n }\r\n <ComboboxChipRemove />\r\n </ComboboxChipUI>\r\n ))}\r\n {overflow > 0 && (\r\n <ComboboxChipUI className=\"shrink-0\">\r\n +{overflow}\r\n </ComboboxChipUI>\r\n )}\r\n </>\r\n )\r\n }}\r\n </ComboboxValue>\r\n </ComboboxChips>\r\n\r\n {/* Text input — shrinks to fit remaining space */}\r\n <ComboboxInputPrimitive\r\n render={\r\n <input\r\n className=\"flex-1 min-w-[80px] bg-transparent outline-none text-body-regular-1 text-text-primary placeholder:text-text-placeholder\"\r\n placeholder={value.length === 0 ? inputPlaceholder : undefined}\r\n />\r\n }\r\n />\r\n </ComboboxInputGroup>\r\n\r\n <ComboboxContent container={container}>\r\n <ComboboxStatus\r\n status={\r\n isPending || items === undefined\r\n ? \"pending\"\r\n : items?.length === 0 && !isCreatingItem\r\n ? \"empty\"\r\n : null\r\n }\r\n />\r\n <ComboboxList>\r\n {items?.map((item) => (\r\n <ComboboxItem\r\n key={item.value}\r\n value={item as Value}\r\n >\r\n <div className=\"flex items-center gap-2 w-full min-w-0\">\r\n {item.image && (\r\n <img\r\n src={item.image}\r\n alt={item.label}\r\n className=\"size-6 rounded-full object-cover shrink-0\"\r\n />\r\n )}\r\n <span className=\"truncate\">{item.label}</span>\r\n </div>\r\n </ComboboxItem>\r\n ))}\r\n {isCreatingItem && (\r\n <ComboboxItem\r\n value={{ label: trimmedInput, value: trimmedInput, tag: true }}\r\n >\r\n <div className=\"flex items-center gap-1.5 w-full min-w-0\">\r\n {!isInputSelected && (\r\n <span className=\"text-text-secondary\">Create:</span>\r\n )}\r\n <span className=\"font-medium text-text-primary truncate\">\r\n {trimmedInput}\r\n </span>\r\n </div>\r\n </ComboboxItem>\r\n )}\r\n <ComboboxInfiniteScroll {...infiniteScroll} />\r\n </ComboboxList>\r\n </ComboboxContent>\r\n </Combobox>\r\n )\r\n}\r\n\r\nexport { ComboboxChip }\r\nexport type { ComboboxChipProps }\r\n"]}
@@ -0,0 +1,9 @@
1
+ import * as React from 'react';
2
+ import * as RPNInput from 'react-phone-number-input';
3
+
4
+ type PhoneInputProps = Omit<React.ComponentProps<"input">, "onChange" | "value" | "ref"> & Omit<RPNInput.Props<typeof RPNInput.default>, "onChange"> & {
5
+ onChange?: (value: RPNInput.Value) => void;
6
+ };
7
+ declare const PhoneInput: React.ForwardRefExoticComponent<PhoneInputProps>;
8
+
9
+ export { PhoneInput, type PhoneInputProps };
@@ -0,0 +1,2 @@
1
+ export{a as PhoneInput}from'../chunk-UFNEGKVA.js';import'../chunk-JFJU2DLY.js';import'../chunk-4YATKUEK.js';import'../chunk-TED2PUK6.js';import'../chunk-XXHHZYH6.js';import'../chunk-KYD4ATTG.js';//# sourceMappingURL=phone-input.js.map
2
+ //# sourceMappingURL=phone-input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"phone-input.js"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xploreu/components",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "Shared UI components for XploreU apps",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -62,13 +62,15 @@
62
62
  "@radix-ui/react-tabs": "^1.1.2",
63
63
  "@radix-ui/react-use-controllable-state": "^1.2.2",
64
64
  "class-variance-authority": "^0.7.1",
65
- "motion": "^12.16.0"
65
+ "motion": "^12.16.0",
66
+ "react-phone-number-input": "^3.4.17"
66
67
  },
67
68
  "devDependencies": {
68
69
  "@base-ui/react": "^1.6.0",
69
70
  "@types/node": "^20",
70
71
  "@types/react": "19.2.17",
71
72
  "@types/react-dom": "19.2.3",
73
+ "@types/react-phone-number-input": "^3.1.37",
72
74
  "lucide-react": "^0.477.0",
73
75
  "react": "^19.2.4",
74
76
  "react-dom": "^19.2.4",