1- import { Fragment , useCallback , useEffect , useMemo , useRef , useState } from "react" ;
1+ import React , { Fragment , useCallback , useEffect , useMemo , useRef , useState } from "react" ;
22import type {
33 ArrayPath ,
44 Control ,
@@ -10,7 +10,7 @@ import type {
1010 UseFieldArrayRemove ,
1111} from "react-hook-form" ;
1212import { Controller , useFieldArray , useFormContext } from "react-hook-form" ;
13- import type { GroupBase , Props } from "react-select" ;
13+ import { createFilter , type GroupBase , type Props } from "react-select" ;
1414
1515import type { scheduleClassNames } from "@calcom/atoms/availability/types" ;
1616import type { ConfigType } from "@calcom/dayjs" ;
@@ -20,6 +20,7 @@ import { useLocale } from "@calcom/lib/hooks/useLocale";
2020import { weekdayNames } from "@calcom/lib/weekday" ;
2121import useMeQuery from "@calcom/trpc/react/hooks/useMeQuery" ;
2222import type { TimeRange } from "@calcom/types/schedule" ;
23+
2324import cn from "@calcom/ui/classNames" ;
2425import { Button } from "@calcom/ui/components/button" ;
2526import { Dropdown , DropdownMenuContent , DropdownMenuTrigger } from "@calcom/ui/components/dropdown" ;
@@ -396,9 +397,36 @@ const LazySelect = ({
396397 filter ( { current : value } ) ;
397398 } , [ filter , value ] ) ;
398399
400+ const [ inputValue , setInputValue ] = React . useState ( "" ) ;
401+ const defaultFilter = React . useMemo ( ( ) => createFilter ( ) , [ ] ) ;
402+ const filteredOptions = React . useMemo ( ( ) => {
403+ const regex = / ^ ( \d { 1 , 2 } ) ( a | p | a m | p m ) $ / i;
404+ const match = inputValue . replaceAll ( " " , "" ) . match ( regex ) ;
405+ if ( ! match ) {
406+ return options . filter ( ( option ) =>
407+ defaultFilter ( { ...option , data : option . label , value : option . label } , inputValue )
408+ ) ;
409+ }
410+
411+ const [ , numberPart , periodPart ] = match ;
412+ const periodLower = periodPart . toLowerCase ( ) ;
413+ const scoredOptions = options
414+ . filter ( ( option ) => option . label && option . label . toLowerCase ( ) . includes ( periodLower ) )
415+ . map ( ( option ) => {
416+ const labelLower = option . label . toLowerCase ( ) ;
417+ const index = labelLower . indexOf ( numberPart ) ;
418+ const score = index >= 0 ? index + labelLower . length : Infinity ;
419+ return { score, option } ;
420+ } )
421+ . sort ( ( a , b ) => a . score - b . score ) ;
422+
423+ const maxScore = scoredOptions [ 0 ] ?. score ;
424+ return scoredOptions . filter ( ( item ) => item . score === maxScore ) . map ( ( item ) => item . option ) ;
425+ } , [ inputValue , options , defaultFilter ] ) ;
426+
399427 return (
400428 < Select
401- options = { options }
429+ options = { filteredOptions }
402430 onMenuOpen = { ( ) => {
403431 if ( min ) filter ( { offset : min } ) ;
404432 if ( max ) filter ( { limit : max } ) ;
@@ -408,6 +436,8 @@ const LazySelect = ({
408436 value = { options . find ( ( option ) => option . value === dayjs ( value ) . toDate ( ) . valueOf ( ) ) }
409437 onMenuClose = { ( ) => filter ( { current : value } ) }
410438 components = { { DropdownIndicator : ( ) => null , IndicatorSeparator : ( ) => null } }
439+ onInputChange = { setInputValue }
440+ filterOption = { ( ) => true }
411441 { ...props }
412442 />
413443 ) ;
0 commit comments