@amboss/design-system 4.16.0 → 4.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"Menu",{enumerable:!0,get:function(){return Menu}});const _interop_require_default=require("@swc/helpers/_/_interop_require_default"),_react=/*#__PURE__*/require("@swc/helpers/_/_interop_require_wildcard")._(require("react")),_styled=/*#__PURE__*/_interop_require_default._(require("@emotion/styled")),_useKeyboard=require("../../shared/useKeyboard"),_Divider=require("../Divider/Divider"),_MenuItem=require("./MenuItem"),_usePopupMenu=require("../../shared/popupMenu/usePopupMenu"),_useOutsideInteract=require("../../shared/useOutsideInteract"),_Portal=require("../Portal/Portal"),isSeperator=item=>"separator"===item,StyledMenu=(0,_styled.default)("div",{target:"e1gy87fm0",label:"StyledMenu"})(({theme})=>{let zIndex=(0,_Portal.usePortalChildZIndex)(theme.variables.zIndex.dropdown);return{position:"absolute",display:"inline-block",width:"fit-content",minWidth:theme.variables.size.dimension.dropdownMenu.width,zIndex,borderRadius:theme.variables.size.borderRadius.s,backgroundColor:theme.values.color.background.primary.default,paddingTop:theme.variables.size.spacing.xs,paddingBottom:theme.variables.size.spacing.xs,":after":{content:'" "',position:"absolute",top:0,left:0,width:"100%",height:"100%",pointerEvents:"none",borderRadius:"inherit",boxShadow:theme.values.elevation[3]}}}),StyledUl=(0,_styled.default)("ul",{target:"e1gy87fm1",label:"StyledUl"})(()=>({margin:0,padding:0,overflow:"hidden"})),StyledLi=(0,_styled.default)("li",{target:"e1gy87fm2",label:"StyledLi"})(()=>({margin:0,padding:0,width:"100%",listStyleType:"none",whiteSpace:"nowrap"})),StyledLiSeparator=(0,_styled.default)(StyledLi,{target:"e1gy87fm3",label:"StyledLiSeparator"})(({theme})=>({marginTop:theme.variables.size.spacing.xs,marginBottom:theme.variables.size.spacing.xs}));function Menu({isOpen,items,portalContainer,triggerRef,placement,onCloseMenu}){let menuRef=(0,_react.useRef)(null),[focusIndex,setFocusIndex]=(0,_react.useState)(0),{menuStyle}=(0,_usePopupMenu.usePopupMenu)({triggerRef,menuRef,isOpen,placement});(0,_useOutsideInteract.useOutsideInteract)({ref:menuRef,excludeRefs:[triggerRef],onInteractOutside:onCloseMenu,isActive:isOpen}),(0,_useKeyboard.useKeyboard)({Escape:onCloseMenu,ArrowUp:()=>{setFocusIndex(index=>index-1)},ArrowDown:()=>{setFocusIndex(index=>index+1)}},menuRef,isOpen),(0,_react.useEffect)(()=>{if(menuRef&&menuRef.current){let buttons=menuRef.current.querySelectorAll("button");buttons[Math.abs(focusIndex)%buttons.length].focus({preventScroll:!0})}isOpen||setFocusIndex(0)},[menuRef,focusIndex,isOpen]);let menuElm=_react.default.createElement(StyledMenu,{ref:menuRef,style:menuStyle},_react.default.createElement(StyledUl,{role:"menu"},items.map((item,index)=>{if(isSeperator(item))return _react.default.createElement(StyledLiSeparator,{role:"separator",key:`menuitem-separator-${index}`},_react.default.createElement(_Divider.Divider,{"aria-hidden":"true"}));let{label,destructive,disabled,emphasized,icon,onSelect}=item;return _react.default.createElement(StyledLi,{role:"menuitem",key:`menuitem-${label}`},_react.default.createElement(_MenuItem.MenuItem,{onSelect:onSelect,icon:icon,label:label,disabled:disabled,destructive:destructive,emphasized:emphasized}))})));return isOpen?_react.default.createElement(_Portal.Portal,{portalContainer:portalContainer},menuElm):null}
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"Menu",{enumerable:!0,get:function(){return Menu}});const _interop_require_default=require("@swc/helpers/_/_interop_require_default"),_react=/*#__PURE__*/require("@swc/helpers/_/_interop_require_wildcard")._(require("react")),_styled=/*#__PURE__*/_interop_require_default._(require("@emotion/styled")),_useKeyboard=require("../../shared/useKeyboard"),_useContainedEscape=require("../../shared/useContainedEscape"),_Divider=require("../Divider/Divider"),_MenuItem=require("./MenuItem"),_usePopupMenu=require("../../shared/popupMenu/usePopupMenu"),_useOutsideInteract=require("../../shared/useOutsideInteract"),_Portal=require("../Portal/Portal"),isSeperator=item=>"separator"===item,StyledMenu=(0,_styled.default)("div",{target:"ecmxohu0",label:"StyledMenu"})(({theme})=>{let zIndex=(0,_Portal.usePortalChildZIndex)(theme.variables.zIndex.dropdown);return{position:"absolute",display:"inline-block",width:"fit-content",minWidth:theme.variables.size.dimension.dropdownMenu.width,zIndex,borderRadius:theme.variables.size.borderRadius.s,backgroundColor:theme.values.color.background.primary.default,paddingTop:theme.variables.size.spacing.xs,paddingBottom:theme.variables.size.spacing.xs,":after":{content:'" "',position:"absolute",top:0,left:0,width:"100%",height:"100%",pointerEvents:"none",borderRadius:"inherit",boxShadow:theme.values.elevation[3]}}}),StyledUl=(0,_styled.default)("ul",{target:"ecmxohu1",label:"StyledUl"})(()=>({margin:0,padding:0,overflow:"hidden"})),StyledLi=(0,_styled.default)("li",{target:"ecmxohu2",label:"StyledLi"})(()=>({margin:0,padding:0,width:"100%",listStyleType:"none",whiteSpace:"nowrap"})),StyledLiSeparator=(0,_styled.default)(StyledLi,{target:"ecmxohu3",label:"StyledLiSeparator"})(({theme})=>({marginTop:theme.variables.size.spacing.xs,marginBottom:theme.variables.size.spacing.xs}));function Menu({isOpen,items,portalContainer,triggerRef,placement,onCloseMenu}){let menuRef=(0,_react.useRef)(null),[focusIndex,setFocusIndex]=(0,_react.useState)(0),{menuStyle}=(0,_usePopupMenu.usePopupMenu)({triggerRef,menuRef,isOpen,placement});(0,_useOutsideInteract.useOutsideInteract)({ref:menuRef,excludeRefs:[triggerRef],onInteractOutside:onCloseMenu,isActive:isOpen}),(0,_useContainedEscape.useContainedEscape)([menuRef,triggerRef],onCloseMenu,isOpen),(0,_useKeyboard.useKeyboard)({ArrowUp:()=>{setFocusIndex(index=>index-1)},ArrowDown:()=>{setFocusIndex(index=>index+1)}},menuRef,isOpen),(0,_react.useEffect)(()=>{if(menuRef&&menuRef.current){let buttons=menuRef.current.querySelectorAll("button");buttons[Math.abs(focusIndex)%buttons.length].focus({preventScroll:!0})}isOpen||setFocusIndex(0)},[menuRef,focusIndex,isOpen]);let menuElm=_react.default.createElement(StyledMenu,{ref:menuRef,style:menuStyle},_react.default.createElement(StyledUl,{role:"menu"},items.map((item,index)=>{if(isSeperator(item))return _react.default.createElement(StyledLiSeparator,{role:"separator",key:`menuitem-separator-${index}`},_react.default.createElement(_Divider.Divider,{"aria-hidden":"true"}));let{label,destructive,disabled,emphasized,icon,onSelect}=item;return _react.default.createElement(StyledLi,{role:"menuitem",key:`menuitem-${label}`},_react.default.createElement(_MenuItem.MenuItem,{onSelect:onSelect,icon:icon,label:label,disabled:disabled,destructive:destructive,emphasized:emphasized}))})));return isOpen?_react.default.createElement(_Portal.Portal,{portalContainer:portalContainer},menuElm):null}
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var target=exports,all={get OPTIONS_LIST_SELECTOR(){return OPTIONS_LIST_SELECTOR},get OptionsList(){return OptionsList},get getOptionId(){return getOptionId},get getOptionsListId(){return getOptionsListId}};for(var name in all)Object.defineProperty(target,name,{enumerable:!0,get:Object.getOwnPropertyDescriptor(all,name).get});const _interop_require_default=require("@swc/helpers/_/_interop_require_default"),_react=/*#__PURE__*/require("@swc/helpers/_/_interop_require_wildcard")._(require("react")),_react1=require("@emotion/react"),_styled=/*#__PURE__*/_interop_require_default._(require("@emotion/styled")),_useKeyboard=require("../../../shared/useKeyboard"),_useWindow=require("../../../shared/useWindow"),_usePopupMenu=require("../../../shared/popupMenu/usePopupMenu"),_VirtualScrollList=require("../../VirtualScrollList/VirtualScrollList"),_Text=require("../../Typography/Text/Text"),_Box=require("../../Box/Box"),_Inline=require("../../Inline/Inline"),_Icon=require("../../Icon/Icon"),_StyledSelectComponents=require("./StyledSelectComponents"),_constants=require("./constants"),_Stack=require("../../Stack/Stack"),_Checkbox=require("../Checkbox/Checkbox"),_Portal=require("../../Portal/Portal"),_ScreenReaderText=require("../../Utilities/ScreenReaderText/ScreenReaderText"),OPTIONS_LIST_SELECTOR='[role="listbox"], [role="option"]';function getOptionId(selectName,optionValue){return`${selectName}Option${optionValue}`}function getOptionsListId(selectName){return`${selectName}OptionsList`}const scrollToItem=({list,itemIndex,behavior})=>{list[itemIndex]?.scrollIntoView?.({behavior,block:"nearest"})},CustomOption=(0,_styled.default)(_StyledSelectComponents.StyledOption,{target:"e1bzrm20",label:"CustomOption"})(({theme})=>({paddingTop:0,paddingBottom:0,"& > div":{paddingTop:theme.variables.size.spacing.xs,paddingBottom:theme.variables.size.spacing.xs},"& > div *":{marginTop:0}})),StyledListContainer=(0,_styled.default)("div",{target:"e1bzrm21",label:"StyledListContainer"})(({theme,maxHeight})=>({maxHeight,boxSizing:"border-box",overflow:"auto",padding:`${theme.variables.size.spacing.xxs} 0`}));function OptionsList({isOpen,isMultiSelect=!1,value,disabled,options=[],portalContainer,triggerRef,triggerWrapperRef,maxHeight,emptyStateMessage="No options available",selectedIndex,optionsListWidth,isVirtualized=!0,name,onCloseDropdown,onSelectedIndexChange,forceChangeFakeSelect}){let optionsListRef=(0,_react.useRef)(null),listContainerRef=(0,_react.useRef)(null),listItemsRef=(0,_react.useRef)(null),refForPositioning=triggerWrapperRef||triggerRef,activeItemIndex=(0,_react.useMemo)(()=>options.findIndex(option=>isMultiSelect?value.includes(option.value):option.value===value),[options,isMultiSelect,value]),{menuStyle:optionsListStyle,calculateStyle}=(0,_usePopupMenu.usePopupMenu)({triggerRef:refForPositioning,menuRef:optionsListRef,isOpen}),win=(0,_useWindow.useWindow)(),{variables}=(0,_react1.useTheme)(),effectiveMaxHeight=(0,_react.useMemo)(()=>{if(!win||!optionsListStyle.top)return maxHeight;let menuViewportMargin=parseInt(variables.size.spacing.xs,10),menuTopInViewport=optionsListStyle.top-(win.scrollY??0),spaceBelow=win.innerHeight-menuTopInViewport-menuViewportMargin;return!Number.isFinite(spaceBelow)||spaceBelow<=0?maxHeight:maxHeight?Math.min(maxHeight,spaceBelow):spaceBelow},[maxHeight,optionsListStyle,win,variables]);(0,_react.useLayoutEffect)(()=>{if(isOpen&&listContainerRef.current&&!isVirtualized&&optionsListStyle.top){let listElm=listContainerRef.current;listElm.clientHeight<listElm.scrollHeight&&(listItemsRef.current=listElm.querySelectorAll("[data-list-item]"),scrollToItem({list:listItemsRef.current,itemIndex:activeItemIndex,behavior:"instant"}))}else listItemsRef.current=null},[isOpen,isVirtualized,listContainerRef,options,maxHeight,optionsListStyle,activeItemIndex]),(0,_react.useEffect)(()=>{listItemsRef.current&&scrollToItem({list:listItemsRef.current,itemIndex:selectedIndex,behavior:"smooth"})},[listItemsRef,selectedIndex]),(0,_useKeyboard.useKeyboard)({Escape:()=>onCloseDropdown(!0),Enter:()=>{let preselectedOption=options[selectedIndex];if(!preselectedOption?.disabled){if(preselectedOption){forceChangeFakeSelect(preselectedOption),isMultiSelect||onCloseDropdown(!0);return}isMultiSelect||onCloseDropdown()}},ArrowUp:()=>{let newIndex=-1===selectedIndex?activeItemIndex:selectedIndex;for(;newIndex>0&&(newIndex-=1,options[newIndex]?.disabled););options[newIndex]?.disabled||onSelectedIndexChange(newIndex)},ArrowDown:()=>{let newIndex=-1===selectedIndex?activeItemIndex:selectedIndex;for(;newIndex<options.length-1&&(newIndex+=1,options[newIndex]?.disabled););options[newIndex]?.disabled||onSelectedIndexChange(newIndex)}},triggerRef,isOpen&&!disabled);let renderItem=index=>{let option=options[index],id=getOptionId(name,option.value);if(isMultiSelect){let isActive=value.includes(option.value);return _react.default.createElement(CustomOption,{role:"option","aria-selected":isActive,"aria-disabled":option.disabled,id:id,key:option.value,active:isActive,disabled:option.disabled??!1,preSelected:selectedIndex===index,"data-list-item":!0,onMouseDown:()=>{option.disabled||forceChangeFakeSelect(option)},onClick:evt=>evt.stopPropagation()},_react.default.createElement(_Checkbox.CheckboxRaw,{name:"",disabled:option.disabled,checked:isActive,size:"s",label:option.label,onChange:()=>null,labelHint:option?.description}))}let isActive=value===option.value,optionText=_react.default.createElement(_Stack.Stack,{space:"zero"},_react.default.createElement(_Text.Text,{color:"primary",size:"m"},option.label),option.description&&_react.default.createElement(_Text.Text,{color:"tertiary",size:"s"},option.description));return _react.default.createElement(_StyledSelectComponents.StyledOption,{role:"option","aria-selected":isActive,"aria-disabled":option.disabled,id:id,key:option.value,active:isActive,disabled:option.disabled??!1,preSelected:selectedIndex===index,"data-list-item":!0,onMouseDown:()=>{option.disabled||(forceChangeFakeSelect(option),onCloseDropdown(!0))}},isActive?_react.default.createElement(_Inline.Inline,{noWrap:!0,alignItems:"spaceBetween"},optionText,_react.default.createElement(_Box.Box,{space:"zero",tSpace:"xxxs"},_react.default.createElement(_Icon.Icon,{name:"check",size:"s",color:"accent"}))):optionText)},listStyle={...optionsListStyle,width:optionsListWidth||refForPositioning.current?.getBoundingClientRect().width},listElm=_react.default.createElement(_StyledSelectComponents.StyledDropdown,{style:listStyle,ref:optionsListRef,onMouseDown:e=>e.preventDefault(),"data-e2e-test-id":"optionsList"},isVirtualized?_react.default.createElement(_VirtualScrollList.VirtualScrollList,{id:getOptionsListId(name),maxHeight:effectiveMaxHeight,itemHeight:36,itemAmount:options.length,emptyState:()=>null,containerStyle:_constants.dropdownContainerStyle,itemInView:selectedIndex,itemTemplate:renderItem,onContentHeightChange:calculateStyle,role:"listbox"}):_react.default.createElement(StyledListContainer,{maxHeight:effectiveMaxHeight,role:"listbox",id:getOptionsListId(name),ref:listContainerRef},options.map((_option,index)=>renderItem(index))));if(!isOpen)return null;let listPortal=options.length?_react.default.createElement(_Portal.Portal,{portalContainer:portalContainer},listElm):null;return _react.default.createElement(_react.default.Fragment,null,_react.default.createElement(_ScreenReaderText.ScreenReaderText,{role:"status","aria-live":"polite"},options.length?"":emptyStateMessage),listPortal)}
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var target=exports,all={get OPTIONS_LIST_SELECTOR(){return OPTIONS_LIST_SELECTOR},get OptionsList(){return OptionsList},get getOptionId(){return getOptionId},get getOptionsListId(){return getOptionsListId}};for(var name in all)Object.defineProperty(target,name,{enumerable:!0,get:Object.getOwnPropertyDescriptor(all,name).get});const _interop_require_default=require("@swc/helpers/_/_interop_require_default"),_react=/*#__PURE__*/require("@swc/helpers/_/_interop_require_wildcard")._(require("react")),_react1=require("@emotion/react"),_styled=/*#__PURE__*/_interop_require_default._(require("@emotion/styled")),_useKeyboard=require("../../../shared/useKeyboard"),_useContainedEscape=require("../../../shared/useContainedEscape"),_useWindow=require("../../../shared/useWindow"),_usePopupMenu=require("../../../shared/popupMenu/usePopupMenu"),_VirtualScrollList=require("../../VirtualScrollList/VirtualScrollList"),_Text=require("../../Typography/Text/Text"),_Box=require("../../Box/Box"),_Inline=require("../../Inline/Inline"),_Icon=require("../../Icon/Icon"),_StyledSelectComponents=require("./StyledSelectComponents"),_constants=require("./constants"),_Stack=require("../../Stack/Stack"),_Checkbox=require("../Checkbox/Checkbox"),_Portal=require("../../Portal/Portal"),_ScreenReaderText=require("../../Utilities/ScreenReaderText/ScreenReaderText"),OPTIONS_LIST_SELECTOR='[role="listbox"], [role="option"]';function getOptionId(selectName,optionValue){return`${selectName}Option${optionValue}`}function getOptionsListId(selectName){return`${selectName}OptionsList`}const scrollToItem=({list,itemIndex,behavior})=>{list[itemIndex]?.scrollIntoView?.({behavior,block:"nearest"})},CustomOption=(0,_styled.default)(_StyledSelectComponents.StyledOption,{target:"evwdew0",label:"CustomOption"})(({theme})=>({paddingTop:0,paddingBottom:0,"& > div":{paddingTop:theme.variables.size.spacing.xs,paddingBottom:theme.variables.size.spacing.xs},"& > div *":{marginTop:0}})),StyledListContainer=(0,_styled.default)("div",{target:"evwdew1",label:"StyledListContainer"})(({theme,maxHeight})=>({maxHeight,boxSizing:"border-box",overflow:"auto",padding:`${theme.variables.size.spacing.xxs} 0`}));function OptionsList({isOpen,isMultiSelect=!1,value,disabled,options=[],portalContainer,triggerRef,triggerWrapperRef,maxHeight,emptyStateMessage="No options available",selectedIndex,optionsListWidth,isVirtualized=!0,name,onCloseDropdown,onSelectedIndexChange,forceChangeFakeSelect}){let optionsListRef=(0,_react.useRef)(null),listContainerRef=(0,_react.useRef)(null),listItemsRef=(0,_react.useRef)(null),refForPositioning=triggerWrapperRef||triggerRef,activeItemIndex=(0,_react.useMemo)(()=>options.findIndex(option=>isMultiSelect?value.includes(option.value):option.value===value),[options,isMultiSelect,value]),{menuStyle:optionsListStyle,calculateStyle}=(0,_usePopupMenu.usePopupMenu)({triggerRef:refForPositioning,menuRef:optionsListRef,isOpen}),win=(0,_useWindow.useWindow)(),{variables}=(0,_react1.useTheme)(),effectiveMaxHeight=(0,_react.useMemo)(()=>{if(!win||!optionsListStyle.top)return maxHeight;let menuViewportMargin=parseInt(variables.size.spacing.xs,10),menuTopInViewport=optionsListStyle.top-(win.scrollY??0),spaceBelow=win.innerHeight-menuTopInViewport-menuViewportMargin;return!Number.isFinite(spaceBelow)||spaceBelow<=0?maxHeight:maxHeight?Math.min(maxHeight,spaceBelow):spaceBelow},[maxHeight,optionsListStyle,win,variables]);(0,_react.useLayoutEffect)(()=>{if(isOpen&&listContainerRef.current&&!isVirtualized&&optionsListStyle.top){let listElm=listContainerRef.current;listElm.clientHeight<listElm.scrollHeight&&(listItemsRef.current=listElm.querySelectorAll("[data-list-item]"),scrollToItem({list:listItemsRef.current,itemIndex:activeItemIndex,behavior:"instant"}))}else listItemsRef.current=null},[isOpen,isVirtualized,listContainerRef,options,maxHeight,optionsListStyle,activeItemIndex]),(0,_react.useEffect)(()=>{listItemsRef.current&&scrollToItem({list:listItemsRef.current,itemIndex:selectedIndex,behavior:"smooth"})},[listItemsRef,selectedIndex]);let closeDropdownWithoutSelect=(0,_react.useCallback)(()=>onCloseDropdown(!0),[onCloseDropdown]);(0,_useContainedEscape.useContainedEscape)([triggerRef],closeDropdownWithoutSelect,isOpen&&!disabled),(0,_useKeyboard.useKeyboard)({Enter:()=>{let preselectedOption=options[selectedIndex];if(!preselectedOption?.disabled){if(preselectedOption){forceChangeFakeSelect(preselectedOption),isMultiSelect||onCloseDropdown(!0);return}isMultiSelect||onCloseDropdown()}},ArrowUp:()=>{let newIndex=-1===selectedIndex?activeItemIndex:selectedIndex;for(;newIndex>0&&(newIndex-=1,options[newIndex]?.disabled););options[newIndex]?.disabled||onSelectedIndexChange(newIndex)},ArrowDown:()=>{let newIndex=-1===selectedIndex?activeItemIndex:selectedIndex;for(;newIndex<options.length-1&&(newIndex+=1,options[newIndex]?.disabled););options[newIndex]?.disabled||onSelectedIndexChange(newIndex)}},triggerRef,isOpen&&!disabled);let renderItem=index=>{let option=options[index],id=getOptionId(name,option.value);if(isMultiSelect){let isActive=value.includes(option.value);return _react.default.createElement(CustomOption,{role:"option","aria-selected":isActive,"aria-disabled":option.disabled,id:id,key:option.value,active:isActive,disabled:option.disabled??!1,preSelected:selectedIndex===index,"data-list-item":!0,onMouseDown:()=>{option.disabled||forceChangeFakeSelect(option)},onClick:evt=>evt.stopPropagation()},_react.default.createElement(_Checkbox.CheckboxRaw,{name:"",disabled:option.disabled,checked:isActive,size:"s",label:option.label,onChange:()=>null,labelHint:option?.description}))}let isActive=value===option.value,optionText=_react.default.createElement(_Stack.Stack,{space:"zero"},_react.default.createElement(_Text.Text,{color:"primary",size:"m"},option.label),option.description&&_react.default.createElement(_Text.Text,{color:"tertiary",size:"s"},option.description));return _react.default.createElement(_StyledSelectComponents.StyledOption,{role:"option","aria-selected":isActive,"aria-disabled":option.disabled,id:id,key:option.value,active:isActive,disabled:option.disabled??!1,preSelected:selectedIndex===index,"data-list-item":!0,onMouseDown:()=>{option.disabled||(forceChangeFakeSelect(option),onCloseDropdown(!0))}},isActive?_react.default.createElement(_Inline.Inline,{noWrap:!0,alignItems:"spaceBetween"},optionText,_react.default.createElement(_Box.Box,{space:"zero",tSpace:"xxxs"},_react.default.createElement(_Icon.Icon,{name:"check",size:"s",color:"accent"}))):optionText)},listStyle={...optionsListStyle,width:optionsListWidth||refForPositioning.current?.getBoundingClientRect().width},listElm=_react.default.createElement(_StyledSelectComponents.StyledDropdown,{style:listStyle,ref:optionsListRef,onMouseDown:e=>e.preventDefault(),"data-e2e-test-id":"optionsList"},isVirtualized?_react.default.createElement(_VirtualScrollList.VirtualScrollList,{id:getOptionsListId(name),maxHeight:effectiveMaxHeight,itemHeight:36,itemAmount:options.length,emptyState:()=>null,containerStyle:_constants.dropdownContainerStyle,itemInView:selectedIndex,itemTemplate:renderItem,onContentHeightChange:calculateStyle,role:"listbox"}):_react.default.createElement(StyledListContainer,{maxHeight:effectiveMaxHeight,role:"listbox",id:getOptionsListId(name),ref:listContainerRef},options.map((_option,index)=>renderItem(index))));if(!isOpen)return null;let listPortal=options.length?_react.default.createElement(_Portal.Portal,{portalContainer:portalContainer},listElm):null;return _react.default.createElement(_react.default.Fragment,null,_react.default.createElement(_ScreenReaderText.ScreenReaderText,{role:"status","aria-live":"polite"},options.length?"":emptyStateMessage),listPortal)}
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"SelectWithCustomTrigger",{enumerable:!0,get:function(){return SelectWithCustomTrigger}});const _interop_require_default=require("@swc/helpers/_/_interop_require_default"),_react=/*#__PURE__*/require("@swc/helpers/_/_interop_require_wildcard")._(require("react")),_styled=/*#__PURE__*/_interop_require_default._(require("@emotion/styled")),_OptionsList=require("../Combobox/OptionsList"),_useKeyboard=require("../../../shared/useKeyboard"),_useTypeAheadSearch=require("./useTypeAheadSearch"),HiddenSelectInput=(0,_styled.default)("select",{target:"ejxvztk0",label:"HiddenSelectInput"})(()=>({display:"none"}));function SelectWithCustomTrigger({renderTrigger,optionsListWidth,options=[],name,value,portalContainer,disabled=!1,maxHeight=230,autoComplete="on",readOnly=!1,excludeFromFormData=!1,onChange}){let[isOpen,setIsOpen]=(0,_react.useState)(!1),[selectedIndex,setSelectedIndex]=(0,_react.useState)(-1),triggerRef=(0,_react.useRef)(null),hiddenSelectRef=(0,_react.useRef)(null),currentOptionIndex=(0,_react.useMemo)(()=>options.findIndex(option=>option.value===value),[options,value]),closeOptionsList=(0,_react.useCallback)(()=>{isOpen&&(setIsOpen(!1),setSelectedIndex(-1))},[isOpen]),openOptionsList=(0,_react.useCallback)(()=>{isOpen||readOnly||(setIsOpen(!0),triggerRef.current?.focus())},[isOpen,readOnly]),toggleOptionsList=(0,_react.useCallback)(()=>{isOpen?closeOptionsList():openOptionsList()},[isOpen,openOptionsList,closeOptionsList]),handleSelectedIndexChange=(0,_react.useCallback)(index=>setSelectedIndex(index),[]),handleChange=(0,_react.useCallback)(option=>{let hiddenSelect=hiddenSelectRef.current;hiddenSelect&&(hiddenSelect.value=option.value,hiddenSelect.dispatchEvent(new Event("change",{bubbles:!0})))},[hiddenSelectRef]),handleSearchMatch=(0,_react.useCallback)(matchedIndex=>{-1!==matchedIndex&&(isOpen?setSelectedIndex(matchedIndex):handleChange(options[matchedIndex]))},[isOpen,options,setSelectedIndex,handleChange]);(0,_useKeyboard.useKeyboard)({"Enter Space ArrowUp ArrowDown":()=>{openOptionsList()}},triggerRef,!isOpen&&!disabled),(0,_useTypeAheadSearch.useTypeAheadSearch)({options,triggerRef,isActive:!disabled,fromIndex:-1!==selectedIndex?selectedIndex:currentOptionIndex,onMatch:handleSearchMatch}),(0,_react.useEffect)(()=>{let triggerElm=triggerRef.current,handlePointerDown=evt=>{evt.preventDefault()};return triggerElm&&!disabled&&(triggerElm.setAttribute("tabIndex","0"),triggerElm.addEventListener("click",toggleOptionsList),triggerElm.addEventListener("blur",closeOptionsList),triggerElm.addEventListener("pointerdown",handlePointerDown)),()=>{triggerElm?.removeEventListener("click",toggleOptionsList),triggerElm?.removeEventListener("blur",closeOptionsList),triggerElm?.removeEventListener("pointerdown",handlePointerDown)}},[triggerRef,disabled,closeOptionsList,toggleOptionsList]),(0,_react.useEffect)(()=>{let triggerElm=triggerRef.current,handleEscapeKeyDown=evt=>{"Escape"===evt.code&&(evt.preventDefault(),evt.stopPropagation(),closeOptionsList())};return triggerElm&&isOpen&&triggerElm.addEventListener("keydown",handleEscapeKeyDown),()=>{triggerElm?.removeEventListener("keydown",handleEscapeKeyDown)}},[triggerRef,isOpen,closeOptionsList]);let optionsListId=(0,_OptionsList.getOptionsListId)(name),ariaActiveDescendant=-1!==selectedIndex?(0,_OptionsList.getOptionId)(name,options[selectedIndex].value):"",triggerElm=renderTrigger({triggerRef,isOpen,disabled,role:"combobox","aria-activedescendant":isOpen?ariaActiveDescendant:"","aria-controls":isOpen?optionsListId:"","aria-expanded":isOpen}),optionsListElm=_react.default.createElement(_OptionsList.OptionsList,{name:name,isOpen:isOpen,isVirtualized:!1,options:options,triggerRef:triggerRef,onCloseDropdown:closeOptionsList,portalContainer:portalContainer,selectedIndex:selectedIndex,onSelectedIndexChange:handleSelectedIndexChange,forceChangeFakeSelect:handleChange,value:value,disabled:disabled,maxHeight:maxHeight,optionsListWidth:optionsListWidth});return _react.default.createElement(_react.default.Fragment,null,triggerElm,optionsListElm,_react.default.createElement(HiddenSelectInput,{name:excludeFromFormData?void 0:name,onChange:onChange,value:value,ref:hiddenSelectRef,autoComplete:autoComplete},_react.default.createElement("option",{value:"","aria-label":"Empty option"}),options.map(option=>_react.default.createElement("option",{value:option.value,key:option.value},option.label))))}
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"SelectWithCustomTrigger",{enumerable:!0,get:function(){return SelectWithCustomTrigger}});const _interop_require_default=require("@swc/helpers/_/_interop_require_default"),_react=/*#__PURE__*/require("@swc/helpers/_/_interop_require_wildcard")._(require("react")),_styled=/*#__PURE__*/_interop_require_default._(require("@emotion/styled")),_OptionsList=require("../Combobox/OptionsList"),_useContainedEscape=require("../../../shared/useContainedEscape"),_useKeyboard=require("../../../shared/useKeyboard"),_useTypeAheadSearch=require("./useTypeAheadSearch"),HiddenSelectInput=(0,_styled.default)("select",{target:"e2kj7nk0",label:"HiddenSelectInput"})(()=>({display:"none"}));function SelectWithCustomTrigger({renderTrigger,optionsListWidth,options=[],name,value,portalContainer,disabled=!1,maxHeight=230,autoComplete="on",readOnly=!1,excludeFromFormData=!1,onChange}){let[isOpen,setIsOpen]=(0,_react.useState)(!1),[selectedIndex,setSelectedIndex]=(0,_react.useState)(-1),triggerRef=(0,_react.useRef)(null),hiddenSelectRef=(0,_react.useRef)(null),currentOptionIndex=(0,_react.useMemo)(()=>options.findIndex(option=>option.value===value),[options,value]),closeOptionsList=(0,_react.useCallback)(()=>{isOpen&&(setIsOpen(!1),setSelectedIndex(-1))},[isOpen]),openOptionsList=(0,_react.useCallback)(()=>{isOpen||readOnly||(setIsOpen(!0),triggerRef.current?.focus())},[isOpen,readOnly]),toggleOptionsList=(0,_react.useCallback)(()=>{isOpen?closeOptionsList():openOptionsList()},[isOpen,openOptionsList,closeOptionsList]),handleSelectedIndexChange=(0,_react.useCallback)(index=>setSelectedIndex(index),[]),handleChange=(0,_react.useCallback)(option=>{let hiddenSelect=hiddenSelectRef.current;hiddenSelect&&(hiddenSelect.value=option.value,hiddenSelect.dispatchEvent(new Event("change",{bubbles:!0})))},[hiddenSelectRef]),handleSearchMatch=(0,_react.useCallback)(matchedIndex=>{-1!==matchedIndex&&(isOpen?setSelectedIndex(matchedIndex):handleChange(options[matchedIndex]))},[isOpen,options,setSelectedIndex,handleChange]);(0,_useKeyboard.useKeyboard)({"Enter Space ArrowUp ArrowDown":()=>{openOptionsList()}},triggerRef,!isOpen&&!disabled),(0,_useTypeAheadSearch.useTypeAheadSearch)({options,triggerRef,isActive:!disabled,fromIndex:-1!==selectedIndex?selectedIndex:currentOptionIndex,onMatch:handleSearchMatch}),(0,_react.useEffect)(()=>{let triggerElm=triggerRef.current,handlePointerDown=evt=>{evt.preventDefault()};return triggerElm&&!disabled&&(triggerElm.setAttribute("tabIndex","0"),triggerElm.addEventListener("click",toggleOptionsList),triggerElm.addEventListener("blur",closeOptionsList),triggerElm.addEventListener("pointerdown",handlePointerDown)),()=>{triggerElm?.removeEventListener("click",toggleOptionsList),triggerElm?.removeEventListener("blur",closeOptionsList),triggerElm?.removeEventListener("pointerdown",handlePointerDown)}},[triggerRef,disabled,closeOptionsList,toggleOptionsList]),(0,_useContainedEscape.useContainedEscape)([triggerRef],closeOptionsList,isOpen);let optionsListId=(0,_OptionsList.getOptionsListId)(name),ariaActiveDescendant=-1!==selectedIndex?(0,_OptionsList.getOptionId)(name,options[selectedIndex].value):"",triggerElm=renderTrigger({triggerRef,isOpen,disabled,role:"combobox","aria-activedescendant":isOpen?ariaActiveDescendant:"","aria-controls":isOpen?optionsListId:"","aria-expanded":isOpen}),optionsListElm=_react.default.createElement(_OptionsList.OptionsList,{name:name,isOpen:isOpen,isVirtualized:!1,options:options,triggerRef:triggerRef,onCloseDropdown:closeOptionsList,portalContainer:portalContainer,selectedIndex:selectedIndex,onSelectedIndexChange:handleSelectedIndexChange,forceChangeFakeSelect:handleChange,value:value,disabled:disabled,maxHeight:maxHeight,optionsListWidth:optionsListWidth});return _react.default.createElement(_react.default.Fragment,null,triggerElm,optionsListElm,_react.default.createElement(HiddenSelectInput,{name:excludeFromFormData?void 0:name,onChange:onChange,value:value,ref:hiddenSelectRef,autoComplete:autoComplete},_react.default.createElement("option",{value:"","aria-label":"Empty option"}),options.map(option=>_react.default.createElement("option",{value:option.value,key:option.value},option.label))))}
@@ -0,0 +1,13 @@
1
+ import type { RefObject } from "react";
2
+ /**
3
+ * useContainedEscape handles Escape on the given elements and stops it there,
4
+ * before it reaches document. An enclosing focus trap with escapeDeactivates
5
+ * (e.g. a Modal) listens on document, so a popup that closes on Escape must
6
+ * stop the event first to close only itself.
7
+ * @param {RefObject[]} refs - Elements that receive keydown while the popup is open, e.g. its trigger.
8
+ * @param {e: KeyboardEvent => void} onEscape - Function invoked when Escape is pressed on one of the elements.
9
+ * @param {boolean} isActive - A flag to determine when the Escape listener needs to be applied.
10
+ *
11
+ * Example: useContainedEscape([triggerRef], closeList, listIsOpen)
12
+ */
13
+ export declare const useContainedEscape: (refs: RefObject<HTMLElement>[], onEscape: (e: KeyboardEvent) => void, isActive: boolean) => void;
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"useContainedEscape",{enumerable:!0,get:function(){return useContainedEscape}});const _react=require("react"),useContainedEscape=(refs,onEscape,isActive)=>{let refsRef=(0,_react.useRef)(refs);refsRef.current=refs,(0,_react.useEffect)(()=>{if(!isActive)return;let elements=refsRef.current.map(ref=>ref.current),handleEscapeKeyDown=evt=>{"Escape"===evt.code&&(evt.preventDefault(),evt.stopPropagation(),onEscape(evt))};return elements.forEach(elm=>elm?.addEventListener("keydown",handleEscapeKeyDown)),()=>{elements.forEach(elm=>elm?.removeEventListener("keydown",handleEscapeKeyDown))}},[onEscape,isActive])};
@@ -1 +1 @@
1
- import React,{useEffect,useRef,useState}from"react";import styled from"@emotion/styled";import{useKeyboard}from"../../shared/useKeyboard";import{Divider}from"../Divider/Divider";import{MenuItem}from"./MenuItem";import{usePopupMenu}from"../../shared/popupMenu/usePopupMenu";import{useOutsideInteract}from"../../shared/useOutsideInteract";import{Portal,usePortalChildZIndex}from"../Portal/Portal";let isSeperator=item=>"separator"===item,StyledMenu=styled("div",{target:"e1gy87fm0",label:"StyledMenu"})(({theme})=>{let zIndex=usePortalChildZIndex(theme.variables.zIndex.dropdown);return{position:"absolute",display:"inline-block",width:"fit-content",minWidth:theme.variables.size.dimension.dropdownMenu.width,zIndex,borderRadius:theme.variables.size.borderRadius.s,backgroundColor:theme.values.color.background.primary.default,paddingTop:theme.variables.size.spacing.xs,paddingBottom:theme.variables.size.spacing.xs,":after":{content:'" "',position:"absolute",top:0,left:0,width:"100%",height:"100%",pointerEvents:"none",borderRadius:"inherit",boxShadow:theme.values.elevation[3]}}}),StyledUl=styled("ul",{target:"e1gy87fm1",label:"StyledUl"})(()=>({margin:0,padding:0,overflow:"hidden"})),StyledLi=styled("li",{target:"e1gy87fm2",label:"StyledLi"})(()=>({margin:0,padding:0,width:"100%",listStyleType:"none",whiteSpace:"nowrap"})),StyledLiSeparator=styled(StyledLi,{target:"e1gy87fm3",label:"StyledLiSeparator"})(({theme})=>({marginTop:theme.variables.size.spacing.xs,marginBottom:theme.variables.size.spacing.xs}));export function Menu({isOpen,items,portalContainer,triggerRef,placement,onCloseMenu}){let menuRef=useRef(null),[focusIndex,setFocusIndex]=useState(0),{menuStyle}=usePopupMenu({triggerRef,menuRef,isOpen,placement});useOutsideInteract({ref:menuRef,excludeRefs:[triggerRef],onInteractOutside:onCloseMenu,isActive:isOpen}),useKeyboard({Escape:onCloseMenu,ArrowUp:()=>{setFocusIndex(index=>index-1)},ArrowDown:()=>{setFocusIndex(index=>index+1)}},menuRef,isOpen),useEffect(()=>{if(menuRef&&menuRef.current){let buttons=menuRef.current.querySelectorAll("button");buttons[Math.abs(focusIndex)%buttons.length].focus({preventScroll:!0})}isOpen||setFocusIndex(0)},[menuRef,focusIndex,isOpen]);let menuElm=React.createElement(StyledMenu,{ref:menuRef,style:menuStyle},React.createElement(StyledUl,{role:"menu"},items.map((item,index)=>{if(isSeperator(item))return React.createElement(StyledLiSeparator,{role:"separator",key:`menuitem-separator-${index}`},React.createElement(Divider,{"aria-hidden":"true"}));let{label,destructive,disabled,emphasized,icon,onSelect}=item;return React.createElement(StyledLi,{role:"menuitem",key:`menuitem-${label}`},React.createElement(MenuItem,{onSelect:onSelect,icon:icon,label:label,disabled:disabled,destructive:destructive,emphasized:emphasized}))})));return isOpen?React.createElement(Portal,{portalContainer:portalContainer},menuElm):null}
1
+ import React,{useEffect,useRef,useState}from"react";import styled from"@emotion/styled";import{useKeyboard}from"../../shared/useKeyboard";import{useContainedEscape}from"../../shared/useContainedEscape";import{Divider}from"../Divider/Divider";import{MenuItem}from"./MenuItem";import{usePopupMenu}from"../../shared/popupMenu/usePopupMenu";import{useOutsideInteract}from"../../shared/useOutsideInteract";import{Portal,usePortalChildZIndex}from"../Portal/Portal";let isSeperator=item=>"separator"===item,StyledMenu=styled("div",{target:"ecmxohu0",label:"StyledMenu"})(({theme})=>{let zIndex=usePortalChildZIndex(theme.variables.zIndex.dropdown);return{position:"absolute",display:"inline-block",width:"fit-content",minWidth:theme.variables.size.dimension.dropdownMenu.width,zIndex,borderRadius:theme.variables.size.borderRadius.s,backgroundColor:theme.values.color.background.primary.default,paddingTop:theme.variables.size.spacing.xs,paddingBottom:theme.variables.size.spacing.xs,":after":{content:'" "',position:"absolute",top:0,left:0,width:"100%",height:"100%",pointerEvents:"none",borderRadius:"inherit",boxShadow:theme.values.elevation[3]}}}),StyledUl=styled("ul",{target:"ecmxohu1",label:"StyledUl"})(()=>({margin:0,padding:0,overflow:"hidden"})),StyledLi=styled("li",{target:"ecmxohu2",label:"StyledLi"})(()=>({margin:0,padding:0,width:"100%",listStyleType:"none",whiteSpace:"nowrap"})),StyledLiSeparator=styled(StyledLi,{target:"ecmxohu3",label:"StyledLiSeparator"})(({theme})=>({marginTop:theme.variables.size.spacing.xs,marginBottom:theme.variables.size.spacing.xs}));export function Menu({isOpen,items,portalContainer,triggerRef,placement,onCloseMenu}){let menuRef=useRef(null),[focusIndex,setFocusIndex]=useState(0),{menuStyle}=usePopupMenu({triggerRef,menuRef,isOpen,placement});useOutsideInteract({ref:menuRef,excludeRefs:[triggerRef],onInteractOutside:onCloseMenu,isActive:isOpen}),useContainedEscape([menuRef,triggerRef],onCloseMenu,isOpen),useKeyboard({ArrowUp:()=>{setFocusIndex(index=>index-1)},ArrowDown:()=>{setFocusIndex(index=>index+1)}},menuRef,isOpen),useEffect(()=>{if(menuRef&&menuRef.current){let buttons=menuRef.current.querySelectorAll("button");buttons[Math.abs(focusIndex)%buttons.length].focus({preventScroll:!0})}isOpen||setFocusIndex(0)},[menuRef,focusIndex,isOpen]);let menuElm=React.createElement(StyledMenu,{ref:menuRef,style:menuStyle},React.createElement(StyledUl,{role:"menu"},items.map((item,index)=>{if(isSeperator(item))return React.createElement(StyledLiSeparator,{role:"separator",key:`menuitem-separator-${index}`},React.createElement(Divider,{"aria-hidden":"true"}));let{label,destructive,disabled,emphasized,icon,onSelect}=item;return React.createElement(StyledLi,{role:"menuitem",key:`menuitem-${label}`},React.createElement(MenuItem,{onSelect:onSelect,icon:icon,label:label,disabled:disabled,destructive:destructive,emphasized:emphasized}))})));return isOpen?React.createElement(Portal,{portalContainer:portalContainer},menuElm):null}
@@ -1 +1 @@
1
- import React,{useRef,useEffect,useLayoutEffect,useMemo}from"react";import{useTheme}from"@emotion/react";import styled from"@emotion/styled";import{useKeyboard}from"../../../shared/useKeyboard";import{useWindow}from"../../../shared/useWindow";import{usePopupMenu}from"../../../shared/popupMenu/usePopupMenu";import{VirtualScrollList}from"../../VirtualScrollList/VirtualScrollList";import{Text}from"../../Typography/Text/Text";import{Box}from"../../Box/Box";import{Inline}from"../../Inline/Inline";import{Icon}from"../../Icon/Icon";import{StyledDropdown,StyledOption}from"./StyledSelectComponents";import{dropdownContainerStyle}from"./constants";import{Stack}from"../../Stack/Stack";import{CheckboxRaw}from"../Checkbox/Checkbox";import{Portal}from"../../Portal/Portal";import{ScreenReaderText}from"../../Utilities/ScreenReaderText/ScreenReaderText";export const OPTIONS_LIST_SELECTOR='[role="listbox"], [role="option"]';export function getOptionId(selectName,optionValue){return`${selectName}Option${optionValue}`}export function getOptionsListId(selectName){return`${selectName}OptionsList`}let scrollToItem=({list,itemIndex,behavior})=>{list[itemIndex]?.scrollIntoView?.({behavior,block:"nearest"})},CustomOption=styled(StyledOption,{target:"e1bzrm20",label:"CustomOption"})(({theme})=>({paddingTop:0,paddingBottom:0,"& > div":{paddingTop:theme.variables.size.spacing.xs,paddingBottom:theme.variables.size.spacing.xs},"& > div *":{marginTop:0}})),StyledListContainer=styled("div",{target:"e1bzrm21",label:"StyledListContainer"})(({theme,maxHeight})=>({maxHeight,boxSizing:"border-box",overflow:"auto",padding:`${theme.variables.size.spacing.xxs} 0`}));export function OptionsList({isOpen,isMultiSelect=!1,value,disabled,options=[],portalContainer,triggerRef,triggerWrapperRef,maxHeight,emptyStateMessage="No options available",selectedIndex,optionsListWidth,isVirtualized=!0,name,onCloseDropdown,onSelectedIndexChange,forceChangeFakeSelect}){let optionsListRef=useRef(null),listContainerRef=useRef(null),listItemsRef=useRef(null),refForPositioning=triggerWrapperRef||triggerRef,activeItemIndex=useMemo(()=>options.findIndex(option=>isMultiSelect?value.includes(option.value):option.value===value),[options,isMultiSelect,value]),{menuStyle:optionsListStyle,calculateStyle}=usePopupMenu({triggerRef:refForPositioning,menuRef:optionsListRef,isOpen}),win=useWindow(),{variables}=useTheme(),effectiveMaxHeight=useMemo(()=>{if(!win||!optionsListStyle.top)return maxHeight;let menuViewportMargin=parseInt(variables.size.spacing.xs,10),menuTopInViewport=optionsListStyle.top-(win.scrollY??0),spaceBelow=win.innerHeight-menuTopInViewport-menuViewportMargin;return!Number.isFinite(spaceBelow)||spaceBelow<=0?maxHeight:maxHeight?Math.min(maxHeight,spaceBelow):spaceBelow},[maxHeight,optionsListStyle,win,variables]);useLayoutEffect(()=>{if(isOpen&&listContainerRef.current&&!isVirtualized&&optionsListStyle.top){let listElm=listContainerRef.current;listElm.clientHeight<listElm.scrollHeight&&(listItemsRef.current=listElm.querySelectorAll("[data-list-item]"),scrollToItem({list:listItemsRef.current,itemIndex:activeItemIndex,behavior:"instant"}))}else listItemsRef.current=null},[isOpen,isVirtualized,listContainerRef,options,maxHeight,optionsListStyle,activeItemIndex]),useEffect(()=>{listItemsRef.current&&scrollToItem({list:listItemsRef.current,itemIndex:selectedIndex,behavior:"smooth"})},[listItemsRef,selectedIndex]),useKeyboard({Escape:()=>onCloseDropdown(!0),Enter:()=>{let preselectedOption=options[selectedIndex];if(!preselectedOption?.disabled){if(preselectedOption){forceChangeFakeSelect(preselectedOption),isMultiSelect||onCloseDropdown(!0);return}isMultiSelect||onCloseDropdown()}},ArrowUp:()=>{let newIndex=-1===selectedIndex?activeItemIndex:selectedIndex;for(;newIndex>0&&(newIndex-=1,options[newIndex]?.disabled););options[newIndex]?.disabled||onSelectedIndexChange(newIndex)},ArrowDown:()=>{let newIndex=-1===selectedIndex?activeItemIndex:selectedIndex;for(;newIndex<options.length-1&&(newIndex+=1,options[newIndex]?.disabled););options[newIndex]?.disabled||onSelectedIndexChange(newIndex)}},triggerRef,isOpen&&!disabled);let renderItem=index=>{let option=options[index],id=getOptionId(name,option.value);if(isMultiSelect){let isActive=value.includes(option.value);return React.createElement(CustomOption,{role:"option","aria-selected":isActive,"aria-disabled":option.disabled,id:id,key:option.value,active:isActive,disabled:option.disabled??!1,preSelected:selectedIndex===index,"data-list-item":!0,onMouseDown:()=>{option.disabled||forceChangeFakeSelect(option)},onClick:evt=>evt.stopPropagation()},React.createElement(CheckboxRaw,{name:"",disabled:option.disabled,checked:isActive,size:"s",label:option.label,onChange:()=>null,labelHint:option?.description}))}let isActive=value===option.value,optionText=React.createElement(Stack,{space:"zero"},React.createElement(Text,{color:"primary",size:"m"},option.label),option.description&&React.createElement(Text,{color:"tertiary",size:"s"},option.description));return React.createElement(StyledOption,{role:"option","aria-selected":isActive,"aria-disabled":option.disabled,id:id,key:option.value,active:isActive,disabled:option.disabled??!1,preSelected:selectedIndex===index,"data-list-item":!0,onMouseDown:()=>{option.disabled||(forceChangeFakeSelect(option),onCloseDropdown(!0))}},isActive?React.createElement(Inline,{noWrap:!0,alignItems:"spaceBetween"},optionText,React.createElement(Box,{space:"zero",tSpace:"xxxs"},React.createElement(Icon,{name:"check",size:"s",color:"accent"}))):optionText)},listStyle={...optionsListStyle,width:optionsListWidth||refForPositioning.current?.getBoundingClientRect().width},listElm=React.createElement(StyledDropdown,{style:listStyle,ref:optionsListRef,onMouseDown:e=>e.preventDefault(),"data-e2e-test-id":"optionsList"},isVirtualized?React.createElement(VirtualScrollList,{id:getOptionsListId(name),maxHeight:effectiveMaxHeight,itemHeight:36,itemAmount:options.length,emptyState:()=>null,containerStyle:dropdownContainerStyle,itemInView:selectedIndex,itemTemplate:renderItem,onContentHeightChange:calculateStyle,role:"listbox"}):React.createElement(StyledListContainer,{maxHeight:effectiveMaxHeight,role:"listbox",id:getOptionsListId(name),ref:listContainerRef},options.map((_option,index)=>renderItem(index))));if(!isOpen)return null;let listPortal=options.length?React.createElement(Portal,{portalContainer:portalContainer},listElm):null;return React.createElement(React.Fragment,null,React.createElement(ScreenReaderText,{role:"status","aria-live":"polite"},options.length?"":emptyStateMessage),listPortal)}
1
+ import React,{useRef,useEffect,useLayoutEffect,useMemo,useCallback}from"react";import{useTheme}from"@emotion/react";import styled from"@emotion/styled";import{useKeyboard}from"../../../shared/useKeyboard";import{useContainedEscape}from"../../../shared/useContainedEscape";import{useWindow}from"../../../shared/useWindow";import{usePopupMenu}from"../../../shared/popupMenu/usePopupMenu";import{VirtualScrollList}from"../../VirtualScrollList/VirtualScrollList";import{Text}from"../../Typography/Text/Text";import{Box}from"../../Box/Box";import{Inline}from"../../Inline/Inline";import{Icon}from"../../Icon/Icon";import{StyledDropdown,StyledOption}from"./StyledSelectComponents";import{dropdownContainerStyle}from"./constants";import{Stack}from"../../Stack/Stack";import{CheckboxRaw}from"../Checkbox/Checkbox";import{Portal}from"../../Portal/Portal";import{ScreenReaderText}from"../../Utilities/ScreenReaderText/ScreenReaderText";export const OPTIONS_LIST_SELECTOR='[role="listbox"], [role="option"]';export function getOptionId(selectName,optionValue){return`${selectName}Option${optionValue}`}export function getOptionsListId(selectName){return`${selectName}OptionsList`}let scrollToItem=({list,itemIndex,behavior})=>{list[itemIndex]?.scrollIntoView?.({behavior,block:"nearest"})},CustomOption=styled(StyledOption,{target:"evwdew0",label:"CustomOption"})(({theme})=>({paddingTop:0,paddingBottom:0,"& > div":{paddingTop:theme.variables.size.spacing.xs,paddingBottom:theme.variables.size.spacing.xs},"& > div *":{marginTop:0}})),StyledListContainer=styled("div",{target:"evwdew1",label:"StyledListContainer"})(({theme,maxHeight})=>({maxHeight,boxSizing:"border-box",overflow:"auto",padding:`${theme.variables.size.spacing.xxs} 0`}));export function OptionsList({isOpen,isMultiSelect=!1,value,disabled,options=[],portalContainer,triggerRef,triggerWrapperRef,maxHeight,emptyStateMessage="No options available",selectedIndex,optionsListWidth,isVirtualized=!0,name,onCloseDropdown,onSelectedIndexChange,forceChangeFakeSelect}){let optionsListRef=useRef(null),listContainerRef=useRef(null),listItemsRef=useRef(null),refForPositioning=triggerWrapperRef||triggerRef,activeItemIndex=useMemo(()=>options.findIndex(option=>isMultiSelect?value.includes(option.value):option.value===value),[options,isMultiSelect,value]),{menuStyle:optionsListStyle,calculateStyle}=usePopupMenu({triggerRef:refForPositioning,menuRef:optionsListRef,isOpen}),win=useWindow(),{variables}=useTheme(),effectiveMaxHeight=useMemo(()=>{if(!win||!optionsListStyle.top)return maxHeight;let menuViewportMargin=parseInt(variables.size.spacing.xs,10),menuTopInViewport=optionsListStyle.top-(win.scrollY??0),spaceBelow=win.innerHeight-menuTopInViewport-menuViewportMargin;return!Number.isFinite(spaceBelow)||spaceBelow<=0?maxHeight:maxHeight?Math.min(maxHeight,spaceBelow):spaceBelow},[maxHeight,optionsListStyle,win,variables]);useLayoutEffect(()=>{if(isOpen&&listContainerRef.current&&!isVirtualized&&optionsListStyle.top){let listElm=listContainerRef.current;listElm.clientHeight<listElm.scrollHeight&&(listItemsRef.current=listElm.querySelectorAll("[data-list-item]"),scrollToItem({list:listItemsRef.current,itemIndex:activeItemIndex,behavior:"instant"}))}else listItemsRef.current=null},[isOpen,isVirtualized,listContainerRef,options,maxHeight,optionsListStyle,activeItemIndex]),useEffect(()=>{listItemsRef.current&&scrollToItem({list:listItemsRef.current,itemIndex:selectedIndex,behavior:"smooth"})},[listItemsRef,selectedIndex]),useContainedEscape([triggerRef],useCallback(()=>onCloseDropdown(!0),[onCloseDropdown]),isOpen&&!disabled),useKeyboard({Enter:()=>{let preselectedOption=options[selectedIndex];if(!preselectedOption?.disabled){if(preselectedOption){forceChangeFakeSelect(preselectedOption),isMultiSelect||onCloseDropdown(!0);return}isMultiSelect||onCloseDropdown()}},ArrowUp:()=>{let newIndex=-1===selectedIndex?activeItemIndex:selectedIndex;for(;newIndex>0&&(newIndex-=1,options[newIndex]?.disabled););options[newIndex]?.disabled||onSelectedIndexChange(newIndex)},ArrowDown:()=>{let newIndex=-1===selectedIndex?activeItemIndex:selectedIndex;for(;newIndex<options.length-1&&(newIndex+=1,options[newIndex]?.disabled););options[newIndex]?.disabled||onSelectedIndexChange(newIndex)}},triggerRef,isOpen&&!disabled);let renderItem=index=>{let option=options[index],id=getOptionId(name,option.value);if(isMultiSelect){let isActive=value.includes(option.value);return React.createElement(CustomOption,{role:"option","aria-selected":isActive,"aria-disabled":option.disabled,id:id,key:option.value,active:isActive,disabled:option.disabled??!1,preSelected:selectedIndex===index,"data-list-item":!0,onMouseDown:()=>{option.disabled||forceChangeFakeSelect(option)},onClick:evt=>evt.stopPropagation()},React.createElement(CheckboxRaw,{name:"",disabled:option.disabled,checked:isActive,size:"s",label:option.label,onChange:()=>null,labelHint:option?.description}))}let isActive=value===option.value,optionText=React.createElement(Stack,{space:"zero"},React.createElement(Text,{color:"primary",size:"m"},option.label),option.description&&React.createElement(Text,{color:"tertiary",size:"s"},option.description));return React.createElement(StyledOption,{role:"option","aria-selected":isActive,"aria-disabled":option.disabled,id:id,key:option.value,active:isActive,disabled:option.disabled??!1,preSelected:selectedIndex===index,"data-list-item":!0,onMouseDown:()=>{option.disabled||(forceChangeFakeSelect(option),onCloseDropdown(!0))}},isActive?React.createElement(Inline,{noWrap:!0,alignItems:"spaceBetween"},optionText,React.createElement(Box,{space:"zero",tSpace:"xxxs"},React.createElement(Icon,{name:"check",size:"s",color:"accent"}))):optionText)},listStyle={...optionsListStyle,width:optionsListWidth||refForPositioning.current?.getBoundingClientRect().width},listElm=React.createElement(StyledDropdown,{style:listStyle,ref:optionsListRef,onMouseDown:e=>e.preventDefault(),"data-e2e-test-id":"optionsList"},isVirtualized?React.createElement(VirtualScrollList,{id:getOptionsListId(name),maxHeight:effectiveMaxHeight,itemHeight:36,itemAmount:options.length,emptyState:()=>null,containerStyle:dropdownContainerStyle,itemInView:selectedIndex,itemTemplate:renderItem,onContentHeightChange:calculateStyle,role:"listbox"}):React.createElement(StyledListContainer,{maxHeight:effectiveMaxHeight,role:"listbox",id:getOptionsListId(name),ref:listContainerRef},options.map((_option,index)=>renderItem(index))));if(!isOpen)return null;let listPortal=options.length?React.createElement(Portal,{portalContainer:portalContainer},listElm):null;return React.createElement(React.Fragment,null,React.createElement(ScreenReaderText,{role:"status","aria-live":"polite"},options.length?"":emptyStateMessage),listPortal)}
@@ -1 +1 @@
1
- import React,{useState,useRef,useEffect,useCallback,useMemo}from"react";import styled from"@emotion/styled";import{getOptionId,getOptionsListId,OptionsList}from"../Combobox/OptionsList";import{useKeyboard}from"../../../shared/useKeyboard";import{useTypeAheadSearch}from"./useTypeAheadSearch";let HiddenSelectInput=styled("select",{target:"ejxvztk0",label:"HiddenSelectInput"})(()=>({display:"none"}));export function SelectWithCustomTrigger({renderTrigger,optionsListWidth,options=[],name,value,portalContainer,disabled=!1,maxHeight=230,autoComplete="on",readOnly=!1,excludeFromFormData=!1,onChange}){let[isOpen,setIsOpen]=useState(!1),[selectedIndex,setSelectedIndex]=useState(-1),triggerRef=useRef(null),hiddenSelectRef=useRef(null),currentOptionIndex=useMemo(()=>options.findIndex(option=>option.value===value),[options,value]),closeOptionsList=useCallback(()=>{isOpen&&(setIsOpen(!1),setSelectedIndex(-1))},[isOpen]),openOptionsList=useCallback(()=>{isOpen||readOnly||(setIsOpen(!0),triggerRef.current?.focus())},[isOpen,readOnly]),toggleOptionsList=useCallback(()=>{isOpen?closeOptionsList():openOptionsList()},[isOpen,openOptionsList,closeOptionsList]),handleSelectedIndexChange=useCallback(index=>setSelectedIndex(index),[]),handleChange=useCallback(option=>{let hiddenSelect=hiddenSelectRef.current;hiddenSelect&&(hiddenSelect.value=option.value,hiddenSelect.dispatchEvent(new Event("change",{bubbles:!0})))},[hiddenSelectRef]),handleSearchMatch=useCallback(matchedIndex=>{-1!==matchedIndex&&(isOpen?setSelectedIndex(matchedIndex):handleChange(options[matchedIndex]))},[isOpen,options,setSelectedIndex,handleChange]);useKeyboard({"Enter Space ArrowUp ArrowDown":()=>{openOptionsList()}},triggerRef,!isOpen&&!disabled),useTypeAheadSearch({options,triggerRef,isActive:!disabled,fromIndex:-1!==selectedIndex?selectedIndex:currentOptionIndex,onMatch:handleSearchMatch}),useEffect(()=>{let triggerElm=triggerRef.current,handlePointerDown=evt=>{evt.preventDefault()};return triggerElm&&!disabled&&(triggerElm.setAttribute("tabIndex","0"),triggerElm.addEventListener("click",toggleOptionsList),triggerElm.addEventListener("blur",closeOptionsList),triggerElm.addEventListener("pointerdown",handlePointerDown)),()=>{triggerElm?.removeEventListener("click",toggleOptionsList),triggerElm?.removeEventListener("blur",closeOptionsList),triggerElm?.removeEventListener("pointerdown",handlePointerDown)}},[triggerRef,disabled,closeOptionsList,toggleOptionsList]),useEffect(()=>{let triggerElm=triggerRef.current,handleEscapeKeyDown=evt=>{"Escape"===evt.code&&(evt.preventDefault(),evt.stopPropagation(),closeOptionsList())};return triggerElm&&isOpen&&triggerElm.addEventListener("keydown",handleEscapeKeyDown),()=>{triggerElm?.removeEventListener("keydown",handleEscapeKeyDown)}},[triggerRef,isOpen,closeOptionsList]);let optionsListId=getOptionsListId(name),ariaActiveDescendant=-1!==selectedIndex?getOptionId(name,options[selectedIndex].value):"",triggerElm=renderTrigger({triggerRef,isOpen,disabled,role:"combobox","aria-activedescendant":isOpen?ariaActiveDescendant:"","aria-controls":isOpen?optionsListId:"","aria-expanded":isOpen}),optionsListElm=React.createElement(OptionsList,{name:name,isOpen:isOpen,isVirtualized:!1,options:options,triggerRef:triggerRef,onCloseDropdown:closeOptionsList,portalContainer:portalContainer,selectedIndex:selectedIndex,onSelectedIndexChange:handleSelectedIndexChange,forceChangeFakeSelect:handleChange,value:value,disabled:disabled,maxHeight:maxHeight,optionsListWidth:optionsListWidth});return React.createElement(React.Fragment,null,triggerElm,optionsListElm,React.createElement(HiddenSelectInput,{name:excludeFromFormData?void 0:name,onChange:onChange,value:value,ref:hiddenSelectRef,autoComplete:autoComplete},React.createElement("option",{value:"","aria-label":"Empty option"}),options.map(option=>React.createElement("option",{value:option.value,key:option.value},option.label))))}
1
+ import React,{useState,useRef,useEffect,useCallback,useMemo}from"react";import styled from"@emotion/styled";import{getOptionId,getOptionsListId,OptionsList}from"../Combobox/OptionsList";import{useContainedEscape}from"../../../shared/useContainedEscape";import{useKeyboard}from"../../../shared/useKeyboard";import{useTypeAheadSearch}from"./useTypeAheadSearch";let HiddenSelectInput=styled("select",{target:"e2kj7nk0",label:"HiddenSelectInput"})(()=>({display:"none"}));export function SelectWithCustomTrigger({renderTrigger,optionsListWidth,options=[],name,value,portalContainer,disabled=!1,maxHeight=230,autoComplete="on",readOnly=!1,excludeFromFormData=!1,onChange}){let[isOpen,setIsOpen]=useState(!1),[selectedIndex,setSelectedIndex]=useState(-1),triggerRef=useRef(null),hiddenSelectRef=useRef(null),currentOptionIndex=useMemo(()=>options.findIndex(option=>option.value===value),[options,value]),closeOptionsList=useCallback(()=>{isOpen&&(setIsOpen(!1),setSelectedIndex(-1))},[isOpen]),openOptionsList=useCallback(()=>{isOpen||readOnly||(setIsOpen(!0),triggerRef.current?.focus())},[isOpen,readOnly]),toggleOptionsList=useCallback(()=>{isOpen?closeOptionsList():openOptionsList()},[isOpen,openOptionsList,closeOptionsList]),handleSelectedIndexChange=useCallback(index=>setSelectedIndex(index),[]),handleChange=useCallback(option=>{let hiddenSelect=hiddenSelectRef.current;hiddenSelect&&(hiddenSelect.value=option.value,hiddenSelect.dispatchEvent(new Event("change",{bubbles:!0})))},[hiddenSelectRef]),handleSearchMatch=useCallback(matchedIndex=>{-1!==matchedIndex&&(isOpen?setSelectedIndex(matchedIndex):handleChange(options[matchedIndex]))},[isOpen,options,setSelectedIndex,handleChange]);useKeyboard({"Enter Space ArrowUp ArrowDown":()=>{openOptionsList()}},triggerRef,!isOpen&&!disabled),useTypeAheadSearch({options,triggerRef,isActive:!disabled,fromIndex:-1!==selectedIndex?selectedIndex:currentOptionIndex,onMatch:handleSearchMatch}),useEffect(()=>{let triggerElm=triggerRef.current,handlePointerDown=evt=>{evt.preventDefault()};return triggerElm&&!disabled&&(triggerElm.setAttribute("tabIndex","0"),triggerElm.addEventListener("click",toggleOptionsList),triggerElm.addEventListener("blur",closeOptionsList),triggerElm.addEventListener("pointerdown",handlePointerDown)),()=>{triggerElm?.removeEventListener("click",toggleOptionsList),triggerElm?.removeEventListener("blur",closeOptionsList),triggerElm?.removeEventListener("pointerdown",handlePointerDown)}},[triggerRef,disabled,closeOptionsList,toggleOptionsList]),useContainedEscape([triggerRef],closeOptionsList,isOpen);let optionsListId=getOptionsListId(name),ariaActiveDescendant=-1!==selectedIndex?getOptionId(name,options[selectedIndex].value):"",triggerElm=renderTrigger({triggerRef,isOpen,disabled,role:"combobox","aria-activedescendant":isOpen?ariaActiveDescendant:"","aria-controls":isOpen?optionsListId:"","aria-expanded":isOpen}),optionsListElm=React.createElement(OptionsList,{name:name,isOpen:isOpen,isVirtualized:!1,options:options,triggerRef:triggerRef,onCloseDropdown:closeOptionsList,portalContainer:portalContainer,selectedIndex:selectedIndex,onSelectedIndexChange:handleSelectedIndexChange,forceChangeFakeSelect:handleChange,value:value,disabled:disabled,maxHeight:maxHeight,optionsListWidth:optionsListWidth});return React.createElement(React.Fragment,null,triggerElm,optionsListElm,React.createElement(HiddenSelectInput,{name:excludeFromFormData?void 0:name,onChange:onChange,value:value,ref:hiddenSelectRef,autoComplete:autoComplete},React.createElement("option",{value:"","aria-label":"Empty option"}),options.map(option=>React.createElement("option",{value:option.value,key:option.value},option.label))))}
@@ -0,0 +1,13 @@
1
+ import type { RefObject } from "react";
2
+ /**
3
+ * useContainedEscape handles Escape on the given elements and stops it there,
4
+ * before it reaches document. An enclosing focus trap with escapeDeactivates
5
+ * (e.g. a Modal) listens on document, so a popup that closes on Escape must
6
+ * stop the event first to close only itself.
7
+ * @param {RefObject[]} refs - Elements that receive keydown while the popup is open, e.g. its trigger.
8
+ * @param {e: KeyboardEvent => void} onEscape - Function invoked when Escape is pressed on one of the elements.
9
+ * @param {boolean} isActive - A flag to determine when the Escape listener needs to be applied.
10
+ *
11
+ * Example: useContainedEscape([triggerRef], closeList, listIsOpen)
12
+ */
13
+ export declare const useContainedEscape: (refs: RefObject<HTMLElement>[], onEscape: (e: KeyboardEvent) => void, isActive: boolean) => void;
@@ -0,0 +1 @@
1
+ import{useEffect,useRef}from"react";export const useContainedEscape=(refs,onEscape,isActive)=>{let refsRef=useRef(refs);refsRef.current=refs,useEffect(()=>{if(!isActive)return;let elements=refsRef.current.map(ref=>ref.current),handleEscapeKeyDown=evt=>{"Escape"===evt.code&&(evt.preventDefault(),evt.stopPropagation(),onEscape(evt))};return elements.forEach(elm=>elm?.addEventListener("keydown",handleEscapeKeyDown)),()=>{elements.forEach(elm=>elm?.removeEventListener("keydown",handleEscapeKeyDown))}},[onEscape,isActive])};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amboss/design-system",
3
- "version": "4.16.0",
3
+ "version": "4.17.0",
4
4
  "description": "the design system for AMBOSS products",
5
5
  "author": "AMBOSS",
6
6
  "license": "ISC",