Browse Source

Implement performance improvements

Prefer using React memoization instead of mem when using inside React.
master
TheoryOfNekomata 4 years ago
parent
commit
6dc7535ee8
8 changed files with 415 additions and 473 deletions
  1. +1
    -2
      package.json
  2. +18
    -22
      src/components/AccidentalKey/AccidentalKey.tsx
  3. +24
    -39
      src/components/Keyboard/Keyboard.tsx
  4. +18
    -22
      src/components/NaturalKey/NaturalKey.tsx
  5. +178
    -201
      src/components/StyledAccidentalKey/StyledAccidentalKey.tsx
  6. +174
    -185
      src/components/StyledNaturalKey/StyledNaturalKey.tsx
  7. +1
    -1
      src/services/getKeyLeft.ts
  8. +1
    -1
      src/services/getKeyWidth.ts

+ 1
- 2
package.json View File

@@ -20,8 +20,7 @@
"build-storybook": "build-storybook"
},
"dependencies": {
"mem": "^6.1.0",
"styled-components": "^5.1.1"
"mem": "^6.1.0"
},
"peerDependencies": {
"react": ">=16"


+ 18
- 22
src/components/AccidentalKey/AccidentalKey.tsx View File

@@ -1,40 +1,36 @@
import * as React from 'react'
import * as PropTypes from 'prop-types'
import styled from 'styled-components'
import keyPropTypes from '../../services/keyPropTypes'

const Base = styled('div')({
width: '100%',
height: '100%',
backgroundColor: 'var(--color-accidental-key, currentColor)',
border: '1px solid',
boxSizing: 'border-box',
position: 'relative',
})

const Highlight = styled('div')({
width: '100%',
height: '100%',
position: 'absolute',
top: 0,
left: 0,
opacity: 0.75,
})

type Props = PropTypes.InferProps<typeof keyPropTypes>

const AccidentalKey: React.FC<Props> = ({ keyChannels }) => (
<Base>
<div
style={{
width: '100%',
height: '100%',
backgroundColor: 'var(--color-accidental-key, currentColor)',
border: '1px solid',
boxSizing: 'border-box',
position: 'relative',
}}
>
{Array.isArray(keyChannels!) &&
keyChannels.map((c) => (
<Highlight
<div
key={c!.channel}
style={{
width: '100%',
height: '100%',
position: 'absolute',
top: 0,
left: 0,
opacity: 0.75,
backgroundColor: `var(--color-channel-${c!.channel}, Highlight)`,
}}
/>
))}
</Base>
</div>
)

AccidentalKey.propTypes = keyPropTypes


+ 24
- 39
src/components/Keyboard/Keyboard.tsx View File

@@ -1,28 +1,11 @@
import * as React from 'react'
import * as PropTypes from 'prop-types'
import styled from 'styled-components'
import mem from 'mem'
import isNaturalKeyUnmemoized from '../../services/isNaturalKey'
import getKeyWidthUnmemoized from '../../services/getKeyWidth'
import getKeyLeftUnmemoized from '../../services/getKeyLeft'
import generateKeys from '../../services/generateKeys'
import * as DefaultAccidentalKey from '../AccidentalKey/AccidentalKey'
import * as DefaultNaturalKey from '../NaturalKey/NaturalKey'

const Base = styled('div')({
position: 'relative',
backgroundColor: 'currentColor',
overflow: 'hidden',
})

const Key = styled('div')({
position: 'absolute',
top: 0,
})

const getKeyWidth = mem(getKeyWidthUnmemoized, { cacheKey: (args) => args.join(':') })
const getKeyLeft = mem(getKeyLeftUnmemoized, { cacheKey: (args) => args.join(':') })
const isNaturalKey = mem(isNaturalKeyUnmemoized)
import DefaultAccidentalKey from '../AccidentalKey/AccidentalKey'
import DefaultNaturalKey from '../NaturalKey/NaturalKey'

export const propTypes = {
/**
@@ -97,47 +80,49 @@ const Keyboard: React.FC<Props> = ({
}) => {
const [keys, setKeys] = React.useState<number[]>([])

const { natural: NaturalKey = DefaultNaturalKey, accidental: AccidentalKey = DefaultAccidentalKey } = keyComponents!

const getKeyWidth = React.useCallback((k) => getKeyWidthUnmemoized(startKey, endKey)(k), [startKey, endKey])
const getKeyLeft = React.useCallback((k) => getKeyLeftUnmemoized(startKey, endKey)(k), [startKey, endKey])
const isNaturalKey = React.useCallback((k) => isNaturalKeyUnmemoized(k), [])

React.useEffect(() => {
setKeys(generateKeys(startKey!, endKey!))
}, [startKey, endKey])

const {
natural: NaturalKey = DefaultNaturalKey.default,
accidental: AccidentalKey = DefaultAccidentalKey.default,
} = keyComponents!

return (
<Base
<div
style={{
width: width!,
height: height!,
position: 'relative',
backgroundColor: 'currentColor',
overflow: 'hidden',
}}
role="presentation"
>
{keys.map((k) => {
const isNatural = isNaturalKey(k)
{keys.map((key) => {
const isNatural = isNaturalKey(key)
const Component: any = isNatural ? NaturalKey! : AccidentalKey!

const width = getKeyWidth(startKey!, endKey!)(k)
const height = isNatural ? 100 : 100 * accidentalKeyLengthRatio!
const left = getKeyLeft(startKey!, endKey!)(k)
const currentKeyChannels = Array.isArray(keyChannels!) ? keyChannels.filter((kc) => kc!.key === k) : null
const currentKeyChannels = Array.isArray(keyChannels!) ? keyChannels.filter((kc) => kc!.key === key) : null

return (
<Key
key={k}
<div
key={key}
style={{
zIndex: isNatural ? 0 : 2,
width: width + '%',
height: height + '%',
left: left + '%',
width: getKeyWidth(key) + '%',
height: (isNatural ? 100 : 100 * accidentalKeyLengthRatio!) + '%',
left: getKeyLeft(key) + '%',
position: 'absolute',
top: 0,
}}
>
<Component keyChannels={currentKeyChannels} />
</Key>
</div>
)
})}
</Base>
</div>
)
}



+ 18
- 22
src/components/NaturalKey/NaturalKey.tsx View File

@@ -1,40 +1,36 @@
import * as React from 'react'
import * as PropTypes from 'prop-types'
import styled from 'styled-components'
import keyPropTypes from '../../services/keyPropTypes'

const Base = styled('div')({
width: '100%',
height: '100%',
backgroundColor: 'var(--color-natural-key, white)',
border: '1px solid',
boxSizing: 'border-box',
position: 'relative',
})

const Highlight = styled('div')({
width: '100%',
height: '100%',
position: 'absolute',
top: 0,
left: 0,
opacity: 0.75,
})

type Props = PropTypes.InferProps<typeof keyPropTypes>

const NaturalKey: React.FC<Props> = ({ keyChannels }) => (
<Base>
<div
style={{
width: '100%',
height: '100%',
backgroundColor: 'var(--color-natural-key, white)',
border: '1px solid',
boxSizing: 'border-box',
position: 'relative',
}}
>
{Array.isArray(keyChannels!) &&
keyChannels.map((c) => (
<Highlight
<div
key={c!.channel}
style={{
width: '100%',
height: '100%',
position: 'absolute',
top: 0,
left: 0,
opacity: 0.75,
backgroundColor: `var(--color-channel-${c!.channel}, Highlight)`,
}}
/>
))}
</Base>
</div>
)

NaturalKey.propTypes = keyPropTypes


+ 178
- 201
src/components/StyledAccidentalKey/StyledAccidentalKey.tsx View File

@@ -1,246 +1,215 @@
import * as React from 'react'
import * as PropTypes from 'prop-types'
import styled from 'styled-components'
import keyPropTypes from '../../services/keyPropTypes'

const DEFAULT_COLOR = '#35313b'
const LIGHT_COLOR = 'white'

const Base = styled('div')({
width: '100%',
height: '100%',
position: 'relative',
})

const B2 = styled('div')({
width: '100%',
height: '100%',
borderRadius: '0 0 calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1))',
backgroundColor: `var(--color-accidental-key, ${DEFAULT_COLOR})`,
maskImage: 'linear-gradient(to bottom, white, rgba(0, 0, 0, 0.9))',
})

const B3 = styled('div')({
width: '100%',
height: '100%',
backgroundColor: `var(--color-accidental-key, ${DEFAULT_COLOR})`,
})

const B4 = styled('div')({
width: '100%',
height: 'calc(4px * var(--size-scale-factor, 1))',
padding: 'calc(1px * var(--size-scale-factor, 1)) 0 0 0',
boxSizing: 'border-box',
position: 'absolute',
top: 0,
left: 0,
})

const B5 = styled('div')({
width: '100%',
height: '100%',
backgroundColor: 'black',
opacity: '0.12',
})

const B6 = styled('div')({
width: 'calc(2px * var(--size-scale-factor, 1))',
height: 'calc(11px * var(--size-scale-factor, 1))',
padding:
'calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1)) 0',
boxSizing: 'border-box',
position: 'absolute',
top: 0,
right: 0,
})

const B7 = styled('div')({
width: '100%',
height: '100%',
backgroundColor: LIGHT_COLOR,
maskImage: 'linear-gradient(to bottom, transparent, white)',
opacity: '0.4',
})

const B8 = styled('div')({
width: 'calc(2px * var(--size-scale-factor, 1))',
height: '100%',
padding:
'calc(10px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1)) calc(6px * var(--size-scale-factor, 1)) 0',
boxSizing: 'border-box',
position: 'absolute',
top: 0,
right: 0,
})

const B9 = styled('div')({
width: '100%',
height: '100%',
backgroundColor: LIGHT_COLOR,
opacity: '0.4',
borderBottomRightRadius: 'calc(1px * var(--size-scale-factor, 1))',
})

const B10 = styled('div')({
width: '100%',
padding:
'0 calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1))',
boxSizing: 'border-box',
position: 'absolute',
bottom: 0,
left: 0,
})

const B11 = styled('div')({
width: '100%',
height: '100%',
backgroundColor: LIGHT_COLOR,
borderRadius:
'calc(4px * var(--size-scale-factor, 1)) calc(4px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1))',
opacity: '0.12',
})

const B12 = styled('div')({
width: '100%',
height: '100%',
padding:
'calc(3px * var(--size-scale-factor, 1)) calc(3px * var(--size-scale-factor, 1)) calc(7px * var(--size-scale-factor, 1)) calc(3px * var(--size-scale-factor, 1))',
boxSizing: 'border-box',
position: 'absolute',
top: 0,
left: 0,
})

const B13 = styled('div')({
width: '100%',
height: '100%',
backgroundColor: LIGHT_COLOR,
maskImage: 'linear-gradient(to bottom, transparent, white)',
borderRadius: 99999,
})

const B14 = styled('div')({
width: '100%',
height: 'calc(6px * var(--size-scale-factor, 1))',
padding:
'0 calc(1px * var(--size-scale-factor, 1)) calc(5px * var(--size-scale-factor, 1)) calc(2px * var(--size-scale-factor, 1))',
boxSizing: 'border-box',
position: 'absolute',
bottom: 0,
left: 0,
})

const B15 = styled('div')({
width: '100%',
height: '100%',
backgroundColor: LIGHT_COLOR,
borderRadius: '0 0 calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1))',
opacity: '0.4',
})

const B16 = styled('div')({
width: '100%',
height: '100%',
backgroundColor: 'black',
position: 'absolute',
top: 0,
left: 0,
borderRadius: '0 0 calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1))',
})

const B17 = styled('div')({
width: '100%',
height: 'calc(6 / 50 * 100%)',
padding: '0 calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1))',
boxSizing: 'border-box',
position: 'absolute',
bottom: 0,
left: 0,
})

const B18 = styled('div')({
width: '100%',
height: 'calc(44 / 50 * 100%)',
padding: 'calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1)) 0',
boxSizing: 'border-box',
position: 'absolute',
top: 0,
left: 0,
})

const B19 = styled('div')({
width: '100%',
height: '100%',
position: 'absolute',
top: 0,
left: 0,
borderRadius: 'calc(1px * var(--size-scale-factor, 1))',
boxShadow: '0 0 0 calc(1px * var(--size-scale-factor, 1)) rgba(0, 0, 0, 0.25)',
})

type Props = PropTypes.InferProps<typeof keyPropTypes>

const StyledAccidentalKey: React.FC<Props> = ({ keyChannels }) => {
const hasKeyChannels = Array.isArray(keyChannels!) && keyChannels.length > 0
return (
<Base
<div
style={{
width: '100%',
height: '100%',
position: 'relative',
// @ts-ignore
'--color-accidental-key': hasKeyChannels ? `var(--color-channel-${keyChannels![0]!.channel})` : undefined,
}}
>
<B19 />
<B16 />
<B17>
<B2
<div
style={{
width: '100%',
height: '100%',
position: 'absolute',
top: 0,
left: 0,
borderRadius: 'calc(1px * var(--size-scale-factor, 1))',
boxShadow: '0 0 0 calc(1px * var(--size-scale-factor, 1)) rgba(0, 0, 0, 0.25)',
}}
/>
<div
style={{
width: '100%',
height: '100%',
backgroundColor: 'black',
position: 'absolute',
top: 0,
left: 0,
borderRadius: '0 0 calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1))',
}}
/>
<div
style={{
width: '100%',
height: 'calc(6 / 50 * 100%)',
padding: '0 calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1))',
boxSizing: 'border-box',
position: 'absolute',
bottom: 0,
left: 0,
}}
>
<div
style={{
width: '100%',
height: '100%',
borderRadius: '0 0 calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1))',
backgroundColor: `var(--color-accidental-key, ${DEFAULT_COLOR})`,
maskImage: 'linear-gradient(to bottom, white, rgba(0, 0, 0, 0.9))',
WebkitMaskImage: 'linear-gradient(to bottom, white, rgba(0, 0, 0, 0.9))',
opacity: hasKeyChannels ? 0.75 : '1',
}}
/>
</B17>
<B18>
<B3
</div>
<div
style={{
width: '100%',
height: 'calc(44 / 50 * 100%)',
padding: 'calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1)) 0',
boxSizing: 'border-box',
position: 'absolute',
top: 0,
left: 0,
}}
>
<div
style={{
width: '100%',
height: '100%',
backgroundColor: `var(--color-accidental-key, ${DEFAULT_COLOR})`,
opacity: hasKeyChannels ? 0.75 : '1',
}}
/>
</B18>
<B4>
<B5 />
</B4>
<B6
</div>
<div
style={{
width: '100%',
height: 'calc(4px * var(--size-scale-factor, 1))',
padding: 'calc(1px * var(--size-scale-factor, 1)) 0 0 0',
boxSizing: 'border-box',
position: 'absolute',
top: 0,
left: 0,
}}
>
<div
style={{
width: '100%',
height: '100%',
backgroundColor: 'black',
opacity: '0.12',
}}
/>
</div>
<div
style={{
width: 'calc(2px * var(--size-scale-factor, 1))',
height: 'calc(11px * var(--size-scale-factor, 1))',
padding:
'calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1)) 0',
boxSizing: 'border-box',
position: 'absolute',
top: 0,
right: 0,
opacity: hasKeyChannels ? 0.5 : '1',
}}
>
<B7 />
</B6>
<B8
<div
style={{
width: '100%',
height: '100%',
backgroundColor: LIGHT_COLOR,
maskImage: 'linear-gradient(to bottom, transparent, white)',
WebkitMaskImage: 'linear-gradient(to bottom, transparent, white)',
opacity: '0.4',
}}
/>
</div>
<div
style={{
width: 'calc(2px * var(--size-scale-factor, 1))',
height: '100%',
padding:
'calc(10px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1)) calc(6px * var(--size-scale-factor, 1)) 0',
boxSizing: 'border-box',
position: 'absolute',
top: 0,
right: 0,
paddingBottom: hasKeyChannels
? 'calc(3px * var(--size-scale-factor, 1))'
: 'calc(5px * var(--size-scale-factor, 1))',
opacity: hasKeyChannels ? 0.5 : '1',
}}
>
<B9 />
</B8>
<B10
<div
style={{
width: '100%',
height: '100%',
backgroundColor: LIGHT_COLOR,
opacity: '0.4',
borderBottomRightRadius: 'calc(1px * var(--size-scale-factor, 1))',
}}
/>
</div>
<div
style={{
width: '100%',
padding:
'0 calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1))',
boxSizing: 'border-box',
position: 'absolute',
bottom: 0,
left: 0,
opacity: hasKeyChannels ? 3 : '4',
}}
>
<B11 />
</B10>
<B12>
<B13
<div
style={{
width: '100%',
height: '100%',
backgroundColor: LIGHT_COLOR,
borderRadius:
'calc(4px * var(--size-scale-factor, 1)) calc(4px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1))',
opacity: '0.12',
}}
/>
</div>
<div
style={{
width: '100%',
height: '100%',
padding:
'calc(3px * var(--size-scale-factor, 1)) calc(3px * var(--size-scale-factor, 1)) calc(7px * var(--size-scale-factor, 1)) calc(3px * var(--size-scale-factor, 1))',
boxSizing: 'border-box',
position: 'absolute',
top: 0,
left: 0,
}}
>
<div
style={{
width: '100%',
height: '100%',
backgroundColor: LIGHT_COLOR,
maskImage: 'linear-gradient(to bottom, transparent, white)',
WebkitMaskImage: 'linear-gradient(to bottom, transparent, white)',
borderRadius: 99999,
opacity: hasKeyChannels ? 0.06 : '0.12',
}}
/>
</B12>
<B14
</div>
<div
style={{
width: '100%',
padding:
'0 calc(1px * var(--size-scale-factor, 1)) calc(5px * var(--size-scale-factor, 1)) calc(2px * var(--size-scale-factor, 1))',
boxSizing: 'border-box',
position: 'absolute',
bottom: 0,
left: 0,
height: hasKeyChannels
? 'calc(4px * var(--size-scale-factor, 1))'
: 'calc(6px * var(--size-scale-factor, 1))',
@@ -250,9 +219,17 @@ const StyledAccidentalKey: React.FC<Props> = ({ keyChannels }) => {
opacity: hasKeyChannels ? 0.5 : '1',
}}
>
<B15 />
</B14>
</Base>
<div
style={{
width: '100%',
height: '100%',
backgroundColor: LIGHT_COLOR,
borderRadius: '0 0 calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1))',
opacity: '0.4',
}}
/>
</div>
</div>
)
}



+ 174
- 185
src/components/StyledNaturalKey/StyledNaturalKey.tsx View File

@@ -1,210 +1,199 @@
import * as React from 'react'
import * as PropTypes from 'prop-types'
import styled from 'styled-components'
import keyPropTypes from '../../services/keyPropTypes'

const DEFAULT_COLOR = '#e3e3e5'
const LIGHT_COLOR = 'white'

const Base = styled('div')({
width: '100%',
height: '100%',
position: 'relative',
})

const N1 = styled('div')({
width: '100%',
height: '100%',
position: 'relative',
})

const N2 = styled('div')({
width: '100%',
height: '100%',
backgroundColor: 'black',
position: 'absolute',
top: '0',
left: '0',
})

const N3 = styled('div')({
width: '100%',
height: '100%',
padding:
'calc(1px * var(--size-scale-factor, 1)) 0 calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1))',
boxSizing: 'border-box',
position: 'absolute',
top: '0',
left: '0',
})

const N4 = styled('div')({
width: '100%',
height: '100%',
backgroundColor: `var(--color-natural-key, ${DEFAULT_COLOR})`,
borderRadius: '0 0 calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1))',
})

const N5 = styled('div')({
width: '100%',
height: 'calc(33 / 80 * 100%)',
padding:
'0 calc(1px * var(--size-scale-factor, 1)) calc(2px * var(--size-scale-factor, 1)) calc(2px * var(--size-scale-factor, 1))',
boxSizing: 'border-box',
backgroundClip: 'content-box',
position: 'absolute',
bottom: '0',
left: '0',
opacity: '0.25',
maskImage: 'linear-gradient(to bottom, transparent, white)',
})

const N6 = styled('div')({
width: '100%',
height: '100%',
backgroundColor: 'black',
padding:
'calc(1px * var(--size-scale-factor, 1)) calc(2px * var(--size-scale-factor, 1)) calc(3px * var(--size-scale-factor, 1)) calc(3px * var(--size-scale-factor, 1))',
boxSizing: 'border-box',
backgroundClip: 'content-box',
position: 'absolute',
bottom: '0',
left: '0',
opacity: '0.08',
maskImage: 'linear-gradient(to bottom, transparent, white)',
})

const N7 = styled('div')({
width: '100%',
height: 'calc(2px * var(--size-scale-factor, 1))',
padding: '0 0 calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1))',
boxSizing: 'border-box',
position: 'absolute',
bottom: '0',
left: '0',
})

const N8 = styled('div')({
width: '100%',
height: '100%',
backgroundColor: 'black',
borderRadius: '0 0 calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1))',
opacity: '0.25',
})
const N9 = styled('div')({
width: 'calc(2px * var(--size-scale-factor, 1))',
height: '100%',
padding:
'calc(1px * var(--size-scale-factor, 1)) 0 calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1))',
boxSizing: 'border-box',
position: 'absolute',
bottom: '0',
left: '0',
})
const N10 = styled('div')({
width: '100%',
height: '100%',
backgroundColor: 'black',
borderRadius: '0 0 0 calc(1px * var(--size-scale-factor, 1))',
opacity: '0.07',
})
const N11 = styled('div')({
width: '100%',
height: 'calc(6px * var(--size-scale-factor, 1))',
padding: 'calc(1px * var(--size-scale-factor, 1)) 0 0 calc(1px * var(--size-scale-factor, 1))',
boxSizing: 'border-box',
position: 'absolute',
top: '0',
left: '0',
})
const N12 = styled('div')({
width: '100%',
height: '100%',
backgroundColor: 'black',
maskImage: 'linear-gradient(to bottom, white, transparent)',
opacity: '0.12',
})
const N13 = styled('div')({
width: '100%',
padding: 'calc(1px * var(--size-scale-factor, 1)) 0 0 calc(1px * var(--size-scale-factor, 1))',
boxSizing: 'border-box',
position: 'absolute',
top: '0',
left: '0',
})
const N14 = styled('div')({
width: '100%',
height: '100%',
backgroundColor: 'black',
opacity: '0.12',
})
const N15 = styled('div')({
width: 'calc(1px * var(--size-scale-factor, 1))',
height: '100%',
padding: 'calc(1px * var(--size-scale-factor, 1)) 0 calc(1px * var(--size-scale-factor, 1)) 0',
boxSizing: 'border-box',
position: 'absolute',
bottom: '0',
right: '0',
})
const N16 = styled('div')({
width: '100%',
height: '100%',
backgroundColor: LIGHT_COLOR,
borderRadius: '0 0 calc(1px * var(--size-scale-factor, 1)) 0',
opacity: '0.12',
})

type Props = PropTypes.InferProps<typeof keyPropTypes>

const StyledNaturalKey: React.FC<Props> = ({ keyChannels }) => {
const hasKeyChannels = Array.isArray(keyChannels!) && keyChannels.length > 0
return (
<Base
<div
style={{
width: '100%',
height: '100%',
position: 'relative',
// @ts-ignore
'--color-natural-key': hasKeyChannels ? `var(--color-channel-${keyChannels![0]!.channel})` : undefined,
}}
>
<N1>
<N2 />
<N3>
<N4
style={{
opacity: hasKeyChannels ? 0.75 : 1,
}}
/>
</N3>
<N5
<div
style={{
width: '100%',
height: '100%',
backgroundColor: 'black',
position: 'absolute',
top: '0',
left: '0',
}}
/>
<div
style={{
width: '100%',
height: '100%',
padding:
'calc(1px * var(--size-scale-factor, 1)) 0 calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1))',
boxSizing: 'border-box',
position: 'absolute',
top: '0',
left: '0',
}}
>
<div
style={{
width: '100%',
height: '100%',
backgroundColor: `var(--color-natural-key, ${DEFAULT_COLOR})`,
borderRadius: '0 0 calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1))',
opacity: hasKeyChannels ? 0.75 : 1,
}}
/>
</div>
<div
style={{
width: '100%',
height: 'calc(33 / 80 * 100%)',
padding:
'0 calc(1px * var(--size-scale-factor, 1)) calc(2px * var(--size-scale-factor, 1)) calc(2px * var(--size-scale-factor, 1))',
boxSizing: 'border-box',
backgroundClip: 'content-box',
position: 'absolute',
bottom: '0',
left: '0',
maskImage: 'linear-gradient(to bottom, transparent, white)',
WebkitMaskImage: 'linear-gradient(to bottom, transparent, white)',
backgroundColor: hasKeyChannels ? 'black' : LIGHT_COLOR,
opacity: hasKeyChannels ? 0.12 : 0.25,
}}
/>
<div
style={{
width: '100%',
height: '100%',
backgroundColor: 'black',
padding:
'calc(1px * var(--size-scale-factor, 1)) calc(2px * var(--size-scale-factor, 1)) calc(3px * var(--size-scale-factor, 1)) calc(3px * var(--size-scale-factor, 1))',
boxSizing: 'border-box',
backgroundClip: 'content-box',
position: 'absolute',
bottom: '0',
left: '0',
opacity: '0.08',
maskImage: 'linear-gradient(to bottom, transparent, white)',
WebkitMaskImage: 'linear-gradient(to bottom, transparent, white)',
}}
/>
<div
style={{
width: '100%',
height: 'calc(2px * var(--size-scale-factor, 1))',
padding: '0 0 calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1))',
boxSizing: 'border-box',
position: 'absolute',
bottom: '0',
left: '0',
}}
>
<div
style={{
width: '100%',
height: '100%',
backgroundColor: 'black',
borderRadius: '0 0 calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1))',
opacity: '0.25',
}}
/>
</div>
<div
style={{
width: 'calc(2px * var(--size-scale-factor, 1))',
height: '100%',
padding:
'calc(1px * var(--size-scale-factor, 1)) 0 calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1))',
boxSizing: 'border-box',
position: 'absolute',
bottom: '0',
left: '0',
}}
>
<div
style={{
backgroundColor: hasKeyChannels ? 'black' : LIGHT_COLOR,
opacity: hasKeyChannels ? 0.12 : 0.25,
width: '100%',
height: '100%',
backgroundColor: 'black',
borderRadius: '0 0 0 calc(1px * var(--size-scale-factor, 1))',
opacity: '0.07',
}}
/>
<N6 />
<N7>
<N8 />
</N7>
<N9>
<N10 />
</N9>
<N11>
<N12 />
</N11>
<N13
</div>
<div
style={{
width: '100%',
height: 'calc(6px * var(--size-scale-factor, 1))',
padding: 'calc(1px * var(--size-scale-factor, 1)) 0 0 calc(1px * var(--size-scale-factor, 1))',
boxSizing: 'border-box',
position: 'absolute',
top: '0',
left: '0',
}}
>
<div
style={{
height: hasKeyChannels
? 'calc(4px * var(--size-scale-factor, 1))'
: 'calc(3px * var(--size-scale-factor, 1))',
width: '100%',
height: '100%',
backgroundColor: 'black',
maskImage: 'linear-gradient(to bottom, white, transparent)',
WebkitMaskImage: 'linear-gradient(to bottom, white, transparent)',
opacity: '0.12',
}}
>
<N14 />
</N13>
<N15>
<N16 />
</N15>
</N1>
</Base>
/>
</div>
<div
style={{
width: '100%',
padding: 'calc(1px * var(--size-scale-factor, 1)) 0 0 calc(1px * var(--size-scale-factor, 1))',
boxSizing: 'border-box',
position: 'absolute',
top: '0',
left: '0',
height: hasKeyChannels
? 'calc(4px * var(--size-scale-factor, 1))'
: 'calc(3px * var(--size-scale-factor, 1))',
}}
>
<div
style={{
width: '100%',
height: '100%',
backgroundColor: 'black',
opacity: '0.12',
}}
/>
</div>
<div
style={{
width: 'calc(1px * var(--size-scale-factor, 1))',
height: '100%',
padding: 'calc(1px * var(--size-scale-factor, 1)) 0 calc(1px * var(--size-scale-factor, 1)) 0',
boxSizing: 'border-box',
position: 'absolute',
bottom: '0',
right: '0',
}}
>
<div
style={{
width: '100%',
height: '100%',
backgroundColor: LIGHT_COLOR,
borderRadius: '0 0 calc(1px * var(--size-scale-factor, 1)) 0',
opacity: '0.12',
}}
/>
</div>
</div>
)
}



+ 1
- 1
src/services/getKeyLeft.ts View File

@@ -9,7 +9,7 @@ const getOctaveCount = mem(getOctaveCountUnmemoized, { cacheKey: (args) => args.
const getFractionalOctaveCount = mem(getFractionalOctaveCountUnmemoized, { cacheKey: (args) => args.join(':') })
const getKeyOctave = mem(getKeyOctaveUnmemoized)

interface GetKeyLeft {
export interface GetKeyLeft {
(k: number): number
}



+ 1
- 1
src/services/getKeyWidth.ts View File

@@ -4,7 +4,7 @@ import getOctaveCountUnmemoized from './getOctaveCount'
import getFractionalOctaveCountUnmemoized from './getFractionalOctaveCount'
import { ACCIDENTAL_KEY_TO_NATURAL_KEY_WIDTH_RATIO } from './constants'

interface GetKeyWidth {
export interface GetKeyWidth {
(k: number): number
}



Loading…
Cancel
Save