diff options
author | Nick Coutsos <[email protected]> | 2022-04-28 23:18:16 -0400 |
---|---|---|
committer | Nick Coutsos <[email protected]> | 2022-04-28 23:18:16 -0400 |
commit | c25dea890ea06b25973a79fe9bee71e06be15bcb (patch) | |
tree | f3a8b5eec9b7aa1711ca64b860833c7756aed01e /app | |
parent | b0ae7d4dd8273ef0eb5e09963bc61a38d3945a57 (diff) | |
download | keymap-editor-c25dea890ea06b25973a79fe9bee71e06be15bcb.tar.gz keymap-editor-c25dea890ea06b25973a79fe9bee71e06be15bcb.zip |
Improve layer renaming
Diffstat (limited to 'app')
-rw-r--r-- | app/src/Keyboard/LayerSelector.js | 70 |
1 files changed, 54 insertions, 16 deletions
diff --git a/app/src/Keyboard/LayerSelector.js b/app/src/Keyboard/LayerSelector.js index 147ea5c..0d61b39 100644 --- a/app/src/Keyboard/LayerSelector.js +++ b/app/src/Keyboard/LayerSelector.js @@ -1,9 +1,24 @@ import PropTypes from 'prop-types' -import { useEffect, useMemo, useRef, useState } from 'react' +import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import Icon from '../Common/Icon' import styles from './styles.module.css' +function stop(fn) { + return function(event) { + event.stopPropagation() + fn() + } +} + +function onKey(mapping) { + return function(event) { + if (mapping[event.key]) { + mapping[event.key]() + } + } +} + function LayerSelector(props) { const ref = useRef(null) const { activeLayer, layers } = props @@ -13,13 +28,14 @@ function LayerSelector(props) { const handleSelect = useMemo(() => function(layer) { if (layer === activeLayer) { + setEditing(layers[activeLayer]) setRenaming(true) return } setRenaming(false) onSelect(layer) - }, [activeLayer, setRenaming, onSelect]) + }, [layers, activeLayer, setEditing, setRenaming, onSelect]) const handleAdd = useMemo(() => function() { onNewLayer() @@ -30,29 +46,46 @@ function LayerSelector(props) { window.confirm(confirmation) && onDeleteLayer(layerIndex) }, [onDeleteLayer]) - const handleClickOutside = useMemo(() => function(event) { - const clickedOutside = ref.current && ref.current.contains(event.target) - if (clickedOutside || !renaming) { + const finishEditing = useCallback(() => { + if (!renaming) { return } setEditing('') setRenaming(false) onRenameLayer(editing) - }, [ - ref, - editing, - renaming, - onRenameLayer, - setEditing, - setRenaming - ]) + }, [editing, renaming, setEditing, setRenaming, onRenameLayer]) + + const cancelEditing = useCallback(() => { + if (!renaming) { + return + } + + setEditing('') + setRenaming(false) + }, [renaming, setEditing, setRenaming]) + + const handleClickOutside = useMemo(() => function(event) { + const clickedOutside = ref.current && !ref.current.contains(event.target) + if (!clickedOutside) { + return + } + + cancelEditing() + }, [ref, cancelEditing]) useEffect(() => { document.addEventListener('click', handleClickOutside) return () => document.removeEventListener('click', handleClickOutside) }, [handleClickOutside]) + const focusInput = useCallback(node => { + if (node) { + node.focus() + node.select() + } + }, []) + return ( <div className={styles['layer-selector']} @@ -64,15 +97,20 @@ function LayerSelector(props) { {layers.map((name, i) => ( <li key={`layer-${i}`} - className={activeLayer === i ? 'active' : ''} + className={activeLayer === i ? styles.active : ''} data-layer={i} - onClick={() => handleSelect(i)} + onClick={stop(() => handleSelect(i))} > <span className={styles.index}>{i}</span> {(activeLayer === i && renaming) ? ( <input + ref={focusInput} className={styles.name} onChange={e => setEditing(e.target.value)} + onKeyDown={onKey({ + Enter: finishEditing, + Escape: cancelEditing + })} value={ (activeLayer === i && renaming) ? editing @@ -85,7 +123,7 @@ function LayerSelector(props) { <Icon name="times-circle" className={styles.delete} - onClick={() => handleDelete(i, name)} + onClick={stop(() => handleDelete(i, name))} /> </span> )} |