- Introduced DashboardObjectToolsContext and DashboardObjectToolsProvider for managing object tools state within the dashboard. - Added ChevronLeftIcon and ChevronRightIcon components for navigation buttons, enhancing user interface consistency. - Updated ObjectTableNavigationButtons to utilize new chevron icons and improved layout for better user experience. - Refactored KeyboardShortcut and Tooltip components for cleaner code and improved functionality.
120 lines
2.7 KiB
JavaScript
120 lines
2.7 KiB
JavaScript
import { useEffect, useRef, useMemo } from 'react'
|
|
import PropTypes from 'prop-types'
|
|
import loglevel from 'loglevel'
|
|
import config from '../../../config'
|
|
import Tooltip from './Tooltip'
|
|
import KeyboardKey from './KeyboardKey'
|
|
const logger = loglevel.getLogger('ApiServerContext')
|
|
logger.setLevel(config.logLevel)
|
|
|
|
const MODIFIER_ALIASES = {
|
|
cmd: 'meta',
|
|
meta: 'meta',
|
|
ctrl: 'control',
|
|
control: 'control',
|
|
alt: 'alt',
|
|
option: 'alt',
|
|
shift: 'shift'
|
|
}
|
|
|
|
function parseShortcut(shortcut) {
|
|
return shortcut
|
|
.toLowerCase()
|
|
.split('+')
|
|
.map((part) => MODIFIER_ALIASES[part] ?? part)
|
|
}
|
|
|
|
function getPressedKey(event) {
|
|
if (
|
|
event.key === 'Meta' ||
|
|
event.key === 'Control' ||
|
|
event.key === 'Alt' ||
|
|
event.key === 'Shift'
|
|
) {
|
|
return event.key.toLowerCase()
|
|
}
|
|
if (event.code) {
|
|
const code = event.code.toLowerCase()
|
|
if (code.startsWith('key')) {
|
|
return code.slice(3)
|
|
}
|
|
return code
|
|
}
|
|
return null
|
|
}
|
|
|
|
const KeyboardShortcut = ({
|
|
shortcut,
|
|
children,
|
|
hint,
|
|
onTrigger,
|
|
log = false
|
|
}) => {
|
|
const pressedKeysRef = useRef(new Set())
|
|
const shortcutKeys = useMemo(() => parseShortcut(shortcut), [shortcut])
|
|
|
|
useEffect(() => {
|
|
const handleKeyDown = (event) => {
|
|
const key = getPressedKey(event)
|
|
if (key) {
|
|
pressedKeysRef.current.add(key)
|
|
}
|
|
|
|
if (log) {
|
|
logger.info('Key Down:', key, 'Pressed Keys:', [
|
|
...pressedKeysRef.current
|
|
])
|
|
}
|
|
|
|
if (
|
|
shortcutKeys.length &&
|
|
shortcutKeys.every((k) => pressedKeysRef.current.has(k))
|
|
) {
|
|
if (typeof onTrigger === 'function') {
|
|
onTrigger(event)
|
|
}
|
|
event.preventDefault()
|
|
}
|
|
}
|
|
|
|
const handleKeyUp = (event) => {
|
|
const key = getPressedKey(event)
|
|
if (key) {
|
|
pressedKeysRef.current.delete(key)
|
|
}
|
|
}
|
|
|
|
window.addEventListener('keydown', handleKeyDown)
|
|
window.addEventListener('keyup', handleKeyUp)
|
|
|
|
return () => {
|
|
window.removeEventListener('keydown', handleKeyDown)
|
|
window.removeEventListener('keyup', handleKeyUp)
|
|
}
|
|
}, [shortcutKeys, onTrigger, log])
|
|
|
|
if (hint) {
|
|
var osSpecificHint = hint.replaceAll('ALT', '⌥')
|
|
|
|
return (
|
|
<Tooltip
|
|
hideBorder
|
|
title={<KeyboardKey size='md'>{osSpecificHint}</KeyboardKey>}
|
|
>
|
|
{children}
|
|
</Tooltip>
|
|
)
|
|
}
|
|
return children
|
|
}
|
|
|
|
KeyboardShortcut.propTypes = {
|
|
shortcut: PropTypes.string.isRequired, // e.g. 'cmd+shift+p'
|
|
onTrigger: PropTypes.func.isRequired,
|
|
children: PropTypes.element.isRequired,
|
|
hint: PropTypes.string, // Optional, e.g. '⌘ ⇧ P'
|
|
log: PropTypes.bool // Optional, e.g. true
|
|
}
|
|
|
|
export default KeyboardShortcut
|