index.mjs 72 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267
  1. import $01b9c$babelruntimehelpersesmextends from "@babel/runtime/helpers/esm/extends";
  2. import {useState as $01b9c$useState, useRef as $01b9c$useRef, createElement as $01b9c$createElement, useCallback as $01b9c$useCallback, forwardRef as $01b9c$forwardRef, useEffect as $01b9c$useEffect, Fragment as $01b9c$Fragment, useMemo as $01b9c$useMemo} from "react";
  3. import {createPortal as $01b9c$createPortal} from "react-dom";
  4. import {clamp as $01b9c$clamp} from "@radix-ui/number";
  5. import {composeEventHandlers as $01b9c$composeEventHandlers} from "@radix-ui/primitive";
  6. import {createCollection as $01b9c$createCollection} from "@radix-ui/react-collection";
  7. import {useComposedRefs as $01b9c$useComposedRefs} from "@radix-ui/react-compose-refs";
  8. import {createContextScope as $01b9c$createContextScope} from "@radix-ui/react-context";
  9. import {useDirection as $01b9c$useDirection} from "@radix-ui/react-direction";
  10. import {DismissableLayer as $01b9c$DismissableLayer} from "@radix-ui/react-dismissable-layer";
  11. import {useFocusGuards as $01b9c$useFocusGuards} from "@radix-ui/react-focus-guards";
  12. import {FocusScope as $01b9c$FocusScope} from "@radix-ui/react-focus-scope";
  13. import {useId as $01b9c$useId} from "@radix-ui/react-id";
  14. import {createPopperScope as $01b9c$createPopperScope, Root as $01b9c$Root, Anchor as $01b9c$Anchor, Content as $01b9c$Content, Arrow as $01b9c$Arrow} from "@radix-ui/react-popper";
  15. import {Portal as $01b9c$Portal} from "@radix-ui/react-portal";
  16. import {Primitive as $01b9c$Primitive} from "@radix-ui/react-primitive";
  17. import {Slot as $01b9c$Slot} from "@radix-ui/react-slot";
  18. import {useCallbackRef as $01b9c$useCallbackRef} from "@radix-ui/react-use-callback-ref";
  19. import {useControllableState as $01b9c$useControllableState} from "@radix-ui/react-use-controllable-state";
  20. import {useLayoutEffect as $01b9c$useLayoutEffect} from "@radix-ui/react-use-layout-effect";
  21. import {usePrevious as $01b9c$usePrevious} from "@radix-ui/react-use-previous";
  22. import {VisuallyHidden as $01b9c$VisuallyHidden} from "@radix-ui/react-visually-hidden";
  23. import {hideOthers as $01b9c$hideOthers} from "aria-hidden";
  24. import {RemoveScroll as $01b9c$RemoveScroll} from "react-remove-scroll";
  25. const $cc7e05a45900e73f$var$OPEN_KEYS = [
  26. ' ',
  27. 'Enter',
  28. 'ArrowUp',
  29. 'ArrowDown'
  30. ];
  31. const $cc7e05a45900e73f$var$SELECTION_KEYS = [
  32. ' ',
  33. 'Enter'
  34. ];
  35. /* -------------------------------------------------------------------------------------------------
  36. * Select
  37. * -----------------------------------------------------------------------------------------------*/ const $cc7e05a45900e73f$var$SELECT_NAME = 'Select';
  38. const [$cc7e05a45900e73f$var$Collection, $cc7e05a45900e73f$var$useCollection, $cc7e05a45900e73f$var$createCollectionScope] = $01b9c$createCollection($cc7e05a45900e73f$var$SELECT_NAME);
  39. const [$cc7e05a45900e73f$var$createSelectContext, $cc7e05a45900e73f$export$286727a75dc039bd] = $01b9c$createContextScope($cc7e05a45900e73f$var$SELECT_NAME, [
  40. $cc7e05a45900e73f$var$createCollectionScope,
  41. $01b9c$createPopperScope
  42. ]);
  43. const $cc7e05a45900e73f$var$usePopperScope = $01b9c$createPopperScope();
  44. const [$cc7e05a45900e73f$var$SelectProvider, $cc7e05a45900e73f$var$useSelectContext] = $cc7e05a45900e73f$var$createSelectContext($cc7e05a45900e73f$var$SELECT_NAME);
  45. const [$cc7e05a45900e73f$var$SelectNativeOptionsProvider, $cc7e05a45900e73f$var$useSelectNativeOptionsContext] = $cc7e05a45900e73f$var$createSelectContext($cc7e05a45900e73f$var$SELECT_NAME);
  46. const $cc7e05a45900e73f$export$ef9b1a59e592288f = (props)=>{
  47. const { __scopeSelect: __scopeSelect , children: children , open: openProp , defaultOpen: defaultOpen , onOpenChange: onOpenChange , value: valueProp , defaultValue: defaultValue , onValueChange: onValueChange , dir: dir , name: name , autoComplete: autoComplete , disabled: disabled , required: required } = props;
  48. const popperScope = $cc7e05a45900e73f$var$usePopperScope(__scopeSelect);
  49. const [trigger, setTrigger] = $01b9c$useState(null);
  50. const [valueNode, setValueNode] = $01b9c$useState(null);
  51. const [valueNodeHasChildren, setValueNodeHasChildren] = $01b9c$useState(false);
  52. const direction = $01b9c$useDirection(dir);
  53. const [open = false, setOpen] = $01b9c$useControllableState({
  54. prop: openProp,
  55. defaultProp: defaultOpen,
  56. onChange: onOpenChange
  57. });
  58. const [value, setValue] = $01b9c$useControllableState({
  59. prop: valueProp,
  60. defaultProp: defaultValue,
  61. onChange: onValueChange
  62. });
  63. const triggerPointerDownPosRef = $01b9c$useRef(null); // We set this to true by default so that events bubble to forms without JS (SSR)
  64. const isFormControl = trigger ? Boolean(trigger.closest('form')) : true;
  65. const [nativeOptionsSet, setNativeOptionsSet] = $01b9c$useState(new Set()); // The native `select` only associates the correct default value if the corresponding
  66. // `option` is rendered as a child **at the same time** as itself.
  67. // Because it might take a few renders for our items to gather the information to build
  68. // the native `option`(s), we generate a key on the `select` to make sure React re-builds it
  69. // each time the options change.
  70. const nativeSelectKey = Array.from(nativeOptionsSet).map((option)=>option.props.value
  71. ).join(';');
  72. return /*#__PURE__*/ $01b9c$createElement($01b9c$Root, popperScope, /*#__PURE__*/ $01b9c$createElement($cc7e05a45900e73f$var$SelectProvider, {
  73. required: required,
  74. scope: __scopeSelect,
  75. trigger: trigger,
  76. onTriggerChange: setTrigger,
  77. valueNode: valueNode,
  78. onValueNodeChange: setValueNode,
  79. valueNodeHasChildren: valueNodeHasChildren,
  80. onValueNodeHasChildrenChange: setValueNodeHasChildren,
  81. contentId: $01b9c$useId(),
  82. value: value,
  83. onValueChange: setValue,
  84. open: open,
  85. onOpenChange: setOpen,
  86. dir: direction,
  87. triggerPointerDownPosRef: triggerPointerDownPosRef,
  88. disabled: disabled
  89. }, /*#__PURE__*/ $01b9c$createElement($cc7e05a45900e73f$var$Collection.Provider, {
  90. scope: __scopeSelect
  91. }, /*#__PURE__*/ $01b9c$createElement($cc7e05a45900e73f$var$SelectNativeOptionsProvider, {
  92. scope: props.__scopeSelect,
  93. onNativeOptionAdd: $01b9c$useCallback((option)=>{
  94. setNativeOptionsSet((prev)=>new Set(prev).add(option)
  95. );
  96. }, []),
  97. onNativeOptionRemove: $01b9c$useCallback((option)=>{
  98. setNativeOptionsSet((prev)=>{
  99. const optionsSet = new Set(prev);
  100. optionsSet.delete(option);
  101. return optionsSet;
  102. });
  103. }, [])
  104. }, children)), isFormControl ? /*#__PURE__*/ $01b9c$createElement($cc7e05a45900e73f$var$BubbleSelect, {
  105. key: nativeSelectKey,
  106. "aria-hidden": true,
  107. required: required,
  108. tabIndex: -1,
  109. name: name,
  110. autoComplete: autoComplete,
  111. value: value // enable form autofill
  112. ,
  113. onChange: (event)=>setValue(event.target.value)
  114. ,
  115. disabled: disabled
  116. }, value === undefined ? /*#__PURE__*/ $01b9c$createElement("option", {
  117. value: ""
  118. }) : null, Array.from(nativeOptionsSet)) : null));
  119. };
  120. /*#__PURE__*/ Object.assign($cc7e05a45900e73f$export$ef9b1a59e592288f, {
  121. displayName: $cc7e05a45900e73f$var$SELECT_NAME
  122. });
  123. /* -------------------------------------------------------------------------------------------------
  124. * SelectTrigger
  125. * -----------------------------------------------------------------------------------------------*/ const $cc7e05a45900e73f$var$TRIGGER_NAME = 'SelectTrigger';
  126. const $cc7e05a45900e73f$export$3ac1e88a1c0b9f1 = /*#__PURE__*/ $01b9c$forwardRef((props, forwardedRef)=>{
  127. const { __scopeSelect: __scopeSelect , disabled: disabled = false , ...triggerProps } = props;
  128. const popperScope = $cc7e05a45900e73f$var$usePopperScope(__scopeSelect);
  129. const context = $cc7e05a45900e73f$var$useSelectContext($cc7e05a45900e73f$var$TRIGGER_NAME, __scopeSelect);
  130. const isDisabled = context.disabled || disabled;
  131. const composedRefs = $01b9c$useComposedRefs(forwardedRef, context.onTriggerChange);
  132. const getItems = $cc7e05a45900e73f$var$useCollection(__scopeSelect);
  133. const [searchRef, handleTypeaheadSearch, resetTypeahead] = $cc7e05a45900e73f$var$useTypeaheadSearch((search)=>{
  134. const enabledItems = getItems().filter((item)=>!item.disabled
  135. );
  136. const currentItem = enabledItems.find((item)=>item.value === context.value
  137. );
  138. const nextItem = $cc7e05a45900e73f$var$findNextItem(enabledItems, search, currentItem);
  139. if (nextItem !== undefined) context.onValueChange(nextItem.value);
  140. });
  141. const handleOpen = ()=>{
  142. if (!isDisabled) {
  143. context.onOpenChange(true); // reset typeahead when we open
  144. resetTypeahead();
  145. }
  146. };
  147. return /*#__PURE__*/ $01b9c$createElement($01b9c$Anchor, $01b9c$babelruntimehelpersesmextends({
  148. asChild: true
  149. }, popperScope), /*#__PURE__*/ $01b9c$createElement($01b9c$Primitive.button, $01b9c$babelruntimehelpersesmextends({
  150. type: "button",
  151. role: "combobox",
  152. "aria-controls": context.contentId,
  153. "aria-expanded": context.open,
  154. "aria-required": context.required,
  155. "aria-autocomplete": "none",
  156. dir: context.dir,
  157. "data-state": context.open ? 'open' : 'closed',
  158. disabled: isDisabled,
  159. "data-disabled": isDisabled ? '' : undefined,
  160. "data-placeholder": context.value === undefined ? '' : undefined
  161. }, triggerProps, {
  162. ref: composedRefs // Enable compatibility with native label or custom `Label` "click" for Safari:
  163. ,
  164. onClick: $01b9c$composeEventHandlers(triggerProps.onClick, (event)=>{
  165. // Whilst browsers generally have no issue focusing the trigger when clicking
  166. // on a label, Safari seems to struggle with the fact that there's no `onClick`.
  167. // We force `focus` in this case. Note: this doesn't create any other side-effect
  168. // because we are preventing default in `onPointerDown` so effectively
  169. // this only runs for a label "click"
  170. event.currentTarget.focus();
  171. }),
  172. onPointerDown: $01b9c$composeEventHandlers(triggerProps.onPointerDown, (event)=>{
  173. // prevent implicit pointer capture
  174. // https://www.w3.org/TR/pointerevents3/#implicit-pointer-capture
  175. const target = event.target;
  176. if (target.hasPointerCapture(event.pointerId)) target.releasePointerCapture(event.pointerId);
  177. // only call handler if it's the left button (mousedown gets triggered by all mouse buttons)
  178. // but not when the control key is pressed (avoiding MacOS right click)
  179. if (event.button === 0 && event.ctrlKey === false) {
  180. handleOpen();
  181. context.triggerPointerDownPosRef.current = {
  182. x: Math.round(event.pageX),
  183. y: Math.round(event.pageY)
  184. }; // prevent trigger from stealing focus from the active item after opening.
  185. event.preventDefault();
  186. }
  187. }),
  188. onKeyDown: $01b9c$composeEventHandlers(triggerProps.onKeyDown, (event)=>{
  189. const isTypingAhead = searchRef.current !== '';
  190. const isModifierKey = event.ctrlKey || event.altKey || event.metaKey;
  191. if (!isModifierKey && event.key.length === 1) handleTypeaheadSearch(event.key);
  192. if (isTypingAhead && event.key === ' ') return;
  193. if ($cc7e05a45900e73f$var$OPEN_KEYS.includes(event.key)) {
  194. handleOpen();
  195. event.preventDefault();
  196. }
  197. })
  198. })));
  199. });
  200. /*#__PURE__*/ Object.assign($cc7e05a45900e73f$export$3ac1e88a1c0b9f1, {
  201. displayName: $cc7e05a45900e73f$var$TRIGGER_NAME
  202. });
  203. /* -------------------------------------------------------------------------------------------------
  204. * SelectValue
  205. * -----------------------------------------------------------------------------------------------*/ const $cc7e05a45900e73f$var$VALUE_NAME = 'SelectValue';
  206. const $cc7e05a45900e73f$export$e288731fd71264f0 = /*#__PURE__*/ $01b9c$forwardRef((props, forwardedRef)=>{
  207. // We ignore `className` and `style` as this part shouldn't be styled.
  208. const { __scopeSelect: __scopeSelect , className: className , style: style , children: children , placeholder: placeholder , ...valueProps } = props;
  209. const context = $cc7e05a45900e73f$var$useSelectContext($cc7e05a45900e73f$var$VALUE_NAME, __scopeSelect);
  210. const { onValueNodeHasChildrenChange: onValueNodeHasChildrenChange } = context;
  211. const hasChildren = children !== undefined;
  212. const composedRefs = $01b9c$useComposedRefs(forwardedRef, context.onValueNodeChange);
  213. $01b9c$useLayoutEffect(()=>{
  214. onValueNodeHasChildrenChange(hasChildren);
  215. }, [
  216. onValueNodeHasChildrenChange,
  217. hasChildren
  218. ]);
  219. return /*#__PURE__*/ $01b9c$createElement($01b9c$Primitive.span, $01b9c$babelruntimehelpersesmextends({}, valueProps, {
  220. ref: composedRefs // we don't want events from the portalled `SelectValue` children to bubble
  221. ,
  222. style: {
  223. pointerEvents: 'none'
  224. }
  225. }), context.value === undefined && placeholder !== undefined ? placeholder : children);
  226. });
  227. /*#__PURE__*/ Object.assign($cc7e05a45900e73f$export$e288731fd71264f0, {
  228. displayName: $cc7e05a45900e73f$var$VALUE_NAME
  229. });
  230. /* -------------------------------------------------------------------------------------------------
  231. * SelectIcon
  232. * -----------------------------------------------------------------------------------------------*/ const $cc7e05a45900e73f$var$ICON_NAME = 'SelectIcon';
  233. const $cc7e05a45900e73f$export$99b400cabb58c515 = /*#__PURE__*/ $01b9c$forwardRef((props, forwardedRef)=>{
  234. const { __scopeSelect: __scopeSelect , children: children , ...iconProps } = props;
  235. return /*#__PURE__*/ $01b9c$createElement($01b9c$Primitive.span, $01b9c$babelruntimehelpersesmextends({
  236. "aria-hidden": true
  237. }, iconProps, {
  238. ref: forwardedRef
  239. }), children || '▼');
  240. });
  241. /*#__PURE__*/ Object.assign($cc7e05a45900e73f$export$99b400cabb58c515, {
  242. displayName: $cc7e05a45900e73f$var$ICON_NAME
  243. });
  244. /* -------------------------------------------------------------------------------------------------
  245. * SelectPortal
  246. * -----------------------------------------------------------------------------------------------*/ const $cc7e05a45900e73f$var$PORTAL_NAME = 'SelectPortal';
  247. const $cc7e05a45900e73f$export$b2af6c9944296213 = (props)=>{
  248. return /*#__PURE__*/ $01b9c$createElement($01b9c$Portal, $01b9c$babelruntimehelpersesmextends({
  249. asChild: true
  250. }, props));
  251. };
  252. /*#__PURE__*/ Object.assign($cc7e05a45900e73f$export$b2af6c9944296213, {
  253. displayName: $cc7e05a45900e73f$var$PORTAL_NAME
  254. });
  255. /* -------------------------------------------------------------------------------------------------
  256. * SelectContent
  257. * -----------------------------------------------------------------------------------------------*/ const $cc7e05a45900e73f$var$CONTENT_NAME = 'SelectContent';
  258. const $cc7e05a45900e73f$export$c973a4b3cb86a03d = /*#__PURE__*/ $01b9c$forwardRef((props, forwardedRef)=>{
  259. const context = $cc7e05a45900e73f$var$useSelectContext($cc7e05a45900e73f$var$CONTENT_NAME, props.__scopeSelect);
  260. const [fragment, setFragment] = $01b9c$useState(); // setting the fragment in `useLayoutEffect` as `DocumentFragment` doesn't exist on the server
  261. $01b9c$useLayoutEffect(()=>{
  262. setFragment(new DocumentFragment());
  263. }, []);
  264. if (!context.open) {
  265. const frag = fragment;
  266. return frag ? /*#__PURE__*/ $01b9c$createPortal(/*#__PURE__*/ $01b9c$createElement($cc7e05a45900e73f$var$SelectContentProvider, {
  267. scope: props.__scopeSelect
  268. }, /*#__PURE__*/ $01b9c$createElement($cc7e05a45900e73f$var$Collection.Slot, {
  269. scope: props.__scopeSelect
  270. }, /*#__PURE__*/ $01b9c$createElement("div", null, props.children))), frag) : null;
  271. }
  272. return /*#__PURE__*/ $01b9c$createElement($cc7e05a45900e73f$var$SelectContentImpl, $01b9c$babelruntimehelpersesmextends({}, props, {
  273. ref: forwardedRef
  274. }));
  275. });
  276. /*#__PURE__*/ Object.assign($cc7e05a45900e73f$export$c973a4b3cb86a03d, {
  277. displayName: $cc7e05a45900e73f$var$CONTENT_NAME
  278. });
  279. /* -------------------------------------------------------------------------------------------------
  280. * SelectContentImpl
  281. * -----------------------------------------------------------------------------------------------*/ const $cc7e05a45900e73f$var$CONTENT_MARGIN = 10;
  282. const [$cc7e05a45900e73f$var$SelectContentProvider, $cc7e05a45900e73f$var$useSelectContentContext] = $cc7e05a45900e73f$var$createSelectContext($cc7e05a45900e73f$var$CONTENT_NAME);
  283. const $cc7e05a45900e73f$var$CONTENT_IMPL_NAME = 'SelectContentImpl';
  284. const $cc7e05a45900e73f$var$SelectContentImpl = /*#__PURE__*/ $01b9c$forwardRef((props, forwardedRef)=>{
  285. const { __scopeSelect: __scopeSelect , position: position = 'item-aligned' , onCloseAutoFocus: onCloseAutoFocus , onEscapeKeyDown: onEscapeKeyDown , onPointerDownOutside: onPointerDownOutside , side: //
  286. // PopperContent props
  287. side , sideOffset: sideOffset , align: align , alignOffset: alignOffset , arrowPadding: arrowPadding , collisionBoundary: collisionBoundary , collisionPadding: collisionPadding , sticky: sticky , hideWhenDetached: hideWhenDetached , avoidCollisions: avoidCollisions , //
  288. ...contentProps } = props;
  289. const context = $cc7e05a45900e73f$var$useSelectContext($cc7e05a45900e73f$var$CONTENT_NAME, __scopeSelect);
  290. const [content, setContent] = $01b9c$useState(null);
  291. const [viewport, setViewport] = $01b9c$useState(null);
  292. const composedRefs = $01b9c$useComposedRefs(forwardedRef, (node)=>setContent(node)
  293. );
  294. const [selectedItem, setSelectedItem] = $01b9c$useState(null);
  295. const [selectedItemText, setSelectedItemText] = $01b9c$useState(null);
  296. const getItems = $cc7e05a45900e73f$var$useCollection(__scopeSelect);
  297. const [isPositioned, setIsPositioned] = $01b9c$useState(false);
  298. const firstValidItemFoundRef = $01b9c$useRef(false); // aria-hide everything except the content (better supported equivalent to setting aria-modal)
  299. $01b9c$useEffect(()=>{
  300. if (content) return $01b9c$hideOthers(content);
  301. }, [
  302. content
  303. ]); // Make sure the whole tree has focus guards as our `Select` may be
  304. // the last element in the DOM (because of the `Portal`)
  305. $01b9c$useFocusGuards();
  306. const focusFirst = $01b9c$useCallback((candidates)=>{
  307. const [firstItem, ...restItems] = getItems().map((item)=>item.ref.current
  308. );
  309. const [lastItem] = restItems.slice(-1);
  310. const PREVIOUSLY_FOCUSED_ELEMENT = document.activeElement;
  311. for (const candidate of candidates){
  312. // if focus is already where we want to go, we don't want to keep going through the candidates
  313. if (candidate === PREVIOUSLY_FOCUSED_ELEMENT) return;
  314. candidate === null || candidate === void 0 || candidate.scrollIntoView({
  315. block: 'nearest'
  316. }); // viewport might have padding so scroll to its edges when focusing first/last items.
  317. if (candidate === firstItem && viewport) viewport.scrollTop = 0;
  318. if (candidate === lastItem && viewport) viewport.scrollTop = viewport.scrollHeight;
  319. candidate === null || candidate === void 0 || candidate.focus();
  320. if (document.activeElement !== PREVIOUSLY_FOCUSED_ELEMENT) return;
  321. }
  322. }, [
  323. getItems,
  324. viewport
  325. ]);
  326. const focusSelectedItem = $01b9c$useCallback(()=>focusFirst([
  327. selectedItem,
  328. content
  329. ])
  330. , [
  331. focusFirst,
  332. selectedItem,
  333. content
  334. ]); // Since this is not dependent on layout, we want to ensure this runs at the same time as
  335. // other effects across components. Hence why we don't call `focusSelectedItem` inside `position`.
  336. $01b9c$useEffect(()=>{
  337. if (isPositioned) focusSelectedItem();
  338. }, [
  339. isPositioned,
  340. focusSelectedItem
  341. ]); // prevent selecting items on `pointerup` in some cases after opening from `pointerdown`
  342. // and close on `pointerup` outside.
  343. const { onOpenChange: onOpenChange , triggerPointerDownPosRef: triggerPointerDownPosRef } = context;
  344. $01b9c$useEffect(()=>{
  345. if (content) {
  346. let pointerMoveDelta = {
  347. x: 0,
  348. y: 0
  349. };
  350. const handlePointerMove = (event)=>{
  351. var _triggerPointerDownPo, _triggerPointerDownPo2, _triggerPointerDownPo3, _triggerPointerDownPo4;
  352. pointerMoveDelta = {
  353. x: Math.abs(Math.round(event.pageX) - ((_triggerPointerDownPo = (_triggerPointerDownPo2 = triggerPointerDownPosRef.current) === null || _triggerPointerDownPo2 === void 0 ? void 0 : _triggerPointerDownPo2.x) !== null && _triggerPointerDownPo !== void 0 ? _triggerPointerDownPo : 0)),
  354. y: Math.abs(Math.round(event.pageY) - ((_triggerPointerDownPo3 = (_triggerPointerDownPo4 = triggerPointerDownPosRef.current) === null || _triggerPointerDownPo4 === void 0 ? void 0 : _triggerPointerDownPo4.y) !== null && _triggerPointerDownPo3 !== void 0 ? _triggerPointerDownPo3 : 0))
  355. };
  356. };
  357. const handlePointerUp = (event)=>{
  358. // If the pointer hasn't moved by a certain threshold then we prevent selecting item on `pointerup`.
  359. if (pointerMoveDelta.x <= 10 && pointerMoveDelta.y <= 10) event.preventDefault();
  360. else // otherwise, if the event was outside the content, close.
  361. if (!content.contains(event.target)) onOpenChange(false);
  362. document.removeEventListener('pointermove', handlePointerMove);
  363. triggerPointerDownPosRef.current = null;
  364. };
  365. if (triggerPointerDownPosRef.current !== null) {
  366. document.addEventListener('pointermove', handlePointerMove);
  367. document.addEventListener('pointerup', handlePointerUp, {
  368. capture: true,
  369. once: true
  370. });
  371. }
  372. return ()=>{
  373. document.removeEventListener('pointermove', handlePointerMove);
  374. document.removeEventListener('pointerup', handlePointerUp, {
  375. capture: true
  376. });
  377. };
  378. }
  379. }, [
  380. content,
  381. onOpenChange,
  382. triggerPointerDownPosRef
  383. ]);
  384. $01b9c$useEffect(()=>{
  385. const close = ()=>onOpenChange(false)
  386. ;
  387. window.addEventListener('blur', close);
  388. window.addEventListener('resize', close);
  389. return ()=>{
  390. window.removeEventListener('blur', close);
  391. window.removeEventListener('resize', close);
  392. };
  393. }, [
  394. onOpenChange
  395. ]);
  396. const [searchRef, handleTypeaheadSearch] = $cc7e05a45900e73f$var$useTypeaheadSearch((search)=>{
  397. const enabledItems = getItems().filter((item)=>!item.disabled
  398. );
  399. const currentItem = enabledItems.find((item)=>item.ref.current === document.activeElement
  400. );
  401. const nextItem = $cc7e05a45900e73f$var$findNextItem(enabledItems, search, currentItem);
  402. if (nextItem) /**
  403. * Imperative focus during keydown is risky so we prevent React's batching updates
  404. * to avoid potential bugs. See: https://github.com/facebook/react/issues/20332
  405. */ setTimeout(()=>nextItem.ref.current.focus()
  406. );
  407. });
  408. const itemRefCallback = $01b9c$useCallback((node, value, disabled)=>{
  409. const isFirstValidItem = !firstValidItemFoundRef.current && !disabled;
  410. const isSelectedItem = context.value !== undefined && context.value === value;
  411. if (isSelectedItem || isFirstValidItem) {
  412. setSelectedItem(node);
  413. if (isFirstValidItem) firstValidItemFoundRef.current = true;
  414. }
  415. }, [
  416. context.value
  417. ]);
  418. const handleItemLeave = $01b9c$useCallback(()=>content === null || content === void 0 ? void 0 : content.focus()
  419. , [
  420. content
  421. ]);
  422. const itemTextRefCallback = $01b9c$useCallback((node, value, disabled)=>{
  423. const isFirstValidItem = !firstValidItemFoundRef.current && !disabled;
  424. const isSelectedItem = context.value !== undefined && context.value === value;
  425. if (isSelectedItem || isFirstValidItem) setSelectedItemText(node);
  426. }, [
  427. context.value
  428. ]);
  429. const SelectPosition = position === 'popper' ? $cc7e05a45900e73f$var$SelectPopperPosition : $cc7e05a45900e73f$var$SelectItemAlignedPosition; // Silently ignore props that are not supported by `SelectItemAlignedPosition`
  430. const popperContentProps = SelectPosition === $cc7e05a45900e73f$var$SelectPopperPosition ? {
  431. side: side,
  432. sideOffset: sideOffset,
  433. align: align,
  434. alignOffset: alignOffset,
  435. arrowPadding: arrowPadding,
  436. collisionBoundary: collisionBoundary,
  437. collisionPadding: collisionPadding,
  438. sticky: sticky,
  439. hideWhenDetached: hideWhenDetached,
  440. avoidCollisions: avoidCollisions
  441. } : {};
  442. return /*#__PURE__*/ $01b9c$createElement($cc7e05a45900e73f$var$SelectContentProvider, {
  443. scope: __scopeSelect,
  444. content: content,
  445. viewport: viewport,
  446. onViewportChange: setViewport,
  447. itemRefCallback: itemRefCallback,
  448. selectedItem: selectedItem,
  449. onItemLeave: handleItemLeave,
  450. itemTextRefCallback: itemTextRefCallback,
  451. focusSelectedItem: focusSelectedItem,
  452. selectedItemText: selectedItemText,
  453. position: position,
  454. isPositioned: isPositioned,
  455. searchRef: searchRef
  456. }, /*#__PURE__*/ $01b9c$createElement($01b9c$RemoveScroll, {
  457. as: $01b9c$Slot,
  458. allowPinchZoom: true
  459. }, /*#__PURE__*/ $01b9c$createElement($01b9c$FocusScope, {
  460. asChild: true // we make sure we're not trapping once it's been closed
  461. ,
  462. trapped: context.open,
  463. onMountAutoFocus: (event)=>{
  464. // we prevent open autofocus because we manually focus the selected item
  465. event.preventDefault();
  466. },
  467. onUnmountAutoFocus: $01b9c$composeEventHandlers(onCloseAutoFocus, (event)=>{
  468. var _context$trigger;
  469. (_context$trigger = context.trigger) === null || _context$trigger === void 0 || _context$trigger.focus({
  470. preventScroll: true
  471. });
  472. event.preventDefault();
  473. })
  474. }, /*#__PURE__*/ $01b9c$createElement($01b9c$DismissableLayer, {
  475. asChild: true,
  476. disableOutsidePointerEvents: true,
  477. onEscapeKeyDown: onEscapeKeyDown,
  478. onPointerDownOutside: onPointerDownOutside // When focus is trapped, a focusout event may still happen.
  479. ,
  480. onFocusOutside: (event)=>event.preventDefault()
  481. ,
  482. onDismiss: ()=>context.onOpenChange(false)
  483. }, /*#__PURE__*/ $01b9c$createElement(SelectPosition, $01b9c$babelruntimehelpersesmextends({
  484. role: "listbox",
  485. id: context.contentId,
  486. "data-state": context.open ? 'open' : 'closed',
  487. dir: context.dir,
  488. onContextMenu: (event)=>event.preventDefault()
  489. }, contentProps, popperContentProps, {
  490. onPlaced: ()=>setIsPositioned(true)
  491. ,
  492. ref: composedRefs,
  493. style: {
  494. // flex layout so we can place the scroll buttons properly
  495. display: 'flex',
  496. flexDirection: 'column',
  497. // reset the outline by default as the content MAY get focused
  498. outline: 'none',
  499. ...contentProps.style
  500. },
  501. onKeyDown: $01b9c$composeEventHandlers(contentProps.onKeyDown, (event)=>{
  502. const isModifierKey = event.ctrlKey || event.altKey || event.metaKey; // select should not be navigated using tab key so we prevent it
  503. if (event.key === 'Tab') event.preventDefault();
  504. if (!isModifierKey && event.key.length === 1) handleTypeaheadSearch(event.key);
  505. if ([
  506. 'ArrowUp',
  507. 'ArrowDown',
  508. 'Home',
  509. 'End'
  510. ].includes(event.key)) {
  511. const items = getItems().filter((item)=>!item.disabled
  512. );
  513. let candidateNodes = items.map((item)=>item.ref.current
  514. );
  515. if ([
  516. 'ArrowUp',
  517. 'End'
  518. ].includes(event.key)) candidateNodes = candidateNodes.slice().reverse();
  519. if ([
  520. 'ArrowUp',
  521. 'ArrowDown'
  522. ].includes(event.key)) {
  523. const currentElement = event.target;
  524. const currentIndex = candidateNodes.indexOf(currentElement);
  525. candidateNodes = candidateNodes.slice(currentIndex + 1);
  526. }
  527. /**
  528. * Imperative focus during keydown is risky so we prevent React's batching updates
  529. * to avoid potential bugs. See: https://github.com/facebook/react/issues/20332
  530. */ setTimeout(()=>focusFirst(candidateNodes)
  531. );
  532. event.preventDefault();
  533. }
  534. })
  535. }))))));
  536. });
  537. /*#__PURE__*/ Object.assign($cc7e05a45900e73f$var$SelectContentImpl, {
  538. displayName: $cc7e05a45900e73f$var$CONTENT_IMPL_NAME
  539. });
  540. /* -------------------------------------------------------------------------------------------------
  541. * SelectItemAlignedPosition
  542. * -----------------------------------------------------------------------------------------------*/ const $cc7e05a45900e73f$var$ITEM_ALIGNED_POSITION_NAME = 'SelectItemAlignedPosition';
  543. const $cc7e05a45900e73f$var$SelectItemAlignedPosition = /*#__PURE__*/ $01b9c$forwardRef((props, forwardedRef)=>{
  544. const { __scopeSelect: __scopeSelect , onPlaced: onPlaced , ...popperProps } = props;
  545. const context = $cc7e05a45900e73f$var$useSelectContext($cc7e05a45900e73f$var$CONTENT_NAME, __scopeSelect);
  546. const contentContext = $cc7e05a45900e73f$var$useSelectContentContext($cc7e05a45900e73f$var$CONTENT_NAME, __scopeSelect);
  547. const [contentWrapper, setContentWrapper] = $01b9c$useState(null);
  548. const [content, setContent] = $01b9c$useState(null);
  549. const composedRefs = $01b9c$useComposedRefs(forwardedRef, (node)=>setContent(node)
  550. );
  551. const getItems = $cc7e05a45900e73f$var$useCollection(__scopeSelect);
  552. const shouldExpandOnScrollRef = $01b9c$useRef(false);
  553. const shouldRepositionRef = $01b9c$useRef(true);
  554. const { viewport: viewport , selectedItem: selectedItem , selectedItemText: selectedItemText , focusSelectedItem: focusSelectedItem } = contentContext;
  555. const position = $01b9c$useCallback(()=>{
  556. if (context.trigger && context.valueNode && contentWrapper && content && viewport && selectedItem && selectedItemText) {
  557. const triggerRect = context.trigger.getBoundingClientRect(); // -----------------------------------------------------------------------------------------
  558. // Horizontal positioning
  559. // -----------------------------------------------------------------------------------------
  560. const contentRect = content.getBoundingClientRect();
  561. const valueNodeRect = context.valueNode.getBoundingClientRect();
  562. const itemTextRect = selectedItemText.getBoundingClientRect();
  563. if (context.dir !== 'rtl') {
  564. const itemTextOffset = itemTextRect.left - contentRect.left;
  565. const left = valueNodeRect.left - itemTextOffset;
  566. const leftDelta = triggerRect.left - left;
  567. const minContentWidth = triggerRect.width + leftDelta;
  568. const contentWidth = Math.max(minContentWidth, contentRect.width);
  569. const rightEdge = window.innerWidth - $cc7e05a45900e73f$var$CONTENT_MARGIN;
  570. const clampedLeft = $01b9c$clamp(left, [
  571. $cc7e05a45900e73f$var$CONTENT_MARGIN,
  572. rightEdge - contentWidth
  573. ]);
  574. contentWrapper.style.minWidth = minContentWidth + 'px';
  575. contentWrapper.style.left = clampedLeft + 'px';
  576. } else {
  577. const itemTextOffset = contentRect.right - itemTextRect.right;
  578. const right = window.innerWidth - valueNodeRect.right - itemTextOffset;
  579. const rightDelta = window.innerWidth - triggerRect.right - right;
  580. const minContentWidth = triggerRect.width + rightDelta;
  581. const contentWidth = Math.max(minContentWidth, contentRect.width);
  582. const leftEdge = window.innerWidth - $cc7e05a45900e73f$var$CONTENT_MARGIN;
  583. const clampedRight = $01b9c$clamp(right, [
  584. $cc7e05a45900e73f$var$CONTENT_MARGIN,
  585. leftEdge - contentWidth
  586. ]);
  587. contentWrapper.style.minWidth = minContentWidth + 'px';
  588. contentWrapper.style.right = clampedRight + 'px';
  589. } // -----------------------------------------------------------------------------------------
  590. // Vertical positioning
  591. // -----------------------------------------------------------------------------------------
  592. const items = getItems();
  593. const availableHeight = window.innerHeight - $cc7e05a45900e73f$var$CONTENT_MARGIN * 2;
  594. const itemsHeight = viewport.scrollHeight;
  595. const contentStyles = window.getComputedStyle(content);
  596. const contentBorderTopWidth = parseInt(contentStyles.borderTopWidth, 10);
  597. const contentPaddingTop = parseInt(contentStyles.paddingTop, 10);
  598. const contentBorderBottomWidth = parseInt(contentStyles.borderBottomWidth, 10);
  599. const contentPaddingBottom = parseInt(contentStyles.paddingBottom, 10);
  600. const fullContentHeight = contentBorderTopWidth + contentPaddingTop + itemsHeight + contentPaddingBottom + contentBorderBottomWidth; // prettier-ignore
  601. const minContentHeight = Math.min(selectedItem.offsetHeight * 5, fullContentHeight);
  602. const viewportStyles = window.getComputedStyle(viewport);
  603. const viewportPaddingTop = parseInt(viewportStyles.paddingTop, 10);
  604. const viewportPaddingBottom = parseInt(viewportStyles.paddingBottom, 10);
  605. const topEdgeToTriggerMiddle = triggerRect.top + triggerRect.height / 2 - $cc7e05a45900e73f$var$CONTENT_MARGIN;
  606. const triggerMiddleToBottomEdge = availableHeight - topEdgeToTriggerMiddle;
  607. const selectedItemHalfHeight = selectedItem.offsetHeight / 2;
  608. const itemOffsetMiddle = selectedItem.offsetTop + selectedItemHalfHeight;
  609. const contentTopToItemMiddle = contentBorderTopWidth + contentPaddingTop + itemOffsetMiddle;
  610. const itemMiddleToContentBottom = fullContentHeight - contentTopToItemMiddle;
  611. const willAlignWithoutTopOverflow = contentTopToItemMiddle <= topEdgeToTriggerMiddle;
  612. if (willAlignWithoutTopOverflow) {
  613. const isLastItem = selectedItem === items[items.length - 1].ref.current;
  614. contentWrapper.style.bottom = "0px";
  615. const viewportOffsetBottom = content.clientHeight - viewport.offsetTop - viewport.offsetHeight;
  616. const clampedTriggerMiddleToBottomEdge = Math.max(triggerMiddleToBottomEdge, selectedItemHalfHeight + (isLastItem ? viewportPaddingBottom : 0) + viewportOffsetBottom + contentBorderBottomWidth);
  617. const height = contentTopToItemMiddle + clampedTriggerMiddleToBottomEdge;
  618. contentWrapper.style.height = height + 'px';
  619. } else {
  620. const isFirstItem = selectedItem === items[0].ref.current;
  621. contentWrapper.style.top = "0px";
  622. const clampedTopEdgeToTriggerMiddle = Math.max(topEdgeToTriggerMiddle, contentBorderTopWidth + viewport.offsetTop + (isFirstItem ? viewportPaddingTop : 0) + selectedItemHalfHeight);
  623. const height = clampedTopEdgeToTriggerMiddle + itemMiddleToContentBottom;
  624. contentWrapper.style.height = height + 'px';
  625. viewport.scrollTop = contentTopToItemMiddle - topEdgeToTriggerMiddle + viewport.offsetTop;
  626. }
  627. contentWrapper.style.margin = `${$cc7e05a45900e73f$var$CONTENT_MARGIN}px 0`;
  628. contentWrapper.style.minHeight = minContentHeight + 'px';
  629. contentWrapper.style.maxHeight = availableHeight + 'px'; // -----------------------------------------------------------------------------------------
  630. onPlaced === null || onPlaced === void 0 || onPlaced(); // we don't want the initial scroll position adjustment to trigger "expand on scroll"
  631. // so we explicitly turn it on only after they've registered.
  632. requestAnimationFrame(()=>shouldExpandOnScrollRef.current = true
  633. );
  634. }
  635. }, [
  636. getItems,
  637. context.trigger,
  638. context.valueNode,
  639. contentWrapper,
  640. content,
  641. viewport,
  642. selectedItem,
  643. selectedItemText,
  644. context.dir,
  645. onPlaced
  646. ]);
  647. $01b9c$useLayoutEffect(()=>position()
  648. , [
  649. position
  650. ]); // copy z-index from content to wrapper
  651. const [contentZIndex, setContentZIndex] = $01b9c$useState();
  652. $01b9c$useLayoutEffect(()=>{
  653. if (content) setContentZIndex(window.getComputedStyle(content).zIndex);
  654. }, [
  655. content
  656. ]); // When the viewport becomes scrollable at the top, the scroll up button will mount.
  657. // Because it is part of the normal flow, it will push down the viewport, thus throwing our
  658. // trigger => selectedItem alignment off by the amount the viewport was pushed down.
  659. // We wait for this to happen and then re-run the positining logic one more time to account for it.
  660. const handleScrollButtonChange = $01b9c$useCallback((node)=>{
  661. if (node && shouldRepositionRef.current === true) {
  662. position();
  663. focusSelectedItem === null || focusSelectedItem === void 0 || focusSelectedItem();
  664. shouldRepositionRef.current = false;
  665. }
  666. }, [
  667. position,
  668. focusSelectedItem
  669. ]);
  670. return /*#__PURE__*/ $01b9c$createElement($cc7e05a45900e73f$var$SelectViewportProvider, {
  671. scope: __scopeSelect,
  672. contentWrapper: contentWrapper,
  673. shouldExpandOnScrollRef: shouldExpandOnScrollRef,
  674. onScrollButtonChange: handleScrollButtonChange
  675. }, /*#__PURE__*/ $01b9c$createElement("div", {
  676. ref: setContentWrapper,
  677. style: {
  678. display: 'flex',
  679. flexDirection: 'column',
  680. position: 'fixed',
  681. zIndex: contentZIndex
  682. }
  683. }, /*#__PURE__*/ $01b9c$createElement($01b9c$Primitive.div, $01b9c$babelruntimehelpersesmextends({}, popperProps, {
  684. ref: composedRefs,
  685. style: {
  686. // When we get the height of the content, it includes borders. If we were to set
  687. // the height without having `boxSizing: 'border-box'` it would be too big.
  688. boxSizing: 'border-box',
  689. // We need to ensure the content doesn't get taller than the wrapper
  690. maxHeight: '100%',
  691. ...popperProps.style
  692. }
  693. }))));
  694. });
  695. /*#__PURE__*/ Object.assign($cc7e05a45900e73f$var$SelectItemAlignedPosition, {
  696. displayName: $cc7e05a45900e73f$var$ITEM_ALIGNED_POSITION_NAME
  697. });
  698. /* -------------------------------------------------------------------------------------------------
  699. * SelectPopperPosition
  700. * -----------------------------------------------------------------------------------------------*/ const $cc7e05a45900e73f$var$POPPER_POSITION_NAME = 'SelectPopperPosition';
  701. const $cc7e05a45900e73f$var$SelectPopperPosition = /*#__PURE__*/ $01b9c$forwardRef((props, forwardedRef)=>{
  702. const { __scopeSelect: __scopeSelect , align: align = 'start' , collisionPadding: collisionPadding = $cc7e05a45900e73f$var$CONTENT_MARGIN , ...popperProps } = props;
  703. const popperScope = $cc7e05a45900e73f$var$usePopperScope(__scopeSelect);
  704. return /*#__PURE__*/ $01b9c$createElement($01b9c$Content, $01b9c$babelruntimehelpersesmextends({}, popperScope, popperProps, {
  705. ref: forwardedRef,
  706. align: align,
  707. collisionPadding: collisionPadding,
  708. style: {
  709. // Ensure border-box for floating-ui calculations
  710. boxSizing: 'border-box',
  711. ...popperProps.style,
  712. '--radix-select-content-transform-origin': 'var(--radix-popper-transform-origin)',
  713. '--radix-select-content-available-width': 'var(--radix-popper-available-width)',
  714. '--radix-select-content-available-height': 'var(--radix-popper-available-height)',
  715. '--radix-select-trigger-width': 'var(--radix-popper-anchor-width)',
  716. '--radix-select-trigger-height': 'var(--radix-popper-anchor-height)'
  717. }
  718. }));
  719. });
  720. /*#__PURE__*/ Object.assign($cc7e05a45900e73f$var$SelectPopperPosition, {
  721. displayName: $cc7e05a45900e73f$var$POPPER_POSITION_NAME
  722. });
  723. /* -------------------------------------------------------------------------------------------------
  724. * SelectViewport
  725. * -----------------------------------------------------------------------------------------------*/ const [$cc7e05a45900e73f$var$SelectViewportProvider, $cc7e05a45900e73f$var$useSelectViewportContext] = $cc7e05a45900e73f$var$createSelectContext($cc7e05a45900e73f$var$CONTENT_NAME, {});
  726. const $cc7e05a45900e73f$var$VIEWPORT_NAME = 'SelectViewport';
  727. const $cc7e05a45900e73f$export$9ed6e7b40248d36d = /*#__PURE__*/ $01b9c$forwardRef((props, forwardedRef)=>{
  728. const { __scopeSelect: __scopeSelect , ...viewportProps } = props;
  729. const contentContext = $cc7e05a45900e73f$var$useSelectContentContext($cc7e05a45900e73f$var$VIEWPORT_NAME, __scopeSelect);
  730. const viewportContext = $cc7e05a45900e73f$var$useSelectViewportContext($cc7e05a45900e73f$var$VIEWPORT_NAME, __scopeSelect);
  731. const composedRefs = $01b9c$useComposedRefs(forwardedRef, contentContext.onViewportChange);
  732. const prevScrollTopRef = $01b9c$useRef(0);
  733. return /*#__PURE__*/ $01b9c$createElement($01b9c$Fragment, null, /*#__PURE__*/ $01b9c$createElement("style", {
  734. dangerouslySetInnerHTML: {
  735. __html: `[data-radix-select-viewport]{scrollbar-width:none;-ms-overflow-style:none;-webkit-overflow-scrolling:touch;}[data-radix-select-viewport]::-webkit-scrollbar{display:none}`
  736. }
  737. }), /*#__PURE__*/ $01b9c$createElement($cc7e05a45900e73f$var$Collection.Slot, {
  738. scope: __scopeSelect
  739. }, /*#__PURE__*/ $01b9c$createElement($01b9c$Primitive.div, $01b9c$babelruntimehelpersesmextends({
  740. "data-radix-select-viewport": "",
  741. role: "presentation"
  742. }, viewportProps, {
  743. ref: composedRefs,
  744. style: {
  745. // we use position: 'relative' here on the `viewport` so that when we call
  746. // `selectedItem.offsetTop` in calculations, the offset is relative to the viewport
  747. // (independent of the scrollUpButton).
  748. position: 'relative',
  749. flex: 1,
  750. overflow: 'auto',
  751. ...viewportProps.style
  752. },
  753. onScroll: $01b9c$composeEventHandlers(viewportProps.onScroll, (event)=>{
  754. const viewport = event.currentTarget;
  755. const { contentWrapper: contentWrapper , shouldExpandOnScrollRef: shouldExpandOnScrollRef } = viewportContext;
  756. if (shouldExpandOnScrollRef !== null && shouldExpandOnScrollRef !== void 0 && shouldExpandOnScrollRef.current && contentWrapper) {
  757. const scrolledBy = Math.abs(prevScrollTopRef.current - viewport.scrollTop);
  758. if (scrolledBy > 0) {
  759. const availableHeight = window.innerHeight - $cc7e05a45900e73f$var$CONTENT_MARGIN * 2;
  760. const cssMinHeight = parseFloat(contentWrapper.style.minHeight);
  761. const cssHeight = parseFloat(contentWrapper.style.height);
  762. const prevHeight = Math.max(cssMinHeight, cssHeight);
  763. if (prevHeight < availableHeight) {
  764. const nextHeight = prevHeight + scrolledBy;
  765. const clampedNextHeight = Math.min(availableHeight, nextHeight);
  766. const heightDiff = nextHeight - clampedNextHeight;
  767. contentWrapper.style.height = clampedNextHeight + 'px';
  768. if (contentWrapper.style.bottom === '0px') {
  769. viewport.scrollTop = heightDiff > 0 ? heightDiff : 0; // ensure the content stays pinned to the bottom
  770. contentWrapper.style.justifyContent = 'flex-end';
  771. }
  772. }
  773. }
  774. }
  775. prevScrollTopRef.current = viewport.scrollTop;
  776. })
  777. }))));
  778. });
  779. /*#__PURE__*/ Object.assign($cc7e05a45900e73f$export$9ed6e7b40248d36d, {
  780. displayName: $cc7e05a45900e73f$var$VIEWPORT_NAME
  781. });
  782. /* -------------------------------------------------------------------------------------------------
  783. * SelectGroup
  784. * -----------------------------------------------------------------------------------------------*/ const $cc7e05a45900e73f$var$GROUP_NAME = 'SelectGroup';
  785. const [$cc7e05a45900e73f$var$SelectGroupContextProvider, $cc7e05a45900e73f$var$useSelectGroupContext] = $cc7e05a45900e73f$var$createSelectContext($cc7e05a45900e73f$var$GROUP_NAME);
  786. const $cc7e05a45900e73f$export$ee25a334c55de1f4 = /*#__PURE__*/ $01b9c$forwardRef((props, forwardedRef)=>{
  787. const { __scopeSelect: __scopeSelect , ...groupProps } = props;
  788. const groupId = $01b9c$useId();
  789. return /*#__PURE__*/ $01b9c$createElement($cc7e05a45900e73f$var$SelectGroupContextProvider, {
  790. scope: __scopeSelect,
  791. id: groupId
  792. }, /*#__PURE__*/ $01b9c$createElement($01b9c$Primitive.div, $01b9c$babelruntimehelpersesmextends({
  793. role: "group",
  794. "aria-labelledby": groupId
  795. }, groupProps, {
  796. ref: forwardedRef
  797. })));
  798. });
  799. /*#__PURE__*/ Object.assign($cc7e05a45900e73f$export$ee25a334c55de1f4, {
  800. displayName: $cc7e05a45900e73f$var$GROUP_NAME
  801. });
  802. /* -------------------------------------------------------------------------------------------------
  803. * SelectLabel
  804. * -----------------------------------------------------------------------------------------------*/ const $cc7e05a45900e73f$var$LABEL_NAME = 'SelectLabel';
  805. const $cc7e05a45900e73f$export$f67338d29bd972f8 = /*#__PURE__*/ $01b9c$forwardRef((props, forwardedRef)=>{
  806. const { __scopeSelect: __scopeSelect , ...labelProps } = props;
  807. const groupContext = $cc7e05a45900e73f$var$useSelectGroupContext($cc7e05a45900e73f$var$LABEL_NAME, __scopeSelect);
  808. return /*#__PURE__*/ $01b9c$createElement($01b9c$Primitive.div, $01b9c$babelruntimehelpersesmextends({
  809. id: groupContext.id
  810. }, labelProps, {
  811. ref: forwardedRef
  812. }));
  813. });
  814. /*#__PURE__*/ Object.assign($cc7e05a45900e73f$export$f67338d29bd972f8, {
  815. displayName: $cc7e05a45900e73f$var$LABEL_NAME
  816. });
  817. /* -------------------------------------------------------------------------------------------------
  818. * SelectItem
  819. * -----------------------------------------------------------------------------------------------*/ const $cc7e05a45900e73f$var$ITEM_NAME = 'SelectItem';
  820. const [$cc7e05a45900e73f$var$SelectItemContextProvider, $cc7e05a45900e73f$var$useSelectItemContext] = $cc7e05a45900e73f$var$createSelectContext($cc7e05a45900e73f$var$ITEM_NAME);
  821. const $cc7e05a45900e73f$export$13ef48a934230896 = /*#__PURE__*/ $01b9c$forwardRef((props, forwardedRef)=>{
  822. const { __scopeSelect: __scopeSelect , value: value , disabled: disabled = false , textValue: textValueProp , ...itemProps } = props;
  823. const context = $cc7e05a45900e73f$var$useSelectContext($cc7e05a45900e73f$var$ITEM_NAME, __scopeSelect);
  824. const contentContext = $cc7e05a45900e73f$var$useSelectContentContext($cc7e05a45900e73f$var$ITEM_NAME, __scopeSelect);
  825. const isSelected = context.value === value;
  826. const [textValue, setTextValue] = $01b9c$useState(textValueProp !== null && textValueProp !== void 0 ? textValueProp : '');
  827. const [isFocused, setIsFocused] = $01b9c$useState(false);
  828. const composedRefs = $01b9c$useComposedRefs(forwardedRef, (node)=>{
  829. var _contentContext$itemR;
  830. return (_contentContext$itemR = contentContext.itemRefCallback) === null || _contentContext$itemR === void 0 ? void 0 : _contentContext$itemR.call(contentContext, node, value, disabled);
  831. });
  832. const textId = $01b9c$useId();
  833. const handleSelect = ()=>{
  834. if (!disabled) {
  835. context.onValueChange(value);
  836. context.onOpenChange(false);
  837. }
  838. };
  839. return /*#__PURE__*/ $01b9c$createElement($cc7e05a45900e73f$var$SelectItemContextProvider, {
  840. scope: __scopeSelect,
  841. value: value,
  842. disabled: disabled,
  843. textId: textId,
  844. isSelected: isSelected,
  845. onItemTextChange: $01b9c$useCallback((node)=>{
  846. setTextValue((prevTextValue)=>{
  847. var _node$textContent;
  848. return prevTextValue || ((_node$textContent = node === null || node === void 0 ? void 0 : node.textContent) !== null && _node$textContent !== void 0 ? _node$textContent : '').trim();
  849. });
  850. }, [])
  851. }, /*#__PURE__*/ $01b9c$createElement($cc7e05a45900e73f$var$Collection.ItemSlot, {
  852. scope: __scopeSelect,
  853. value: value,
  854. disabled: disabled,
  855. textValue: textValue
  856. }, /*#__PURE__*/ $01b9c$createElement($01b9c$Primitive.div, $01b9c$babelruntimehelpersesmextends({
  857. role: "option",
  858. "aria-labelledby": textId,
  859. "data-highlighted": isFocused ? '' : undefined // `isFocused` caveat fixes stuttering in VoiceOver
  860. ,
  861. "aria-selected": isSelected && isFocused,
  862. "data-state": isSelected ? 'checked' : 'unchecked',
  863. "aria-disabled": disabled || undefined,
  864. "data-disabled": disabled ? '' : undefined,
  865. tabIndex: disabled ? undefined : -1
  866. }, itemProps, {
  867. ref: composedRefs,
  868. onFocus: $01b9c$composeEventHandlers(itemProps.onFocus, ()=>setIsFocused(true)
  869. ),
  870. onBlur: $01b9c$composeEventHandlers(itemProps.onBlur, ()=>setIsFocused(false)
  871. ),
  872. onPointerUp: $01b9c$composeEventHandlers(itemProps.onPointerUp, handleSelect),
  873. onPointerMove: $01b9c$composeEventHandlers(itemProps.onPointerMove, (event)=>{
  874. if (disabled) {
  875. var _contentContext$onIte;
  876. (_contentContext$onIte = contentContext.onItemLeave) === null || _contentContext$onIte === void 0 || _contentContext$onIte.call(contentContext);
  877. } else // even though safari doesn't support this option, it's acceptable
  878. // as it only means it might scroll a few pixels when using the pointer.
  879. event.currentTarget.focus({
  880. preventScroll: true
  881. });
  882. }),
  883. onPointerLeave: $01b9c$composeEventHandlers(itemProps.onPointerLeave, (event)=>{
  884. if (event.currentTarget === document.activeElement) {
  885. var _contentContext$onIte2;
  886. (_contentContext$onIte2 = contentContext.onItemLeave) === null || _contentContext$onIte2 === void 0 || _contentContext$onIte2.call(contentContext);
  887. }
  888. }),
  889. onKeyDown: $01b9c$composeEventHandlers(itemProps.onKeyDown, (event)=>{
  890. var _contentContext$searc;
  891. const isTypingAhead = ((_contentContext$searc = contentContext.searchRef) === null || _contentContext$searc === void 0 ? void 0 : _contentContext$searc.current) !== '';
  892. if (isTypingAhead && event.key === ' ') return;
  893. if ($cc7e05a45900e73f$var$SELECTION_KEYS.includes(event.key)) handleSelect(); // prevent page scroll if using the space key to select an item
  894. if (event.key === ' ') event.preventDefault();
  895. })
  896. }))));
  897. });
  898. /*#__PURE__*/ Object.assign($cc7e05a45900e73f$export$13ef48a934230896, {
  899. displayName: $cc7e05a45900e73f$var$ITEM_NAME
  900. });
  901. /* -------------------------------------------------------------------------------------------------
  902. * SelectItemText
  903. * -----------------------------------------------------------------------------------------------*/ const $cc7e05a45900e73f$var$ITEM_TEXT_NAME = 'SelectItemText';
  904. const $cc7e05a45900e73f$export$3572fb0fb821ff49 = /*#__PURE__*/ $01b9c$forwardRef((props, forwardedRef)=>{
  905. // We ignore `className` and `style` as this part shouldn't be styled.
  906. const { __scopeSelect: __scopeSelect , className: className , style: style , ...itemTextProps } = props;
  907. const context = $cc7e05a45900e73f$var$useSelectContext($cc7e05a45900e73f$var$ITEM_TEXT_NAME, __scopeSelect);
  908. const contentContext = $cc7e05a45900e73f$var$useSelectContentContext($cc7e05a45900e73f$var$ITEM_TEXT_NAME, __scopeSelect);
  909. const itemContext = $cc7e05a45900e73f$var$useSelectItemContext($cc7e05a45900e73f$var$ITEM_TEXT_NAME, __scopeSelect);
  910. const nativeOptionsContext = $cc7e05a45900e73f$var$useSelectNativeOptionsContext($cc7e05a45900e73f$var$ITEM_TEXT_NAME, __scopeSelect);
  911. const [itemTextNode, setItemTextNode] = $01b9c$useState(null);
  912. const composedRefs = $01b9c$useComposedRefs(forwardedRef, (node)=>setItemTextNode(node)
  913. , itemContext.onItemTextChange, (node)=>{
  914. var _contentContext$itemT;
  915. return (_contentContext$itemT = contentContext.itemTextRefCallback) === null || _contentContext$itemT === void 0 ? void 0 : _contentContext$itemT.call(contentContext, node, itemContext.value, itemContext.disabled);
  916. });
  917. const textContent = itemTextNode === null || itemTextNode === void 0 ? void 0 : itemTextNode.textContent;
  918. const nativeOption = $01b9c$useMemo(()=>/*#__PURE__*/ $01b9c$createElement("option", {
  919. key: itemContext.value,
  920. value: itemContext.value,
  921. disabled: itemContext.disabled
  922. }, textContent)
  923. , [
  924. itemContext.disabled,
  925. itemContext.value,
  926. textContent
  927. ]);
  928. const { onNativeOptionAdd: onNativeOptionAdd , onNativeOptionRemove: onNativeOptionRemove } = nativeOptionsContext;
  929. $01b9c$useLayoutEffect(()=>{
  930. onNativeOptionAdd(nativeOption);
  931. return ()=>onNativeOptionRemove(nativeOption)
  932. ;
  933. }, [
  934. onNativeOptionAdd,
  935. onNativeOptionRemove,
  936. nativeOption
  937. ]);
  938. return /*#__PURE__*/ $01b9c$createElement($01b9c$Fragment, null, /*#__PURE__*/ $01b9c$createElement($01b9c$Primitive.span, $01b9c$babelruntimehelpersesmextends({
  939. id: itemContext.textId
  940. }, itemTextProps, {
  941. ref: composedRefs
  942. })), itemContext.isSelected && context.valueNode && !context.valueNodeHasChildren ? /*#__PURE__*/ $01b9c$createPortal(itemTextProps.children, context.valueNode) : null);
  943. });
  944. /*#__PURE__*/ Object.assign($cc7e05a45900e73f$export$3572fb0fb821ff49, {
  945. displayName: $cc7e05a45900e73f$var$ITEM_TEXT_NAME
  946. });
  947. /* -------------------------------------------------------------------------------------------------
  948. * SelectItemIndicator
  949. * -----------------------------------------------------------------------------------------------*/ const $cc7e05a45900e73f$var$ITEM_INDICATOR_NAME = 'SelectItemIndicator';
  950. const $cc7e05a45900e73f$export$6b9198de19accfe6 = /*#__PURE__*/ $01b9c$forwardRef((props, forwardedRef)=>{
  951. const { __scopeSelect: __scopeSelect , ...itemIndicatorProps } = props;
  952. const itemContext = $cc7e05a45900e73f$var$useSelectItemContext($cc7e05a45900e73f$var$ITEM_INDICATOR_NAME, __scopeSelect);
  953. return itemContext.isSelected ? /*#__PURE__*/ $01b9c$createElement($01b9c$Primitive.span, $01b9c$babelruntimehelpersesmextends({
  954. "aria-hidden": true
  955. }, itemIndicatorProps, {
  956. ref: forwardedRef
  957. })) : null;
  958. });
  959. /*#__PURE__*/ Object.assign($cc7e05a45900e73f$export$6b9198de19accfe6, {
  960. displayName: $cc7e05a45900e73f$var$ITEM_INDICATOR_NAME
  961. });
  962. /* -------------------------------------------------------------------------------------------------
  963. * SelectScrollUpButton
  964. * -----------------------------------------------------------------------------------------------*/ const $cc7e05a45900e73f$var$SCROLL_UP_BUTTON_NAME = 'SelectScrollUpButton';
  965. const $cc7e05a45900e73f$export$d8117927658af6d7 = /*#__PURE__*/ $01b9c$forwardRef((props, forwardedRef)=>{
  966. const contentContext = $cc7e05a45900e73f$var$useSelectContentContext($cc7e05a45900e73f$var$SCROLL_UP_BUTTON_NAME, props.__scopeSelect);
  967. const viewportContext = $cc7e05a45900e73f$var$useSelectViewportContext($cc7e05a45900e73f$var$SCROLL_UP_BUTTON_NAME, props.__scopeSelect);
  968. const [canScrollUp1, setCanScrollUp] = $01b9c$useState(false);
  969. const composedRefs = $01b9c$useComposedRefs(forwardedRef, viewportContext.onScrollButtonChange);
  970. $01b9c$useLayoutEffect(()=>{
  971. if (contentContext.viewport && contentContext.isPositioned) {
  972. const viewport = contentContext.viewport;
  973. function handleScroll() {
  974. const canScrollUp = viewport.scrollTop > 0;
  975. setCanScrollUp(canScrollUp);
  976. }
  977. handleScroll();
  978. viewport.addEventListener('scroll', handleScroll);
  979. return ()=>viewport.removeEventListener('scroll', handleScroll)
  980. ;
  981. }
  982. }, [
  983. contentContext.viewport,
  984. contentContext.isPositioned
  985. ]);
  986. return canScrollUp1 ? /*#__PURE__*/ $01b9c$createElement($cc7e05a45900e73f$var$SelectScrollButtonImpl, $01b9c$babelruntimehelpersesmextends({}, props, {
  987. ref: composedRefs,
  988. onAutoScroll: ()=>{
  989. const { viewport: viewport , selectedItem: selectedItem } = contentContext;
  990. if (viewport && selectedItem) viewport.scrollTop = viewport.scrollTop - selectedItem.offsetHeight;
  991. }
  992. })) : null;
  993. });
  994. /*#__PURE__*/ Object.assign($cc7e05a45900e73f$export$d8117927658af6d7, {
  995. displayName: $cc7e05a45900e73f$var$SCROLL_UP_BUTTON_NAME
  996. });
  997. /* -------------------------------------------------------------------------------------------------
  998. * SelectScrollDownButton
  999. * -----------------------------------------------------------------------------------------------*/ const $cc7e05a45900e73f$var$SCROLL_DOWN_BUTTON_NAME = 'SelectScrollDownButton';
  1000. const $cc7e05a45900e73f$export$ff951e476c12189 = /*#__PURE__*/ $01b9c$forwardRef((props, forwardedRef)=>{
  1001. const contentContext = $cc7e05a45900e73f$var$useSelectContentContext($cc7e05a45900e73f$var$SCROLL_DOWN_BUTTON_NAME, props.__scopeSelect);
  1002. const viewportContext = $cc7e05a45900e73f$var$useSelectViewportContext($cc7e05a45900e73f$var$SCROLL_DOWN_BUTTON_NAME, props.__scopeSelect);
  1003. const [canScrollDown1, setCanScrollDown] = $01b9c$useState(false);
  1004. const composedRefs = $01b9c$useComposedRefs(forwardedRef, viewportContext.onScrollButtonChange);
  1005. $01b9c$useLayoutEffect(()=>{
  1006. if (contentContext.viewport && contentContext.isPositioned) {
  1007. const viewport = contentContext.viewport;
  1008. function handleScroll() {
  1009. const maxScroll = viewport.scrollHeight - viewport.clientHeight; // we use Math.ceil here because if the UI is zoomed-in
  1010. // `scrollTop` is not always reported as an integer
  1011. const canScrollDown = Math.ceil(viewport.scrollTop) < maxScroll;
  1012. setCanScrollDown(canScrollDown);
  1013. }
  1014. handleScroll();
  1015. viewport.addEventListener('scroll', handleScroll);
  1016. return ()=>viewport.removeEventListener('scroll', handleScroll)
  1017. ;
  1018. }
  1019. }, [
  1020. contentContext.viewport,
  1021. contentContext.isPositioned
  1022. ]);
  1023. return canScrollDown1 ? /*#__PURE__*/ $01b9c$createElement($cc7e05a45900e73f$var$SelectScrollButtonImpl, $01b9c$babelruntimehelpersesmextends({}, props, {
  1024. ref: composedRefs,
  1025. onAutoScroll: ()=>{
  1026. const { viewport: viewport , selectedItem: selectedItem } = contentContext;
  1027. if (viewport && selectedItem) viewport.scrollTop = viewport.scrollTop + selectedItem.offsetHeight;
  1028. }
  1029. })) : null;
  1030. });
  1031. /*#__PURE__*/ Object.assign($cc7e05a45900e73f$export$ff951e476c12189, {
  1032. displayName: $cc7e05a45900e73f$var$SCROLL_DOWN_BUTTON_NAME
  1033. });
  1034. const $cc7e05a45900e73f$var$SelectScrollButtonImpl = /*#__PURE__*/ $01b9c$forwardRef((props, forwardedRef)=>{
  1035. const { __scopeSelect: __scopeSelect , onAutoScroll: onAutoScroll , ...scrollIndicatorProps } = props;
  1036. const contentContext = $cc7e05a45900e73f$var$useSelectContentContext('SelectScrollButton', __scopeSelect);
  1037. const autoScrollTimerRef = $01b9c$useRef(null);
  1038. const getItems = $cc7e05a45900e73f$var$useCollection(__scopeSelect);
  1039. const clearAutoScrollTimer = $01b9c$useCallback(()=>{
  1040. if (autoScrollTimerRef.current !== null) {
  1041. window.clearInterval(autoScrollTimerRef.current);
  1042. autoScrollTimerRef.current = null;
  1043. }
  1044. }, []);
  1045. $01b9c$useEffect(()=>{
  1046. return ()=>clearAutoScrollTimer()
  1047. ;
  1048. }, [
  1049. clearAutoScrollTimer
  1050. ]); // When the viewport becomes scrollable on either side, the relevant scroll button will mount.
  1051. // Because it is part of the normal flow, it will push down (top button) or shrink (bottom button)
  1052. // the viewport, potentially causing the active item to now be partially out of view.
  1053. // We re-run the `scrollIntoView` logic to make sure it stays within the viewport.
  1054. $01b9c$useLayoutEffect(()=>{
  1055. var _activeItem$ref$curre;
  1056. const activeItem = getItems().find((item)=>item.ref.current === document.activeElement
  1057. );
  1058. activeItem === null || activeItem === void 0 || (_activeItem$ref$curre = activeItem.ref.current) === null || _activeItem$ref$curre === void 0 || _activeItem$ref$curre.scrollIntoView({
  1059. block: 'nearest'
  1060. });
  1061. }, [
  1062. getItems
  1063. ]);
  1064. return /*#__PURE__*/ $01b9c$createElement($01b9c$Primitive.div, $01b9c$babelruntimehelpersesmextends({
  1065. "aria-hidden": true
  1066. }, scrollIndicatorProps, {
  1067. ref: forwardedRef,
  1068. style: {
  1069. flexShrink: 0,
  1070. ...scrollIndicatorProps.style
  1071. },
  1072. onPointerDown: $01b9c$composeEventHandlers(scrollIndicatorProps.onPointerDown, ()=>{
  1073. if (autoScrollTimerRef.current === null) autoScrollTimerRef.current = window.setInterval(onAutoScroll, 50);
  1074. }),
  1075. onPointerMove: $01b9c$composeEventHandlers(scrollIndicatorProps.onPointerMove, ()=>{
  1076. var _contentContext$onIte3;
  1077. (_contentContext$onIte3 = contentContext.onItemLeave) === null || _contentContext$onIte3 === void 0 || _contentContext$onIte3.call(contentContext);
  1078. if (autoScrollTimerRef.current === null) autoScrollTimerRef.current = window.setInterval(onAutoScroll, 50);
  1079. }),
  1080. onPointerLeave: $01b9c$composeEventHandlers(scrollIndicatorProps.onPointerLeave, ()=>{
  1081. clearAutoScrollTimer();
  1082. })
  1083. }));
  1084. });
  1085. /* -------------------------------------------------------------------------------------------------
  1086. * SelectSeparator
  1087. * -----------------------------------------------------------------------------------------------*/ const $cc7e05a45900e73f$var$SEPARATOR_NAME = 'SelectSeparator';
  1088. const $cc7e05a45900e73f$export$eba4b1df07cb1d3 = /*#__PURE__*/ $01b9c$forwardRef((props, forwardedRef)=>{
  1089. const { __scopeSelect: __scopeSelect , ...separatorProps } = props;
  1090. return /*#__PURE__*/ $01b9c$createElement($01b9c$Primitive.div, $01b9c$babelruntimehelpersesmextends({
  1091. "aria-hidden": true
  1092. }, separatorProps, {
  1093. ref: forwardedRef
  1094. }));
  1095. });
  1096. /*#__PURE__*/ Object.assign($cc7e05a45900e73f$export$eba4b1df07cb1d3, {
  1097. displayName: $cc7e05a45900e73f$var$SEPARATOR_NAME
  1098. });
  1099. /* -------------------------------------------------------------------------------------------------
  1100. * SelectArrow
  1101. * -----------------------------------------------------------------------------------------------*/ const $cc7e05a45900e73f$var$ARROW_NAME = 'SelectArrow';
  1102. const $cc7e05a45900e73f$export$314f4cb8f8099628 = /*#__PURE__*/ $01b9c$forwardRef((props, forwardedRef)=>{
  1103. const { __scopeSelect: __scopeSelect , ...arrowProps } = props;
  1104. const popperScope = $cc7e05a45900e73f$var$usePopperScope(__scopeSelect);
  1105. const context = $cc7e05a45900e73f$var$useSelectContext($cc7e05a45900e73f$var$ARROW_NAME, __scopeSelect);
  1106. const contentContext = $cc7e05a45900e73f$var$useSelectContentContext($cc7e05a45900e73f$var$ARROW_NAME, __scopeSelect);
  1107. return context.open && contentContext.position === 'popper' ? /*#__PURE__*/ $01b9c$createElement($01b9c$Arrow, $01b9c$babelruntimehelpersesmextends({}, popperScope, arrowProps, {
  1108. ref: forwardedRef
  1109. })) : null;
  1110. });
  1111. /*#__PURE__*/ Object.assign($cc7e05a45900e73f$export$314f4cb8f8099628, {
  1112. displayName: $cc7e05a45900e73f$var$ARROW_NAME
  1113. });
  1114. /* -----------------------------------------------------------------------------------------------*/ const $cc7e05a45900e73f$var$BubbleSelect = /*#__PURE__*/ $01b9c$forwardRef((props, forwardedRef)=>{
  1115. const { value: value , ...selectProps } = props;
  1116. const ref = $01b9c$useRef(null);
  1117. const composedRefs = $01b9c$useComposedRefs(forwardedRef, ref);
  1118. const prevValue = $01b9c$usePrevious(value); // Bubble value change to parents (e.g form change event)
  1119. $01b9c$useEffect(()=>{
  1120. const select = ref.current;
  1121. const selectProto = window.HTMLSelectElement.prototype;
  1122. const descriptor = Object.getOwnPropertyDescriptor(selectProto, 'value');
  1123. const setValue = descriptor.set;
  1124. if (prevValue !== value && setValue) {
  1125. const event = new Event('change', {
  1126. bubbles: true
  1127. });
  1128. setValue.call(select, value);
  1129. select.dispatchEvent(event);
  1130. }
  1131. }, [
  1132. prevValue,
  1133. value
  1134. ]);
  1135. /**
  1136. * We purposefully use a `select` here to support form autofill as much
  1137. * as possible.
  1138. *
  1139. * We purposefully do not add the `value` attribute here to allow the value
  1140. * to be set programatically and bubble to any parent form `onChange` event.
  1141. * Adding the `value` will cause React to consider the programatic
  1142. * dispatch a duplicate and it will get swallowed.
  1143. *
  1144. * We use `VisuallyHidden` rather than `display: "none"` because Safari autofill
  1145. * won't work otherwise.
  1146. */ return /*#__PURE__*/ $01b9c$createElement($01b9c$VisuallyHidden, {
  1147. asChild: true
  1148. }, /*#__PURE__*/ $01b9c$createElement("select", $01b9c$babelruntimehelpersesmextends({}, selectProps, {
  1149. ref: composedRefs,
  1150. defaultValue: value
  1151. })));
  1152. });
  1153. $cc7e05a45900e73f$var$BubbleSelect.displayName = 'BubbleSelect';
  1154. function $cc7e05a45900e73f$var$useTypeaheadSearch(onSearchChange) {
  1155. const handleSearchChange = $01b9c$useCallbackRef(onSearchChange);
  1156. const searchRef = $01b9c$useRef('');
  1157. const timerRef = $01b9c$useRef(0);
  1158. const handleTypeaheadSearch = $01b9c$useCallback((key)=>{
  1159. const search = searchRef.current + key;
  1160. handleSearchChange(search);
  1161. (function updateSearch(value) {
  1162. searchRef.current = value;
  1163. window.clearTimeout(timerRef.current); // Reset `searchRef` 1 second after it was last updated
  1164. if (value !== '') timerRef.current = window.setTimeout(()=>updateSearch('')
  1165. , 1000);
  1166. })(search);
  1167. }, [
  1168. handleSearchChange
  1169. ]);
  1170. const resetTypeahead = $01b9c$useCallback(()=>{
  1171. searchRef.current = '';
  1172. window.clearTimeout(timerRef.current);
  1173. }, []);
  1174. $01b9c$useEffect(()=>{
  1175. return ()=>window.clearTimeout(timerRef.current)
  1176. ;
  1177. }, []);
  1178. return [
  1179. searchRef,
  1180. handleTypeaheadSearch,
  1181. resetTypeahead
  1182. ];
  1183. }
  1184. /**
  1185. * This is the "meat" of the typeahead matching logic. It takes in a list of items,
  1186. * the search and the current item, and returns the next item (or `undefined`).
  1187. *
  1188. * We normalize the search because if a user has repeatedly pressed a character,
  1189. * we want the exact same behavior as if we only had that one character
  1190. * (ie. cycle through items starting with that character)
  1191. *
  1192. * We also reorder the items by wrapping the array around the current item.
  1193. * This is so we always look forward from the current item, and picking the first
  1194. * item will always be the correct one.
  1195. *
  1196. * Finally, if the normalized search is exactly one character, we exclude the
  1197. * current item from the values because otherwise it would be the first to match always
  1198. * and focus would never move. This is as opposed to the regular case, where we
  1199. * don't want focus to move if the current item still matches.
  1200. */ function $cc7e05a45900e73f$var$findNextItem(items, search, currentItem) {
  1201. const isRepeated = search.length > 1 && Array.from(search).every((char)=>char === search[0]
  1202. );
  1203. const normalizedSearch = isRepeated ? search[0] : search;
  1204. const currentItemIndex = currentItem ? items.indexOf(currentItem) : -1;
  1205. let wrappedItems = $cc7e05a45900e73f$var$wrapArray(items, Math.max(currentItemIndex, 0));
  1206. const excludeCurrentItem = normalizedSearch.length === 1;
  1207. if (excludeCurrentItem) wrappedItems = wrappedItems.filter((v)=>v !== currentItem
  1208. );
  1209. const nextItem = wrappedItems.find((item)=>item.textValue.toLowerCase().startsWith(normalizedSearch.toLowerCase())
  1210. );
  1211. return nextItem !== currentItem ? nextItem : undefined;
  1212. }
  1213. /**
  1214. * Wraps an array around itself at a given start index
  1215. * Example: `wrapArray(['a', 'b', 'c', 'd'], 2) === ['c', 'd', 'a', 'b']`
  1216. */ function $cc7e05a45900e73f$var$wrapArray(array, startIndex) {
  1217. return array.map((_, index)=>array[(startIndex + index) % array.length]
  1218. );
  1219. }
  1220. const $cc7e05a45900e73f$export$be92b6f5f03c0fe9 = $cc7e05a45900e73f$export$ef9b1a59e592288f;
  1221. const $cc7e05a45900e73f$export$41fb9f06171c75f4 = $cc7e05a45900e73f$export$3ac1e88a1c0b9f1;
  1222. const $cc7e05a45900e73f$export$4c8d1a57a761ef94 = $cc7e05a45900e73f$export$e288731fd71264f0;
  1223. const $cc7e05a45900e73f$export$f04a61298a47a40f = $cc7e05a45900e73f$export$99b400cabb58c515;
  1224. const $cc7e05a45900e73f$export$602eac185826482c = $cc7e05a45900e73f$export$b2af6c9944296213;
  1225. const $cc7e05a45900e73f$export$7c6e2c02157bb7d2 = $cc7e05a45900e73f$export$c973a4b3cb86a03d;
  1226. const $cc7e05a45900e73f$export$d5c6c08dc2d3ca7 = $cc7e05a45900e73f$export$9ed6e7b40248d36d;
  1227. const $cc7e05a45900e73f$export$eb2fcfdbd7ba97d4 = $cc7e05a45900e73f$export$ee25a334c55de1f4;
  1228. const $cc7e05a45900e73f$export$b04be29aa201d4f5 = $cc7e05a45900e73f$export$f67338d29bd972f8;
  1229. const $cc7e05a45900e73f$export$6d08773d2e66f8f2 = $cc7e05a45900e73f$export$13ef48a934230896;
  1230. const $cc7e05a45900e73f$export$d6e5bf9c43ea9319 = $cc7e05a45900e73f$export$3572fb0fb821ff49;
  1231. const $cc7e05a45900e73f$export$c3468e2714d175fa = $cc7e05a45900e73f$export$6b9198de19accfe6;
  1232. const $cc7e05a45900e73f$export$2f60d3ec9ad468f2 = $cc7e05a45900e73f$export$d8117927658af6d7;
  1233. const $cc7e05a45900e73f$export$bf1aedc3039c8d63 = $cc7e05a45900e73f$export$ff951e476c12189;
  1234. const $cc7e05a45900e73f$export$1ff3c3f08ae963c0 = $cc7e05a45900e73f$export$eba4b1df07cb1d3;
  1235. const $cc7e05a45900e73f$export$21b07c8f274aebd5 = $cc7e05a45900e73f$export$314f4cb8f8099628;
  1236. export {$cc7e05a45900e73f$export$286727a75dc039bd as createSelectScope, $cc7e05a45900e73f$export$ef9b1a59e592288f as Select, $cc7e05a45900e73f$export$3ac1e88a1c0b9f1 as SelectTrigger, $cc7e05a45900e73f$export$e288731fd71264f0 as SelectValue, $cc7e05a45900e73f$export$99b400cabb58c515 as SelectIcon, $cc7e05a45900e73f$export$b2af6c9944296213 as SelectPortal, $cc7e05a45900e73f$export$c973a4b3cb86a03d as SelectContent, $cc7e05a45900e73f$export$9ed6e7b40248d36d as SelectViewport, $cc7e05a45900e73f$export$ee25a334c55de1f4 as SelectGroup, $cc7e05a45900e73f$export$f67338d29bd972f8 as SelectLabel, $cc7e05a45900e73f$export$13ef48a934230896 as SelectItem, $cc7e05a45900e73f$export$3572fb0fb821ff49 as SelectItemText, $cc7e05a45900e73f$export$6b9198de19accfe6 as SelectItemIndicator, $cc7e05a45900e73f$export$d8117927658af6d7 as SelectScrollUpButton, $cc7e05a45900e73f$export$ff951e476c12189 as SelectScrollDownButton, $cc7e05a45900e73f$export$eba4b1df07cb1d3 as SelectSeparator, $cc7e05a45900e73f$export$314f4cb8f8099628 as SelectArrow, $cc7e05a45900e73f$export$be92b6f5f03c0fe9 as Root, $cc7e05a45900e73f$export$41fb9f06171c75f4 as Trigger, $cc7e05a45900e73f$export$4c8d1a57a761ef94 as Value, $cc7e05a45900e73f$export$f04a61298a47a40f as Icon, $cc7e05a45900e73f$export$602eac185826482c as Portal, $cc7e05a45900e73f$export$7c6e2c02157bb7d2 as Content, $cc7e05a45900e73f$export$d5c6c08dc2d3ca7 as Viewport, $cc7e05a45900e73f$export$eb2fcfdbd7ba97d4 as Group, $cc7e05a45900e73f$export$b04be29aa201d4f5 as Label, $cc7e05a45900e73f$export$6d08773d2e66f8f2 as Item, $cc7e05a45900e73f$export$d6e5bf9c43ea9319 as ItemText, $cc7e05a45900e73f$export$c3468e2714d175fa as ItemIndicator, $cc7e05a45900e73f$export$2f60d3ec9ad468f2 as ScrollUpButton, $cc7e05a45900e73f$export$bf1aedc3039c8d63 as ScrollDownButton, $cc7e05a45900e73f$export$1ff3c3f08ae963c0 as Separator, $cc7e05a45900e73f$export$21b07c8f274aebd5 as Arrow};
  1237. //# sourceMappingURL=index.mjs.map