@contentful/f36-multiselect 5.8.0 → 6.0.0-alpha.2

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/esm/index.js CHANGED
@@ -1,19 +1,2 @@
1
- import l, { useState, useRef, useCallback, useMemo } from 'react';
2
- import { Checkbox, TextInput } from '@contentful/f36-forms';
3
- import { Text, Subheading } from '@contentful/f36-typography';
4
- import { cx, css } from 'emotion';
5
- import r from '@contentful/f36-tokens';
6
- import { Flex, mergeRefs, getMenuItemStyles } from '@contentful/f36-core';
7
- import { getStringMatch } from '@contentful/f36-utils';
8
- import { Button, IconButton } from '@contentful/f36-button';
9
- import { CaretDownIcon, XIcon, MagnifyingGlassIcon } from '@contentful/f36-icons';
10
- import { SkeletonContainer, SkeletonBodyText } from '@contentful/f36-skeleton';
11
- import { Popover } from '@contentful/f36-popover';
12
- import { Tooltip } from '@contentful/f36-tooltip';
13
- import Xe from 'react-focus-lock';
14
-
15
- var me=Object.defineProperty,ue=Object.defineProperties;var ge=Object.getOwnPropertyDescriptors;var L=Object.getOwnPropertySymbols;var _=Object.prototype.hasOwnProperty,q=Object.prototype.propertyIsEnumerable;var G=(e,t,o)=>t in e?me(e,t,{enumerable:!0,configurable:!0,writable:!0,value:o}):e[t]=o,M=(e,t)=>{for(var o in t||(t={}))_.call(t,o)&&G(e,o,t[o]);if(L)for(var o of L(t))q.call(t,o)&&G(e,o,t[o]);return e},w=(e,t)=>ue(e,ge(t));var B=(e,t)=>{var o={};for(var n in e)_.call(e,n)&&t.indexOf(n)<0&&(o[n]=e[n]);if(e!=null&&L)for(var n of L(e))t.indexOf(n)<0&&q.call(e,n)&&(o[n]=e[n]);return o};var b=()=>({multiselect:css({position:"relative",width:"100%"}),triggerButton:css({justifyContent:"space-between"}),currentSelection:css({display:"inline-block",width:"100%",whiteSpace:"nowrap",textOverflow:"ellipsis",overflow:"hidden",verticalAlign:"bottom",marginRight:r.spacing2Xs}),currentSelectionWithClearButton:css({paddingRight:"40px"}),currentSelectionAddition:css({color:r.gray600}),searchBar:css({paddingTop:r.spacing2Xs,position:"sticky",top:"0px",zIndex:r.zIndexWorkbenchHeader,backgroundColor:r.colorWhite}),inputField:css({padding:`6px ${r.spacingXl} 10px ${r.spacingXs}`,textOverflow:"ellipsis",whiteSpace:"nowrap",border:"none",borderRadius:"0px",borderBottom:`1px solid ${r.gray200}`,boxShadow:"none","&:focus, &:active, &:active:hover":{boxShadow:"none",borderBottom:`1px solid ${r.gray200}`}}),toggleButton:css({position:"absolute",top:"1px",right:"1px",zIndex:r.zIndexDefault,padding:r.spacing2Xs,height:r.spacingXl}),content:e=>css({overflow:"auto",maxHeight:`${e}px`}),container:css({}),list:css({listStyle:"none",padding:`${r.spacing2Xs}`,margin:0}),groupTitle:css({padding:`6px ${r.spacingXs}`,lineHeight:r.lineHeightM}),noMatchesTitle:css({color:r.gray500,margin:r.spacingM,textAlign:"center"}),clearSelectionButton:css({marginLeft:"-80px"}),selectAll:css({borderBottom:`1px solid ${r.gray200}`,marginBottom:r.spacing2Xs,paddingBottom:r.spacing2Xs,"label > *":{fontWeight:r.fontWeightMedium}}),option:css({listStyleType:"none"}),optionText:css({alignItems:"center",display:"flex",span:{color:r.gray900,fontWeight:r.fontWeightDemiBold}}),optionCheck:({isActive:e,isDisabled:t})=>css({label:cx(getMenuItemStyles({isActive:e,isDisabled:t}),css({width:"100%"}))})});var v=C=>{var x=C,{children:e,label:t,value:o,itemId:n,onSelectItem:s,searchValue:a,isChecked:f=!1,isDisabled:h=!1,className:p}=x,g=B(x,["children","label","value","itemId","onSelectItem","searchValue","isChecked","isDisabled","className"]);let m=b();return l.createElement("li",M({className:cx(m.option,p)},g),l.createElement(Checkbox,{id:n,value:o,onChange:S=>s(S),isChecked:f,isDisabled:h,className:m.optionCheck({isActive:f,isDisabled:h})},l.createElement(Text,{className:m.optionText,"data-test-id":`cf-multiselect-list-item-${n}`},typeof t=="string"?l.createElement(N,{item:t,inputValue:a}):e)))};function N({item:e,inputValue:t=""}){let{before:o,match:n,after:s}=getStringMatch(e,t.trim());return o.length+n.length+s.length===0?l.createElement(l.Fragment,null,e):l.createElement(l.Fragment,null,o,l.createElement("span",{"data-test-id":"cf-multiselect-item-match"},n),s)}N.displayName="HighlightedItem";var Q=({searchValue:e,setSearchValue:t,onSearchValueChange:o,searchInputName:n,searchInputRef:s,resetSearchRef:a,searchPlaceholder:f="Search",focusList:h})=>{let p=b(),g=useRef(null),C=useCallback(m=>{t(m.target.value),o==null||o(m);},[o,t]),x=useCallback(()=>{if(!e)return;h(),Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype,"value").set.call(g.current,"");let S=new Event("change",{bubbles:!0});g.current.dispatchEvent(S);},[e,h]);return l.createElement("div",{className:p.searchBar},l.createElement(TextInput,{"aria-label":"Search",type:"text",value:e,className:p.inputField,testId:"cf-multiselect-search",placeholder:f,onChange:C,ref:mergeRefs(s,g),name:n,size:"small"}),l.createElement(IconButton,{ref:a,"aria-label":e?"Clear search":"Search",className:p.toggleButton,variant:"transparent",icon:e?l.createElement(XIcon,{color:r.gray600}):l.createElement(MagnifyingGlassIcon,{color:r.gray600}),onClick:x,isDisabled:!e,size:"small"}))};var ee=(e,t,o)=>l.Children.map(e,n=>{if(!l.isValidElement(n))return n;if(t(n))return o(n);let s=ee(n.props.children,t,o);return l.cloneElement(n,{children:s})}),te=(e,t)=>{let o=0;return l.Children.forEach(e,n=>{l.isValidElement(n)&&(t(n)?o+=1:o+=te(n.props.children,t));}),o};function De(e,t){let{className:o,startIcon:n,placeholder:s="Select one or more Items",currentSelection:a=[],toggleRef:f,toggleButtonAriaLabel:h="Toggle Multiselect",isLoading:p=!1,testId:g="cf-multiselect",noMatchesMessage:C="No matches found",searchProps:x={},popoverProps:m={},children:S,onBlur:E,onClearSelection:P,clearButtonProps:O={tooltip:"Clear selection",ariaLabel:"Clear selection"}}=e,{listMaxHeight:ne=180,listRef:le,onClose:D}=m,c=b(),[T,re]=useState(""),[F,$]=useState(!1),z=useRef(null),A=a.length>1&&typeof P=="function",V=typeof x.onSearchValueChange=="function",H=useCallback(()=>{var u;(u=z.current)==null||u.focus();},[]),ie=u=>{P==null||P(),u.stopPropagation();},se=useCallback(()=>{if(a.length===0)return l.createElement(l.Fragment,null,s);let u=a.length-1,y=cx(c.currentSelection,A&&c.currentSelectionWithClearButton);return u===0?l.createElement("span",{"data-test-id":"cf-multiselect-current-selection",className:y},a[0]):l.createElement("span",{"data-test-id":"cf-multiselect-current-selection",className:y},a[0]," ",l.createElement("span",{className:c.currentSelectionAddition},"and ",u," more"))},[a,s,A,c.currentSelection,c.currentSelectionAddition,c.currentSelectionWithClearButton]),j=useMemo(()=>te(S,u=>u.type===v),[S]),ce=l.useCallback(u=>ee(u,y=>y.type===v,y=>{let ae=pe=>{var U;H(),(U=y.props)==null||U.onSelectItem(pe);};return l.cloneElement(y,{searchValue:T,onSelectItem:ae})}),[T,H]);return l.createElement("div",{"data-test-id":g,className:cx(c.multiselect,o),ref:t},l.createElement(Popover,w(M({renderOnlyWhenOpen:!1,isFullWidth:!0},m),{isOpen:F,onClose:()=>{$(!1),D&&D();}}),l.createElement(Flex,{alignItems:"center"},l.createElement(Popover.Trigger,null,l.createElement(Button,M({"aria-label":h,ref:f,onClick:()=>$(!F),startIcon:n,endIcon:l.createElement(CaretDownIcon,null),isFullWidth:!0,className:c.triggerButton},e.triggerButtonProps),se())),A&&l.createElement("div",{className:c.clearSelectionButton},l.createElement(Tooltip,{content:O.tooltip?O.tooltip:"Clear selection",showDelay:800,placement:"top",as:"div"},l.createElement(IconButton,{onClick:ie,icon:l.createElement(XIcon,null),"aria-label":O.ariaLabel?O.ariaLabel:"Clear selection",size:"small"})))),l.createElement(Popover.Content,{ref:mergeRefs(le,z),className:cx(c.content(ne),m.className,c.container),testId:"cf-multiselect-container",onBlur:()=>E==null?void 0:E()},l.createElement(Xe,{focusOptions:{preventScroll:!0},returnFocus:!0},V&&l.createElement(Q,w(M({},x),{setSearchValue:re,searchValue:T,focusList:H})),p&&l.createElement(Fe,null),!p&&j>0&&l.createElement("ul",{className:c.list,"data-test-id":"cf-multiselect-items"},V?ce(S):S),!p&&j===0&&l.createElement(Subheading,{className:c.noMatchesTitle},C)))))}var Fe=()=>l.createElement(SkeletonContainer,{svgHeight:16},l.createElement(SkeletonBodyText,{numberOfLines:1})),oe=l.forwardRef(De);var X=h=>{var p=h,{label:e,itemId:t="SelectAll",onSelectItem:o,isChecked:n=!1,selectAllOptionLabel:s={checked:"Deselect all",unchecked:"Select all"},className:a}=p,f=B(p,["label","itemId","onSelectItem","isChecked","selectAllOptionLabel","className"]);let g=b(),C=e||n?s.checked:s.unchecked;return l.createElement(v,M({value:"all",label:C,itemId:t,onSelectItem:o,isChecked:n,className:cx(g.selectAll,a)},f))};var k=oe;k.HighlightedItem=N;k.Option=v;k.SelectAll=X;
16
-
17
- export { k as Multiselect, v as MultiselectOption, X as SelectAllOption };
18
- //# sourceMappingURL=out.js.map
1
+ import n,{useState,useRef,useCallback,useMemo}from'react';import {Checkbox,TextInput}from'@contentful/f36-forms';import {Subheading,Text}from'@contentful/f36-typography';import {css,cx}from'@emotion/css';import i from'@contentful/f36-tokens';import {Flex,mergeRefs,getMenuItemStyles}from'@contentful/f36-core';import {getStringMatch}from'@contentful/f36-utils';import {Button,IconButton}from'@contentful/f36-button';import {CaretDownIcon,XIcon,MagnifyingGlassIcon}from'@contentful/f36-icons';import {SkeletonContainer,SkeletonBodyText}from'@contentful/f36-skeleton';import {Popover}from'@contentful/f36-popover';import Xe from'react-focus-lock';var de=Object.defineProperty,ge=Object.defineProperties;var fe=Object.getOwnPropertyDescriptors;var L=Object.getOwnPropertySymbols;var U=Object.prototype.hasOwnProperty,G=Object.prototype.propertyIsEnumerable;var j=(e,t,o)=>t in e?de(e,t,{enumerable:true,configurable:true,writable:true,value:o}):e[t]=o,M=(e,t)=>{for(var o in t||(t={}))U.call(t,o)&&j(e,o,t[o]);if(L)for(var o of L(t))G.call(t,o)&&j(e,o,t[o]);return e},H=(e,t)=>ge(e,fe(t));var B=(e,t)=>{var o={};for(var l in e)U.call(e,l)&&t.indexOf(l)<0&&(o[l]=e[l]);if(e!=null&&L)for(var l of L(e))t.indexOf(l)<0&&G.call(e,l)&&(o[l]=e[l]);return o};var S=()=>({multiselect:css({position:"relative",width:"100%"}),triggerButton:css({justifyContent:"space-between"}),currentSelection:css({display:"inline-block",width:"100%",whiteSpace:"nowrap",textOverflow:"ellipsis",overflow:"hidden",verticalAlign:"bottom",marginRight:i.spacing2Xs}),currentSelectionWithClearButton:css({paddingRight:"40px"}),currentSelectionAddition:css({color:i.gray600}),searchBar:css({paddingTop:i.spacing2Xs,position:"sticky",top:"0px",zIndex:i.zIndexWorkbenchHeader,backgroundColor:i.colorWhite}),inputField:css({padding:`6px ${i.spacingXl} 10px ${i.spacingXs}`,textOverflow:"ellipsis",whiteSpace:"nowrap",border:"none",borderRadius:"0px",borderBottom:`1px solid ${i.gray200}`,boxShadow:"none","&:focus, &:active, &:active:hover":{boxShadow:"none",borderBottom:`1px solid ${i.gray200}`}}),toggleButton:css({position:"absolute",top:"1px",right:"1px",zIndex:i.zIndexDefault,padding:i.spacing2Xs,height:i.spacingXl}),content:e=>css({overflow:"auto",maxHeight:`${e}px`}),container:css({}),list:css({listStyle:"none",padding:`${i.spacing2Xs}`,margin:0}),groupTitle:css({padding:`6px ${i.spacingXs}`,lineHeight:i.lineHeightM}),noMatchesTitle:css({color:i.gray500,margin:i.spacingM,textAlign:"center"}),clearSelectionButton:css({marginLeft:"-80px"}),selectAll:css({borderBottom:`1px solid ${i.gray200}`,marginBottom:i.spacing2Xs,paddingBottom:i.spacing2Xs,"label > *":{fontWeight:i.fontWeightMedium}}),option:css({listStyleType:"none"}),optionText:css({alignItems:"center",display:"flex",span:{color:i.gray900,fontWeight:i.fontWeightDemiBold}}),optionCheck:({isActive:e,isDisabled:t})=>css({label:cx(getMenuItemStyles({isActive:e,isDisabled:t}),css({width:"100%"}))})});var J=n.createContext(void 0),K=()=>{let e=n.useContext(J);if(e===void 0)throw new Error("component must be rendered within a Accordion component");return e},Q=J.Provider;var b=f=>{var h=f,{children:e,label:t,value:o,itemId:l,onSelectItem:s,isChecked:c=false,isDisabled:g=false,className:v}=h,p=B(h,["children","label","value","itemId","onSelectItem","isChecked","isDisabled","className"]);let x=S(),{focusList:u,searchValue:y}=K();return n.createElement("li",M({className:cx(x.option,v)},p),n.createElement(Checkbox,{id:l,value:o,onChange:C=>{u(),s(C);},isChecked:c,isDisabled:g,className:x.optionCheck({isActive:c,isDisabled:g})},n.createElement(Text,{className:x.optionText,"data-test-id":`cf-multiselect-list-item-${l}`},typeof t=="string"?n.createElement(T,{item:t,inputValue:y}):e)))};function T({item:e,inputValue:t=""}){let{before:o,match:l,after:s}=getStringMatch(e,t.trim());return o.length+l.length+s.length===0?n.createElement(n.Fragment,null,e):n.createElement(n.Fragment,null,o,n.createElement("span",{"data-test-id":"cf-multiselect-item-match"},l),s)}T.displayName="HighlightedItem";var _=({searchValue:e,setSearchValue:t,onSearchValueChange:o,searchInputName:l,searchInputRef:s,resetSearchRef:c,searchPlaceholder:g="Search",focusList:v})=>{let p=S(),f=useRef(null),h=useCallback(u=>{t(u.target.value),o==null||o(u);},[o,t]),x=useCallback(()=>{if(!e)return;v(),Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype,"value").set.call(f.current,"");let y=new Event("change",{bubbles:true});f.current.dispatchEvent(y);},[e,v]);return n.createElement("div",{className:p.searchBar},n.createElement(TextInput,{"aria-label":"Search",type:"text",value:e,className:p.inputField,testId:"cf-multiselect-search",placeholder:g,onChange:h,ref:mergeRefs(s,f),name:l,size:"small"}),n.createElement(IconButton,{ref:c,"aria-label":e?"Clear search":"Search",className:p.toggleButton,variant:"transparent",icon:e?n.createElement(XIcon,{color:i.gray600}):n.createElement(MagnifyingGlassIcon,{color:i.gray600}),onClick:x,isDisabled:!e,size:"small"}))};var ne=(e,t)=>{let o=0;return n.Children.forEach(e,l=>{if(!n.isValidElement(l))return;let s=l;t(s)?o+=1:o+=ne(s.props.children,t);}),o};function le(e,t){let{className:o,startIcon:l,placeholder:s="Select one or more Items",currentSelection:c=[],toggleRef:g,toggleButtonAriaLabel:v="Toggle Multiselect",isLoading:p=false,testId:f="cf-multiselect",noMatchesMessage:h="No matches found",searchProps:x={},popoverProps:u={},children:y,onBlur:C,onClearSelection:I,clearButtonProps:O={tooltip:"Clear selection",ariaLabel:"Clear selection"}}=e,{listMaxHeight:re=180,listRef:se,onClose:X}=u,a=S(),[k,ce]=useState(""),[D,F]=useState(false),$=useRef(null),w=c.length>1&&typeof I=="function",ae=typeof x.onSearchValueChange=="function",A=useCallback(()=>{var m;(m=$.current)==null||m.focus();},[]),pe=m=>{I==null||I(),m.stopPropagation();},ue=useCallback(()=>{if(c.length===0)return n.createElement(n.Fragment,null,s);let m=c.length-1,V=cx(a.currentSelection,w&&a.currentSelectionWithClearButton);return m===0?n.createElement("span",{"data-test-id":"cf-multiselect-current-selection",className:V},c[0]):n.createElement("span",{"data-test-id":"cf-multiselect-current-selection",className:V},c[0]," ",n.createElement("span",{className:a.currentSelectionAddition},"and ",m," more"))},[c,s,w,a.currentSelection,a.currentSelectionAddition,a.currentSelectionWithClearButton]),z=useMemo(()=>ne(y,m=>m.type===b),[y]),me=useMemo(()=>({focusList:A,searchValue:k}),[A,k]);return n.createElement(Q,{value:me},n.createElement("div",{"data-test-id":f,className:cx(a.multiselect,o),ref:t},n.createElement(Popover,H(M({renderOnlyWhenOpen:false,isFullWidth:true},u),{isOpen:D,onClose:()=>{F(false),X&&X();}}),n.createElement(Flex,{alignItems:"center"},n.createElement(Popover.Trigger,{ref:g},n.createElement(Button,M({"aria-label":v,onClick:()=>F(!D),startIcon:l,endIcon:n.createElement(CaretDownIcon,null),isFullWidth:true,className:a.triggerButton},e.triggerButtonProps),ue())),w&&n.createElement("div",{className:a.clearSelectionButton},n.createElement(IconButton,{onClick:pe,icon:n.createElement(XIcon,null),"aria-label":O.ariaLabel?O.ariaLabel:"Clear selection",size:"small",withTooltip:true,tooltipProps:{content:O.tooltip?O.tooltip:"Clear selection",showDelay:800,placement:"top",as:"div"}}))),n.createElement(Popover.Content,{ref:mergeRefs(se,$),className:cx(a.content(re),u.className,a.container),testId:"cf-multiselect-container",onBlur:()=>C==null?void 0:C()},n.createElement(Xe,{focusOptions:{preventScroll:true},returnFocus:true},ae&&n.createElement(_,H(M({},x),{setSearchValue:ce,searchValue:k,focusList:A})),p&&n.createElement(De,null),!p&&z>0&&n.createElement("ul",{className:a.list,"data-test-id":"cf-multiselect-items"},y),!p&&z===0&&n.createElement(Subheading,{className:a.noMatchesTitle},h))))))}var De=()=>n.createElement(SkeletonContainer,{svgHeight:16},n.createElement(SkeletonBodyText,{numberOfLines:1}));le.displayName="Multiselect";var ie=n.forwardRef(le);var W=v=>{var p=v,{label:e,itemId:t="SelectAll",onSelectItem:o,isChecked:l=false,selectAllOptionLabel:s={checked:"Deselect all",unchecked:"Select all"},className:c}=p,g=B(p,["label","itemId","onSelectItem","isChecked","selectAllOptionLabel","className"]);let f=S(),h=e||l?s.checked:s.unchecked;return n.createElement(b,M({value:"all",label:h,itemId:t,onSelectItem:o,isChecked:l,className:cx(f.selectAll,c)},g))};var N=ie;N.HighlightedItem=T;N.Option=b;N.SelectAll=W;export{N as Multiselect,b as MultiselectOption,W as SelectAllOption};//# sourceMappingURL=index.js.map
19
2
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/MultiselectOption.tsx","../../src/Multiselect.styles.ts","../../src/Multiselect.tsx","../../src/MultiselectSearch.tsx","../../src/SelectAllOption.tsx","../../src/CompoundMultiselect.tsx"],"names":["React","Checkbox","Text","css","cx","tokens","getMenuItemStyles","getMultiselectStyles","listMaxHeight","isActive","isDisabled","getStringMatch","MultiselectOption","_a","_b","children","label","value","itemId","onSelectItem","searchValue","isChecked","className","rest","__objRest","styles","__spreadValues","event","HighlightedItem","item","inputValue","before","match","after","useRef","useState","useCallback","useMemo","mergeRefs","Flex","Button","IconButton","CaretDownIcon","XIcon","SkeletonContainer","SkeletonBodyText","Popover","Subheading","Tooltip","FocusLock","TextInput","MagnifyingGlassIcon","MultiselectSearch","setSearchValue","onSearchValueChange","searchInputName","searchInputRef","resetSearchRef","searchPlaceholder","focusList","internalSearchInputRef","handleSearchChange","resetSearchInput","forcedEvent","iterateOverChildren","filter","callback","child","childChildren","countMatchingChildren","counter","_Multiselect","props","ref","startIcon","placeholder","currentSelection","toggleRef","toggleButtonAriaLabel","isLoading","testId","noMatchesMessage","searchProps","popoverProps","onBlur","onClearSelection","clearButtonProps","listRef","onClose","isOpen","setIsOpen","internalListRef","showClearButton","hasSearch","handleClearSelection","e","renderMultiselectLabel","leftoverCount","currentSelectionClassName","optionsLength","enrichOptions","__spreadProps","ListItemLoadingState","Multiselect","SelectAllOption","selectAllOptionLabel","otherProps","displayLabel"],"mappings":"qlBAAA,OAAOA,MAAW,QAClB,OAAS,YAAAC,OAAgB,wBACzB,OAAS,QAAAC,OAAY,6BCFrB,OAAS,OAAAC,EAAK,MAAAC,OAAU,UACxB,OAAOC,MAAY,yBACnB,OAAS,qBAAAC,OAAyB,uBAE3B,IAAMC,EAAuB,KAAO,CACzC,YAAaJ,EAAI,CACf,SAAU,WACV,MAAO,MACT,CAAC,EACD,cAAeA,EAAI,CACjB,eAAgB,eAClB,CAAC,EACD,iBAAkBA,EAAI,CACpB,QAAS,eACT,MAAO,OACP,WAAY,SACZ,aAAc,WACd,SAAU,SACV,cAAe,SACf,YAAaE,EAAO,UACtB,CAAC,EACD,gCAAiCF,EAAI,CACnC,aAAc,MAChB,CAAC,EACD,yBAA0BA,EAAI,CAC5B,MAAOE,EAAO,OAChB,CAAC,EACD,UAAWF,EAAI,CACb,WAAYE,EAAO,WACnB,SAAU,SACV,IAAK,MACL,OAAQA,EAAO,sBACf,gBAAiBA,EAAO,UAC1B,CAAC,EACD,WAAYF,EAAI,CACd,QAAS,OAAOE,EAAO,SAAS,SAASA,EAAO,SAAS,GACzD,aAAc,WACd,WAAY,SACZ,OAAQ,OACR,aAAc,MACd,aAAc,aAAaA,EAAO,OAAO,GACzC,UAAW,OACX,oCAAqC,CACnC,UAAW,OACX,aAAc,aAAaA,EAAO,OAAO,EAC3C,CACF,CAAC,EACD,aAAcF,EAAI,CAChB,SAAU,WACV,IAAK,MACL,MAAO,MACP,OAAQE,EAAO,cACf,QAASA,EAAO,WAChB,OAAQA,EAAO,SACjB,CAAC,EACD,QAAUG,GACRL,EAAI,CACF,SAAU,OACV,UAAW,GAAGK,CAAa,IAC7B,CAAC,EACH,UAAWL,EAAI,CAAC,CAAC,EACjB,KAAMA,EAAI,CACR,UAAW,OACX,QAAS,GAAGE,EAAO,UAAU,GAC7B,OAAQ,CACV,CAAC,EACD,WAAYF,EAAI,CAEd,QAAS,OAAOE,EAAO,SAAS,GAChC,WAAYA,EAAO,WACrB,CAAC,EACD,eAAgBF,EAAI,CAClB,MAAOE,EAAO,QACd,OAAQA,EAAO,SACf,UAAW,QACb,CAAC,EACD,qBAAsBF,EAAI,CACxB,WAAY,OACd,CAAC,EACD,UAAWA,EAAI,CACb,aAAc,aAAaE,EAAO,OAAO,GACzC,aAAcA,EAAO,WACrB,cAAeA,EAAO,WACtB,YAAa,CACX,WAAYA,EAAO,gBACrB,CACF,CAAC,EACD,OAAQF,EAAI,CACV,cAAe,MACjB,CAAC,EACD,WAAYA,EAAI,CACd,WAAY,SACZ,QAAS,OACT,KAAM,CACJ,MAAOE,EAAO,QACd,WAAYA,EAAO,kBACrB,CACF,CAAC,EACD,YAAa,CAAC,CACZ,SAAAI,EACA,WAAAC,CACF,IAIEP,EAAI,CACF,MAAOC,GACLE,GAAkB,CAAE,SAAAG,EAAU,WAAAC,CAAW,CAAC,EAC1CP,EAAI,CACF,MAAO,MACT,CAAC,CACH,CACF,CAAC,CACL,GD7GA,OAAS,kBAAAQ,OAAsB,wBAC/B,OAAS,MAAAP,OAAU,UA2BZ,IAAMQ,EAAqBC,GAWJ,CAXI,IAAAC,EAAAD,EAChC,UAAAE,EACA,MAAAC,EACA,MAAAC,EACA,OAAAC,EACA,aAAAC,EACA,YAAAC,EACA,UAAAC,EAAY,GACZ,WAAAX,EAAa,GACb,UAAAY,CAzCF,EAgCkCR,EAU7BS,EAAAC,EAV6BV,EAU7B,CATH,WACA,QACA,QACA,SACA,eACA,cACA,YACA,aACA,cAGA,IAAMW,EAASlB,EAAqB,EAEpC,OACEP,EAAA,cAAC,KAAA0B,EAAA,CAAG,UAAWtB,GAAGqB,EAAO,OAAQH,CAAS,GAAOC,GAC/CvB,EAAA,cAACC,GAAA,CACC,GAAIiB,EACJ,MAAOD,EACP,SAAWU,GAAUR,EAAaQ,CAAK,EACvC,UAAWN,EACX,WAAYX,EACZ,UAAWe,EAAO,YAAY,CAAE,SAAUJ,EAAW,WAAAX,CAAW,CAAC,GAEjEV,EAAA,cAACE,GAAA,CACC,UAAWuB,EAAO,WAClB,eAAc,4BAA4BP,CAAM,IAE/C,OAAOF,GAAU,SAChBhB,EAAA,cAAC4B,EAAA,CAAgB,KAAMZ,EAAO,WAAYI,EAAa,EAEvDL,CAEJ,CACF,CACF,CAEJ,EAEO,SAASa,EAAgB,CAC9B,KAAAC,EACA,WAAAC,EAAa,EACf,EAGG,CACD,GAAM,CAAE,OAAAC,EAAQ,MAAAC,EAAO,MAAAC,CAAM,EAAItB,GAAekB,EAAMC,EAAW,KAAK,CAAC,EAEvE,OAAIC,EAAO,OAASC,EAAM,OAASC,EAAM,SAAW,EAC3CjC,EAAA,cAAAA,EAAA,cAAG6B,CAAK,EAIf7B,EAAA,cAAAA,EAAA,cACG+B,EACD/B,EAAA,cAAC,QAAK,eAAa,6BAA6BgC,CAAM,EACrDC,CACH,CAEJ,CAEAL,EAAgB,YAAc,kBE7F9B,OAAO5B,GAAS,UAAAkC,GAAQ,YAAAC,EAAU,eAAAC,EAAa,WAAAC,OAAe,QAC9D,OAAS,MAAAjC,MAAU,UAEnB,OAAS,aAAAkC,GAA6B,QAAAC,OAAY,uBAClD,OAAS,UAAAC,GAAQ,cAAAC,OAAoC,yBACrD,OAAS,iBAAAC,GAAe,SAAAC,OAAa,wBAErC,OAAS,qBAAAC,GAAmB,oBAAAC,OAAwB,2BACpD,OAAS,WAAAC,MAAkC,0BAC3C,OAAS,cAAAC,OAAkB,6BAC3B,OAAS,WAAAC,OAAe,0BAIxB,OAAOC,OAAe,mBCdtB,OAAOjD,GAAS,eAAAoC,EAAa,UAAAF,OAAc,QAC3C,OAAO7B,MAAY,yBACnB,OAAS,aAAA6C,OAAiB,wBAC1B,OAAS,SAAAP,GAAO,uBAAAQ,OAA2B,wBAC3C,OAAS,cAAAV,OAAkB,yBAE3B,OAAS,aAAAH,OAAiB,uBA+CnB,IAAMc,EAAoB,CAAC,CAChC,YAAAhC,EACA,eAAAiC,EACA,oBAAAC,EACA,gBAAAC,EACA,eAAAC,EACA,eAAAC,EACA,kBAAAC,EAAoB,SACpB,UAAAC,CACF,IAA8B,CAC5B,IAAMlC,EAASlB,EAAqB,EAC9BqD,EAAyB1B,GAAyB,IAAI,EAEtD2B,EAAqBzB,EACxBT,GAAU,CACT0B,EAAe1B,EAAM,OAAO,KAAK,EACjC2B,GAAA,MAAAA,EAAsB3B,EACxB,EACA,CAAC2B,EAAqBD,CAAc,CACtC,EAEMS,EAAmB1B,EAAY,IAAM,CACzC,GAAI,CAAChB,EAAa,OAClBuC,EAAU,EAGqB,OAAO,yBACpC,OAAO,iBAAiB,UACxB,OACF,EAAE,IACqB,KAAKC,EAAuB,QAAS,EAAE,EAC9D,IAAMG,EAAc,IAAI,MAAM,SAAU,CAAE,QAAS,EAAK,CAAC,EACzDH,EAAuB,QAAQ,cAAcG,CAAW,CAC1D,EAAG,CAAC3C,EAAauC,CAAS,CAAC,EAE3B,OACE3D,EAAA,cAAC,OAAI,UAAWyB,EAAO,WACrBzB,EAAA,cAACkD,GAAA,CACC,aAAW,SACX,KAAK,OACL,MAAO9B,EACP,UAAWK,EAAO,WAClB,OAAO,wBACP,YAAaiC,EACb,SAAUG,EACV,IAAKvB,GAAUkB,EAAgBI,CAAsB,EACrD,KAAML,EACN,KAAK,QACP,EACAvD,EAAA,cAACyC,GAAA,CACC,IAAKgB,EACL,aAAYrC,EAAc,eAAiB,SAC3C,UAAWK,EAAO,aAClB,QAAQ,cACR,KACEL,EACEpB,EAAA,cAAC2C,GAAA,CAAM,MAAOtC,EAAO,QAAS,EAE9BL,EAAA,cAACmD,GAAA,CAAoB,MAAO9C,EAAO,QAAS,EAGhD,QAASyD,EACT,WAAY,CAAC1C,EACb,KAAK,QACP,CACF,CAEJ,EDEA,IAAM4C,GAAsB,CAC1BjD,EACAkD,EACAC,IAEOlE,EAAM,SAAS,IAAIe,EAAWoD,GAAU,CAE7C,GAAI,CAACnE,EAAM,eAAemE,CAAK,EAAG,OAAOA,EACzC,GAAIF,EAAOE,CAAK,EACd,OAAOD,EAASC,CAAK,EAEvB,IAAMC,EAAgBJ,GACpBG,EAAM,MAAM,SACZF,EACAC,CACF,EACA,OAAOlE,EAAM,aAAamE,EAAO,CAAE,SAAUC,CAAc,CAAY,CACzE,CAAC,EAIGC,GAAwB,CAC5BtD,EACAkD,IACW,CACX,IAAIK,EAAU,EACd,OAAAtE,EAAM,SAAS,QAAQe,EAAWoD,GAAU,CAErCnE,EAAM,eAAemE,CAAK,IAC1BF,EAAOE,CAAK,EAGfG,GAAW,EAFXA,GAAWD,GAAsBF,EAAM,MAAM,SAAUF,CAAM,EAIjE,CAAC,EACMK,CACT,EAEA,SAASC,GAAaC,EAAyBC,EAAgC,CAC7E,GAAM,CACJ,UAAAnD,EACA,UAAAoD,EACA,YAAAC,EAAc,2BACd,iBAAAC,EAAmB,CAAC,EACpB,UAAAC,EACA,sBAAAC,EAAwB,qBACxB,UAAAC,EAAY,GACZ,OAAAC,EAAS,iBACT,iBAAAC,EAAmB,mBACnB,YAAAC,EAAc,CAAC,EACf,aAAAC,EAAe,CAAC,EAChB,SAAApE,EACA,OAAAqE,EACA,iBAAAC,EACA,iBAAAC,EAAmB,CACjB,QAAS,kBACT,UAAW,iBACb,CACF,EAAId,EAEE,CAAE,cAAAhE,GAAgB,IAAK,QAAA+E,GAAS,QAAAC,CAAQ,EAAIL,EAE5C1D,EAASlB,EAAqB,EAE9B,CAACa,EAAaiC,EAAc,EAAIlB,EAAS,EAAE,EAC3C,CAACsD,EAAQC,CAAS,EAAIvD,EAAS,EAAK,EAEpCwD,EAAkBzD,GAAyB,IAAI,EAE/C0D,EACJhB,EAAiB,OAAS,GAAK,OAAOS,GAAqB,WAEvDQ,EAAY,OAAOX,EAAY,qBAAwB,WAEvDvB,EAAYvB,EAAY,IAAM,CApMtC,IAAAvB,GAyMIA,EAAA8E,EAAgB,UAAhB,MAAA9E,EAAyB,OAC3B,EAAG,CAAC,CAAC,EAECiF,GAAwBC,GAA2C,CACvEV,GAAA,MAAAA,IACAU,EAAE,gBAAgB,CACpB,EAEMC,GAAyB5D,EAAY,IAAM,CAC/C,GAAIwC,EAAiB,SAAW,EAC9B,OAAO5E,EAAA,cAAAA,EAAA,cAAG2E,CAAY,EAExB,IAAMsB,EAAgBrB,EAAiB,OAAS,EAC1CsB,EAA4B9F,EAChCqB,EAAO,iBACPmE,GAAmBnE,EAAO,+BAC5B,EACA,OAAIwE,IAAkB,EAElBjG,EAAA,cAAC,QACC,eAAa,mCACb,UAAWkG,GAEVtB,EAAiB,CAAC,CACrB,EAIF5E,EAAA,cAAC,QACC,eAAa,mCACb,UAAWkG,GAEVtB,EAAiB,CAAC,EAAG,IACtB5E,EAAA,cAAC,QAAK,UAAWyB,EAAO,0BAA0B,OAC3CwE,EAAc,OACrB,CACF,CAEJ,EAAG,CACDrB,EACAD,EACAiB,EACAnE,EAAO,iBACPA,EAAO,yBACPA,EAAO,+BACT,CAAC,EAEK0E,EAAgB9D,GACpB,IACEgC,GACEtD,EACCoD,GAAUA,EAAM,OAASvD,CAC5B,EACF,CAACG,CAAQ,CACX,EAGMqF,GAAgBpG,EAAM,YACzBe,GACQiD,GACLjD,EACCoD,GAAUA,EAAM,OAASvD,EACzBuD,GAAU,CACT,IAAMhD,GAAgBQ,IAA+C,CAxQ/E,IAAAd,EAyQY8C,EAAU,GACV9C,EAAAsD,EAAM,QAAN,MAAAtD,EAAa,aAAac,GAC5B,EACA,OAAO3B,EAAM,aAAamE,EAAO,CAC/B,YAAA/C,EACA,aAAAD,EACF,CAAoC,CACtC,CACF,EAEF,CAACC,EAAauC,CAAS,CACzB,EAEA,OACE3D,EAAA,cAAC,OACC,eAAcgF,EACd,UAAW5E,EAAGqB,EAAO,YAAaH,CAAS,EAC3C,IAAKmD,GAELzE,EAAA,cAAC8C,EAAAuD,EAAA3E,EAAA,CACC,mBAAoB,GACpB,YAAW,IACPyD,GAHL,CAKC,OAAQM,EACR,QAAS,IAAM,CACbC,EAAU,EAAK,EACXF,GACFA,EAAQ,CAEZ,IAEAxF,EAAA,cAACuC,GAAA,CAAK,WAAW,UACfvC,EAAA,cAAC8C,EAAQ,QAAR,KACC9C,EAAA,cAACwC,GAAAd,EAAA,CACC,aAAYoD,EACZ,IAAKD,EACL,QAAS,IAAMa,EAAU,CAACD,CAAM,EAChC,UAAWf,EACX,QAAS1E,EAAA,cAAC0C,GAAA,IAAc,EACxB,YAAW,GACX,UAAWjB,EAAO,eACd+C,EAAM,oBAETwB,GAAuB,CAC1B,CACF,EACCJ,GACC5F,EAAA,cAAC,OAAI,UAAWyB,EAAO,sBACrBzB,EAAA,cAACgD,GAAA,CACC,QACEsC,EAAiB,QACbA,EAAiB,QACjB,kBAEN,UAAW,IACX,UAAU,MACV,GAAG,OAEHtF,EAAA,cAACyC,GAAA,CACC,QAASqD,GACT,KAAM9F,EAAA,cAAC2C,GAAA,IAAM,EACb,aACE2C,EAAiB,UACbA,EAAiB,UACjB,kBAEN,KAAK,QACP,CACF,CACF,CAEJ,EACAtF,EAAA,cAAC8C,EAAQ,QAAR,CACC,IAAKR,GAAUiD,GAASI,CAAe,EACvC,UAAWvF,EACTqB,EAAO,QAAQjB,EAAa,EAC5B2E,EAAa,UACb1D,EAAO,SACT,EACA,OAAO,2BACP,OAAQ,IAAM2D,GAAA,YAAAA,KAEdpF,EAAA,cAACiD,GAAA,CAAU,aAAc,CAAE,cAAe,EAAK,EAAG,YAAa,IAC5D4C,GACC7F,EAAA,cAACoD,EAAAiD,EAAA3E,EAAA,GACKwD,GADL,CAEC,eAAgB7B,GAChB,YAAajC,EACb,UAAWuC,GACb,EAEDoB,GAAa/E,EAAA,cAACsG,GAAA,IAAqB,EAEnC,CAACvB,GAAaoB,EAAgB,GAC7BnG,EAAA,cAAC,MAAG,UAAWyB,EAAO,KAAM,eAAa,wBACtCoE,EAAYO,GAAcrF,CAAQ,EAAIA,CACzC,EAGD,CAACgE,GAAaoB,IAAkB,GAC/BnG,EAAA,cAAC+C,GAAA,CAAW,UAAWtB,EAAO,gBAC3BwD,CACH,CAEJ,CACF,CACF,CACF,CAEJ,CAEA,IAAMqB,GAAuB,IAEzBtG,EAAA,cAAC4C,GAAA,CAAkB,UAAW,IAC5B5C,EAAA,cAAC6C,GAAA,CAAiB,cAAe,EAAG,CACtC,EAQS0D,GAAcvG,EAAM,WAAWuE,EAAY,EErYxD,OAAOvE,OAAW,QAGlB,OAAS,MAAAI,OAAU,UA4BZ,IAAMoG,EAAmB3F,GAWJ,CAXI,IAAAC,EAAAD,EAC9B,OAAAG,EACA,OAAAE,EAAS,YACT,aAAAC,EACA,UAAAE,EAAY,GACZ,qBAAAoF,EAAuB,CACrB,QAAS,eACT,UAAW,YACb,EACA,UAAAnF,CAxCF,EA+BgCR,EAU3B4F,EAAAlF,EAV2BV,EAU3B,CATH,QACA,SACA,eACA,YACA,uBAIA,cAGA,IAAMW,EAASlB,EAAqB,EAC9BoG,EACJ3F,GAASK,EACLoF,EAAqB,QACrBA,EAAqB,UAC3B,OACEzG,GAAA,cAACY,EAAAc,EAAA,CACC,MAAM,MACN,MAAOiF,EACP,OAAQzF,EACR,aAAcC,EACd,UAAWE,EACX,UAAWjB,GAAGqB,EAAO,UAAWH,CAAS,GACrCoF,EACN,CAEJ,ECjDO,IAAMH,EAAcA,GAC3BA,EAAY,gBAAkB3E,EAC9B2E,EAAY,OAAS3F,EACrB2F,EAAY,UAAYC","sourcesContent":["import React from 'react';\nimport { Checkbox } from '@contentful/f36-forms';\nimport { Text } from '@contentful/f36-typography';\nimport { getMultiselectStyles } from './Multiselect.styles';\nimport { getStringMatch } from '@contentful/f36-utils';\nimport { cx } from 'emotion';\n\ntype LabelOrChildren =\n | {\n /**\n * When using React children it is your own responsibility to highlight\n * the matching part of the item label. Use the `HighlightedItem`\n * component for this.\n */\n children: React.ReactNode;\n label?: never;\n }\n | {\n children?: never;\n label: string;\n };\n\nexport type MultiselectOptionProps = {\n value: string;\n itemId: string;\n searchValue?: string;\n className?: string;\n onSelectItem: (event: React.ChangeEvent<HTMLInputElement>) => void;\n isChecked?: boolean;\n isDisabled?: boolean;\n} & LabelOrChildren;\n\nexport const MultiselectOption = ({\n children,\n label,\n value,\n itemId,\n onSelectItem,\n searchValue,\n isChecked = false,\n isDisabled = false,\n className,\n ...rest\n}: MultiselectOptionProps) => {\n const styles = getMultiselectStyles();\n\n return (\n <li className={cx(styles.option, className)} {...rest}>\n <Checkbox\n id={itemId}\n value={value}\n onChange={(event) => onSelectItem(event)}\n isChecked={isChecked}\n isDisabled={isDisabled}\n className={styles.optionCheck({ isActive: isChecked, isDisabled })}\n >\n <Text\n className={styles.optionText}\n data-test-id={`cf-multiselect-list-item-${itemId}`}\n >\n {typeof label === 'string' ? (\n <HighlightedItem item={label} inputValue={searchValue} />\n ) : (\n children\n )}\n </Text>\n </Checkbox>\n </li>\n );\n};\n\nexport function HighlightedItem({\n item,\n inputValue = '',\n}: {\n item: string;\n inputValue?: string;\n}) {\n const { before, match, after } = getStringMatch(item, inputValue.trim());\n\n if (before.length + match.length + after.length === 0) {\n return <>{item}</>;\n }\n\n return (\n <>\n {before}\n <span data-test-id=\"cf-multiselect-item-match\">{match}</span>\n {after}\n </>\n );\n}\n\nHighlightedItem.displayName = 'HighlightedItem';\n","import { css, cx } from 'emotion';\nimport tokens from '@contentful/f36-tokens';\nimport { getMenuItemStyles } from '@contentful/f36-core';\n\nexport const getMultiselectStyles = () => ({\n multiselect: css({\n position: 'relative',\n width: '100%',\n }),\n triggerButton: css({\n justifyContent: 'space-between',\n }),\n currentSelection: css({\n display: 'inline-block',\n width: '100%',\n whiteSpace: 'nowrap',\n textOverflow: 'ellipsis',\n overflow: 'hidden',\n verticalAlign: 'bottom',\n marginRight: tokens.spacing2Xs,\n }),\n currentSelectionWithClearButton: css({\n paddingRight: '40px',\n }),\n currentSelectionAddition: css({\n color: tokens.gray600,\n }),\n searchBar: css({\n paddingTop: tokens.spacing2Xs,\n position: 'sticky',\n top: '0px',\n zIndex: tokens.zIndexWorkbenchHeader,\n backgroundColor: tokens.colorWhite,\n }),\n inputField: css({\n padding: `6px ${tokens.spacingXl} 10px ${tokens.spacingXs}`,\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n border: 'none',\n borderRadius: '0px',\n borderBottom: `1px solid ${tokens.gray200}`,\n boxShadow: 'none',\n '&:focus, &:active, &:active:hover': {\n boxShadow: 'none',\n borderBottom: `1px solid ${tokens.gray200}`,\n },\n }),\n toggleButton: css({\n position: 'absolute',\n top: '1px',\n right: '1px',\n zIndex: tokens.zIndexDefault,\n padding: tokens.spacing2Xs,\n height: tokens.spacingXl,\n }),\n content: (listMaxHeight: number) =>\n css({\n overflow: 'auto',\n maxHeight: `${listMaxHeight}px`,\n }),\n container: css({}),\n list: css({\n listStyle: 'none',\n padding: `${tokens.spacing2Xs}`,\n margin: 0,\n }),\n groupTitle: css({\n // Magic number to get a height of 32px on the item\n padding: `6px ${tokens.spacingXs}`,\n lineHeight: tokens.lineHeightM,\n }),\n noMatchesTitle: css({\n color: tokens.gray500,\n margin: tokens.spacingM,\n textAlign: 'center',\n }),\n clearSelectionButton: css({\n marginLeft: '-80px',\n }),\n selectAll: css({\n borderBottom: `1px solid ${tokens.gray200}`,\n marginBottom: tokens.spacing2Xs,\n paddingBottom: tokens.spacing2Xs,\n 'label > *': {\n fontWeight: tokens.fontWeightMedium,\n },\n }),\n option: css({\n listStyleType: 'none',\n }),\n optionText: css({\n alignItems: 'center',\n display: 'flex',\n span: {\n color: tokens.gray900,\n fontWeight: tokens.fontWeightDemiBold,\n },\n }),\n optionCheck: ({\n isActive,\n isDisabled,\n }: {\n isActive?: boolean;\n isDisabled?: boolean;\n }) =>\n css({\n label: cx(\n getMenuItemStyles({ isActive, isDisabled }),\n css({\n width: '100%',\n }),\n ),\n }),\n});\n","import React, { useRef, useState, useCallback, useMemo } from 'react';\nimport { cx } from 'emotion';\n\nimport { mergeRefs, type CommonProps, Flex } from '@contentful/f36-core';\nimport { Button, IconButton, type ButtonProps } from '@contentful/f36-button';\nimport { CaretDownIcon, XIcon } from '@contentful/f36-icons';\n\nimport { SkeletonContainer, SkeletonBodyText } from '@contentful/f36-skeleton';\nimport { Popover, type PopoverProps } from '@contentful/f36-popover';\nimport { Subheading } from '@contentful/f36-typography';\nimport { Tooltip } from '@contentful/f36-tooltip';\n\nimport { getMultiselectStyles } from './Multiselect.styles';\nimport { MultiselectOption, MultiselectOptionProps } from './MultiselectOption';\nimport FocusLock from 'react-focus-lock';\n\nimport type { MultiselectSearchProps as SearchProps } from './MultiselectSearch';\nimport { MultiselectSearch } from './MultiselectSearch';\n\ntype ClearButtonProps = {\n /**\n * Aria label for the clear button\n * @default 'Clear selection'\n */\n ariaLabel?: string;\n\n /**\n * Tooltip for the clear button\n * @default 'Clear selection'\n */\n tooltip?: string;\n};\n\nexport interface MultiselectProps extends CommonProps {\n /** Select Options */\n children?: React.ReactNode;\n\n /**\n * Set a custom icon for the text input\n */\n startIcon?: React.ReactElement;\n\n /**\n * Placeholder shown before selecting any elements. Defaults to 'Select one or more items'\n */\n placeholder?: string;\n\n /**\n * current Selected items, to be shown on the trigger button\n */\n currentSelection?: Array<string>;\n\n /**\n * Sets the list to show its loading state\n * @default false\n */\n isLoading?: boolean;\n\n /**\n * Use this prop to get a ref to the toggle button of the component\n */\n toggleRef?: React.Ref<HTMLButtonElement>;\n\n /**\n * Aria label for the toggle button that opens the list\n * @default 'Toggle Multiselect'\n */\n toggleButtonAriaLabel?: string;\n\n /**\n * Props to pass to the optional search field\n */\n searchProps?: SearchProps;\n\n /**\n * Props to pass to the trigger button\n */\n triggerButtonProps?: ButtonProps;\n\n /**\n * A message that will be shown when it is not possible to find any option that matches the search value\n * @default \"No matches\"\n */\n noMatchesMessage?: string;\n\n /**\n * Props to pass to the Popover (Dropdown) component\n */\n popoverProps?: Partial<PopoverProps> & {\n /**\n * It sets the max-height, in pixels, of the list\n * The default value is the height of 5 single line items\n * @default 180\n */\n listMaxHeight?: number;\n\n /**\n * Use this prop to get a ref to the list of items of the component\n */\n listRef?: React.Ref<HTMLUListElement>;\n } & Pick<CommonProps, 'className'>;\n\n /**\n * Function called when the popover loses its focus.\n */\n onBlur?: () => void;\n\n /**\n * Function called when the clear all button is clicked\n * If no function is provided the clear button is not shown\n */\n onClearSelection?: () => void;\n\n /**\n * Clear Button Props used for localization\n * @default { ariaLabel: 'Clear selection', tooltip: 'Clear selection' }\n */\n clearButtonProps?: ClearButtonProps;\n}\n\n// Scan through the whole hierachy until `filter` returns true and apply `transform`\n// Inspired from https://stackoverflow.com/a/70676868/17269164\nconst iterateOverChildren = (\n children: React.ReactNode,\n filter: (child: React.ReactElement) => boolean,\n callback: (child: React.ReactElement) => React.ReactElement | void,\n): React.ReactNode => {\n return React.Children.map(children, (child) => {\n // equal to (if (child == null || typeof child == 'string'))\n if (!React.isValidElement(child)) return child;\n if (filter(child)) {\n return callback(child);\n }\n const childChildren = iterateOverChildren(\n child.props.children,\n filter,\n callback,\n );\n return React.cloneElement(child, { children: childChildren } as unknown);\n });\n};\n\n// Scan through the whole hierachy to count the number of children where `filter` returns true\nconst countMatchingChildren = (\n children: React.ReactNode,\n filter: (child: React.ReactElement) => boolean,\n): number => {\n let counter = 0;\n React.Children.forEach(children, (child) => {\n // equal to (if (child == null || typeof child == 'string'))\n if (!React.isValidElement(child)) return;\n if (!filter(child)) {\n counter += countMatchingChildren(child.props.children, filter);\n } else {\n counter += 1;\n }\n });\n return counter;\n};\n\nfunction _Multiselect(props: MultiselectProps, ref: React.Ref<HTMLDivElement>) {\n const {\n className,\n startIcon,\n placeholder = 'Select one or more Items',\n currentSelection = [],\n toggleRef,\n toggleButtonAriaLabel = 'Toggle Multiselect',\n isLoading = false,\n testId = 'cf-multiselect',\n noMatchesMessage = 'No matches found',\n searchProps = {},\n popoverProps = {},\n children,\n onBlur,\n onClearSelection,\n clearButtonProps = {\n tooltip: 'Clear selection',\n ariaLabel: 'Clear selection',\n },\n } = props;\n\n const { listMaxHeight = 180, listRef, onClose } = popoverProps;\n\n const styles = getMultiselectStyles();\n\n const [searchValue, setSearchValue] = useState('');\n const [isOpen, setIsOpen] = useState(false);\n\n const internalListRef = useRef<HTMLUListElement>(null);\n\n const showClearButton =\n currentSelection.length > 1 && typeof onClearSelection === 'function';\n\n const hasSearch = typeof searchProps.onSearchValueChange === 'function';\n\n const focusList = useCallback(() => {\n // Clearing the search input or selecting an item triggers a rerendering and\n // thereby the client loses the focus on the clicked element. To avoid having\n // the focus on the document body (which breaks `closeOnBlur`), we force it\n // back to the list in the popup.\n internalListRef.current?.focus();\n }, []);\n\n const handleClearSelection = (e: React.MouseEvent<HTMLButtonElement>) => {\n onClearSelection?.();\n e.stopPropagation();\n };\n\n const renderMultiselectLabel = useCallback(() => {\n if (currentSelection.length === 0) {\n return <>{placeholder}</>;\n }\n const leftoverCount = currentSelection.length - 1;\n const currentSelectionClassName = cx(\n styles.currentSelection,\n showClearButton && styles.currentSelectionWithClearButton,\n );\n if (leftoverCount === 0) {\n return (\n <span\n data-test-id=\"cf-multiselect-current-selection\"\n className={currentSelectionClassName}\n >\n {currentSelection[0]}\n </span>\n );\n }\n return (\n <span\n data-test-id=\"cf-multiselect-current-selection\"\n className={currentSelectionClassName}\n >\n {currentSelection[0]}{' '}\n <span className={styles.currentSelectionAddition}>\n and {leftoverCount} more\n </span>\n </span>\n );\n }, [\n currentSelection,\n placeholder,\n showClearButton,\n styles.currentSelection,\n styles.currentSelectionAddition,\n styles.currentSelectionWithClearButton,\n ]);\n\n const optionsLength = useMemo(\n () =>\n countMatchingChildren(\n children,\n (child) => child.type === MultiselectOption,\n ),\n [children],\n );\n\n // clones and enriches the multiselect options\n const enrichOptions = React.useCallback(\n (children: React.ReactNode): React.ReactNode => {\n return iterateOverChildren(\n children,\n (child) => child.type === MultiselectOption,\n (child) => {\n const onSelectItem = (event: React.ChangeEvent<HTMLInputElement>) => {\n focusList();\n child.props?.onSelectItem(event);\n };\n return React.cloneElement(child, {\n searchValue,\n onSelectItem,\n } as Partial<MultiselectOptionProps>);\n },\n );\n },\n [searchValue, focusList],\n );\n\n return (\n <div\n data-test-id={testId}\n className={cx(styles.multiselect, className)}\n ref={ref}\n >\n <Popover\n renderOnlyWhenOpen={false}\n isFullWidth\n {...popoverProps}\n // popoverProps should never overwrite the internal opening logic\n isOpen={isOpen}\n onClose={() => {\n setIsOpen(false);\n if (onClose) {\n onClose();\n }\n }}\n >\n <Flex alignItems=\"center\">\n <Popover.Trigger>\n <Button\n aria-label={toggleButtonAriaLabel}\n ref={toggleRef}\n onClick={() => setIsOpen(!isOpen)}\n startIcon={startIcon}\n endIcon={<CaretDownIcon />}\n isFullWidth\n className={styles.triggerButton}\n {...props.triggerButtonProps}\n >\n {renderMultiselectLabel()}\n </Button>\n </Popover.Trigger>\n {showClearButton && (\n <div className={styles.clearSelectionButton}>\n <Tooltip\n content={\n clearButtonProps.tooltip\n ? clearButtonProps.tooltip\n : 'Clear selection'\n }\n showDelay={800}\n placement=\"top\"\n as=\"div\"\n >\n <IconButton\n onClick={handleClearSelection}\n icon={<XIcon />}\n aria-label={\n clearButtonProps.ariaLabel\n ? clearButtonProps.ariaLabel\n : 'Clear selection'\n }\n size=\"small\"\n />\n </Tooltip>\n </div>\n )}\n </Flex>\n <Popover.Content\n ref={mergeRefs(listRef, internalListRef)}\n className={cx(\n styles.content(listMaxHeight),\n popoverProps.className,\n styles.container,\n )}\n testId=\"cf-multiselect-container\"\n onBlur={() => onBlur?.()}\n >\n <FocusLock focusOptions={{ preventScroll: true }} returnFocus={true}>\n {hasSearch && (\n <MultiselectSearch\n {...searchProps}\n setSearchValue={setSearchValue}\n searchValue={searchValue}\n focusList={focusList}\n />\n )}\n {isLoading && <ListItemLoadingState />}\n\n {!isLoading && optionsLength > 0 && (\n <ul className={styles.list} data-test-id=\"cf-multiselect-items\">\n {hasSearch ? enrichOptions(children) : children}\n </ul>\n )}\n\n {!isLoading && optionsLength === 0 && (\n <Subheading className={styles.noMatchesTitle}>\n {noMatchesMessage}\n </Subheading>\n )}\n </FocusLock>\n </Popover.Content>\n </Popover>\n </div>\n );\n}\n\nconst ListItemLoadingState = () => {\n return (\n <SkeletonContainer svgHeight={16}>\n <SkeletonBodyText numberOfLines={1} />\n </SkeletonContainer>\n );\n};\n\n/**\n * The Multiselect is a component that will allow a user to select multiple items.\n * It has an optional\n */\nexport const Multiselect = React.forwardRef(_Multiselect);\n","import React, { useCallback, useRef } from 'react';\nimport tokens from '@contentful/f36-tokens';\nimport { TextInput } from '@contentful/f36-forms';\nimport { XIcon, MagnifyingGlassIcon } from '@contentful/f36-icons';\nimport { IconButton } from '@contentful/f36-button';\nimport { getMultiselectStyles } from './Multiselect.styles';\nimport { mergeRefs } from '@contentful/f36-core';\n\nexport interface MultiselectSearchProps {\n /**\n * Function called whenever the search input value changes\n */\n onSearchValueChange?: (\n event: React.ChangeEvent<HTMLInputElement>,\n ) => void | undefined;\n\n /**\n * This is the value will be passed to the `placeholder` prop of the input.\n * @default \"Search\"\n */\n searchPlaceholder?: string;\n\n /**\n * Pass a form name to the search text input\n */\n searchInputName?: string;\n\n /**\n * Use this prop to get a ref to the search input element of the component\n */\n searchInputRef?: React.Ref<HTMLInputElement>;\n\n /**\n * Use this prop to get a ref to the reset search button of the component\n */\n resetSearchRef?: React.Ref<HTMLButtonElement>;\n\n /**\n * State from the parent component\n */\n searchValue?: string;\n\n /**\n * State setter of the parent\n */\n setSearchValue?: React.Dispatch<React.SetStateAction<string>>;\n\n /**\n * List helper function\n */\n focusList?: () => void;\n}\n\nexport const MultiselectSearch = ({\n searchValue,\n setSearchValue,\n onSearchValueChange,\n searchInputName,\n searchInputRef,\n resetSearchRef,\n searchPlaceholder = 'Search',\n focusList,\n}: MultiselectSearchProps) => {\n const styles = getMultiselectStyles();\n const internalSearchInputRef = useRef<HTMLInputElement>(null);\n\n const handleSearchChange = useCallback(\n (event) => {\n setSearchValue(event.target.value);\n onSearchValueChange?.(event);\n },\n [onSearchValueChange, setSearchValue],\n );\n\n const resetSearchInput = useCallback(() => {\n if (!searchValue) return;\n focusList();\n // this looks a bit hacky, but is the official way of externally triggering the onChange handler for an input\n // https://stackoverflow.com/a/46012210/17269164\n const nativeInputValueSetter = Object.getOwnPropertyDescriptor(\n window.HTMLInputElement.prototype,\n 'value',\n ).set;\n nativeInputValueSetter.call(internalSearchInputRef.current, '');\n const forcedEvent = new Event('change', { bubbles: true });\n internalSearchInputRef.current.dispatchEvent(forcedEvent);\n }, [searchValue, focusList]);\n\n return (\n <div className={styles.searchBar}>\n <TextInput\n aria-label=\"Search\"\n type=\"text\"\n value={searchValue}\n className={styles.inputField}\n testId=\"cf-multiselect-search\"\n placeholder={searchPlaceholder}\n onChange={handleSearchChange}\n ref={mergeRefs(searchInputRef, internalSearchInputRef)}\n name={searchInputName}\n size=\"small\"\n />\n <IconButton\n ref={resetSearchRef}\n aria-label={searchValue ? 'Clear search' : 'Search'}\n className={styles.toggleButton}\n variant=\"transparent\"\n icon={\n searchValue ? (\n <XIcon color={tokens.gray600} />\n ) : (\n <MagnifyingGlassIcon color={tokens.gray600} />\n )\n }\n onClick={resetSearchInput}\n isDisabled={!searchValue}\n size=\"small\"\n />\n </div>\n );\n};\n","import React from 'react';\nimport { MultiselectOption, MultiselectOptionProps } from './MultiselectOption';\nimport { getMultiselectStyles } from './Multiselect.styles';\nimport { cx } from 'emotion';\n\n/**\n * Labels for the select all option\n */\ntype SelectAllOptionLabel = {\n /**\n * Label for the select all option when it is checked\n * @default 'Deselect all'\n */\n checked: string;\n\n /**\n * Label for the select all option when it is unchecked\n * @default 'Select all'\n */\n unchecked: string;\n};\nexport interface SelectAllOptionProps\n extends Omit<\n MultiselectOptionProps,\n 'children' | 'value' | 'itemId' | 'label'\n > {\n label?: string;\n itemId?: string;\n selectAllOptionLabel?: SelectAllOptionLabel;\n}\n\nexport const SelectAllOption = ({\n label,\n itemId = 'SelectAll',\n onSelectItem,\n isChecked = false,\n selectAllOptionLabel = {\n checked: 'Deselect all',\n unchecked: 'Select all',\n },\n className,\n ...otherProps\n}: SelectAllOptionProps) => {\n const styles = getMultiselectStyles();\n const displayLabel =\n label || isChecked\n ? selectAllOptionLabel.checked\n : selectAllOptionLabel.unchecked;\n return (\n <MultiselectOption\n value=\"all\"\n label={displayLabel}\n itemId={itemId}\n onSelectItem={onSelectItem}\n isChecked={isChecked}\n className={cx(styles.selectAll, className)}\n {...otherProps}\n />\n );\n};\n","import { Multiselect as OriginalMultiSelect } from './Multiselect';\nimport { HighlightedItem, MultiselectOption } from './MultiselectOption';\nimport { SelectAllOption } from './SelectAllOption';\n\ntype CompoundMultiselect = typeof OriginalMultiSelect & {\n HighlightedItem: typeof HighlightedItem;\n Option: typeof MultiselectOption;\n SelectAll: typeof SelectAllOption;\n};\n\nexport const Multiselect = OriginalMultiSelect as CompoundMultiselect;\nMultiselect.HighlightedItem = HighlightedItem;\nMultiselect.Option = MultiselectOption;\nMultiselect.SelectAll = SelectAllOption;\n"]}
1
+ {"version":3,"sources":["../../src/MultiselectOption.tsx","../../src/Multiselect.styles.ts","../../src/MultiselectContext.tsx","../../src/MultiselectSearch.tsx","../../src/Multiselect.tsx","../../src/SelectAllOption.tsx","../../src/CompoundMultiselect.tsx"],"names":["getMultiselectStyles","css","tokens","listMaxHeight","isActive","isDisabled","cx","getMenuItemStyles","MultiselectContext","React","useMultiselectContext","context","MultiselectContextProvider","MultiselectOption","_a","_b","children","label","value","itemId","onSelectItem","isChecked","className","rest","__objRest","styles","focusList","searchValue","__spreadValues","Checkbox","event","Text","HighlightedItem","item","inputValue","before","match","after","getStringMatch","MultiselectSearch","setSearchValue","onSearchValueChange","searchInputName","searchInputRef","resetSearchRef","searchPlaceholder","internalSearchInputRef","useRef","handleSearchChange","useCallback","resetSearchInput","forcedEvent","TextInput","mergeRefs","IconButton","XIcon","MagnifyingGlassIcon","countMatchingChildren","filter","counter","child","el","MultiselectBase","props","ref","startIcon","placeholder","currentSelection","toggleRef","toggleButtonAriaLabel","isLoading","testId","noMatchesMessage","searchProps","popoverProps","onBlur","onClearSelection","clearButtonProps","listRef","onClose","useState","isOpen","setIsOpen","internalListRef","showClearButton","hasSearch","handleClearSelection","e","renderMultiselectLabel","leftoverCount","currentSelectionClassName","optionsLength","useMemo","contextValue","Popover","__spreadProps","Flex","Button","CaretDownIcon","FocusLock","ListItemLoadingState","Subheading","SkeletonContainer","SkeletonBodyText","Multiselect","SelectAllOption","selectAllOptionLabel","otherProps","displayLabel"],"mappings":"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","file":"index.js","sourcesContent":["import React from 'react';\nimport { Checkbox } from '@contentful/f36-forms';\nimport { Text } from '@contentful/f36-typography';\nimport { getMultiselectStyles } from './Multiselect.styles';\nimport { getStringMatch } from '@contentful/f36-utils';\nimport { cx } from '@emotion/css';\nimport { useMultiselectContext } from './MultiselectContext';\n\ntype LabelOrChildren =\n | {\n /**\n * When using React children it is your own responsibility to highlight\n * the matching part of the item label. Use the `HighlightedItem`\n * component for this.\n */\n children: React.ReactNode;\n label?: never;\n }\n | {\n children?: never;\n label: string;\n };\n\nexport type MultiselectOptionProps = {\n value: string;\n itemId: string;\n className?: string;\n onSelectItem: (event: React.ChangeEvent<HTMLInputElement>) => void;\n isChecked?: boolean;\n isDisabled?: boolean;\n} & LabelOrChildren;\n\nexport const MultiselectOption = ({\n children,\n label,\n value,\n itemId,\n onSelectItem,\n isChecked = false,\n isDisabled = false,\n className,\n ...rest\n}: MultiselectOptionProps) => {\n const styles = getMultiselectStyles();\n const { focusList, searchValue } = useMultiselectContext();\n\n return (\n <li className={cx(styles.option, className)} {...rest}>\n <Checkbox\n id={itemId}\n value={value}\n onChange={(event) => {\n focusList();\n onSelectItem(event);\n }}\n isChecked={isChecked}\n isDisabled={isDisabled}\n className={styles.optionCheck({ isActive: isChecked, isDisabled })}\n >\n <Text\n className={styles.optionText}\n data-test-id={`cf-multiselect-list-item-${itemId}`}\n >\n {typeof label === 'string' ? (\n <HighlightedItem item={label} inputValue={searchValue} />\n ) : (\n children\n )}\n </Text>\n </Checkbox>\n </li>\n );\n};\n\nexport function HighlightedItem({\n item,\n inputValue = '',\n}: {\n item: string;\n inputValue?: string;\n}) {\n const { before, match, after } = getStringMatch(item, inputValue.trim());\n\n if (before.length + match.length + after.length === 0) {\n return <>{item}</>;\n }\n\n return (\n <>\n {before}\n <span data-test-id=\"cf-multiselect-item-match\">{match}</span>\n {after}\n </>\n );\n}\n\nHighlightedItem.displayName = 'HighlightedItem';\n","import { css, cx } from '@emotion/css';\nimport tokens from '@contentful/f36-tokens';\nimport { getMenuItemStyles } from '@contentful/f36-core';\n\nexport const getMultiselectStyles = () => ({\n multiselect: css({\n position: 'relative',\n width: '100%',\n }),\n triggerButton: css({\n justifyContent: 'space-between',\n }),\n currentSelection: css({\n display: 'inline-block',\n width: '100%',\n whiteSpace: 'nowrap',\n textOverflow: 'ellipsis',\n overflow: 'hidden',\n verticalAlign: 'bottom',\n marginRight: tokens.spacing2Xs,\n }),\n currentSelectionWithClearButton: css({\n paddingRight: '40px',\n }),\n currentSelectionAddition: css({\n color: tokens.gray600,\n }),\n searchBar: css({\n paddingTop: tokens.spacing2Xs,\n position: 'sticky',\n top: '0px',\n zIndex: tokens.zIndexWorkbenchHeader,\n backgroundColor: tokens.colorWhite,\n }),\n inputField: css({\n padding: `6px ${tokens.spacingXl} 10px ${tokens.spacingXs}`,\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n border: 'none',\n borderRadius: '0px',\n borderBottom: `1px solid ${tokens.gray200}`,\n boxShadow: 'none',\n '&:focus, &:active, &:active:hover': {\n boxShadow: 'none',\n borderBottom: `1px solid ${tokens.gray200}`,\n },\n }),\n toggleButton: css({\n position: 'absolute',\n top: '1px',\n right: '1px',\n zIndex: tokens.zIndexDefault,\n padding: tokens.spacing2Xs,\n height: tokens.spacingXl,\n }),\n content: (listMaxHeight: number) =>\n css({\n overflow: 'auto',\n maxHeight: `${listMaxHeight}px`,\n }),\n container: css({}),\n list: css({\n listStyle: 'none',\n padding: `${tokens.spacing2Xs}`,\n margin: 0,\n }),\n groupTitle: css({\n // Magic number to get a height of 32px on the item\n padding: `6px ${tokens.spacingXs}`,\n lineHeight: tokens.lineHeightM,\n }),\n noMatchesTitle: css({\n color: tokens.gray500,\n margin: tokens.spacingM,\n textAlign: 'center',\n }),\n clearSelectionButton: css({\n marginLeft: '-80px',\n }),\n selectAll: css({\n borderBottom: `1px solid ${tokens.gray200}`,\n marginBottom: tokens.spacing2Xs,\n paddingBottom: tokens.spacing2Xs,\n 'label > *': {\n fontWeight: tokens.fontWeightMedium,\n },\n }),\n option: css({\n listStyleType: 'none',\n }),\n optionText: css({\n alignItems: 'center',\n display: 'flex',\n span: {\n color: tokens.gray900,\n fontWeight: tokens.fontWeightDemiBold,\n },\n }),\n optionCheck: ({\n isActive,\n isDisabled,\n }: {\n isActive?: boolean;\n isDisabled?: boolean;\n }) =>\n css({\n label: cx(\n getMenuItemStyles({ isActive, isDisabled }),\n css({\n width: '100%',\n }),\n ),\n }),\n});\n","import React from 'react';\n\nexport type MultiselectContextType = {\n focusList: () => void;\n searchValue: string;\n};\n\nconst MultiselectContext = React.createContext<\n MultiselectContextType | undefined\n>(undefined);\n\nexport const useMultiselectContext = () => {\n const context = React.useContext(MultiselectContext);\n\n if (context === undefined) {\n throw new Error('component must be rendered within a Accordion component');\n }\n\n return context;\n};\n\nexport const MultiselectContextProvider = MultiselectContext.Provider;\n","import React, { useCallback, useRef } from 'react';\nimport tokens from '@contentful/f36-tokens';\nimport { TextInput } from '@contentful/f36-forms';\nimport { XIcon, MagnifyingGlassIcon } from '@contentful/f36-icons';\nimport { IconButton } from '@contentful/f36-button';\nimport { getMultiselectStyles } from './Multiselect.styles';\nimport { mergeRefs } from '@contentful/f36-core';\n\nexport interface MultiselectSearchProps {\n /**\n * Function called whenever the search input value changes\n */\n onSearchValueChange?: (\n event: React.ChangeEvent<HTMLInputElement>,\n ) => void | undefined;\n\n /**\n * This is the value will be passed to the `placeholder` prop of the input.\n * @default \"Search\"\n */\n searchPlaceholder?: string;\n\n /**\n * Pass a form name to the search text input\n */\n searchInputName?: string;\n\n /**\n * Use this prop to get a ref to the search input element of the component\n */\n searchInputRef?: React.Ref<HTMLInputElement>;\n\n /**\n * Use this prop to get a ref to the reset search button of the component\n */\n resetSearchRef?: React.Ref<HTMLButtonElement>;\n\n /**\n * State from the parent component\n */\n searchValue?: string;\n\n /**\n * State setter of the parent\n */\n setSearchValue?: React.Dispatch<React.SetStateAction<string>>;\n\n /**\n * List helper function\n */\n focusList?: () => void;\n}\n\nexport const MultiselectSearch = ({\n searchValue,\n setSearchValue,\n onSearchValueChange,\n searchInputName,\n searchInputRef,\n resetSearchRef,\n searchPlaceholder = 'Search',\n focusList,\n}: MultiselectSearchProps) => {\n const styles = getMultiselectStyles();\n const internalSearchInputRef = useRef<HTMLInputElement>(null);\n\n const handleSearchChange = useCallback(\n (event) => {\n setSearchValue(event.target.value);\n onSearchValueChange?.(event);\n },\n [onSearchValueChange, setSearchValue],\n );\n\n const resetSearchInput = useCallback(() => {\n if (!searchValue) return;\n focusList();\n // this looks a bit hacky, but is the official way of externally triggering the onChange handler for an input\n // https://stackoverflow.com/a/46012210/17269164\n const nativeInputValueSetter = Object.getOwnPropertyDescriptor(\n window.HTMLInputElement.prototype,\n 'value',\n ).set;\n nativeInputValueSetter.call(internalSearchInputRef.current, '');\n const forcedEvent = new Event('change', { bubbles: true });\n internalSearchInputRef.current.dispatchEvent(forcedEvent);\n }, [searchValue, focusList]);\n\n return (\n <div className={styles.searchBar}>\n <TextInput\n aria-label=\"Search\"\n type=\"text\"\n value={searchValue}\n className={styles.inputField}\n testId=\"cf-multiselect-search\"\n placeholder={searchPlaceholder}\n onChange={handleSearchChange}\n ref={mergeRefs(searchInputRef, internalSearchInputRef)}\n name={searchInputName}\n size=\"small\"\n />\n <IconButton\n ref={resetSearchRef}\n aria-label={searchValue ? 'Clear search' : 'Search'}\n className={styles.toggleButton}\n variant=\"transparent\"\n icon={\n searchValue ? (\n <XIcon color={tokens.gray600} />\n ) : (\n <MagnifyingGlassIcon color={tokens.gray600} />\n )\n }\n onClick={resetSearchInput}\n isDisabled={!searchValue}\n size=\"small\"\n />\n </div>\n );\n};\n","import React, { useRef, useState, useCallback, useMemo } from 'react';\nimport { cx } from '@emotion/css';\n\nimport { mergeRefs, type CommonProps, Flex } from '@contentful/f36-core';\nimport { Button, IconButton, type ButtonProps } from '@contentful/f36-button';\nimport { CaretDownIcon, XIcon } from '@contentful/f36-icons';\n\nimport { SkeletonContainer, SkeletonBodyText } from '@contentful/f36-skeleton';\nimport { Popover, type PopoverProps } from '@contentful/f36-popover';\nimport { Subheading } from '@contentful/f36-typography';\n\nimport { getMultiselectStyles } from './Multiselect.styles';\nimport { MultiselectOption } from './MultiselectOption';\nimport FocusLock from 'react-focus-lock';\n\nimport type { MultiselectSearchProps as SearchProps } from './MultiselectSearch';\nimport { MultiselectSearch } from './MultiselectSearch';\nimport {\n MultiselectContextProvider,\n MultiselectContextType,\n} from './MultiselectContext';\n\ntype ClearButtonProps = {\n /**\n * Aria label for the clear button\n * @default 'Clear selection'\n */\n ariaLabel?: string;\n\n /**\n * Tooltip for the clear button\n * @default 'Clear selection'\n */\n tooltip?: string;\n};\n\nexport interface MultiselectProps extends CommonProps {\n /** Select Options */\n children?: React.ReactNode;\n\n /**\n * Set a custom icon for the text input\n */\n startIcon?: React.ReactElement;\n\n /**\n * Placeholder shown before selecting any elements. Defaults to 'Select one or more items'\n */\n placeholder?: string;\n\n /**\n * current Selected items, to be shown on the trigger button\n */\n currentSelection?: Array<string>;\n\n /**\n * Sets the list to show its loading state\n * @default false\n */\n isLoading?: boolean;\n\n /**\n * Use this prop to get a ref to the toggle button of the component\n */\n toggleRef?: React.Ref<HTMLButtonElement>;\n\n /**\n * Aria label for the toggle button that opens the list\n * @default 'Toggle Multiselect'\n */\n toggleButtonAriaLabel?: string;\n\n /**\n * Props to pass to the optional search field\n */\n searchProps?: SearchProps;\n\n /**\n * Props to pass to the trigger button\n */\n triggerButtonProps?: ButtonProps;\n\n /**\n * A message that will be shown when it is not possible to find any option that matches the search value\n * @default \"No matches\"\n */\n noMatchesMessage?: string;\n\n /**\n * Props to pass to the Popover (Dropdown) component\n */\n popoverProps?: Partial<PopoverProps> & {\n /**\n * It sets the max-height, in pixels, of the list\n * The default value is the height of 5 single line items\n * @default 180\n */\n listMaxHeight?: number;\n\n /**\n * Use this prop to get a ref to the list of items of the component\n */\n listRef?: React.Ref<HTMLUListElement>;\n } & Pick<CommonProps, 'className'>;\n\n /**\n * Function called when the popover loses its focus.\n */\n onBlur?: () => void;\n\n /**\n * Function called when the clear all button is clicked\n * If no function is provided the clear button is not shown\n */\n onClearSelection?: () => void;\n\n /**\n * Clear Button Props used for localization\n * @default { ariaLabel: 'Clear selection', tooltip: 'Clear selection' }\n */\n clearButtonProps?: ClearButtonProps;\n}\n\n// Scan through the whole hierachy to count the number of children where `filter` returns true\nconst countMatchingChildren = (\n children: React.ReactNode,\n filter: (child: React.ReactElement) => boolean,\n): number => {\n let counter = 0;\n React.Children.forEach(children, (child) => {\n if (!React.isValidElement(child)) return;\n // Narrow props to include optional children for recursive descent\n const el = child as React.ReactElement<{ children?: React.ReactNode }>;\n if (!filter(el)) {\n counter += countMatchingChildren(el.props.children, filter);\n } else {\n counter += 1;\n }\n });\n return counter;\n};\n\nfunction MultiselectBase(\n props: MultiselectProps,\n ref: React.Ref<HTMLDivElement>,\n) {\n const {\n className,\n startIcon,\n placeholder = 'Select one or more Items',\n currentSelection = [],\n toggleRef,\n toggleButtonAriaLabel = 'Toggle Multiselect',\n isLoading = false,\n testId = 'cf-multiselect',\n noMatchesMessage = 'No matches found',\n searchProps = {},\n popoverProps = {},\n children,\n onBlur,\n onClearSelection,\n clearButtonProps = {\n tooltip: 'Clear selection',\n ariaLabel: 'Clear selection',\n },\n } = props;\n\n const { listMaxHeight = 180, listRef, onClose } = popoverProps;\n\n const styles = getMultiselectStyles();\n\n const [searchValue, setSearchValue] = useState('');\n const [isOpen, setIsOpen] = useState(false);\n\n const internalListRef = useRef<HTMLUListElement>(null);\n\n const showClearButton =\n currentSelection.length > 1 && typeof onClearSelection === 'function';\n\n const hasSearch = typeof searchProps.onSearchValueChange === 'function';\n\n const focusList = useCallback(() => {\n // Clearing the search input or selecting an item triggers a rerendering and\n // thereby the client loses the focus on the clicked element. To avoid having\n // the focus on the document body (which breaks `closeOnBlur`), we force it\n // back to the list in the popup.\n internalListRef.current?.focus();\n }, []);\n\n const handleClearSelection = (e: React.MouseEvent<HTMLButtonElement>) => {\n onClearSelection?.();\n e.stopPropagation();\n };\n\n const renderMultiselectLabel = useCallback(() => {\n if (currentSelection.length === 0) {\n return <>{placeholder}</>;\n }\n const leftoverCount = currentSelection.length - 1;\n const currentSelectionClassName = cx(\n styles.currentSelection,\n showClearButton && styles.currentSelectionWithClearButton,\n );\n if (leftoverCount === 0) {\n return (\n <span\n data-test-id=\"cf-multiselect-current-selection\"\n className={currentSelectionClassName}\n >\n {currentSelection[0]}\n </span>\n );\n }\n return (\n <span\n data-test-id=\"cf-multiselect-current-selection\"\n className={currentSelectionClassName}\n >\n {currentSelection[0]}{' '}\n <span className={styles.currentSelectionAddition}>\n and {leftoverCount} more\n </span>\n </span>\n );\n }, [\n currentSelection,\n placeholder,\n showClearButton,\n styles.currentSelection,\n styles.currentSelectionAddition,\n styles.currentSelectionWithClearButton,\n ]);\n\n const optionsLength = useMemo(\n () =>\n countMatchingChildren(\n children,\n (child) => child.type === MultiselectOption,\n ),\n [children],\n );\n\n const contextValue: MultiselectContextType = useMemo(\n () => ({\n focusList,\n searchValue,\n }),\n [focusList, searchValue],\n );\n\n return (\n <MultiselectContextProvider value={contextValue}>\n <div\n data-test-id={testId}\n className={cx(styles.multiselect, className)}\n ref={ref}\n >\n <Popover\n renderOnlyWhenOpen={false}\n isFullWidth\n {...popoverProps}\n // popoverProps should never overwrite the internal opening logic\n isOpen={isOpen}\n onClose={() => {\n setIsOpen(false);\n if (onClose) {\n onClose();\n }\n }}\n >\n <Flex alignItems=\"center\">\n <Popover.Trigger ref={toggleRef}>\n <Button\n aria-label={toggleButtonAriaLabel}\n onClick={() => setIsOpen(!isOpen)}\n startIcon={startIcon}\n endIcon={<CaretDownIcon />}\n isFullWidth\n className={styles.triggerButton}\n {...props.triggerButtonProps}\n >\n {renderMultiselectLabel()}\n </Button>\n </Popover.Trigger>\n {showClearButton && (\n <div className={styles.clearSelectionButton}>\n <IconButton\n onClick={handleClearSelection}\n icon={<XIcon />}\n aria-label={\n clearButtonProps.ariaLabel\n ? clearButtonProps.ariaLabel\n : 'Clear selection'\n }\n size=\"small\"\n withTooltip\n tooltipProps={{\n content: clearButtonProps.tooltip\n ? clearButtonProps.tooltip\n : 'Clear selection',\n\n showDelay: 800,\n placement: 'top',\n as: 'div',\n }}\n />\n </div>\n )}\n </Flex>\n <Popover.Content\n ref={mergeRefs(listRef, internalListRef)}\n className={cx(\n styles.content(listMaxHeight),\n popoverProps.className,\n styles.container,\n )}\n testId=\"cf-multiselect-container\"\n onBlur={() => onBlur?.()}\n >\n <FocusLock\n focusOptions={{ preventScroll: true }}\n returnFocus={true}\n >\n {hasSearch && (\n <MultiselectSearch\n {...searchProps}\n setSearchValue={setSearchValue}\n searchValue={searchValue}\n focusList={focusList}\n />\n )}\n {isLoading && <ListItemLoadingState />}\n\n {!isLoading && optionsLength > 0 && (\n <ul className={styles.list} data-test-id=\"cf-multiselect-items\">\n {children}\n </ul>\n )}\n\n {!isLoading && optionsLength === 0 && (\n <Subheading className={styles.noMatchesTitle}>\n {noMatchesMessage}\n </Subheading>\n )}\n </FocusLock>\n </Popover.Content>\n </Popover>\n </div>\n </MultiselectContextProvider>\n );\n}\n\nconst ListItemLoadingState = () => {\n return (\n <SkeletonContainer svgHeight={16}>\n <SkeletonBodyText numberOfLines={1} />\n </SkeletonContainer>\n );\n};\n\nMultiselectBase.displayName = 'Multiselect';\nexport const Multiselect = React.forwardRef(MultiselectBase);\n","import React from 'react';\nimport { MultiselectOption, MultiselectOptionProps } from './MultiselectOption';\nimport { getMultiselectStyles } from './Multiselect.styles';\nimport { cx } from '@emotion/css';\n\n/**\n * Labels for the select all option\n */\ntype SelectAllOptionLabel = {\n /**\n * Label for the select all option when it is checked\n * @default 'Deselect all'\n */\n checked: string;\n\n /**\n * Label for the select all option when it is unchecked\n * @default 'Select all'\n */\n unchecked: string;\n};\nexport interface SelectAllOptionProps\n extends Omit<\n MultiselectOptionProps,\n 'children' | 'value' | 'itemId' | 'label'\n > {\n label?: string;\n itemId?: string;\n selectAllOptionLabel?: SelectAllOptionLabel;\n}\n\nexport const SelectAllOption = ({\n label,\n itemId = 'SelectAll',\n onSelectItem,\n isChecked = false,\n selectAllOptionLabel = {\n checked: 'Deselect all',\n unchecked: 'Select all',\n },\n className,\n ...otherProps\n}: SelectAllOptionProps) => {\n const styles = getMultiselectStyles();\n const displayLabel =\n label || isChecked\n ? selectAllOptionLabel.checked\n : selectAllOptionLabel.unchecked;\n return (\n <MultiselectOption\n value=\"all\"\n label={displayLabel}\n itemId={itemId}\n onSelectItem={onSelectItem}\n isChecked={isChecked}\n className={cx(styles.selectAll, className)}\n {...otherProps}\n />\n );\n};\n","import { Multiselect as OriginalMultiSelect } from './Multiselect';\nimport { HighlightedItem, MultiselectOption } from './MultiselectOption';\nimport { SelectAllOption } from './SelectAllOption';\n\ntype CompoundMultiselect = typeof OriginalMultiSelect & {\n HighlightedItem: typeof HighlightedItem;\n Option: typeof MultiselectOption;\n SelectAll: typeof SelectAllOption;\n};\n\nexport const Multiselect = OriginalMultiSelect as CompoundMultiselect;\nMultiselect.HighlightedItem = HighlightedItem;\nMultiselect.Option = MultiselectOption;\nMultiselect.SelectAll = SelectAllOption;\n"]}
package/dist/index.d.mts CHANGED
@@ -3,7 +3,7 @@ import { CommonProps } from '@contentful/f36-core';
3
3
  import { ButtonProps } from '@contentful/f36-button';
