Prefer using React memoization instead of mem when using inside React.master
@@ -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" | |||
@@ -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 | |||
@@ -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> | |||
) | |||
} | |||
@@ -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 | |||
@@ -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> | |||
) | |||
} | |||
@@ -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> | |||
) | |||
} | |||
@@ -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 | |||
} | |||
@@ -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 | |||
} | |||