Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F104946686
useListbox.js
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Thu, Mar 13, 14:28
Size
8 KB
Mime Type
text/x-java
Expires
Sat, Mar 15, 14:28 (1 d, 23 h)
Engine
blob
Format
Raw Data
Handle
24874008
Attached To
rOACCT Open Access Compliance Check Tool (OACCT)
useListbox.js
View Options
import
_extends
from
"@babel/runtime/helpers/esm/extends"
;
import
*
as
React
from
'react'
;
import
{
unstable_useForkRef
as
useForkRef
,
unstable_useId
as
useId
}
from
'@mui/utils'
;
import
{
ActionTypes
}
from
'./useListbox.types'
;
import
defaultReducer
from
'./defaultListboxReducer'
;
import
useControllableReducer
from
'./useControllableReducer'
;
import
areArraysEqual
from
'../utils/areArraysEqual'
;
const
TEXT_NAVIGATION_RESET_TIMEOUT
=
500
;
// milliseconds
const
defaultOptionComparer
=
(
optionA
,
optionB
)
=>
optionA
===
optionB
;
const
defaultIsOptionDisabled
=
()
=>
false
;
const
defaultOptionStringifier
=
option
=>
typeof
option
===
'string'
?
option
:
String
(
option
);
export
default
function
useListbox
(
props
)
{
var
_props$optionIdGenera
,
_options$highlightedI
;
const
{
disabledItemsFocusable
=
false
,
disableListWrap
=
false
,
focusManagement
=
'activeDescendant'
,
id
:
idProp
,
isOptionDisabled
=
defaultIsOptionDisabled
,
listboxRef
:
externalListboxRef
,
multiple
=
false
,
optionComparer
=
defaultOptionComparer
,
optionStringifier
=
defaultOptionStringifier
,
options
,
stateReducer
:
externalReducer
}
=
props
;
const
id
=
useId
(
idProp
);
function
defaultIdGenerator
(
_
,
index
)
{
return
`
$
{
id
}
-
option
-
$
{
index
}
`
;
}
const
optionIdGenerator
=
(
_props$optionIdGenera
=
props
.
optionIdGenerator
)
!=
null
?
_props$optionIdGenera
:
defaultIdGenerator
;
const
propsWithDefaults
=
_extends
({},
props
,
{
disabledItemsFocusable
,
disableListWrap
,
focusManagement
,
isOptionDisabled
,
multiple
,
optionComparer
,
optionStringifier
});
const
listboxRef
=
React
.
useRef
(
null
);
const
handleRef
=
useForkRef
(
externalListboxRef
,
listboxRef
);
const
textCriteriaRef
=
React
.
useRef
({
searchString
:
''
,
lastTime
:
null
});
const
[{
highlightedValue
,
selectedValue
},
dispatch
]
=
useControllableReducer
(
defaultReducer
,
externalReducer
,
propsWithDefaults
);
const
highlightedIndex
=
React
.
useMemo
(()
=>
{
return
highlightedValue
==
null
?
-
1
:
options
.
findIndex
(
option
=>
optionComparer
(
option
,
highlightedValue
));
},
[
highlightedValue
,
options
,
optionComparer
]);
const
previousOptions
=
React
.
useRef
([]);
React
.
useEffect
(()
=>
{
if
(
areArraysEqual
(
previousOptions
.
current
,
options
,
optionComparer
))
{
return
;
}
dispatch
({
type
:
ActionTypes
.
optionsChange
,
event
:
null
,
options
,
previousOptions
:
previousOptions
.
current
,
props
:
propsWithDefaults
});
previousOptions
.
current
=
options
;
// No need to re-run this effect if props change
// eslint-disable-next-line react-hooks/exhaustive-deps
},
[
options
,
optionComparer
,
dispatch
]);
const
setSelectedValue
=
React
.
useCallback
(
option
=>
{
dispatch
({
type
:
ActionTypes
.
setValue
,
event
:
null
,
value
:
option
});
},
[
dispatch
]);
const
setHighlightedValue
=
React
.
useCallback
(
option
=>
{
dispatch
({
type
:
ActionTypes
.
setHighlight
,
event
:
null
,
highlight
:
option
});
},
[
dispatch
]);
const
createHandleOptionClick
=
(
option
,
other
)
=>
event
=>
{
var
_other$onClick
;
(
_other$onClick
=
other
.
onClick
)
==
null
?
void
0
:
_other$onClick
.
call
(
other
,
event
);
if
(
event
.
defaultPrevented
)
{
return
;
}
event
.
preventDefault
();
dispatch
({
type
:
ActionTypes
.
optionClick
,
option
,
event
,
props
:
propsWithDefaults
});
};
const
createHandleOptionPointerOver
=
(
option
,
other
)
=>
event
=>
{
var
_other$onMouseOver
;
(
_other$onMouseOver
=
other
.
onMouseOver
)
==
null
?
void
0
:
_other$onMouseOver
.
call
(
other
,
event
);
if
(
event
.
defaultPrevented
)
{
return
;
}
dispatch
({
type
:
ActionTypes
.
optionHover
,
option
,
event
,
props
:
propsWithDefaults
});
};
const
createHandleKeyDown
=
other
=>
event
=>
{
var
_other$onKeyDown
;
(
_other$onKeyDown
=
other
.
onKeyDown
)
==
null
?
void
0
:
_other$onKeyDown
.
call
(
other
,
event
);
if
(
event
.
defaultPrevented
)
{
return
;
}
const
keysToPreventDefault
=
[
'ArrowUp'
,
'ArrowDown'
,
'Home'
,
'End'
,
'PageUp'
,
'PageDown'
];
if
(
focusManagement
===
'activeDescendant'
)
{
// When the child element is focused using the activeDescendant attribute,
// the listbox handles keyboard events on its behalf.
// We have to `preventDefault()` is this case to prevent the browser from
// scrolling the view when space is pressed or submitting forms when enter is pressed.
keysToPreventDefault
.
push
(
' '
,
'Enter'
);
}
if
(
keysToPreventDefault
.
includes
(
event
.
key
))
{
event
.
preventDefault
();
}
dispatch
({
type
:
ActionTypes
.
keyDown
,
event
,
props
:
propsWithDefaults
});
// Handle text navigation
if
(
event
.
key
.
length
===
1
&&
event
.
key
!==
' '
)
{
const
textCriteria
=
textCriteriaRef
.
current
;
const
lowerKey
=
event
.
key
.
toLowerCase
();
const
currentTime
=
performance
.
now
();
if
(
textCriteria
.
searchString
.
length
>
0
&&
textCriteria
.
lastTime
&&
currentTime
-
textCriteria
.
lastTime
>
TEXT_NAVIGATION_RESET_TIMEOUT
)
{
textCriteria
.
searchString
=
lowerKey
;
}
else
if
(
textCriteria
.
searchString
.
length
!==
1
||
lowerKey
!==
textCriteria
.
searchString
)
{
// If there is just one character in the buffer and the key is the same, do not append
textCriteria
.
searchString
+=
lowerKey
;
}
textCriteria
.
lastTime
=
currentTime
;
dispatch
({
type
:
ActionTypes
.
textNavigation
,
event
,
searchString
:
textCriteria
.
searchString
,
props
:
propsWithDefaults
});
}
};
const
createHandleBlur
=
other
=>
event
=>
{
var
_other$onBlur
,
_listboxRef$current
;
(
_other$onBlur
=
other
.
onBlur
)
==
null
?
void
0
:
_other$onBlur
.
call
(
other
,
event
);
if
(
event
.
defaultPrevented
)
{
return
;
}
if
((
_listboxRef$current
=
listboxRef
.
current
)
!=
null
&&
_listboxRef$current
.
contains
(
document
.
activeElement
))
{
// focus is within the listbox
return
;
}
dispatch
({
type
:
ActionTypes
.
blur
,
event
,
props
:
propsWithDefaults
});
};
const
getRootProps
=
(
otherHandlers
=
{})
=>
{
return
_extends
({},
otherHandlers
,
{
'aria-activedescendant'
:
focusManagement
===
'activeDescendant'
&&
highlightedValue
!=
null
?
optionIdGenerator
(
highlightedValue
,
highlightedIndex
)
:
undefined
,
id
,
onBlur
:
createHandleBlur
(
otherHandlers
),
onKeyDown
:
createHandleKeyDown
(
otherHandlers
),
role
:
'listbox'
,
tabIndex
:
focusManagement
===
'DOM'
?
-
1
:
0
,
ref
:
handleRef
});
};
const
getOptionState
=
option
=>
{
let
selected
;
const
index
=
options
.
findIndex
(
opt
=>
optionComparer
(
opt
,
option
));
if
(
multiple
)
{
var
_ref
;
selected
=
((
_ref
=
selectedValue
)
!=
null
?
_ref
:
[]).
some
(
value
=>
value
!=
null
&&
optionComparer
(
option
,
value
));
}
else
{
selected
=
optionComparer
(
option
,
selectedValue
);
}
const
disabled
=
isOptionDisabled
(
option
,
index
);
return
{
selected
,
disabled
,
highlighted
:
highlightedIndex
===
index
};
};
const
getOptionTabIndex
=
optionState
=>
{
if
(
focusManagement
===
'activeDescendant'
)
{
return
undefined
;
}
if
(
!
optionState
.
highlighted
)
{
return
-
1
;
}
if
(
optionState
.
disabled
&&
!
disabledItemsFocusable
)
{
return
-
1
;
}
return
0
;
};
const
getOptionProps
=
(
option
,
otherHandlers
=
{})
=>
{
const
optionState
=
getOptionState
(
option
);
const
index
=
options
.
findIndex
(
opt
=>
optionComparer
(
opt
,
option
));
return
_extends
({},
otherHandlers
,
{
'aria-disabled'
:
optionState
.
disabled
||
undefined
,
'aria-selected'
:
optionState
.
selected
,
id
:
optionIdGenerator
(
option
,
index
),
onClick
:
createHandleOptionClick
(
option
,
otherHandlers
),
onPointerOver
:
createHandleOptionPointerOver
(
option
,
otherHandlers
),
role
:
'option'
,
tabIndex
:
getOptionTabIndex
(
optionState
)
});
};
React
.
useDebugValue
({
highlightedOption
:
options
[
highlightedIndex
],
selectedOption
:
selectedValue
});
return
{
getRootProps
,
getOptionProps
,
getOptionState
,
highlightedOption
:
(
_options$highlightedI
=
options
[
highlightedIndex
])
!=
null
?
_options$highlightedI
:
null
,
selectedOption
:
selectedValue
,
setSelectedValue
,
setHighlightedValue
};
}
Event Timeline
Log In to Comment