4
4
  import { PopoverProps } from '@contentful/f36-popover';
5
5
 
6
- declare type LabelOrChildren = {
6
+ type LabelOrChildren = {
7
7
  /**
8
8
  * When using React children it is your own responsibility to highlight
9
9
  * the matching part of the item label. Use the `HighlightedItem`
@@ -15,20 +15,19 @@ declare type LabelOrChildren = {
15
15
  children?: never;
16
16
  label: string;
17
17
  };
18
- declare type MultiselectOptionProps = {
18
+ type MultiselectOptionProps = {
19
19
  value: string;
20
20
  itemId: string;
21
- searchValue?: string;
22
21
  className?: string;
23
22
  onSelectItem: (event: React.ChangeEvent<HTMLInputElement>) => void;
24
23
  isChecked?: boolean;
25
24
  isDisabled?: boolean;
26
25
  } & LabelOrChildren;
27
- declare const MultiselectOption: ({ children, label, value, itemId, onSelectItem, searchValue, isChecked, isDisabled, className, ...rest }: MultiselectOptionProps) => JSX.Element;
26
+ declare const MultiselectOption: ({ children, label, value, itemId, onSelectItem, isChecked, isDisabled, className, ...rest }: MultiselectOptionProps) => React.JSX.Element;
28
27
  declare function HighlightedItem({ item, inputValue, }: {
29
28
  item: string;
30
29
  inputValue?: string;
31
- }): JSX.Element;
30
+ }): React.JSX.Element;
32
31
  declare namespace HighlightedItem {
33
32
  var displayName: string;
34
33
  }
@@ -69,7 +68,7 @@ interface MultiselectSearchProps {
69
68
  focusList?: () => void;
70
69
  }
71
70
 
72
- declare type ClearButtonProps = {
71
+ type ClearButtonProps = {
73
72
  /**
74
73
  * Aria label for the clear button
75
74
  * @default 'Clear selection'
@@ -153,16 +152,12 @@ interface MultiselectProps extends CommonProps {
153
152
  */
154
153
  clearButtonProps?: ClearButtonProps;
155
154
  }
156
- /**
157
- * The Multiselect is a component that will allow a user to select multiple items.
158
- * It has an optional
159
- */
160
155
  declare const Multiselect$1: React.ForwardRefExoticComponent<MultiselectProps & React.RefAttributes<HTMLDivElement>>;
161
156
 
162
157
  /**
163
158
  * Labels for the select all option
164
159
  */
165
- declare type SelectAllOptionLabel = {
160
+ type SelectAllOptionLabel = {
166
161
  /**
167
162
  * Label for the select all option when it is checked
168
163
  * @default 'Deselect all'
@@ -179,13 +174,13 @@ interface SelectAllOptionProps extends Omit<MultiselectOptionProps, 'children' |
179
174
  itemId?: string;
180
175
  selectAllOptionLabel?: SelectAllOptionLabel;
181
176
  }
182
- declare const SelectAllOption: ({ label, itemId, onSelectItem, isChecked, selectAllOptionLabel, className, ...otherProps }: SelectAllOptionProps) => JSX.Element;
177
+ declare const SelectAllOption: ({ label, itemId, onSelectItem, isChecked, selectAllOptionLabel, className, ...otherProps }: SelectAllOptionProps) => React.JSX.Element;
183
178
 
184
- declare type CompoundMultiselect = typeof Multiselect$1 & {
179
+ type CompoundMultiselect = typeof Multiselect$1 & {
185
180
  HighlightedItem: typeof HighlightedItem;
186
181
  Option: typeof MultiselectOption;
187
182
  SelectAll: typeof SelectAllOption;
188
183
  };
189
184
  declare const Multiselect: CompoundMultiselect;
190
185
 
191
- export { Multiselect, MultiselectOption, MultiselectOptionProps, MultiselectProps, SelectAllOption, SelectAllOptionProps };
186
+ export { Multiselect, MultiselectOption, type MultiselectOptionProps, type MultiselectProps, SelectAllOption, type SelectAllOptionProps };
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ import { CommonProps } from '@contentful/f36-core';
3
3
  import { ButtonProps } from '@contentful/f36-button';
4
4
  import { PopoverProps } from '@contentful/f36-popover';
5
5
 
6
- declare type LabelOrChildren = {
6
+ type LabelOrChildren = {
7
7
  /**
8
8
  * When using React children it is your own responsibility to highlight
9
9
  * the matching part of the item label. Use the `HighlightedItem`
@@ -15,20 +15,19 @@ declare type LabelOrChildren = {
15
15
  children?: never;
16
16
  label: string;
17
17
  };
18
- declare type MultiselectOptionProps = {
18
+ type MultiselectOptionProps = {
19
19
  value: string;
20
20
  itemId: string;
21
- searchValue?: string;
22
21
  className?: string;
23
22
  onSelectItem: (event: React.ChangeEvent<HTMLInputElement>) => void;
24
23
  isChecked?: boolean;
25
24
  isDisabled?: boolean;
26
25
  } & LabelOrChildren;
27
- declare const MultiselectOption: ({ children, label, value, itemId, onSelectItem, searchValue, isChecked, isDisabled, className, ...rest }: MultiselectOptionProps) => JSX.Element;
26
+ declare const MultiselectOption: ({ children, label, value, itemId, onSelectItem, isChecked, isDisabled, className, ...rest }: MultiselectOptionProps) => React.JSX.Element;
28
27
  declare function HighlightedItem({ item, inputValue, }: {
29
28
  item: string;
30
29
  inputValue?: string;
31
- }): JSX.Element;
30
+ }): React.JSX.Element;
32
31
  declare namespace HighlightedItem {
33
32
  var displayName: string;
34
33
  }
@@ -69,7 +68,7 @@ interface MultiselectSearchProps {
69
68
  focusList?: () => void;
70
69
  }
71
70
 
72
- declare type ClearButtonProps = {
71
+ type ClearButtonProps = {
73
72
  /**
74
73
  * Aria label for the clear button
75
74
  * @default 'Clear selection'
@@ -153,16 +152,12 @@ interface MultiselectProps extends CommonProps {
153
152
  */
154
153
  clearButtonProps?: ClearButtonProps;
155
154
  }
156
- /**
157
- * The Multiselect is a component that will allow a user to select multiple items.
158
- * It has an optional
159
- */
160
155
  declare const Multiselect$1: React.ForwardRefExoticComponent<MultiselectProps & React.RefAttributes<HTMLDivElement>>;
161
156
 
162
157
  /**
163
158
  * Labels for the select all option
164
159
  */
165
- declare type SelectAllOptionLabel = {
160
+ type SelectAllOptionLabel = {
166
161
  /**
167
162
  * Label for the select all option when it is checked
168
163
  * @default 'Deselect all'
@@ -179,13 +174,13 @@ interface SelectAllOptionProps extends Omit<MultiselectOptionProps, 'children' |
179
174
  itemId?: string;
180
175
  selectAllOptionLabel?: SelectAllOptionLabel;
181
176
  }
182
- declare const SelectAllOption: ({ label, itemId, onSelectItem, isChecked, selectAllOptionLabel, className, ...otherProps }: SelectAllOptionProps) => JSX.Element;
177
+ declare const SelectAllOption: ({ label, itemId, onSelectItem, isChecked, selectAllOptionLabel, className, ...otherProps }: SelectAllOptionProps) => React.JSX.Element;
183
178
 
184
- declare type CompoundMultiselect = typeof Multiselect$1 & {
179
+ type CompoundMultiselect = typeof Multiselect$1 & {
185
180
  HighlightedItem: typeof HighlightedItem;
186
181
  Option: typeof MultiselectOption;
187
182
  SelectAll: typeof SelectAllOption;
188
183
  };
189
184
  declare const Multiselect: CompoundMultiselect;
190
185
 
191
- export { Multiselect, MultiselectOption, MultiselectOptionProps, MultiselectProps, SelectAllOption, SelectAllOptionProps };
186
+ export { Multiselect, MultiselectOption, type MultiselectOptionProps, type MultiselectProps, SelectAllOption, type SelectAllOptionProps };
package/dist/index.js CHANGED
@@ -1,29 +1,2 @@
1
- 'use strict';
2
-
3
- var l = require('react');
4
- var f36Forms = require('@contentful/f36-forms');
5
- var f36Typography = require('@contentful/f36-typography');
6
- var emotion = require('emotion');
7
- var r = require('@contentful/f36-tokens');
8
- var f36Core = require('@contentful/f36-core');
9
- var f36Utils = require('@contentful/f36-utils');
10
- var f36Button = require('@contentful/f36-button');
11
- var f36Icons = require('@contentful/f36-icons');
12
- var f36Skeleton = require('@contentful/f36-skeleton');
13
- var f36Popover = require('@contentful/f36-popover');
14
- var f36Tooltip = require('@contentful/f36-tooltip');
15
- var Xe = require('react-focus-lock');
16
-
17
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
18
-
19
- var l__default = /*#__PURE__*/_interopDefault(l);
20
- var r__default = /*#__PURE__*/_interopDefault(r);
21
- var Xe__default = /*#__PURE__*/_interopDefault(Xe);
22
-
23
- var me=Object.defineProperty,ue=Object.defineProperties;var ge=Object.getOwnPropertyDescriptors;var L=Object.getOwnPropertySymbols;var _=Object.prototype.hasOwnProperty,q=Object.prototype.propertyIsEnumerable;var G=(e,t,o)=>t in e?me(e,t,{enumerable:!0,configurable:!0,writable:!0,value:o}):e[t]=o,M=(e,t)=>{for(var o in t||(t={}))_.call(t,o)&&G(e,o,t[o]);if(L)for(var o of L(t))q.call(t,o)&&G(e,o,t[o]);return e},w=(e,t)=>ue(e,ge(t));var B=(e,t)=>{var o={};for(var n in e)_.call(e,n)&&t.indexOf(n)<0&&(o[n]=e[n]);if(e!=null&&L)for(var n of L(e))t.indexOf(n)<0&&q.call(e,n)&&(o[n]=e[n]);return o};var b=()=>({multiselect:emotion.css({position:"relative",width:"100%"}),triggerButton:emotion.css({justifyContent:"space-between"}),currentSelection:emotion.css({display:"inline-block",width:"100%",whiteSpace:"nowrap",textOverflow:"ellipsis",overflow:"hidden",verticalAlign:"bottom",marginRight:r__default.default.spacing2Xs}),currentSelectionWithClearButton:emotion.css({paddingRight:"40px"}),currentSelectionAddition:emotion.css({color:r__default.default.gray600}),searchBar:emotion.css({paddingTop:r__default.default.spacing2Xs,position:"sticky",top:"0px",zIndex:r__default.default.zIndexWorkbenchHeader,backgroundColor:r__default.default.colorWhite}),inputField:emotion.css({padding:`6px ${r__default.default.spacingXl} 10px ${r__default.default.spacingXs}`,textOverflow:"ellipsis",whiteSpace:"nowrap",border:"none",borderRadius:"0px",borderBottom:`1px solid ${r__default.default.gray200}`,boxShadow:"none","&:focus, &:active, &:active:hover":{boxShadow:"none",borderBottom:`1px solid ${r__default.default.gray200}`}}),toggleButton:emotion.css({position:"absolute",top:"1px",right:"1px",zIndex:r__default.default.zIndexDefault,padding:r__default.default.spacing2Xs,height:r__default.default.spacingXl}),content:e=>emotion.css({overflow:"auto",maxHeight:`${e}px`}),container:emotion.css({}),list:emotion.css({listStyle:"none",padding:`${r__default.default.spacing2Xs}`,margin:0}),groupTitle:emotion.css({padding:`6px ${r__default.default.spacingXs}`,lineHeight:r__default.default.lineHeightM}),noMatchesTitle:emotion.css({color:r__default.default.gray500,margin:r__default.default.spacingM,textAlign:"center"}),clearSelectionButton:emotion.css({marginLeft:"-80px"}),selectAll:emotion.css({borderBottom:`1px solid ${r__default.default.gray200}`,marginBottom:r__default.default.spacing2Xs,paddingBottom:r__default.default.spacing2Xs,"label > *":{fontWeight:r__default.default.fontWeightMedium}}),option:emotion.css({listStyleType:"none"}),optionText:emotion.css({alignItems:"center",display:"flex",span:{color:r__default.default.gray900,fontWeight:r__default.default.fontWeightDemiBold}}),optionCheck:({isActive:e,isDisabled:t})=>emotion.css({label:emotion.cx(f36Core.getMenuItemStyles({isActive:e,isDisabled:t}),emotion.css({width:"100%"}))})});var v=C=>{var x=C,{children:e,label:t,value:o,itemId:n,onSelectItem:s,searchValue:a,isChecked:f=!1,isDisabled:h=!1,className:p}=x,g=B(x,["children","label","value","itemId","onSelectItem","searchValue","isChecked","isDisabled","className"]);let m=b();return l__default.default.createElement("li",M({className:emotion.cx(m.option,p)},g),l__default.default.createElement(f36Forms.Checkbox,{id:n,value:o,onChange:S=>s(S),isChecked:f,isDisabled:h,className:m.optionCheck({isActive:f,isDisabled:h})},l__default.default.createElement(f36Typography.Text,{className:m.optionText,"data-test-id":`cf-multiselect-list-item-${n}`},typeof t=="string"?l__default.default.createElement(N,{item:t,inputValue:a}):e)))};function N({item:e,inputValue:t=""}){let{before:o,match:n,after:s}=f36Utils.getStringMatch(e,t.trim());return o.length+n.length+s.length===0?l__default.default.createElement(l__default.default.Fragment,null,e):l__default.default.createElement(l__default.default.Fragment,null,o,l__default.default.createElement("span",{"data-test-id":"cf-multiselect-item-match"},n),s)}N.displayName="HighlightedItem";var Q=({searchValue:e,setSearchValue:t,onSearchValueChange:o,searchInputName:n,searchInputRef:s,resetSearchRef:a,searchPlaceholder:f="Search",focusList:h})=>{let p=b(),g=l.useRef(null),C=l.useCallback(m=>{t(m.target.value),o==null||o(m);},[o,t]),x=l.useCallback(()=>{if(!e)return;h(),Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype,"value").set.call(g.current,"");let S=new Event("change",{bubbles:!0});g.current.dispatchEvent(S);},[e,h]);return l__default.default.createElement("div",{className:p.searchBar},l__default.default.createElement(f36Forms.TextInput,{"aria-label":"Search",type:"text",value:e,className:p.inputField,testId:"cf-multiselect-search",placeholder:f,onChange:C,ref:f36Core.mergeRefs(s,g),name:n,size:"small"}),l__default.default.createElement(f36Button.IconButton,{ref:a,"aria-label":e?"Clear search":"Search",className:p.toggleButton,variant:"transparent",icon:e?l__default.default.createElement(f36Icons.XIcon,{color:r__default.default.gray600}):l__default.default.createElement(f36Icons.MagnifyingGlassIcon,{color:r__default.default.gray600}),onClick:x,isDisabled:!e,size:"small"}))};var ee=(e,t,o)=>l__default.default.Children.map(e,n=>{if(!l__default.default.isValidElement(n))return n;if(t(n))return o(n);let s=ee(n.props.children,t,o);return l__default.default.cloneElement(n,{children:s})}),te=(e,t)=>{let o=0;return l__default.default.Children.forEach(e,n=>{l__default.default.isValidElement(n)&&(t(n)?o+=1:o+=te(n.props.children,t));}),o};function De(e,t){let{className:o,startIcon:n,placeholder:s="Select one or more Items",currentSelection:a=[],toggleRef:f,toggleButtonAriaLabel:h="Toggle Multiselect",isLoading:p=!1,testId:g="cf-multiselect",noMatchesMessage:C="No matches found",searchProps:x={},popoverProps:m={},children:S,onBlur:E,onClearSelection:P,clearButtonProps:O={tooltip:"Clear selection",ariaLabel:"Clear selection"}}=e,{listMaxHeight:ne=180,listRef:le,onClose:D}=m,c=b(),[T,re]=l.useState(""),[F,$]=l.useState(!1),z=l.useRef(null),A=a.length>1&&typeof P=="function",V=typeof x.onSearchValueChange=="function",H=l.useCallback(()=>{var u;(u=z.current)==null||u.focus();},[]),ie=u=>{P==null||P(),u.stopPropagation();},se=l.useCallback(()=>{if(a.length===0)return l__default.default.createElement(l__default.default.Fragment,null,s);let u=a.length-1,y=emotion.cx(c.currentSelection,A&&c.currentSelectionWithClearButton);return u===0?l__default.default.createElement("span",{"data-test-id":"cf-multiselect-current-selection",className:y},a[0]):l__default.default.createElement("span",{"data-test-id":"cf-multiselect-current-selection",className:y},a[0]," ",l__default.default.createElement("span",{className:c.currentSelectionAddition},"and ",u," more"))},[a,s,A,c.currentSelection,c.currentSelectionAddition,c.currentSelectionWithClearButton]),j=l.useMemo(()=>te(S,u=>u.type===v),[S]),ce=l__default.default.useCallback(u=>ee(u,y=>y.type===v,y=>{let ae=pe=>{var U;H(),(U=y.props)==null||U.onSelectItem(pe);};return l__default.default.cloneElement(y,{searchValue:T,onSelectItem:ae})}),[T,H]);return l__default.default.createElement("div",{"data-test-id":g,className:emotion.cx(c.multiselect,o),ref:t},l__default.default.createElement(f36Popover.Popover,w(M({renderOnlyWhenOpen:!1,isFullWidth:!0},m),{isOpen:F,onClose:()=>{$(!1),D&&D();}}),l__default.default.createElement(f36Core.Flex,{alignItems:"center"},l__default.default.createElement(f36Popover.Popover.Trigger,null,l__default.default.createElement(f36Button.Button,M({"aria-label":h,ref:f,onClick:()=>$(!F),startIcon:n,endIcon:l__default.default.createElement(f36Icons.CaretDownIcon,null),isFullWidth:!0,className:c.triggerButton},e.triggerButtonProps),se())),A&&l__default.default.createElement("div",{className:c.clearSelectionButton},l__default.default.createElement(f36Tooltip.Tooltip,{content:O.tooltip?O.tooltip:"Clear selection",showDelay:800,placement:"top",as:"div"},l__default.default.createElement(f36Button.IconButton,{onClick:ie,icon:l__default.default.createElement(f36Icons.XIcon,null),"aria-label":O.ariaLabel?O.ariaLabel:"Clear selection",size:"small"})))),l__default.default.createElement(f36Popover.Popover.Content,{ref:f36Core.mergeRefs(le,z),className:emotion.cx(c.content(ne),m.className,c.container),testId:"cf-multiselect-container",onBlur:()=>E==null?void 0:E()},l__default.default.createElement(Xe__default.default,{focusOptions:{preventScroll:!0},returnFocus:!0},V&&l__default.default.createElement(Q,w(M({},x),{setSearchValue:re,searchValue:T,focusList:H})),p&&l__default.default.createElement(Fe,null),!p&&j>0&&l__default.default.createElement("ul",{className:c.list,"data-test-id":"cf-multiselect-items"},V?ce(S):S),!p&&j===0&&l__default.default.createElement(f36Typography.Subheading,{className:c.noMatchesTitle},C)))))}var Fe=()=>l__default.default.createElement(f36Skeleton.SkeletonContainer,{svgHeight:16},l__default.default.createElement(f36Skeleton.SkeletonBodyText,{numberOfLines:1})),oe=l__default.default.forwardRef(De);var X=h=>{var p=h,{label:e,itemId:t="SelectAll",onSelectItem:o,isChecked:n=!1,selectAllOptionLabel:s={checked:"Deselect all",unchecked:"Select all"},className:a}=p,f=B(p,["label","itemId","onSelectItem","isChecked","selectAllOptionLabel","className"]);let g=b(),C=e||n?s.checked:s.unchecked;return l__default.default.createElement(v,M({value:"all",label:C,itemId:t,onSelectItem:o,isChecked:n,className:emotion.cx(g.selectAll,a)},f))};var k=oe;k.HighlightedItem=N;k.Option=v;k.SelectAll=X;
24
-
25
- exports.Multiselect = k;
26
- exports.MultiselectOption = v;
27
- exports.SelectAllOption = X;
28
- //# sourceMappingURL=out.js.map
1
+ 'use strict';var n=require('react'),f36Forms=require('@contentful/f36-forms'),f36Typography=require('@contentful/f36-typography'),css=require('@emotion/css'),i=require('@contentful/f36-tokens'),f36Core=require('@contentful/f36-core'),f36Utils=require('@contentful/f36-utils'),f36Button=require('@contentful/f36-button'),f36Icons=require('@contentful/f36-icons'),f36Skeleton=require('@contentful/f36-skeleton'),f36Popover=require('@contentful/f36-popover'),Xe=require('react-focus-lock');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var n__default=/*#__PURE__*/_interopDefault(n);var i__default=/*#__PURE__*/_interopDefault(i);var Xe__default=/*#__PURE__*/_interopDefault(Xe);var de=Object.defineProperty,ge=Object.defineProperties;var fe=Object.getOwnPropertyDescriptors;var L=Object.getOwnPropertySymbols;var U=Object.prototype.hasOwnProperty,G=Object.prototype.propertyIsEnumerable;var j=(e,t,o)=>t in e?de(e,t,{enumerable:true,configurable:true,writable:true,value:o}):e[t]=o,M=(e,t)=>{for(var o in t||(t={}))U.call(t,o)&&j(e,o,t[o]);if(L)for(var o of L(t))G.call(t,o)&&j(e,o,t[o]);return e},H=(e,t)=>ge(e,fe(t));var B=(e,t)=>{var o={};for(var l in e)U.call(e,l)&&t.indexOf(l)<0&&(o[l]=e[l]);if(e!=null&&L)for(var l of L(e))t.indexOf(l)<0&&G.call(e,l)&&(o[l]=e[l]);return o};var S=()=>({multiselect:css.css({position:"relative",width:"100%"}),triggerButton:css.css({justifyContent:"space-between"}),currentSelection:css.css({display:"inline-block",width:"100%",whiteSpace:"nowrap",textOverflow:"ellipsis",overflow:"hidden",verticalAlign:"bottom",marginRight:i__default.default.spacing2Xs}),currentSelectionWithClearButton:css.css({paddingRight:"40px"}),currentSelectionAddition:css.css({color:i__default.default.gray600}),searchBar:css.css({paddingTop:i__default.default.spacing2Xs,position:"sticky",top:"0px",zIndex:i__default.default.zIndexWorkbenchHeader,backgroundColor:i__default.default.colorWhite}),inputField:css.css({padding:`6px ${i__default.default.spacingXl} 10px ${i__default.default.spacingXs}`,textOverflow:"ellipsis",whiteSpace:"nowrap",border:"none",borderRadius:"0px",borderBottom:`1px solid ${i__default.default.gray200}`,boxShadow:"none","&:focus, &:active, &:active:hover":{boxShadow:"none",borderBottom:`1px solid ${i__default.default.gray200}`}}),toggleButton:css.css({position:"absolute",top:"1px",right:"1px",zIndex:i__default.default.zIndexDefault,padding:i__default.default.spacing2Xs,height:i__default.default.spacingXl}),content:e=>css.css({overflow:"auto",maxHeight:`${e}px`}),container:css.css({}),list:css.css({listStyle:"none",padding:`${i__default.default.spacing2Xs}`,margin:0}),groupTitle:css.css({padding:`6px ${i__default.default.spacingXs}`,lineHeight:i__default.default.lineHeightM}),noMatchesTitle:css.css({color:i__default.default.gray500,margin:i__default.default.spacingM,textAlign:"center"}),clearSelectionButton:css.css({marginLeft:"-80px"}),selectAll:css.css({borderBottom:`1px solid ${i__default.default.gray200}`,marginBottom:i__default.default.spacing2Xs,paddingBottom:i__default.default.spacing2Xs,"label > *":{fontWeight:i__default.default.fontWeightMedium}}),option:css.css({listStyleType:"none"}),optionText:css.css({alignItems:"center",display:"flex",span:{color:i__default.default.gray900,fontWeight:i__default.default.fontWeightDemiBold}}),optionCheck:({isActive:e,isDisabled:t})=>css.css({label:css.cx(f36Core.getMenuItemStyles({isActive:e,isDisabled:t}),css.css({width:"100%"}))})});var J=n__default.default.createContext(void 0),K=()=>{let e=n__default.default.useContext(J);if(e===void 0)throw new Error("component must be rendered within a Accordion component");return e},Q=J.Provider;var b=f=>{var h=f,{children:e,label:t,value:o,itemId:l,onSelectItem:s,isChecked:c=false,isDisabled:g=false,className:v}=h,p=B(h,["children","label","value","itemId","onSelectItem","isChecked","isDisabled","className"]);let x=S(),{focusList:u,searchValue:y}=K();return n__default.default.createElement("li",M({className:css.cx(x.option,v)},p),n__default.default.createElement(f36Forms.Checkbox,{id:l,value:o,onChange:C=>{u(),s(C);},isChecked:c,isDisabled:g,className:x.optionCheck({isActive:c,isDisabled:g})},n__default.default.createElement(f36Typography.Text,{className:x.optionText,"data-test-id":`cf-multiselect-list-item-${l}`},typeof t=="string"?n__default.default.createElement(T,{item:t,inputValue:y}):e)))};function T({item:e,inputValue:t=""}){let{before:o,match:l,after:s}=f36Utils.getStringMatch(e,t.trim());return o.length+l.length+s.length===0?n__default.default.createElement(n__default.default.Fragment,null,e):n__default.default.createElement(n__default.default.Fragment,null,o,n__default.default.createElement("span",{"data-test-id":"cf-multiselect-item-match"},l),s)}T.displayName="HighlightedItem";var _=({searchValue:e,setSearchValue:t,onSearchValueChange:o,searchInputName:l,searchInputRef:s,resetSearchRef:c,searchPlaceholder:g="Search",focusList:v})=>{let p=S(),f=n.useRef(null),h=n.useCallback(u=>{t(u.target.value),o==null||o(u);},[o,t]),x=n.useCallback(()=>{if(!e)return;v(),Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype,"value").set.call(f.current,"");let y=new Event("change",{bubbles:true});f.current.dispatchEvent(y);},[e,v]);return n__default.default.createElement("div",{className:p.searchBar},n__default.default.createElement(f36Forms.TextInput,{"aria-label":"Search",type:"text",value:e,className:p.inputField,testId:"cf-multiselect-search",placeholder:g,onChange:h,ref:f36Core.mergeRefs(s,f),name:l,size:"small"}),n__default.default.createElement(f36Button.IconButton,{ref:c,"aria-label":e?"Clear search":"Search",className:p.toggleButton,variant:"transparent",icon:e?n__default.default.createElement(f36Icons.XIcon,{color:i__default.default.gray600}):n__default.default.createElement(f36Icons.MagnifyingGlassIcon,{color:i__default.default.gray600}),onClick:x,isDisabled:!e,size:"small"}))};var ne=(e,t)=>{let o=0;return n__default.default.Children.forEach(e,l=>{if(!n__default.default.isValidElement(l))return;let s=l;t(s)?o+=1:o+=ne(s.props.children,t);}),o};function le(e,t){let{className:o,startIcon:l,placeholder:s="Select one or more Items",currentSelection:c=[],toggleRef:g,toggleButtonAriaLabel:v="Toggle Multiselect",isLoading:p=false,testId:f="cf-multiselect",noMatchesMessage:h="No matches found",searchProps:x={},popoverProps:u={},children:y,onBlur:C,onClearSelection:I,clearButtonProps:O={tooltip:"Clear selection",ariaLabel:"Clear selection"}}=e,{listMaxHeight:re=180,listRef:se,onClose:X}=u,a=S(),[k,ce]=n.useState(""),[D,F]=n.useState(false),$=n.useRef(null),w=c.length>1&&typeof I=="function",ae=typeof x.onSearchValueChange=="function",A=n.useCallback(()=>{var m;(m=$.current)==null||m.focus();},[]),pe=m=>{I==null||I(),m.stopPropagation();},ue=n.useCallback(()=>{if(c.length===0)return n__default.default.createElement(n__default.default.Fragment,null,s);let m=c.length-1,V=css.cx(a.currentSelection,w&&a.currentSelectionWithClearButton);return m===0?n__default.default.createElement("span",{"data-test-id":"cf-multiselect-current-selection",className:V},c[0]):n__default.default.createElement("span",{"data-test-id":"cf-multiselect-current-selection",className:V},c[0]," ",n__default.default.createElement("span",{className:a.currentSelectionAddition},"and ",m," more"))},[c,s,w,a.currentSelection,a.currentSelectionAddition,a.currentSelectionWithClearButton]),z=n.useMemo(()=>ne(y,m=>m.type===b),[y]),me=n.useMemo(()=>({focusList:A,searchValue:k}),[A,k]);return n__default.default.createElement(Q,{value:me},n__default.default.createElement("div",{"data-test-id":f,className:css.cx(a.multiselect,o),ref:t},n__default.default.createElement(f36Popover.Popover,H(M({renderOnlyWhenOpen:false,isFullWidth:true},u),{isOpen:D,onClose:()=>{F(false),X&&X();}}),n__default.default.createElement(f36Core.Flex,{alignItems:"center"},n__default.default.createElement(f36Popover.Popover.Trigger,{ref:g},n__default.default.createElement(f36Button.Button,M({"aria-label":v,onClick:()=>F(!D),startIcon:l,endIcon:n__default.default.createElement(f36Icons.CaretDownIcon,null),isFullWidth:true,className:a.triggerButton},e.triggerButtonProps),ue())),w&&n__default.default.createElement("div",{className:a.clearSelectionButton},n__default.default.createElement(f36Button.IconButton,{onClick:pe,icon:n__default.default.createElement(f36Icons.XIcon,null),"aria-label":O.ariaLabel?O.ariaLabel:"Clear selection",size:"small",withTooltip:true,tooltipProps:{content:O.tooltip?O.tooltip:"Clear selection",showDelay:800,placement:"top",as:"div"}}))),n__default.default.createElement(f36Popover.Popover.Content,{ref:f36Core.mergeRefs(se,$),className:css.cx(a.content(re),u.className,a.container),testId:"cf-multiselect-container",onBlur:()=>C==null?void 0:C()},n__default.default.createElement(Xe__default.default,{focusOptions:{preventScroll:true},returnFocus:true},ae&&n__default.default.createElement(_,H(M({},x),{setSearchValue:ce,searchValue:k,focusList:A})),p&&n__default.default.createElement(De,null),!p&&z>0&&n__default.default.createElement("ul",{className:a.list,"data-test-id":"cf-multiselect-items"},y),!p&&z===0&&n__default.default.createElement(f36Typography.Subheading,{className:a.noMatchesTitle},h))))))}var De=()=>n__default.default.createElement(f36Skeleton.SkeletonContainer,{svgHeight:16},n__default.default.createElement(f36Skeleton.SkeletonBodyText,{numberOfLines:1}));le.displayName="Multiselect";var ie=n__default.default.forwardRef(le);var W=v=>{var p=v,{label:e,itemId:t="SelectAll",onSelectItem:o,isChecked:l=false,selectAllOptionLabel:s={checked:"Deselect all",unchecked:"Select all"},className:c}=p,g=B(p,["label","itemId","onSelectItem","isChecked","selectAllOptionLabel","className"]);let f=S(),h=e||l?s.checked:s.unchecked;return n__default.default.createElement(b,M({value:"all",label:h,itemId:t,onSelectItem:o,isChecked:l,className:css.cx(f.selectAll,c)},g))};var N=ie;N.HighlightedItem=T;N.Option=b;N.SelectAll=W;exports.Multiselect=N;exports.MultiselectOption=b;exports.SelectAllOption=W;//# sourceMappingURL=index.js.map
29
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/MultiselectOption.tsx","../src/Multiselect.styles.ts","../src/Multiselect.tsx","../src/MultiselectSearch.tsx","../src/SelectAllOption.tsx","../src/CompoundMultiselect.tsx"],"names":["React","Checkbox","Text","css","cx","tokens","getMenuItemStyles","getMultiselectStyles","listMaxHeight","isActive","isDisabled","getStringMatch","MultiselectOption","_a","_b","children","label","value","itemId","onSelectItem","searchValue","isChecked","className","rest","__objRest","styles","__spreadValues","event","HighlightedItem","item","inputValue","before","match","after","useRef","useState","useCallback","useMemo","mergeRefs","Flex","Button","IconButton","CaretDownIcon","XIcon","SkeletonContainer","SkeletonBodyText","Popover","Subheading","Tooltip","FocusLock","TextInput","MagnifyingGlassIcon","MultiselectSearch","setSearchValue","onSearchValueChange","searchInputName","searchInputRef","resetSearchRef","searchPlaceholder","focusList","internalSearchInputRef","handleSearchChange","resetSearchInput","forcedEvent","iterateOverChildren","filter","callback","child","childChildren","countMatchingChildren","counter","_Multiselect","props","ref","startIcon","placeholder","currentSelection","toggleRef","toggleButtonAriaLabel","isLoading","testId","noMatchesMessage","searchProps","popoverProps","onBlur","onClearSelection","clearButtonProps","listRef","onClose","isOpen","setIsOpen","internalListRef","showClearButton","hasSearch","handleClearSelection","e","renderMultiselectLabel","leftoverCount","currentSelectionClassName","optionsLength","enrichOptions","__spreadProps","ListItemLoadingState","Multiselect","SelectAllOption","selectAllOptionLabel","otherProps","displayLabel"],"mappings":"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","sourcesContent":["import React from 'react';\nimport { Checkbox } from '@contentful/f36-forms';\nimport { Text } from '@contentful/f36-typography';\nimport { getMultiselectStyles } from './Multiselect.styles';\nimport { getStringMatch } from '@contentful/f36-utils';\nimport { cx } from 'emotion';\n\ntype LabelOrChildren =\n | {\n /**\n * When using React children it is your own responsibility to highlight\n * the matching part of the item label. Use the `HighlightedItem`\n * component for this.\n */\n children: React.ReactNode;\n label?: never;\n }\n | {\n children?: never;\n label: string;\n };\n\nexport type MultiselectOptionProps = {\n value: string;\n itemId: string;\n searchValue?: string;\n className?: string;\n onSelectItem: (event: React.ChangeEvent<HTMLInputElement>) => void;\n isChecked?: boolean;\n isDisabled?: boolean;\n} & LabelOrChildren;\n\nexport const MultiselectOption = ({\n children,\n label,\n value,\n itemId,\n onSelectItem,\n searchValue,\n isChecked = false,\n isDisabled = false,\n className,\n ...rest\n}: MultiselectOptionProps) => {\n const styles = getMultiselectStyles();\n\n return (\n <li className={cx(styles.option, className)} {...rest}>\n <Checkbox\n id={itemId}\n value={value}\n onChange={(event) => onSelectItem(event)}\n isChecked={isChecked}\n isDisabled={isDisabled}\n className={styles.optionCheck({ isActive: isChecked, isDisabled })}\n >\n <Text\n className={styles.optionText}\n data-test-id={`cf-multiselect-list-item-${itemId}`}\n >\n {typeof label === 'string' ? (\n <HighlightedItem item={label} inputValue={searchValue} />\n ) : (\n children\n )}\n </Text>\n </Checkbox>\n </li>\n );\n};\n\nexport function HighlightedItem({\n item,\n inputValue = '',\n}: {\n item: string;\n inputValue?: string;\n}) {\n const { before, match, after } = getStringMatch(item, inputValue.trim());\n\n if (before.length + match.length + after.length === 0) {\n return <>{item}</>;\n }\n\n return (\n <>\n {before}\n <span data-test-id=\"cf-multiselect-item-match\">{match}</span>\n {after}\n </>\n );\n}\n\nHighlightedItem.displayName = 'HighlightedItem';\n","import { css, cx } from 'emotion';\nimport tokens from '@contentful/f36-tokens';\nimport { getMenuItemStyles } from '@contentful/f36-core';\n\nexport const getMultiselectStyles = () => ({\n multiselect: css({\n position: 'relative',\n width: '100%',\n }),\n triggerButton: css({\n justifyContent: 'space-between',\n }),\n currentSelection: css({\n display: 'inline-block',\n width: '100%',\n whiteSpace: 'nowrap',\n textOverflow: 'ellipsis',\n overflow: 'hidden',\n verticalAlign: 'bottom',\n marginRight: tokens.spacing2Xs,\n }),\n currentSelectionWithClearButton: css({\n paddingRight: '40px',\n }),\n currentSelectionAddition: css({\n color: tokens.gray600,\n }),\n searchBar: css({\n paddingTop: tokens.spacing2Xs,\n position: 'sticky',\n top: '0px',\n zIndex: tokens.zIndexWorkbenchHeader,\n backgroundColor: tokens.colorWhite,\n }),\n inputField: css({\n padding: `6px ${tokens.spacingXl} 10px ${tokens.spacingXs}`,\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n border: 'none',\n borderRadius: '0px',\n borderBottom: `1px solid ${tokens.gray200}`,\n boxShadow: 'none',\n '&:focus, &:active, &:active:hover': {\n boxShadow: 'none',\n borderBottom: `1px solid ${tokens.gray200}`,\n },\n }),\n toggleButton: css({\n position: 'absolute',\n top: '1px',\n right: '1px',\n zIndex: tokens.zIndexDefault,\n padding: tokens.spacing2Xs,\n height: tokens.spacingXl,\n }),\n content: (listMaxHeight: number) =>\n css({\n overflow: 'auto',\n maxHeight: `${listMaxHeight}px`,\n }),\n container: css({}),\n list: css({\n listStyle: 'none',\n padding: `${tokens.spacing2Xs}`,\n margin: 0,\n }),\n groupTitle: css({\n // Magic number to get a height of 32px on the item\n padding: `6px ${tokens.spacingXs}`,\n lineHeight: tokens.lineHeightM,\n }),\n noMatchesTitle: css({\n color: tokens.gray500,\n margin: tokens.spacingM,\n textAlign: 'center',\n }),\n clearSelectionButton: css({\n marginLeft: '-80px',\n }),\n selectAll: css({\n borderBottom: `1px solid ${tokens.gray200}`,\n marginBottom: tokens.spacing2Xs,\n paddingBottom: tokens.spacing2Xs,\n 'label > *': {\n fontWeight: tokens.fontWeightMedium,\n },\n }),\n option: css({\n listStyleType: 'none',\n }),\n optionText: css({\n alignItems: 'center',\n display: 'flex',\n span: {\n color: tokens.gray900,\n fontWeight: tokens.fontWeightDemiBold,\n },\n }),\n optionCheck: ({\n isActive,\n isDisabled,\n }: {\n isActive?: boolean;\n isDisabled?: boolean;\n }) =>\n css({\n label: cx(\n getMenuItemStyles({ isActive, isDisabled }),\n css({\n width: '100%',\n }),\n ),\n }),\n});\n","import React, { useRef, useState, useCallback, useMemo } from 'react';\nimport { cx } from 'emotion';\n\nimport { mergeRefs, type CommonProps, Flex } from '@contentful/f36-core';\nimport { Button, IconButton, type ButtonProps } from '@contentful/f36-button';\nimport { CaretDownIcon, XIcon } from '@contentful/f36-icons';\n\nimport { SkeletonContainer, SkeletonBodyText } from '@contentful/f36-skeleton';\nimport { Popover, type PopoverProps } from '@contentful/f36-popover';\nimport { Subheading } from '@contentful/f36-typography';\nimport { Tooltip } from '@contentful/f36-tooltip';\n\nimport { getMultiselectStyles } from './Multiselect.styles';\nimport { MultiselectOption, MultiselectOptionProps } from './MultiselectOption';\nimport FocusLock from 'react-focus-lock';\n\nimport type { MultiselectSearchProps as SearchProps } from './MultiselectSearch';\nimport { MultiselectSearch } from './MultiselectSearch';\n\ntype ClearButtonProps = {\n /**\n * Aria label for the clear button\n * @default 'Clear selection'\n */\n ariaLabel?: string;\n\n /**\n * Tooltip for the clear button\n * @default 'Clear selection'\n */\n tooltip?: string;\n};\n\nexport interface MultiselectProps extends CommonProps {\n /** Select Options */\n children?: React.ReactNode;\n\n /**\n * Set a custom icon for the text input\n */\n startIcon?: React.ReactElement;\n\n /**\n * Placeholder shown before selecting any elements. Defaults to 'Select one or more items'\n */\n placeholder?: string;\n\n /**\n * current Selected items, to be shown on the trigger button\n */\n currentSelection?: Array<string>;\n\n /**\n * Sets the list to show its loading state\n * @default false\n */\n isLoading?: boolean;\n\n /**\n * Use this prop to get a ref to the toggle button of the component\n */\n toggleRef?: React.Ref<HTMLButtonElement>;\n\n /**\n * Aria label for the toggle button that opens the list\n * @default 'Toggle Multiselect'\n */\n toggleButtonAriaLabel?: string;\n\n /**\n * Props to pass to the optional search field\n */\n searchProps?: SearchProps;\n\n /**\n * Props to pass to the trigger button\n */\n triggerButtonProps?: ButtonProps;\n\n /**\n * A message that will be shown when it is not possible to find any option that matches the search value\n * @default \"No matches\"\n */\n noMatchesMessage?: string;\n\n /**\n * Props to pass to the Popover (Dropdown) component\n */\n popoverProps?: Partial<PopoverProps> & {\n /**\n * It sets the max-height, in pixels, of the list\n * The default value is the height of 5 single line items\n * @default 180\n */\n listMaxHeight?: number;\n\n /**\n * Use this prop to get a ref to the list of items of the component\n */\n listRef?: React.Ref<HTMLUListElement>;\n } & Pick<CommonProps, 'className'>;\n\n /**\n * Function called when the popover loses its focus.\n */\n onBlur?: () => void;\n\n /**\n * Function called when the clear all button is clicked\n * If no function is provided the clear button is not shown\n */\n onClearSelection?: () => void;\n\n /**\n * Clear Button Props used for localization\n * @default { ariaLabel: 'Clear selection', tooltip: 'Clear selection' }\n */\n clearButtonProps?: ClearButtonProps;\n}\n\n// Scan through the whole hierachy until `filter` returns true and apply `transform`\n// Inspired from https://stackoverflow.com/a/70676868/17269164\nconst iterateOverChildren = (\n children: React.ReactNode,\n filter: (child: React.ReactElement) => boolean,\n callback: (child: React.ReactElement) => React.ReactElement | void,\n): React.ReactNode => {\n return React.Children.map(children, (child) => {\n // equal to (if (child == null || typeof child == 'string'))\n if (!React.isValidElement(child)) return child;\n if (filter(child)) {\n return callback(child);\n }\n const childChildren = iterateOverChildren(\n child.props.children,\n filter,\n callback,\n );\n return React.cloneElement(child, { children: childChildren } as unknown);\n });\n};\n\n// Scan through the whole hierachy to count the number of children where `filter` returns true\nconst countMatchingChildren = (\n children: React.ReactNode,\n filter: (child: React.ReactElement) => boolean,\n): number => {\n let counter = 0;\n React.Children.forEach(children, (child) => {\n // equal to (if (child == null || typeof child == 'string'))\n if (!React.isValidElement(child)) return;\n if (!filter(child)) {\n counter += countMatchingChildren(child.props.children, filter);\n } else {\n counter += 1;\n }\n });\n return counter;\n};\n\nfunction _Multiselect(props: MultiselectProps, ref: React.Ref<HTMLDivElement>) {\n const {\n className,\n startIcon,\n placeholder = 'Select one or more Items',\n currentSelection = [],\n toggleRef,\n toggleButtonAriaLabel = 'Toggle Multiselect',\n isLoading = false,\n testId = 'cf-multiselect',\n noMatchesMessage = 'No matches found',\n searchProps = {},\n popoverProps = {},\n children,\n onBlur,\n onClearSelection,\n clearButtonProps = {\n tooltip: 'Clear selection',\n ariaLabel: 'Clear selection',\n },\n } = props;\n\n const { listMaxHeight = 180, listRef, onClose } = popoverProps;\n\n const styles = getMultiselectStyles();\n\n const [searchValue, setSearchValue] = useState('');\n const [isOpen, setIsOpen] = useState(false);\n\n const internalListRef = useRef<HTMLUListElement>(null);\n\n const showClearButton =\n currentSelection.length > 1 && typeof onClearSelection === 'function';\n\n const hasSearch = typeof searchProps.onSearchValueChange === 'function';\n\n const focusList = useCallback(() => {\n // Clearing the search input or selecting an item triggers a rerendering and\n // thereby the client loses the focus on the clicked element. To avoid having\n // the focus on the document body (which breaks `closeOnBlur`), we force it\n // back to the list in the popup.\n internalListRef.current?.focus();\n }, []);\n\n const handleClearSelection = (e: React.MouseEvent<HTMLButtonElement>) => {\n onClearSelection?.();\n e.stopPropagation();\n };\n\n const renderMultiselectLabel = useCallback(() => {\n if (currentSelection.length === 0) {\n return <>{placeholder}</>;\n }\n const leftoverCount = currentSelection.length - 1;\n const currentSelectionClassName = cx(\n styles.currentSelection,\n showClearButton && styles.currentSelectionWithClearButton,\n );\n if (leftoverCount === 0) {\n return (\n <span\n data-test-id=\"cf-multiselect-current-selection\"\n className={currentSelectionClassName}\n >\n {currentSelection[0]}\n </span>\n );\n }\n return (\n <span\n data-test-id=\"cf-multiselect-current-selection\"\n className={currentSelectionClassName}\n >\n {currentSelection[0]}{' '}\n <span className={styles.currentSelectionAddition}>\n and {leftoverCount} more\n </span>\n </span>\n );\n }, [\n currentSelection,\n placeholder,\n showClearButton,\n styles.currentSelection,\n styles.currentSelectionAddition,\n styles.currentSelectionWithClearButton,\n ]);\n\n const optionsLength = useMemo(\n () =>\n countMatchingChildren(\n children,\n (child) => child.type === MultiselectOption,\n ),\n [children],\n );\n\n // clones and enriches the multiselect options\n const enrichOptions = React.useCallback(\n (children: React.ReactNode): React.ReactNode => {\n return iterateOverChildren(\n children,\n (child) => child.type === MultiselectOption,\n (child) => {\n const onSelectItem = (event: React.ChangeEvent<HTMLInputElement>) => {\n focusList();\n child.props?.onSelectItem(event);\n };\n return React.cloneElement(child, {\n searchValue,\n onSelectItem,\n } as Partial<MultiselectOptionProps>);\n },\n );\n },\n [searchValue, focusList],\n );\n\n return (\n <div\n data-test-id={testId}\n className={cx(styles.multiselect, className)}\n ref={ref}\n >\n <Popover\n renderOnlyWhenOpen={false}\n isFullWidth\n {...popoverProps}\n // popoverProps should never overwrite the internal opening logic\n isOpen={isOpen}\n onClose={() => {\n setIsOpen(false);\n if (onClose) {\n onClose();\n }\n }}\n >\n <Flex alignItems=\"center\">\n <Popover.Trigger>\n <Button\n aria-label={toggleButtonAriaLabel}\n ref={toggleRef}\n onClick={() => setIsOpen(!isOpen)}\n startIcon={startIcon}\n endIcon={<CaretDownIcon />}\n isFullWidth\n className={styles.triggerButton}\n {...props.triggerButtonProps}\n >\n {renderMultiselectLabel()}\n </Button>\n </Popover.Trigger>\n {showClearButton && (\n <div className={styles.clearSelectionButton}>\n <Tooltip\n content={\n clearButtonProps.tooltip\n ? clearButtonProps.tooltip\n : 'Clear selection'\n }\n showDelay={800}\n placement=\"top\"\n as=\"div\"\n >\n <IconButton\n onClick={handleClearSelection}\n icon={<XIcon />}\n aria-label={\n clearButtonProps.ariaLabel\n ? clearButtonProps.ariaLabel\n : 'Clear selection'\n }\n size=\"small\"\n />\n </Tooltip>\n </div>\n )}\n </Flex>\n <Popover.Content\n ref={mergeRefs(listRef, internalListRef)}\n className={cx(\n styles.content(listMaxHeight),\n popoverProps.className,\n styles.container,\n )}\n testId=\"cf-multiselect-container\"\n onBlur={() => onBlur?.()}\n >\n <FocusLock focusOptions={{ preventScroll: true }} returnFocus={true}>\n {hasSearch && (\n <MultiselectSearch\n {...searchProps}\n setSearchValue={setSearchValue}\n searchValue={searchValue}\n focusList={focusList}\n />\n )}\n {isLoading && <ListItemLoadingState />}\n\n {!isLoading && optionsLength > 0 && (\n <ul className={styles.list} data-test-id=\"cf-multiselect-items\">\n {hasSearch ? enrichOptions(children) : children}\n </ul>\n )}\n\n {!isLoading && optionsLength === 0 && (\n <Subheading className={styles.noMatchesTitle}>\n {noMatchesMessage}\n </Subheading>\n )}\n </FocusLock>\n </Popover.Content>\n </Popover>\n </div>\n );\n}\n\nconst ListItemLoadingState = () => {\n return (\n <SkeletonContainer svgHeight={16}>\n <SkeletonBodyText numberOfLines={1} />\n </SkeletonContainer>\n );\n};\n\n/**\n * The Multiselect is a component that will allow a user to select multiple items.\n * It has an optional\n */\nexport const Multiselect = React.forwardRef(_Multiselect);\n","import React, { useCallback, useRef } from 'react';\nimport tokens from '@contentful/f36-tokens';\nimport { TextInput } from '@contentful/f36-forms';\nimport { XIcon, MagnifyingGlassIcon } from '@contentful/f36-icons';\nimport { IconButton } from '@contentful/f36-button';\nimport { getMultiselectStyles } from './Multiselect.styles';\nimport { mergeRefs } from '@contentful/f36-core';\n\nexport interface MultiselectSearchProps {\n /**\n * Function called whenever the search input value changes\n */\n onSearchValueChange?: (\n event: React.ChangeEvent<HTMLInputElement>,\n ) => void | undefined;\n\n /**\n * This is the value will be passed to the `placeholder` prop of the input.\n * @default \"Search\"\n */\n searchPlaceholder?: string;\n\n /**\n * Pass a form name to the search text input\n */\n searchInputName?: string;\n\n /**\n * Use this prop to get a ref to the search input element of the component\n */\n searchInputRef?: React.Ref<HTMLInputElement>;\n\n /**\n * Use this prop to get a ref to the reset search button of the component\n */\n resetSearchRef?: React.Ref<HTMLButtonElement>;\n\n /**\n * State from the parent component\n */\n searchValue?: string;\n\n /**\n * State setter of the parent\n */\n setSearchValue?: React.Dispatch<React.SetStateAction<string>>;\n\n /**\n * List helper function\n */\n focusList?: () => void;\n}\n\nexport const MultiselectSearch = ({\n searchValue,\n setSearchValue,\n onSearchValueChange,\n searchInputName,\n searchInputRef,\n resetSearchRef,\n searchPlaceholder = 'Search',\n focusList,\n}: MultiselectSearchProps) => {\n const styles = getMultiselectStyles();\n const internalSearchInputRef = useRef<HTMLInputElement>(null);\n\n const handleSearchChange = useCallback(\n (event) => {\n setSearchValue(event.target.value);\n onSearchValueChange?.(event);\n },\n [onSearchValueChange, setSearchValue],\n );\n\n const resetSearchInput = useCallback(() => {\n if (!searchValue) return;\n focusList();\n // this looks a bit hacky, but is the official way of externally triggering the onChange handler for an input\n // https://stackoverflow.com/a/46012210/17269164\n const nativeInputValueSetter = Object.getOwnPropertyDescriptor(\n window.HTMLInputElement.prototype,\n 'value',\n ).set;\n nativeInputValueSetter.call(internalSearchInputRef.current, '');\n const forcedEvent = new Event('change', { bubbles: true });\n internalSearchInputRef.current.dispatchEvent(forcedEvent);\n }, [searchValue, focusList]);\n\n return (\n <div className={styles.searchBar}>\n <TextInput\n aria-label=\"Search\"\n type=\"text\"\n value={searchValue}\n className={styles.inputField}\n testId=\"cf-multiselect-search\"\n placeholder={searchPlaceholder}\n onChange={handleSearchChange}\n ref={mergeRefs(searchInputRef, internalSearchInputRef)}\n name={searchInputName}\n size=\"small\"\n />\n <IconButton\n ref={resetSearchRef}\n aria-label={searchValue ? 'Clear search' : 'Search'}\n className={styles.toggleButton}\n variant=\"transparent\"\n icon={\n searchValue ? (\n <XIcon color={tokens.gray600} />\n ) : (\n <MagnifyingGlassIcon color={tokens.gray600} />\n )\n }\n onClick={resetSearchInput}\n isDisabled={!searchValue}\n size=\"small\"\n />\n </div>\n );\n};\n","import React from 'react';\nimport { MultiselectOption, MultiselectOptionProps } from './MultiselectOption';\nimport { getMultiselectStyles } from './Multiselect.styles';\nimport { cx } from 'emotion';\n\n/**\n * Labels for the select all option\n */\ntype SelectAllOptionLabel = {\n /**\n * Label for the select all option when it is checked\n * @default 'Deselect all'\n */\n checked: string;\n\n /**\n * Label for the select all option when it is unchecked\n * @default 'Select all'\n */\n unchecked: string;\n};\nexport interface SelectAllOptionProps\n extends Omit<\n MultiselectOptionProps,\n 'children' | 'value' | 'itemId' | 'label'\n > {\n label?: string;\n itemId?: string;\n selectAllOptionLabel?: SelectAllOptionLabel;\n}\n\nexport const SelectAllOption = ({\n label,\n itemId = 'SelectAll',\n onSelectItem,\n isChecked = false,\n selectAllOptionLabel = {\n checked: 'Deselect all',\n unchecked: 'Select all',\n },\n className,\n ...otherProps\n}: SelectAllOptionProps) => {\n const styles = getMultiselectStyles();\n const displayLabel =\n label || isChecked\n ? selectAllOptionLabel.checked\n : selectAllOptionLabel.unchecked;\n return (\n <MultiselectOption\n value=\"all\"\n label={displayLabel}\n itemId={itemId}\n onSelectItem={onSelectItem}\n isChecked={isChecked}\n className={cx(styles.selectAll, className)}\n {...otherProps}\n />\n );\n};\n","import { Multiselect as OriginalMultiSelect } from './Multiselect';\nimport { HighlightedItem, MultiselectOption } from './MultiselectOption';\nimport { SelectAllOption } from './SelectAllOption';\n\ntype CompoundMultiselect = typeof OriginalMultiSelect & {\n HighlightedItem: typeof HighlightedItem;\n Option: typeof MultiselectOption;\n SelectAll: typeof SelectAllOption;\n};\n\nexport const Multiselect = OriginalMultiSelect as CompoundMultiselect;\nMultiselect.HighlightedItem = HighlightedItem;\nMultiselect.Option = MultiselectOption;\nMultiselect.SelectAll = SelectAllOption;\n"]}
1
+ {"version":3,"sources":["../src/MultiselectOption.tsx","../src/Multiselect.styles.ts","../src/MultiselectContext.tsx","../src/MultiselectSearch.tsx","../src/Multiselect.tsx","../src/SelectAllOption.tsx","../src/CompoundMultiselect.tsx"],"names":["getMultiselectStyles","css","tokens","listMaxHeight","isActive","isDisabled","cx","getMenuItemStyles","MultiselectContext","React","useMultiselectContext","context","MultiselectContextProvider","MultiselectOption","_a","_b","children","label","value","itemId","onSelectItem","isChecked","className","rest","__objRest","styles","focusList","searchValue","__spreadValues","Checkbox","event","Text","HighlightedItem","item","inputValue","before","match","after","getStringMatch","MultiselectSearch","setSearchValue","onSearchValueChange","searchInputName","searchInputRef","resetSearchRef","searchPlaceholder","internalSearchInputRef","useRef","handleSearchChange","useCallback","resetSearchInput","forcedEvent","TextInput","mergeRefs","IconButton","XIcon","MagnifyingGlassIcon","countMatchingChildren","filter","counter","child","el","MultiselectBase","props","ref","startIcon","placeholder","currentSelection","toggleRef","toggleButtonAriaLabel","isLoading","testId","noMatchesMessage","searchProps","popoverProps","onBlur","onClearSelection","clearButtonProps","listRef","onClose","useState","isOpen","setIsOpen","internalListRef","showClearButton","hasSearch","handleClearSelection","e","renderMultiselectLabel","leftoverCount","currentSelectionClassName","optionsLength","useMemo","contextValue","Popover","__spreadProps","Flex","Button","CaretDownIcon","FocusLock","ListItemLoadingState","Subheading","SkeletonContainer","SkeletonBodyText","Multiselect","SelectAllOption","selectAllOptionLabel","otherProps","displayLabel"],"mappings":"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","file":"index.js","sourcesContent":["import React from 'react';\nimport { Checkbox } from '@contentful/f36-forms';\nimport { Text } from '@contentful/f36-typography';\nimport { getMultiselectStyles } from './Multiselect.styles';\nimport { getStringMatch } from '@contentful/f36-utils';\nimport { cx } from '@emotion/css';\nimport { useMultiselectContext } from './MultiselectContext';\n\ntype LabelOrChildren =\n | {\n /**\n * When using React children it is your own responsibility to highlight\n * the matching part of the item label. Use the `HighlightedItem`\n * component for this.\n */\n children: React.ReactNode;\n label?: never;\n }\n | {\n children?: never;\n label: string;\n };\n\nexport type MultiselectOptionProps = {\n value: string;\n itemId: string;\n className?: string;\n onSelectItem: (event: React.ChangeEvent<HTMLInputElement>) => void;\n isChecked?: boolean;\n isDisabled?: boolean;\n} & LabelOrChildren;\n\nexport const MultiselectOption = ({\n children,\n label,\n value,\n itemId,\n onSelectItem,\n isChecked = false,\n isDisabled = false,\n className,\n ...rest\n}: MultiselectOptionProps) => {\n const styles = getMultiselectStyles();\n const { focusList, searchValue } = useMultiselectContext();\n\n return (\n <li className={cx(styles.option, className)} {...rest}>\n <Checkbox\n id={itemId}\n value={value}\n onChange={(event) => {\n focusList();\n onSelectItem(event);\n }}\n isChecked={isChecked}\n isDisabled={isDisabled}\n className={styles.optionCheck({ isActive: isChecked, isDisabled })}\n >\n <Text\n className={styles.optionText}\n data-test-id={`cf-multiselect-list-item-${itemId}`}\n >\n {typeof label === 'string' ? (\n <HighlightedItem item={label} inputValue={searchValue} />\n ) : (\n children\n )}\n </Text>\n </Checkbox>\n </li>\n );\n};\n\nexport function HighlightedItem({\n item,\n inputValue = '',\n}: {\n item: string;\n inputValue?: string;\n}) {\n const { before, match, after } = getStringMatch(item, inputValue.trim());\n\n if (before.length + match.length + after.length === 0) {\n return <>{item}</>;\n }\n\n return (\n <>\n {before}\n <span data-test-id=\"cf-multiselect-item-match\">{match}</span>\n {after}\n </>\n );\n}\n\nHighlightedItem.displayName = 'HighlightedItem';\n","import { css, cx } from '@emotion/css';\nimport tokens from '@contentful/f36-tokens';\nimport { getMenuItemStyles } from '@contentful/f36-core';\n\nexport const getMultiselectStyles = () => ({\n multiselect: css({\n position: 'relative',\n width: '100%',\n }),\n triggerButton: css({\n justifyContent: 'space-between',\n }),\n currentSelection: css({\n display: 'inline-block',\n width: '100%',\n whiteSpace: 'nowrap',\n textOverflow: 'ellipsis',\n overflow: 'hidden',\n verticalAlign: 'bottom',\n marginRight: tokens.spacing2Xs,\n }),\n currentSelectionWithClearButton: css({\n paddingRight: '40px',\n }),\n currentSelectionAddition: css({\n color: tokens.gray600,\n }),\n searchBar: css({\n paddingTop: tokens.spacing2Xs,\n position: 'sticky',\n top: '0px',\n zIndex: tokens.zIndexWorkbenchHeader,\n backgroundColor: tokens.colorWhite,\n }),\n inputField: css({\n padding: `6px ${tokens.spacingXl} 10px ${tokens.spacingXs}`,\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n border: 'none',\n borderRadius: '0px',\n borderBottom: `1px solid ${tokens.gray200}`,\n boxShadow: 'none',\n '&:focus, &:active, &:active:hover': {\n boxShadow: 'none',\n borderBottom: `1px solid ${tokens.gray200}`,\n },\n }),\n toggleButton: css({\n position: 'absolute',\n top: '1px',\n right: '1px',\n zIndex: tokens.zIndexDefault,\n padding: tokens.spacing2Xs,\n height: tokens.spacingXl,\n }),\n content: (listMaxHeight: number) =>\n css({\n overflow: 'auto',\n maxHeight: `${listMaxHeight}px`,\n }),\n container: css({}),\n list: css({\n listStyle: 'none',\n padding: `${tokens.spacing2Xs}`,\n margin: 0,\n }),\n groupTitle: css({\n // Magic number to get a height of 32px on the item\n padding: `6px ${tokens.spacingXs}`,\n lineHeight: tokens.lineHeightM,\n }),\n noMatchesTitle: css({\n color: tokens.gray500,\n margin: tokens.spacingM,\n textAlign: 'center',\n }),\n clearSelectionButton: css({\n marginLeft: '-80px',\n }),\n selectAll: css({\n borderBottom: `1px solid ${tokens.gray200}`,\n marginBottom: tokens.spacing2Xs,\n paddingBottom: tokens.spacing2Xs,\n 'label > *': {\n fontWeight: tokens.fontWeightMedium,\n },\n }),\n option: css({\n listStyleType: 'none',\n }),\n optionText: css({\n alignItems: 'center',\n display: 'flex',\n span: {\n color: tokens.gray900,\n fontWeight: tokens.fontWeightDemiBold,\n },\n }),\n optionCheck: ({\n isActive,\n isDisabled,\n }: {\n isActive?: boolean;\n isDisabled?: boolean;\n }) =>\n css({\n label: cx(\n getMenuItemStyles({ isActive, isDisabled }),\n css({\n width: '100%',\n }),\n ),\n }),\n});\n","import React from 'react';\n\nexport type MultiselectContextType = {\n focusList: () => void;\n searchValue: string;\n};\n\nconst MultiselectContext = React.createContext<\n MultiselectContextType | undefined\n>(undefined);\n\nexport const useMultiselectContext = () => {\n const context = React.useContext(MultiselectContext);\n\n if (context === undefined) {\n throw new Error('component must be rendered within a Accordion component');\n }\n\n return context;\n};\n\nexport const MultiselectContextProvider = MultiselectContext.Provider;\n","import React, { useCallback, useRef } from 'react';\nimport tokens from '@contentful/f36-tokens';\nimport { TextInput } from '@contentful/f36-forms';\nimport { XIcon, MagnifyingGlassIcon } from '@contentful/f36-icons';\nimport { IconButton } from '@contentful/f36-button';\nimport { getMultiselectStyles } from './Multiselect.styles';\nimport { mergeRefs } from '@contentful/f36-core';\n\nexport interface MultiselectSearchProps {\n /**\n * Function called whenever the search input value changes\n */\n onSearchValueChange?: (\n event: React.ChangeEvent<HTMLInputElement>,\n ) => void | undefined;\n\n /**\n * This is the value will be passed to the `placeholder` prop of the input.\n * @default \"Search\"\n */\n searchPlaceholder?: string;\n\n /**\n * Pass a form name to the search text input\n */\n searchInputName?: string;\n\n /**\n * Use this prop to get a ref to the search input element of the component\n */\n searchInputRef?: React.Ref<HTMLInputElement>;\n\n /**\n * Use this prop to get a ref to the reset search button of the component\n */\n resetSearchRef?: React.Ref<HTMLButtonElement>;\n\n /**\n * State from the parent component\n */\n searchValue?: string;\n\n /**\n * State setter of the parent\n */\n setSearchValue?: React.Dispatch<React.SetStateAction<string>>;\n\n /**\n * List helper function\n */\n focusList?: () => void;\n}\n\nexport const MultiselectSearch = ({\n searchValue,\n setSearchValue,\n onSearchValueChange,\n searchInputName,\n searchInputRef,\n resetSearchRef,\n searchPlaceholder = 'Search',\n focusList,\n}: MultiselectSearchProps) => {\n const styles = getMultiselectStyles();\n const internalSearchInputRef = useRef<HTMLInputElement>(null);\n\n const handleSearchChange = useCallback(\n (event) => {\n setSearchValue(event.target.value);\n onSearchValueChange?.(event);\n },\n [onSearchValueChange, setSearchValue],\n );\n\n const resetSearchInput = useCallback(() => {\n if (!searchValue) return;\n focusList();\n // this looks a bit hacky, but is the official way of externally triggering the onChange handler for an input\n // https://stackoverflow.com/a/46012210/17269164\n const nativeInputValueSetter = Object.getOwnPropertyDescriptor(\n window.HTMLInputElement.prototype,\n 'value',\n ).set;\n nativeInputValueSetter.call(internalSearchInputRef.current, '');\n const forcedEvent = new Event('change', { bubbles: true });\n internalSearchInputRef.current.dispatchEvent(forcedEvent);\n }, [searchValue, focusList]);\n\n return (\n <div className={styles.searchBar}>\n <TextInput\n aria-label=\"Search\"\n type=\"text\"\n value={searchValue}\n className={styles.inputField}\n testId=\"cf-multiselect-search\"\n placeholder={searchPlaceholder}\n onChange={handleSearchChange}\n ref={mergeRefs(searchInputRef, internalSearchInputRef)}\n name={searchInputName}\n size=\"small\"\n />\n <IconButton\n ref={resetSearchRef}\n aria-label={searchValue ? 'Clear search' : 'Search'}\n className={styles.toggleButton}\n variant=\"transparent\"\n icon={\n searchValue ? (\n <XIcon color={tokens.gray600} />\n ) : (\n <MagnifyingGlassIcon color={tokens.gray600} />\n )\n }\n onClick={resetSearchInput}\n isDisabled={!searchValue}\n size=\"small\"\n />\n </div>\n );\n};\n","import React, { useRef, useState, useCallback, useMemo } from 'react';\nimport { cx } from '@emotion/css';\n\nimport { mergeRefs, type CommonProps, Flex } from '@contentful/f36-core';\nimport { Button, IconButton, type ButtonProps } from '@contentful/f36-button';\nimport { CaretDownIcon, XIcon } from '@contentful/f36-icons';\n\nimport { SkeletonContainer, SkeletonBodyText } from '@contentful/f36-skeleton';\nimport { Popover, type PopoverProps } from '@contentful/f36-popover';\nimport { Subheading } from '@contentful/f36-typography';\n\nimport { getMultiselectStyles } from './Multiselect.styles';\nimport { MultiselectOption } from './MultiselectOption';\nimport FocusLock from 'react-focus-lock';\n\nimport type { MultiselectSearchProps as SearchProps } from './MultiselectSearch';\nimport { MultiselectSearch } from './MultiselectSearch';\nimport {\n MultiselectContextProvider,\n MultiselectContextType,\n} from './MultiselectContext';\n\ntype ClearButtonProps = {\n /**\n * Aria label for the clear button\n * @default 'Clear selection'\n */\n ariaLabel?: string;\n\n /**\n * Tooltip for the clear button\n * @default 'Clear selection'\n */\n tooltip?: string;\n};\n\nexport interface MultiselectProps extends CommonProps {\n /** Select Options */\n children?: React.ReactNode;\n\n /**\n * Set a custom icon for the text input\n */\n startIcon?: React.ReactElement;\n\n /**\n * Placeholder shown before selecting any elements. Defaults to 'Select one or more items'\n */\n placeholder?: string;\n\n /**\n * current Selected items, to be shown on the trigger button\n */\n currentSelection?: Array<string>;\n\n /**\n * Sets the list to show its loading state\n * @default false\n */\n isLoading?: boolean;\n\n /**\n * Use this prop to get a ref to the toggle button of the component\n */\n toggleRef?: React.Ref<HTMLButtonElement>;\n\n /**\n * Aria label for the toggle button that opens the list\n * @default 'Toggle Multiselect'\n */\n toggleButtonAriaLabel?: string;\n\n /**\n * Props to pass to the optional search field\n */\n searchProps?: SearchProps;\n\n /**\n * Props to pass to the trigger button\n */\n triggerButtonProps?: ButtonProps;\n\n /**\n * A message that will be shown when it is not possible to find any option that matches the search value\n * @default \"No matches\"\n */\n noMatchesMessage?: string;\n\n /**\n * Props to pass to the Popover (Dropdown) component\n */\n popoverProps?: Partial<PopoverProps> & {\n /**\n * It sets the max-height, in pixels, of the list\n * The default value is the height of 5 single line items\n * @default 180\n */\n listMaxHeight?: number;\n\n /**\n * Use this prop to get a ref to the list of items of the component\n */\n listRef?: React.Ref<HTMLUListElement>;\n } & Pick<CommonProps, 'className'>;\n\n /**\n * Function called when the popover loses its focus.\n */\n onBlur?: () => void;\n\n /**\n * Function called when the clear all button is clicked\n * If no function is provided the clear button is not shown\n */\n onClearSelection?: () => void;\n\n /**\n * Clear Button Props used for localization\n * @default { ariaLabel: 'Clear selection', tooltip: 'Clear selection' }\n */\n clearButtonProps?: ClearButtonProps;\n}\n\n// Scan through the whole hierachy to count the number of children where `filter` returns true\nconst countMatchingChildren = (\n children: React.ReactNode,\n filter: (child: React.ReactElement) => boolean,\n): number => {\n let counter = 0;\n React.Children.forEach(children, (child) => {\n if (!React.isValidElement(child)) return;\n // Narrow props to include optional children for recursive descent\n const el = child as React.ReactElement<{ children?: React.ReactNode }>;\n if (!filter(el)) {\n counter += countMatchingChildren(el.props.children, filter);\n } else {\n counter += 1;\n }\n });\n return counter;\n};\n\nfunction MultiselectBase(\n props: MultiselectProps,\n ref: React.Ref<HTMLDivElement>,\n) {\n const {\n className,\n startIcon,\n placeholder = 'Select one or more Items',\n currentSelection = [],\n toggleRef,\n toggleButtonAriaLabel = 'Toggle Multiselect',\n isLoading = false,\n testId = 'cf-multiselect',\n noMatchesMessage = 'No matches found',\n searchProps = {},\n popoverProps = {},\n children,\n onBlur,\n onClearSelection,\n clearButtonProps = {\n tooltip: 'Clear selection',\n ariaLabel: 'Clear selection',\n },\n } = props;\n\n const { listMaxHeight = 180, listRef, onClose } = popoverProps;\n\n const styles = getMultiselectStyles();\n\n const [searchValue, setSearchValue] = useState('');\n const [isOpen, setIsOpen] = useState(false);\n\n const internalListRef = useRef<HTMLUListElement>(null);\n\n const showClearButton =\n currentSelection.length > 1 && typeof onClearSelection === 'function';\n\n const hasSearch = typeof searchProps.onSearchValueChange === 'function';\n\n const focusList = useCallback(() => {\n // Clearing the search input or selecting an item triggers a rerendering and\n // thereby the client loses the focus on the clicked element. To avoid having\n // the focus on the document body (which breaks `closeOnBlur`), we force it\n // back to the list in the popup.\n internalListRef.current?.focus();\n }, []);\n\n const handleClearSelection = (e: React.MouseEvent<HTMLButtonElement>) => {\n onClearSelection?.();\n e.stopPropagation();\n };\n\n const renderMultiselectLabel = useCallback(() => {\n if (currentSelection.length === 0) {\n return <>{placeholder}</>;\n }\n const leftoverCount = currentSelection.length - 1;\n const currentSelectionClassName = cx(\n styles.currentSelection,\n showClearButton && styles.currentSelectionWithClearButton,\n );\n if (leftoverCount === 0) {\n return (\n <span\n data-test-id=\"cf-multiselect-current-selection\"\n className={currentSelectionClassName}\n >\n {currentSelection[0]}\n </span>\n );\n }\n return (\n <span\n data-test-id=\"cf-multiselect-current-selection\"\n className={currentSelectionClassName}\n >\n {currentSelection[0]}{' '}\n <span className={styles.currentSelectionAddition}>\n and {leftoverCount} more\n </span>\n </span>\n );\n }, [\n currentSelection,\n placeholder,\n showClearButton,\n styles.currentSelection,\n styles.currentSelectionAddition,\n styles.currentSelectionWithClearButton,\n ]);\n\n const optionsLength = useMemo(\n () =>\n countMatchingChildren(\n children,\n (child) => child.type === MultiselectOption,\n ),\n [children],\n );\n\n const contextValue: MultiselectContextType = useMemo(\n () => ({\n focusList,\n searchValue,\n }),\n [focusList, searchValue],\n );\n\n return (\n <MultiselectContextProvider value={contextValue}>\n <div\n data-test-id={testId}\n className={cx(styles.multiselect, className)}\n ref={ref}\n >\n <Popover\n renderOnlyWhenOpen={false}\n isFullWidth\n {...popoverProps}\n // popoverProps should never overwrite the internal opening logic\n isOpen={isOpen}\n onClose={() => {\n setIsOpen(false);\n if (onClose) {\n onClose();\n }\n }}\n >\n <Flex alignItems=\"center\">\n <Popover.Trigger ref={toggleRef}>\n <Button\n aria-label={toggleButtonAriaLabel}\n onClick={() => setIsOpen(!isOpen)}\n startIcon={startIcon}\n endIcon={<CaretDownIcon />}\n isFullWidth\n className={styles.triggerButton}\n {...props.triggerButtonProps}\n >\n {renderMultiselectLabel()}\n </Button>\n </Popover.Trigger>\n {showClearButton && (\n <div className={styles.clearSelectionButton}>\n <IconButton\n onClick={handleClearSelection}\n icon={<XIcon />}\n aria-label={\n clearButtonProps.ariaLabel\n ? clearButtonProps.ariaLabel\n : 'Clear selection'\n }\n size=\"small\"\n withTooltip\n tooltipProps={{\n content: clearButtonProps.tooltip\n ? clearButtonProps.tooltip\n : 'Clear selection',\n\n showDelay: 800,\n placement: 'top',\n as: 'div',\n }}\n />\n </div>\n )}\n </Flex>\n <Popover.Content\n ref={mergeRefs(listRef, internalListRef)}\n className={cx(\n styles.content(listMaxHeight),\n popoverProps.className,\n styles.container,\n )}\n testId=\"cf-multiselect-container\"\n onBlur={() => onBlur?.()}\n >\n <FocusLock\n focusOptions={{ preventScroll: true }}\n returnFocus={true}\n >\n {hasSearch && (\n <MultiselectSearch\n {...searchProps}\n setSearchValue={setSearchValue}\n searchValue={searchValue}\n focusList={focusList}\n />\n )}\n {isLoading && <ListItemLoadingState />}\n\n {!isLoading && optionsLength > 0 && (\n <ul className={styles.list} data-test-id=\"cf-multiselect-items\">\n {children}\n </ul>\n )}\n\n {!isLoading && optionsLength === 0 && (\n <Subheading className={styles.noMatchesTitle}>\n {noMatchesMessage}\n </Subheading>\n )}\n </FocusLock>\n </Popover.Content>\n </Popover>\n </div>\n </MultiselectContextProvider>\n );\n}\n\nconst ListItemLoadingState = () => {\n return (\n <SkeletonContainer svgHeight={16}>\n <SkeletonBodyText numberOfLines={1} />\n </SkeletonContainer>\n );\n};\n\nMultiselectBase.displayName = 'Multiselect';\nexport const Multiselect = React.forwardRef(MultiselectBase);\n","import React from 'react';\nimport { MultiselectOption, MultiselectOptionProps } from './MultiselectOption';\nimport { getMultiselectStyles } from './Multiselect.styles';\nimport { cx } from '@emotion/css';\n\n/**\n * Labels for the select all option\n */\ntype SelectAllOptionLabel = {\n /**\n * Label for the select all option when it is checked\n * @default 'Deselect all'\n */\n checked: string;\n\n /**\n * Label for the select all option when it is unchecked\n * @default 'Select all'\n */\n unchecked: string;\n};\nexport interface SelectAllOptionProps\n extends Omit<\n MultiselectOptionProps,\n 'children' | 'value' | 'itemId' | 'label'\n > {\n label?: string;\n itemId?: string;\n selectAllOptionLabel?: SelectAllOptionLabel;\n}\n\nexport const SelectAllOption = ({\n label,\n itemId = 'SelectAll',\n onSelectItem,\n isChecked = false,\n selectAllOptionLabel = {\n checked: 'Deselect all',\n unchecked: 'Select all',\n },\n className,\n ...otherProps\n}: SelectAllOptionProps) => {\n const styles = getMultiselectStyles();\n const displayLabel =\n label || isChecked\n ? selectAllOptionLabel.checked\n : selectAllOptionLabel.unchecked;\n return (\n <MultiselectOption\n value=\"all\"\n label={displayLabel}\n itemId={itemId}\n onSelectItem={onSelectItem}\n isChecked={isChecked}\n className={cx(styles.selectAll, className)}\n {...otherProps}\n />\n );\n};\n","import { Multiselect as OriginalMultiSelect } from './Multiselect';\nimport { HighlightedItem, MultiselectOption } from './MultiselectOption';\nimport { SelectAllOption } from './SelectAllOption';\n\ntype CompoundMultiselect = typeof OriginalMultiSelect & {\n HighlightedItem: typeof HighlightedItem;\n Option: typeof MultiselectOption;\n SelectAll: typeof SelectAllOption;\n};\n\nexport const Multiselect = OriginalMultiSelect as CompoundMultiselect;\nMultiselect.HighlightedItem = HighlightedItem;\nMultiselect.Option = MultiselectOption;\nMultiselect.SelectAll = SelectAllOption;\n"]}
package/package.json CHANGED
@@ -1,28 +1,28 @@
1
1
  {
2
2
  "name": "@contentful/f36-multiselect",
3
- "version": "5.8.0",
3
+ "version": "6.0.0-alpha.2",
4
4
  "description": "Forma 36: Multiselect Component",
5
5
  "scripts": {
6
6
  "build": "tsup"
7
7
  },
8
8
  "dependencies": {
9
9
  "@babel/runtime": "^7.27.1",
10
- "@contentful/f36-button": "^5.8.0",
11
- "@contentful/f36-core": "^5.8.0",
12
- "@contentful/f36-forms": "^5.8.0",
13
- "@contentful/f36-icons": "^5.8.0",
14
- "@contentful/f36-popover": "^5.8.0",
15
- "@contentful/f36-skeleton": "^5.8.0",
16
- "@contentful/f36-tokens": "^5.1.0",
17
- "@contentful/f36-tooltip": "^5.8.0",
18
- "@contentful/f36-typography": "^5.8.0",
19
- "@contentful/f36-utils": "^5.2.0",
20
- "emotion": "^10.0.17",
10
+ "@contentful/f36-button": "^6.0.0-alpha.0",
11
+ "@contentful/f36-core": "^6.0.0-alpha.0",
12
+ "@contentful/f36-forms": "^6.0.0-alpha.0",
13
+ "@contentful/f36-icons": "^6.0.0-alpha.0",
14
+ "@contentful/f36-popover": "^6.0.0-alpha.0",
15
+ "@contentful/f36-skeleton": "^6.0.0-alpha.0",
16
+ "@contentful/f36-tokens": "^6.0.0-alpha.0",
17
+ "@contentful/f36-tooltip": "^6.0.0-alpha.0",
18
+ "@contentful/f36-typography": "^6.0.0-alpha.0",
19
+ "@contentful/f36-utils": "^6.0.0-alpha.0",
20
+ "@emotion/css": "^11.13.5",
21
21
  "react-focus-lock": "^2.9.5"
22
22
  },
23
23
  "peerDependencies": {
24
- "react": ">=16.8",
25
- "react-dom": ">=16.8"
24
+ "react": ">=19.1.0",
25
+ "react-dom": ">=19.1.0"
26
26
  },
27
27
  "license": "MIT",
28
28
  "files": [