소스 검색

Remove tuning

Tuning is dealt with outside of the component. Fretboard only deals with which frets are fretted on each string.
master
부모
커밋
be73ccbf74
5개의 변경된 파일248개의 추가작업 그리고 298개의 파일을 삭제
  1. +163
    -0
      src/components/Fret/Fret.tsx
  2. +11
    -10
      src/components/Fretboard/Fretboard.stories.tsx
  3. +47
    -278
      src/components/Fretboard/Fretboard.tsx
  4. +25
    -0
      src/components/FretboardString/FretboardString.tsx
  5. +2
    -10
      src/index.tsx

+ 163
- 0
src/components/Fret/Fret.tsx 파일 보기

@@ -0,0 +1,163 @@
import * as React from 'react'
import * as PropTypes from 'prop-types'

const propTypes = {
fretNumber: PropTypes.number.isRequired,
totalFrets: PropTypes.number.isRequired,
firstString: PropTypes.bool,
strings: PropTypes.number.isRequired,
landmarks: PropTypes.bool,
fretted: PropTypes.bool,
capoFret: PropTypes.number,
name: PropTypes.string,
}

type Props = PropTypes.InferProps<typeof propTypes>

const Fret: React.FC<Props> = ({
fretNumber,
totalFrets,
children,
firstString,
strings,
landmarks = false,
fretted = false,
capoFret = 0,
name,
}) => (
<div
style={{
display: 'block',
position: 'relative',
width: fretNumber > 0 ? `${(totalFrets - fretNumber) / 12 * 100 + 100}%` : '0.5rem',
height: '1rem',
flexShrink: fretNumber > 0 ? undefined : 0,
padding: 0,
borderWidth: '0 0.0625rem',
borderStyle: 'none solid',
}}
>
{
landmarks
&& (fretNumber % 12 === 3 || fretNumber % 12 === 5 || fretNumber % 12 === 7 || fretNumber % 12 === 9 || fretNumber % 12 === 0)
&& fretNumber > 0
&& firstString
&& (
<div
style={{
position: 'absolute',
top: 0,
height: `${strings! * 100}%`,
width: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'space-around',
flexDirection: 'column',
}}
>
<div
style={{
width: '0.75rem',
height: '0.75rem',
backgroundColor: 'currentColor',
opacity: 0.5,
borderRadius: '50%',
}}
/>
{fretNumber > 0 && fretNumber % 12 === 0 && (
<div
style={{
width: '0.75rem',
height: '0.75rem',
backgroundColor: 'currentColor',
opacity: 0.5,
borderRadius: '50%',
}}
/>
)}
</div>
)
}
<div
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
display: 'flex',
alignItems: 'center',
}}
>
{children}
</div>
{
fretted
&& (
<div
style={{
position: 'absolute',
top: 0,
left: 0,
height: '100%',
width: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'space-around',
flexDirection: 'column',
color: 'red',
zIndex: 1,
}}
>
<div
style={{
display: 'grid',
placeContent: 'center',
width: name ? '2rem' : '0.75rem',
height: name ? '1.5rem' : '0.75rem',
backgroundColor: 'currentColor',
borderRadius: name ? '0.75rem' : '0.375rem',
}}
>
<div
style={{
color: 'white',
}}
>
{name}
</div>
</div>
</div>
)
}
{
fretNumber > 0
&& capoFret === fretNumber
&& firstString
&& (
<div
style={{
position: 'absolute',
top: 0,
height: `${strings! * 100}%`,
width: '100%',
}}
>
<div
style={{
margin: '0 auto',
width: '0.75rem',
height: '100%',
backgroundColor: 'currentColor',
borderRadius: '0.375rem',
}}
/>
</div>
)
}
</div>
)

Fret.propTypes = propTypes

export default Fret

+ 11
- 10
src/components/Fretboard/Fretboard.stories.tsx 파일 보기

