diff options
-rw-r--r-- | app/src/Keyboard/Keys/Key.js | 125 | ||||
-rw-r--r-- | app/src/Keyboard/Keys/KeyParamlist.js | 15 | ||||
-rw-r--r-- | app/src/Keyboard/Keys/KeyValue.js | 16 | ||||
-rw-r--r-- | app/src/Keyboard/Keys/keyPropTypes.js | 31 | ||||
-rw-r--r-- | app/src/Keyboard/Keys/util.js | 89 |
5 files changed, 185 insertions, 91 deletions
diff --git a/app/src/Keyboard/Keys/Key.js b/app/src/Keyboard/Keys/Key.js index 8f4928e..99846f0 100644 --- a/app/src/Keyboard/Keys/Key.js +++ b/app/src/Keyboard/Keys/Key.js @@ -1,110 +1,38 @@ import cloneDeep from 'lodash/cloneDeep' import get from 'lodash/get' -import keyBy from 'lodash/keyBy' import pick from 'lodash/pick' +import PropTypes from 'prop-types' import { useContext, useState } from 'react' -import { DefinitionsContext, SearchContext } from '../../providers' +import { SearchContext } from '../../providers' import { getBehaviourParams } from '../../keymap' import { getKeyStyles } from '../../key-units' import KeyParamlist from './KeyParamlist' -import Modal from '../../Common/Modal' -import ValuePicker from '../../ValuePicker' - +import * as keyPropTypes from './keyPropTypes' +import { + createPromptMessage, + hydrateTree, + isSimple, + isComplex, + makeIndex +} from './util' import styles from './styles.module.css' +import Modal from '../../Common/Modal' +import ValuePicker from '../../ValuePicker' -function makeIndex (tree) { - const index = [] - ;(function traverse(tree) { - const params = tree.params || [] - index.push(tree) - params.forEach(traverse) - })(tree) - - return index -} - -function isSimple(normalized) { - const [first] = normalized.params - const symbol = get(first, 'source.symbol', get(first, 'source.code', '')) - const shortSymbol = symbol.length === 1 - const singleParam = normalized.params.length === 1 - return singleParam && shortSymbol -} - -function isComplex(normalized, behaviourParams) { - const [first] = normalized.params - const symbol = get(first, 'source.symbol', get(first, 'value', '')) - const isLongSymbol = symbol.length > 4 - const isMultiParam = behaviourParams.length > 1 - const isNestedParam = get(first, 'params', []).length > 0 - - return isLongSymbol || isMultiParam || isNestedParam -} - -function createPromptMessage(param) { - const promptMapping = { - layer: 'Select layer', - mod: 'Select modifier', - behaviour: 'Select behaviour', - command: 'Select command', - keycode: 'Select key code' - } - - if (param.name) { - return `Select ${param.name}` - } - - return ( - promptMapping[param] || - promptMapping.keycode - ) -} - -export default function Key(props) { - const { behaviours } = useContext(DefinitionsContext) +function Key(props) { const { getSearchTargets, sources } = useContext(SearchContext) - const { position, rotation, size } = props + const { position, rotation, size } = props const { label, value, params, onUpdate } = props const [editing, setEditing] = useState(null) const bind = value - const behaviour = get(behaviours.indexed, bind) + const behaviour = get(sources.behaviours, bind) const behaviourParams = getBehaviourParams(params, behaviour) - const commands = keyBy(behaviour.commands, 'code') - - function getSourceValue(value, as) { - if (as === 'command') return commands[value] - if (as === 'raw' || as.enum) return { code: value } - return sources?.[as]?.[value] - } - - function normalize(node, as) { - if (!node) { - return { value: undefined, params: [] } - } - const { value, params } = node - const source = getSourceValue(value, as) - - return { - value, - source, - params: get(source, 'params', []).map((as, i) => ( - normalize(params[i], as) - )) - } - } - - const normalized = { - value, - source: behaviour, - params: behaviourParams.map((as, i) => ( - normalize(params[i], as) - )) - } + const normalized = hydrateTree(value, params, sources) const index = makeIndex(normalized) const positioningStyle = getKeyStyles(position, size, rotation) @@ -185,3 +113,24 @@ export default function Key(props) { ) } +Key.propTypes = { + position: PropTypes.shape({ + x: PropTypes.number.isRequired, + y: PropTypes.number.isRequired + }), + rotation: PropTypes.shape({ + a: PropTypes.number, + rx: PropTypes.number, + ry: PropTypes.number + }), + size: PropTypes.shape({ + u: PropTypes.number.isRequired, + h: PropTypes.number.isRequired + }), + label: PropTypes.string, + value: keyPropTypes.value.isRequired, + params: PropTypes.arrayOf(keyPropTypes.node), + onUpdate: PropTypes.func.isRequired +} + +export default Key diff --git a/app/src/Keyboard/Keys/KeyParamlist.js b/app/src/Keyboard/Keys/KeyParamlist.js index 58680bd..af539a1 100644 --- a/app/src/Keyboard/Keys/KeyParamlist.js +++ b/app/src/Keyboard/Keys/KeyParamlist.js @@ -1,8 +1,11 @@ import get from 'lodash/get' +import PropTypes from 'prop-types' + +import * as keyPropTypes from './keyPropTypes' import KeyValue from './KeyValue' import styles from './styles.module.css' -export default function KeyParamlist(props) { +function KeyParamlist(props) { const { index, params, values, onSelect, root } = props return ( <span @@ -32,3 +35,13 @@ export default function KeyParamlist(props) { </span> ) } + +KeyParamlist.propTypes = { + index: keyPropTypes.index.isRequired, + params: PropTypes.arrayOf(keyPropTypes.param).isRequired, + values: PropTypes.arrayOf(keyPropTypes.node).isRequired, + source: keyPropTypes.source, + onSelect: PropTypes.func.isRequired +} + +export default KeyParamlist diff --git a/app/src/Keyboard/Keys/KeyValue.js b/app/src/Keyboard/Keys/KeyValue.js index 7aea967..b05c51d 100644 --- a/app/src/Keyboard/Keys/KeyValue.js +++ b/app/src/Keyboard/Keys/KeyValue.js @@ -1,13 +1,15 @@ import { useMemo } from 'react' +import PropTypes from 'prop-types' -import Icon from '../../Common/Icon' +import * as keyPropTypes from './keyPropTypes' import styles from './styles.module.css' +import Icon from '../../Common/Icon' function NullKey() { return <span>⦸</span> } -export default function KeyValue(props) { +function KeyValue(props) { const { param, index, value, source, onSelect } = props const title = source && `(${source.code}) ${source.description}` const text = source && <span>{source?.symbol || source?.code}</span> @@ -33,3 +35,13 @@ export default function KeyValue(props) { </span> ) } + +KeyValue.propTypes = { + index: PropTypes.number.isRequired, + param: keyPropTypes.param.isRequired, + value: keyPropTypes.value.isRequired, + source: keyPropTypes.source, + onSelect: PropTypes.func.isRequired +} + +export default KeyValue diff --git a/app/src/Keyboard/Keys/keyPropTypes.js b/app/src/Keyboard/Keys/keyPropTypes.js new file mode 100644 index 0000000..3a4d5b3 --- /dev/null +++ b/app/src/Keyboard/Keys/keyPropTypes.js @@ -0,0 +1,31 @@ +import PropTypes from 'prop-types' + +export const param = PropTypes.oneOf( + ['code', 'layer', 'mod'] +) +export const params = PropTypes.arrayOf(param) +export const value = PropTypes.oneOfType([ + PropTypes.string, + PropTypes.number +]) +export const source = PropTypes.shape({ + params, + code: value.isRequired, + description: PropTypes.string, + symbol: PropTypes.string, + faIcon: PropTypes.string +}) + +export const node = PropTypes.shape({ + value, + source, + params: PropTypes.arrayOf( + PropTypes.shape({ + value, + source, + params: PropTypes.arrayOf(PropTypes.object) + }) + ) +}) + +export const index = PropTypes.arrayOf(node) diff --git a/app/src/Keyboard/Keys/util.js b/app/src/Keyboard/Keys/util.js new file mode 100644 index 0000000..466ccce --- /dev/null +++ b/app/src/Keyboard/Keys/util.js @@ -0,0 +1,89 @@ +import get from 'lodash/get' +import keyBy from 'lodash/keyBy' + +import { getBehaviourParams } from '../../keymap' + +export function makeIndex (tree) { + const index = [] + ;(function traverse(tree) { + const params = tree.params || [] + index.push(tree) + params.forEach(traverse) + })(tree) + + return index +} + +export function isSimple(normalized) { + const [first] = normalized.params + const symbol = get(first, 'source.symbol', get(first, 'source.code', '')) + const shortSymbol = symbol.length === 1 + const singleParam = normalized.params.length === 1 + return singleParam && shortSymbol +} + +export function isComplex(normalized, behaviourParams) { + const [first] = normalized.params + const symbol = get(first, 'source.symbol', get(first, 'value', '')) + const isLongSymbol = symbol.length > 4 + const isMultiParam = behaviourParams.length > 1 + const isNestedParam = get(first, 'params', []).length > 0 + + return isLongSymbol || isMultiParam || isNestedParam +} + +export function createPromptMessage(param) { + const promptMapping = { + layer: 'Select layer', + mod: 'Select modifier', + behaviour: 'Select behaviour', + command: 'Select command', + keycode: 'Select key code' + } + + if (param.name) { + return `Select ${param.name}` + } + + return ( + promptMapping[param] || + promptMapping.keycode + ) +} + +export function hydrateTree(value, params, sources) { + const bind = value + const behaviour = get(sources.behaviours, bind) + const behaviourParams = getBehaviourParams(params, behaviour) + const commands = keyBy(behaviour.commands, 'code') + + function getSourceValue(value, as) { + if (as === 'command') return commands[value] + if (as === 'raw' || as.enum) return { code: value } + return sources?.[as]?.[value] + } + + function hydrateNode(node, as) { + if (!node) { + return { value: undefined, params: [] } + } + const { value, params } = node + const source = getSourceValue(value, as) + + return { + value, + source, + params: get(source, 'params', []).map((as, i) => ( + hydrateNode(params[i], as) + )) + } + } + + return { + value, + source: behaviour, + params: behaviourParams.map((as, i) => ( + hydrateNode(params[i], as) + )) + } +} |