aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorNick Coutsos <[email protected]>2022-04-25 21:07:03 -0400
committerNick Coutsos <[email protected]>2022-04-25 21:07:03 -0400
commitaf736e74be5f6438d60a650ff78598b6b0269e28 (patch)
tree4f4af6c98a0846ee929417cce318276037588647
parentee1f81027b2d9a55caee4457fbcc5317fb13cd9d (diff)
downloadkeymap-editor-af736e74be5f6438d60a650ff78598b6b0269e28.tar.gz
keymap-editor-af736e74be5f6438d60a650ff78598b6b0269e28.zip
Refactor keyboard components and define more proptypes
-rw-r--r--app/src/Keyboard/Keys/Key.js125
-rw-r--r--app/src/Keyboard/Keys/KeyParamlist.js15
-rw-r--r--app/src/Keyboard/Keys/KeyValue.js16
-rw-r--r--app/src/Keyboard/Keys/keyPropTypes.js31
-rw-r--r--app/src/Keyboard/Keys/util.js89
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)
+ ))
+ }
+}