@@ -9,20 +9,21 @@ export default {
// you consume the story in a test.
export const Default = (props?: Partial<Props>) => <Fretboard {...props} />

export const ReducedFrets = (props?: Partial<Props>) => <Fretboard {...props} frets={18} />
export const ReducedFrets = (props?: Partial<Props>) => <Fretboard {...props} landmarks frets={18} />

export const FixedTunings = (props?: Partial<Props>) => <Fretboard {...props} fixedTunings displayTunings />
export const Fretted = (props?: Partial<Props>) => <Fretboard {...props} landmarks fretted={[0, 0, 1, 2, 2, 0]} />

export const Fretted = (props?: Partial<Props>) => <Fretboard {...props} fretted={[0, 0, 1, 2, 2, 0]} />
export const FrettedWithNames = (props?: Partial<Props>) => <Fretboard {...props} landmarks fretted={[0, 0, 1, 2, 2, 0]} frettedNames={['E', 'B', 'G#', 'E', 'B', 'E']} />

export const Tunable = (props?: Partial<Props>) => <Fretboard {...props} displayTunings />
export const Mirror = (props?: Partial<Props>) => <Fretboard {...props} landmarks
mirror
/>

export const LeftHanded = (props?: Partial<Props>) => <Fretboard {...props} leftHanded />
export const MirrorFrettedWithNames = (props?: Partial<Props>) => <Fretboard {...props} mirror
landmarks fretted={[0, 0, 1, 2, 2, 0]} frettedNames={['E', 'B', 'G#', 'E', 'B', 'E']} />

export const Bass = (props?: Partial<Props>) => <Fretboard {...props} tunings={[43, 38, 33, 28]} />
export const Bass = (props?: Partial<Props>) => <Fretboard {...props} landmarks strings={4} />

export const ExtendedGuitar = (props?: Partial<Props>) => <Fretboard {...props} tunings={[64, 59, 55, 50, 45, 40, 35, 30]} />
export const ExtendedGuitar = (props?: Partial<Props>) => <Fretboard {...props} landmarks strings={8} />

// export const ExtendedBass = (props?: Partial<Props>) => <Fretboard {...props} tunings={[48, 43, 38, 33, 28, 23]} />

export const WithCapo = (props?: Partial<Props>) => <Fretboard {...props} capoFret={8} />
export const WithCapo = (props?: Partial<Props>) => <Fretboard {...props} landmarks capoFret={8} />

+ 47
- 278
src/components/Fretboard/Fretboard.tsx 파일 보기

@@ -1,314 +1,83 @@
import React, {ChangeEventHandler, FC} from 'react'
import React, {FC} from 'react'
import * as PropTypes from 'prop-types'
import FretboardString from '../FretboardString/FretboardString'
import Fret from '../Fret/Fret'

const propTypes = {
tunings: PropTypes.arrayOf(PropTypes.number),
strings: PropTypes.number,
frets: PropTypes.number,
leftHanded: PropTypes.bool,
mirror: PropTypes.bool,
fixedTunings: PropTypes.bool,
displayTunings: PropTypes.bool,
capoFret: PropTypes.number,
fretted: PropTypes.arrayOf(PropTypes.number),
landmarks: PropTypes.bool,
frettedNames: PropTypes.arrayOf(PropTypes.string),
}

export type Props = PropTypes.InferProps<typeof propTypes>

const PITCHES = 'C C# D D# E F F# G G# A A# B'.split(' ')

const getPitchName = (n: number) => PITCHES[n % 12] + Math.floor(n / 12)

const Fretboard: FC<Props> = ({
tunings = [64, 59, 55, 50, 45, 40],
strings = 6,
frets = 24,
leftHanded = false,
fixedTunings = false,
displayTunings = false,
mirror = false,
capoFret = 0,
fretted = [],
landmarks = false,
frettedNames = [],
}) => {
const [clientSide, setClientSide, ] = React.useState(false)
const [pitches, setPitches, ] = React.useState<string[]>(tunings!.map(t => getPitchName(t!)))

const updateStringPitch = (currentStringNumber: number): ChangeEventHandler<HTMLInputElement> => e => {
const { value } = e.target
setPitches(oldPitches => [
...oldPitches.slice(0, currentStringNumber),
getPitchName(Number(value)),
...oldPitches.slice(currentStringNumber + 1),
])
}

React.useEffect(() => {
setClientSide(true)
}, [])

// React.useEffect(() => {
// if (!Array.isArray(tunings!)) {
// return
// }
//
// setPitches(() => tunings.map(t => getPitchName(t!)))
// }, [tunings])

if (!Array.isArray(tunings!)) {
return null
}

const strings = tunings!.map(t => new Array(frets).fill(0).map((_, i) => t! + i + 1))
const str: boolean[][] = new Array(strings)
.fill(null)
.map(() => new Array(frets)
.fill(null)
.map(() => false)
)

return (
<div
style={{
border: '0.0625rem solid',
boxSizing: 'border-box',
userSelect: 'none',
}}
>
{strings!.map((stringPitches, stringNumber) => (
{str!.map((f, stringNumber: number) => (
<div
style={{
display: 'flex',
flexDirection: leftHanded ? 'row-reverse' : 'row',
flexDirection: mirror ? 'row-reverse' : 'row',
}}
>
{
displayTunings
&& (
<div
style={{
display: 'block',
width: '5rem',
height: '1rem',
padding: '0 0 0 1rem',
boxSizing: 'border-box',
position: 'relative',
flexShrink: 0,
}}
>
<div
style={{
display: 'block',
width: '100%',
height: '100%',
padding: 0,
boxSizing: 'border-box',
position: 'relative',
}}
>
<span
style={{
display: 'block',
width: '2rem',
height: '100%',
position: 'absolute',
top: 0,
left: 0,
pointerEvents: 'none',
}}
>
{pitches[stringNumber]}
</span>
<input
type="number"
style={{
display: 'block',
width: '100%',
height: '100%',
padding: 0,
boxSizing: 'border-box',
border: 0,
backgroundColor: 'transparent',
font: 'inherit',
textAlign: 'right',
}}
readOnly={!clientSide || Boolean(fixedTunings)}
onChange={updateStringPitch(stringNumber)}
defaultValue={tunings[stringNumber]!}
min={0}
max={127}
/>
</div>
</div>
)
}
<div
style={{
display: 'block',
position: 'relative',
width: '0.5rem',
height: '1rem',
flexShrink: 0,
padding: 0,
borderWidth: '0 0.0625rem',
borderStyle: 'none solid',
}}
<Fret
fretNumber={0}
totalFrets={frets!}
firstString={stringNumber === 0}
strings={strings!}
landmarks={landmarks}
fretted={fretted![stringNumber] === 0}
capoFret={capoFret}
name={frettedNames![stringNumber]}
>
<button
type="button"
style={{
position: 'relative',
display: 'block',
width: '100%',
height: '100%',
flexShrink: 0,
padding: 0,
border: 0,
backgroundColor: 'transparent',
}}
<FretboardString
stringNumber={stringNumber}
/>
</Fret>
{f.map((_, i) => (
<Fret
fretNumber={i + 1}
totalFrets={frets!}
firstString={stringNumber === 0}
strings={strings!}
landmarks={landmarks}
fretted={fretted![stringNumber] === i + 1}
capoFret={capoFret}
name={frettedNames![stringNumber]}
>
<span
style={{
display: 'block',
width: '100%',
height: `${0.03125 + stringNumber * 0.03125}rem`,
backgroundColor: 'currentColor',
}}

<FretboardString
stringNumber={stringNumber}
/>
{
fretted![stringNumber] === 0
&& (
<span
style={{
position: 'absolute',
top: 0,
left: 0,
height: '100%',
width: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'space-around',
flexDirection: 'column',
color: 'red',
}}
>
<span
style={{
width: '0.75rem',
height: '0.75rem',
backgroundColor: 'currentColor',
borderRadius: '50%',
}}
/>
</span>
)
}
</button>
</div>
{stringPitches.map((_, i) => (
<div
style={{
width: `${(frets! - i - 1) / 12 * 100 + 100}%`,
height: '1rem',
position: 'relative',
}}
>
{(i % 12 === 2 || i % 12 === 4 || i % 12 === 6 || i % 12 === 8 || i % 12 === 11) && stringNumber === 0 && (
<div
style={{
position: 'absolute',
top: 0,
height: `${tunings.length * 100}%`,
width: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'space-around',
flexDirection: 'column',
}}
>
<div
style={{
width: '0.75rem',
height: '0.75rem',
backgroundColor: 'currentColor',
opacity: 0.5,
borderRadius: '50%',
}}
/>
{i % 12 === 11 && (
<div
style={{
width: '0.75rem',
height: '0.75rem',
backgroundColor: 'currentColor',
opacity: 0.5,
borderRadius: '50%',
}}
/>
)}
</div>
)}
<button
key={i}
type="button"
style={{
position: 'relative',
display: 'block',
width: '100%',
height: '1rem',
padding: 0,
borderWidth: '0 0.0625rem',
borderStyle: 'none solid',
backgroundColor: 'transparent',
}}
>
<span
style={{
display: 'block',
width: '100%',
height: `${0.03125 + stringNumber * 0.03125}rem`,
backgroundColor: 'currentColor',
}}
/>
{
fretted![stringNumber] === i + 1
&& (
<span
style={{
position: 'absolute',
top: 0,
left: 0,
height: '100%',
width: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'space-around',
flexDirection: 'column',
color: 'red',
}}
>
<span
style={{
width: '0.75rem',
height: '0.75rem',
backgroundColor: 'currentColor',
borderRadius: '50%',
}}
/>
</span>
)
}
</button>
{
capoFret === (i + 1) && stringNumber === 0 && (
<div
style={{
position: 'absolute',
top: 0,
height: `${tunings.length * 100}%`,
width: '100%',
}}
>
<div
style={{
width: '0.75rem',
height: '100%',
backgroundColor: 'currentColor',
borderRadius: '0.375rem',
}}
/>
</div>
)
}
</div>
</Fret>
))}
</div>
))}


+ 25
- 0
src/components/FretboardString/FretboardString.tsx 파일 보기

@@ -0,0 +1,25 @@
import * as React from 'react'
import * as PropTypes from 'prop-types'

const propTypes = {
stringNumber: PropTypes.number.isRequired,
}

type Props = PropTypes.InferProps<typeof propTypes>

const FretboardString: React.FC<Props> = ({
stringNumber,
}) => (
<span
style={{
display: 'block',
width: '100%',
height: `${0.03125 + stringNumber * 0.03125}rem`,
backgroundColor: 'currentColor',
}}
/>
)

FretboardString.propTypes = propTypes

export default FretboardString

+ 2
- 10
src/index.tsx 파일 보기

@@ -1,11 +1,3 @@
import React, { FC, HTMLAttributes, ReactChild } from 'react'
import Fretboard from './components/Fretboard/Fretboard'

export interface Props extends HTMLAttributes<HTMLDivElement> {
children?: ReactChild
}

// Please do not use types off of a default export module or else Storybook Docs will suffer.
// see: https://github.com/storybookjs/storybook/issues/9556
export const Thing: FC<Props> = ({ children }) => {
return <div>{children || `the snozzberries taste like snozzberries`}</div>
}
export default Fretboard

불러오는 중...
취소
저장