@spark-ui/dropdown
Version:
Displays a list of options for the user to pick from—triggered by a button. Differs from Select in that it offers multiple select and its list is not native.
2 lines (1 loc) • 11.8 kB
JavaScript
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react"),Pe=require("@spark-ui/form-field"),O=require("@spark-ui/popover"),T=require("downshift"),h=require("class-variance-authority"),q=require("@spark-ui/use-merge-refs"),z=require("@spark-ui/icon"),Se=require("@spark-ui/visually-hidden"),Oe=(e,n)=>{const l=((r,a)=>{let i=0;for(const o of r.keys()){if(i===a)return o;i++}})(e,n);return l!==void 0?e.get(l):void 0},H=e=>e?e.type.displayName:"",le=(e,n=[])=>(t.Children.forEach(e,l=>{if(t.isValidElement(l)){if(H(l)==="Dropdown.Item"){const r=l.props;n.push({value:r.value,disabled:!!r.disabled,text:B(r.children)})}l.props.children&&le(l.props.children,n)}}),n),B=(e,n="")=>typeof e=="string"?e:(t.Children.forEach(e,l=>{t.isValidElement(l)&&(H(l)==="Dropdown.ItemText"&&(n=l.props.children),l.props.children&&B(l.props.children,n))}),n),ee=e=>{const n=new Map;return le(e).forEach(l=>{n.set(l.value,l)}),n},ne=(e,n)=>t.Children.toArray(e).some(l=>!!t.isValidElement(l)&&(H(l)===n||!!l.props.children&&ne(l.props.children,n))),re=t.createContext(null),S=":dropdown",ae=({children:e,defaultValue:n,value:l,onValueChange:r,open:a,onOpenChange:i,defaultOpen:o,multiple:d=!1,disabled:c=!1,readOnly:u=!1,state:p})=>{const[m,f]=t.useState(ee(e)),[I,w]=t.useState(ne(e,"Dropdown.Popover")),[b,k]=t.useState("mouse"),N=Pe.useFormFieldControl(),pe=N.state||p,me=`${S}-label-${t.useId()}`,he=`${S}-input-${t.useId()}`,ge=N.id||he,fe=N.labelId||me,ve=N.disabled??c,ye=N.readOnly??u,Y=(({itemsMap:D,defaultValue:x,value:g,onValueChange:C,open:P,onOpenChange:V,defaultOpen:M,multiple:v,id:be,labelId:xe})=>{const L=[...D.values()],$=T.useMultipleSelection({selectedItems:g!=null&&v?L.filter(s=>v?g.includes(s.value):g===s.value):void 0,initialSelectedItems:x!=null&&v?L.filter(s=>v?x.includes(s.value):x===s.value):void 0,onSelectedItemsChange:({selectedItems:s})=>{s!=null&&v&&C?.(s.map(y=>y.value))}});return{...T.useSelect({items:L,isItemDisabled:s=>s.disabled,itemToString:s=>s?s.text:"",id:be,labelId:xe,isOpen:P,onIsOpenChange:({isOpen:s})=>{s!=null&&V?.(s)},initialIsOpen:M??!1,stateReducer:(s,{changes:y,type:Ne})=>{if(!v)return y;const{selectedItems:Ee,removeSelectedItem:De,addSelectedItem:Ce}=$;switch(Ne){case T.useSelect.stateChangeTypes.ToggleButtonKeyDownEnter:case T.useSelect.stateChangeTypes.ToggleButtonKeyDownSpaceButton:case T.useSelect.stateChangeTypes.ItemClick:return y.selectedItem!=null&&(Ee.some(Te=>Te.value===y.selectedItem?.value)?De(y.selectedItem):Ce(y.selectedItem)),{...y,isOpen:!0,highlightedIndex:s.highlightedIndex};default:return y}},selectedItem:g==null||v?void 0:D.get(g)||null,initialSelectedItem:x==null&&g==null||v?void 0:D.get(x)||null,onSelectedItemChange:({selectedItem:s})=>{s?.value==null||v||C?.(s?.value)},scrollIntoView:s=>{s&&s.scrollIntoView({block:"nearest"})}}),...$,selectedItems:[...new Set($.selectedItems)]}})({itemsMap:m,defaultValue:n,value:l,onValueChange:r,open:a,onOpenChange:i,defaultOpen:o,multiple:d,id:ge,labelId:fe});t.useEffect(()=>{const D=ee(e),x=[...m.values()],g=[...D.values()];(x.length!==g.length||x.some((C,P)=>{const V=C.value!==g[P]?.value,M=C.text!==g[P]?.text;return V||M}))&&f(D)},[e]);const[Ie,we]=I?[O.Popover,{open:!0}]:[t.Fragment,{}];return t.createElement(re.Provider,{value:{multiple:d,disabled:ve,readOnly:ye,...Y,itemsMap:m,highlightedItem:Oe(m,Y.highlightedIndex),hasPopover:I,setHasPopover:w,state:pe,lastInteractionType:b,setLastInteractionType:k}},t.createElement(Ie,{...we},e))},E=()=>{const e=t.useContext(re);if(!e)throw Error("useDropdownContext must be used within a Dropdown provider");return e},se=({children:e,...n})=>t.createElement(ae,{...n},e);se.displayName="Dropdown";const F=({className:e,ref:n})=>t.createElement("div",{ref:n,className:h.cx("my-md border-b-sm border-outline",e)});F.displayName="Dropdown.Divider";const oe=t.createContext(null),ke=({children:e})=>{const n=`${S}-group-label-${t.useId()}`;return t.createElement(oe.Provider,{value:{labelId:n}},e)},ie=()=>{const e=t.useContext(oe);if(!e)throw Error("useDropdownGroupContext must be used within a DropdownGroup provider");return e},G=({children:e,ref:n,...l})=>t.createElement(ke,null,t.createElement(Ve,{ref:n,...l},e)),Ve=({children:e,className:n,ref:l})=>{const{labelId:r}=ie();return t.createElement("div",{ref:l,role:"group","aria-labelledby":r,className:h.cx(n)},e)};G.displayName="Dropdown.Group";const de=t.createContext(null),Me=({value:e,disabled:n=!1,children:l})=>{const{multiple:r,itemsMap:a,selectedItem:i,selectedItems:o}=E(),[d,c]=t.useState(void 0),u=function(f,I){let w=0;for(const[b]of f.entries()){if(b===I)return w;w++}return-1}(a,e),p={disabled:n,value:e,text:B(l)},m=r?o.some(f=>f.value===e):i?.value===e;return t.createElement(de.Provider,{value:{textId:d,setTextId:c,isSelected:m,itemData:p,index:u,disabled:n}},l)},R=()=>{const e=t.useContext(de);if(!e)throw Error("useDropdownItemContext must be used within a DropdownItem provider");return e},j=({children:e,ref:n,...l})=>{const{value:r,disabled:a}=l;return t.createElement(Me,{value:r,disabled:a},t.createElement($e,{ref:n,...l},e))},Le=h.cva("px-lg py-md text-body-1",{variants:{selected:{true:"font-bold"},disabled:{true:"opacity-dim-3 cursor-not-allowed",false:"cursor-pointer"},highlighted:{true:""},interactionType:{mouse:"",keyboard:""}},compoundVariants:[{highlighted:!0,interactionType:"mouse",class:"bg-surface-hovered"},{highlighted:!0,interactionType:"keyboard",class:"u-outline"}]}),$e=({className:e,disabled:n=!1,value:l,children:r,ref:a})=>{const{getItemProps:i,highlightedItem:o,lastInteractionType:d}=E(),{textId:c,index:u,itemData:p,isSelected:m}=R(),f=o?.value===l,{ref:I,...w}=i({item:p,index:u}),b=q.useMergeRefs(a,I);return t.createElement("li",{ref:b,className:h.cx(Le({selected:m,disabled:n,highlighted:f,interactionType:d,className:e})),key:l,...w,"aria-selected":m,"aria-labelledby":c},r)};j.displayName="Dropdown.Item";const ce=({title:e,fill:n="currentColor",stroke:l="none",ref:r,...a})=>t.createElement("svg",{ref:r,viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg","data-title":"Check",...e&&{"data-title":e},fill:n,stroke:l,...a,dangerouslySetInnerHTML:{__html:(e===void 0?"":`<title>${e}</title>`)+'<path d="m8.92,19.08c-.18,0-.36-.03-.53-.1s-.33-.17-.47-.31l-5.49-5.34c-.28-.28-.42-.61-.42-1s.14-.73.42-1c.28-.28.62-.41,1.02-.41s.74.14,1.05.41l4.43,4.3,10.62-10.29c.28-.28.62-.42,1.02-.43.39,0,.73.13,1.02.43.28.28.42.61.42,1s-.14.73-.42,1l-11.65,11.32c-.14.14-.3.24-.47.31-.17.07-.35.1-.53.1Z"/>'}});ce.displayName="Check";const A=({className:e,children:n,label:l,ref:r})=>{const{disabled:a,isSelected:i}=R(),o=n||t.createElement(z.Icon,{size:"sm"},t.createElement(ce,{"aria-label":l}));return t.createElement("span",{ref:r,className:h.cx("min-h-sz-16 min-w-sz-16 flex",a&&"opacity-dim-3",e)},i&&o)};A.displayName="Dropdown.ItemIndicator";const _=({children:e,className:n,ref:l,...r})=>{const{isOpen:a,getMenuProps:i,hasPopover:o,setLastInteractionType:d}=E(),{ref:c,...u}=i({onMouseMove:()=>{d("mouse")}}),p=t.useRef(null),m=q.useMergeRefs(l,c,p);return t.useLayoutEffect(()=>{o&&p.current&&p.current.parentElement&&(p.current.parentElement.style.pointerEvents=a?"":"none",p.current.style.pointerEvents=a?"":"none")},[a,o]),t.createElement("ul",{ref:m,className:h.cx(n,"flex flex-col",a?"pointer-events-auto! block":"pointer-events-none invisible absolute opacity-0",o&&"p-lg"),...r,...u,"data-spark-component":"dropdown-items"},e)};_.displayName="Dropdown.Items";const K=({children:e,ref:n})=>{const l=`${S}-item-text-${t.useId()}`,{setTextId:r}=R();return t.useEffect(()=>(r(l),()=>r(void 0))),t.createElement("span",{id:l,className:h.cx("inline"),ref:n},e)};K.displayName="Dropdown.ItemText";const W=({children:e,className:n,ref:l})=>{const{labelId:r}=ie();return t.createElement("div",{ref:l,id:r,className:h.cx("px-md py-sm text-body-2 text-neutral italic",n)},e)};W.displayName="Dropdown.Label";const Z=({children:e})=>t.createElement(z.Icon,{size:"sm",className:"shrink-0"},e);Z.displayName="Dropdown.LeadingIcon";const J=({children:e,matchTriggerWidth:n=!0,sideOffset:l=4,className:r,elevation:a="dropdown",ref:i,...o})=>{const d=E();return t.useEffect(()=>(d.setHasPopover(!0),()=>d.setHasPopover(!1)),[]),t.createElement(O.Popover.Content,{ref:i,inset:!0,asChild:!0,matchTriggerWidth:n,elevation:a,className:h.cx("relative",r),sideOffset:l,onOpenAutoFocus:c=>{c.preventDefault()},...o,"data-spark-component":"dropdown-popover"},e)};J.displayName="Dropdown.Popover";const Q=({children:e,...n})=>t.createElement(O.Popover.Portal,{...n},e);Q.displayName="Dropdown.Portal";const ue=({title:e,fill:n="currentColor",stroke:l="none",ref:r,...a})=>t.createElement("svg",{ref:r,viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg","data-title":"ArrowHorizontalDown",...e&&{"data-title":e},fill:n,stroke:l,...a,dangerouslySetInnerHTML:{__html:(e===void 0?"":`<title>${e}</title>`)+'<path fill-rule="evenodd" d="m2.33,7.3c.43-.4,1.14-.4,1.57,0l8.1,7.48,8.1-7.48c.43-.4,1.14-.4,1.57,0,.43.4.43,1.06,0,1.47l-8.34,7.7c-.17.17-.37.3-.6.39-.23.09-.48.14-.73.14s-.5-.05-.73-.14c-.23-.09-.43-.22-.6-.39L2.33,8.77c-.43-.4-.43-1.06,0-1.47Z"/>'}});ue.displayName="ArrowHorizontalDown";const qe=h.cva(["flex w-full items-center justify-between","min-h-sz-44 rounded-lg bg-surface text-on-surface px-lg","text-body-1","ring-1 outline-hidden ring-inset focus:ring-2"],{variants:{state:{undefined:"ring-outline focus:ring-outline-high",error:"ring-error",alert:"ring-alert",success:"ring-success"},disabled:{true:"disabled:bg-on-surface/dim-5 cursor-not-allowed text-on-surface/dim-3"},readOnly:{true:"disabled:bg-on-surface/dim-5 cursor-not-allowed text-on-surface/dim-3"}},compoundVariants:[{disabled:!1,state:void 0,class:"hover:ring-outline-high"}]}),U=({"aria-label":e,children:n,className:l,ref:r})=>{const{getToggleButtonProps:a,getDropdownProps:i,getLabelProps:o,hasPopover:d,disabled:c,readOnly:u,state:p,setLastInteractionType:m}=E(),[f,I]=d?[O.Popover.Trigger,{asChild:!0}]:[t.Fragment,{}],{ref:w,...b}=a({...i(),onKeyDown:()=>{m("keyboard")}}),k=b["aria-expanded"],N=q.useMergeRefs(r,w);return t.createElement(t.Fragment,null,e&&t.createElement(Se.VisuallyHidden,null,t.createElement("label",{...o()},e)),t.createElement(f,{...I},t.createElement("button",{type:"button",ref:N,disabled:c||u,className:qe({className:l,state:p,disabled:c,readOnly:u}),...b,"data-spark-component":"dropdown-trigger"},t.createElement("span",{className:"gap-md flex items-center justify-start"},n),t.createElement(z.Icon,{className:h.cx("ml-md shrink-0 rotate-0 transition duration-100 ease-in",{"rotate-180":k}),size:"sm"},t.createElement(ue,null)))))};U.displayName="Dropdown.Trigger";const X=({children:e,className:n,placeholder:l,ref:r})=>{const{selectedItem:a,multiple:i,selectedItems:o}=E(),d=!!(i?o.length:a),c=i?o[0]?.text:a?.text,u=o.length>1?", +"+(o.length-1):"";return t.createElement("span",{ref:r,className:h.cx("flex shrink items-center text-left",n)},t.createElement("span",{className:h.cx("line-clamp-1 flex-1 overflow-hidden break-all text-ellipsis",!d&&"text-on-surface/dim-1")},d?e||c:l),u&&t.createElement("span",null,u))};X.displayName="Dropdown.Value";const te=Object.assign(se,{Group:G,Item:j,Items:_,ItemText:K,ItemIndicator:A,Label:W,Popover:J,Divider:F,Trigger:U,Value:X,LeadingIcon:Z,Portal:Q});te.displayName="Dropdown",G.displayName="Dropdown.Group",_.displayName="Dropdown.Items",j.displayName="Dropdown.Item",K.displayName="Dropdown.ItemText",A.displayName="Dropdown.ItemIndicator",W.displayName="Dropdown.Label",J.displayName="Dropdown.Popover",F.displayName="Dropdown.Divider",U.displayName="Dropdown.Trigger",X.displayName="Dropdown.Value",Z.displayName="Dropdown.LeadingIcon",Q.displayName="Dropdown.Portal",exports.Dropdown=te,exports.DropdownProvider=ae,exports.useDropdownContext=E;