Skip to content

Commit e42b38e

Browse files
committed
Added Keyboard Type functionality
Added Qwerty, Dvorak, and Colemak type functionality.
1 parent bcc3007 commit e42b38e

File tree

10 files changed

+159
-19
lines changed

10 files changed

+159
-19
lines changed

src/components/Keyboards/Key.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React from 'react';
22
import styled from 'styled-components';
33
import { motion } from 'framer-motion';
44
import { Microsoft } from '@mui/icons-material';
5+
import { KeyboardLayoutType, getKeyMapping } from './keyboardTypes';
56

67
export type KeySize =
78
| '1u' | '1.05u' | '1.1u' | '1.15u' | '1.2u' | '1.25u' | '1.3u' | '1.35u' | '1.4u' | '1.45u'
@@ -25,6 +26,7 @@ export interface KeyLabel {
2526

2627
export interface KeyProps {
2728
label: KeyLabel;
29+
keyboardType?: KeyboardLayoutType;
2830
size?: KeySize;
2931
isPressed?: boolean;
3032
isTested?: boolean;
@@ -143,6 +145,7 @@ const WindowsIcon = styled(Microsoft)`
143145

144146
const Key: React.FC<KeyProps> = ({
145147
label,
148+
keyboardType = 'qwerty',
146149
size = '1u',
147150
isPressed = false,
148151
isTested = false,
@@ -152,6 +155,9 @@ const Key: React.FC<KeyProps> = ({
152155
}) => {
153156
const width = KEY_UNIT * sizeMap[size];
154157
const isWindowsKey = label.primary === 'Win';
158+
159+
// Get the mapped label based on keyboard type
160+
const mappedLabel = isSpecialKey ? label : getKeyMapping(keyboardType, label.primary, label);
155161

156162
return (
157163
<KeyContainer
@@ -181,8 +187,8 @@ const Key: React.FC<KeyProps> = ({
181187
<WindowsIcon />
182188
) : (
183189
<>
184-
{label.secondary && <SecondaryText>{label.secondary}</SecondaryText>}
185-
<PrimaryText>{label.primary}</PrimaryText>
190+
{mappedLabel.secondary && <SecondaryText>{mappedLabel.secondary}</SecondaryText>}
191+
<PrimaryText>{mappedLabel.primary}</PrimaryText>
186192
</>
187193
)}
188194
</KeyText>

src/components/Keyboards/Keyboard60.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ import styled from 'styled-components';
33
import { motion } from 'framer-motion';
44
import Key from './Key';
55
import { useKeyboardEvents } from './useKeyboardEvents';
6+
import { KeyboardLayoutType } from './keyboardTypes';
67

78
interface Keyboard60Props {
89
onKeyPress?: (key: string) => void;
910
onReset?: () => void;
11+
keyboardType?: KeyboardLayoutType;
1012
}
1113

1214
// Styled components for the keyboard
@@ -83,13 +85,14 @@ const layoutVariants = {
8385
},
8486
};
8587

86-
const Keyboard60: React.FC<Keyboard60Props> = ({ onKeyPress, onReset }) => {
88+
const Keyboard60: React.FC<Keyboard60Props> = ({ onKeyPress, onReset, keyboardType = 'qwerty' }) => {
8789
// Use the keyboard events hook to handle key presses
8890
const [{ testedKeys, pressedKeys }, { handleKeyPress }] = useKeyboardEvents(onKeyPress, onReset);
8991

9092
// Helper function to create key props
9193
const createKeyProps = (displayName: string, keyName: string, secondary?: string, isSpecial: boolean = false) => ({
9294
label: { primary: displayName, secondary },
95+
keyboardType,
9396
onKeyPress: () => handleKeyPress(keyName),
9497
isTested: testedKeys.has(keyName),
9598
isPressed: pressedKeys.has(keyName),

src/components/Keyboards/Keyboard65.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ import styled from 'styled-components';
33
import { motion } from 'framer-motion';
44
import Key, { KeySize } from './Key';
55
import { useKeyboardEvents } from './useKeyboardEvents';
6+
import { KeyboardLayoutType } from './keyboardTypes';
67

78
interface Keyboard65Props {
89
onKeyPress?: (key: string) => void;
910
onReset?: () => void;
11+
keyboardType?: KeyboardLayoutType;
1012
}
1113

1214
// Styled components for the keyboard
@@ -79,7 +81,7 @@ const layoutVariants = {
7981
},
8082
};
8183

82-
const Keyboard65: React.FC<Keyboard65Props> = ({ onKeyPress, onReset }) => {
84+
const Keyboard65: React.FC<Keyboard65Props> = ({ onKeyPress, onReset, keyboardType }) => {
8385
const [{ testedKeys, pressedKeys }, { handleKeyPress }] = useKeyboardEvents(onKeyPress, onReset);
8486

8587
// Helper function to create key props
@@ -89,6 +91,7 @@ const Keyboard65: React.FC<Keyboard65Props> = ({ onKeyPress, onReset }) => {
8991
isTested: testedKeys.has(keyName),
9092
isPressed: pressedKeys.has(keyName),
9193
isSpecialKey: isSpecial,
94+
keyboardType,
9295
});
9396

9497
return (

src/components/Keyboards/Keyboard75.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ import styled from 'styled-components';
33
import { motion } from 'framer-motion';
44
import Key, { KeySize } from './Key';
55
import { useKeyboardEvents } from './useKeyboardEvents';
6+
import { KeyboardLayoutType } from './keyboardTypes';
67

78
interface Keyboard75Props {
89
onKeyPress?: (key: string) => void;
910
onReset?: () => void;
11+
keyboardType?: KeyboardLayoutType;
1012
}
1113

1214
// Styled components for the keyboard
@@ -76,7 +78,7 @@ const layoutVariants = {
7678
},
7779
};
7880

79-
const Keyboard75: React.FC<Keyboard75Props> = ({ onKeyPress, onReset }) => {
81+
const Keyboard75: React.FC<Keyboard75Props> = ({ onKeyPress, onReset, keyboardType }) => {
8082
// Use the keyboard events hook to handle key presses
8183
const [{ testedKeys, pressedKeys }, { handleKeyPress }] = useKeyboardEvents(onKeyPress, onReset);
8284

@@ -88,6 +90,7 @@ const Keyboard75: React.FC<Keyboard75Props> = ({ onKeyPress, onReset }) => {
8890
isPressed: pressedKeys.has(keyName),
8991
isSpecialKey: isSpecial,
9092
size,
93+
keyboardType,
9194
});
9295

9396
return (

src/components/Keyboards/KeyboardFull.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ import React from 'react';
22
import styled from 'styled-components';
33
import Key, { KeySize } from './Key';
44
import { useKeyboardEvents } from './useKeyboardEvents';
5+
import { KeyboardLayoutType } from './keyboardTypes';
56

67
interface KeyboardFullProps {
78
onKeyPress?: (key: string) => void;
89
onReset?: () => void;
10+
keyboardType?: KeyboardLayoutType;
911
}
1012

1113
const KeyboardContainer = styled.div`
@@ -74,7 +76,7 @@ const MainAndNumpadRow = styled.div`
7476
gap: 2px;
7577
`;
7678

77-
const KeyboardFull: React.FC<KeyboardFullProps> = ({ onKeyPress, onReset }) => {
79+
const KeyboardFull: React.FC<KeyboardFullProps> = ({ onKeyPress, onReset, keyboardType }) => {
7880
const [{ testedKeys, pressedKeys }, { handleKeyPress }] = useKeyboardEvents(onKeyPress, onReset);
7981

8082
// Helper function to create key props
@@ -85,6 +87,7 @@ const KeyboardFull: React.FC<KeyboardFullProps> = ({ onKeyPress, onReset }) => {
8587
isTested: testedKeys.has(keyName),
8688
isPressed: pressedKeys.has(keyName),
8789
isSpecialKey: isSpecial,
90+
keyboardType,
8891
};
8992

9093
// Only add size if a width is provided, and map it to a valid KeySize

src/components/Keyboards/KeyboardSelector.tsx

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import Keyboard65 from './Keyboard65';
66
import Keyboard75 from './Keyboard75';
77
import KeyboardTKL from './KeyboardTKL';
88
import KeyboardFull from './KeyboardFull';
9+
import { KeyboardLayoutType } from './keyboardTypes';
910

1011
// We'll add more keyboard layouts as they're implemented
1112
export type KeyboardType = '60%' | '65%' | '75%' | 'TKL' | 'Full';
@@ -14,6 +15,7 @@ interface KeyboardSelectorProps {
1415
onKeyPress?: (key: string) => void;
1516
onReset?: () => void;
1617
initialLayout?: KeyboardType;
18+
keyboardType?: KeyboardLayoutType;
1719
}
1820

1921
const Container = styled.div`
@@ -53,7 +55,8 @@ const containerVariants = {
5355
const KeyboardSelector: React.FC<KeyboardSelectorProps> = ({
5456
onKeyPress,
5557
onReset,
56-
initialLayout = '75%'
58+
initialLayout = '75%',
59+
keyboardType = 'qwerty'
5760
}) => {
5861
const [currentLayout, setCurrentLayout] = useState<KeyboardType>(initialLayout);
5962
const [direction, setDirection] = useState<number>(0);
@@ -75,17 +78,17 @@ const KeyboardSelector: React.FC<KeyboardSelectorProps> = ({
7578
const renderKeyboard = () => {
7679
switch (currentLayout) {
7780
case '60%':
78-
return <Keyboard60 onKeyPress={onKeyPress} onReset={onReset} />;
81+
return <Keyboard60 onKeyPress={onKeyPress} onReset={onReset} keyboardType={keyboardType} />;
7982
case '65%':
80-
return <Keyboard65 onKeyPress={onKeyPress} onReset={onReset} />;
83+
return <Keyboard65 onKeyPress={onKeyPress} onReset={onReset} keyboardType={keyboardType} />;
8184
case '75%':
82-
return <Keyboard75 onKeyPress={onKeyPress} onReset={onReset} />;
85+
return <Keyboard75 onKeyPress={onKeyPress} onReset={onReset} keyboardType={keyboardType} />;
8386
case 'TKL':
84-
return <KeyboardTKL onKeyPress={onKeyPress} onReset={onReset} />;
87+
return <KeyboardTKL onKeyPress={onKeyPress} onReset={onReset} keyboardType={keyboardType} />;
8588
case 'Full':
86-
return <KeyboardFull onKeyPress={onKeyPress} onReset={onReset} />;
89+
return <KeyboardFull onKeyPress={onKeyPress} onReset={onReset} keyboardType={keyboardType} />;
8790
default:
88-
return <Keyboard75 onKeyPress={onKeyPress} onReset={onReset} />;
91+
return <Keyboard75 onKeyPress={onKeyPress} onReset={onReset} keyboardType={keyboardType} />;
8992
}
9093
};
9194

src/components/Keyboards/KeyboardTKL.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ import styled from 'styled-components';
33
import { motion } from 'framer-motion';
44
import Key, { KeySize } from './Key';
55
import { useKeyboardEvents } from './useKeyboardEvents';
6+
import { KeyboardLayoutType } from './keyboardTypes';
67

78
interface KeyboardTKLProps {
89
onKeyPress?: (key: string) => void;
910
onReset?: () => void;
11+
keyboardType?: KeyboardLayoutType;
1012
}
1113

1214
const KeyboardContainer = styled(motion.div)`
@@ -85,7 +87,7 @@ const layoutVariants = {
8587
},
8688
};
8789

88-
const KeyboardTKL: React.FC<KeyboardTKLProps> = ({ onKeyPress, onReset }) => {
90+
const KeyboardTKL: React.FC<KeyboardTKLProps> = ({ onKeyPress, onReset, keyboardType }) => {
8991
const [{ testedKeys, pressedKeys }, { handleKeyPress }] = useKeyboardEvents(onKeyPress, onReset);
9092

9193
// Helper function to create key props
@@ -96,6 +98,7 @@ const KeyboardTKL: React.FC<KeyboardTKLProps> = ({ onKeyPress, onReset }) => {
9698
isTested: testedKeys.has(keyName),
9799
isPressed: pressedKeys.has(keyName),
98100
isSpecialKey: isSpecial,
101+
keyboardType,
99102
};
100103

101104
// Only add size if a width is provided, and map it to a valid KeySize

src/components/Keyboards/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ export { default as KeyboardFull } from './KeyboardFull';
77
export { default as KeyboardSelector } from './KeyboardSelector';
88
export { useKeyboardEvents } from './useKeyboardEvents';
99
export type { KeyboardType } from './KeyboardSelector';
10+
export type { KeyboardLayoutType } from './keyboardTypes';
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
// Keyboard type mappings for different keyboard layouts
2+
// This file contains the character mappings for QWERTY, Dvorak, and Colemak layouts
3+
4+
export type KeyboardLayoutType = 'qwerty' | 'dvorak' | 'colemak';
5+
6+
// Define interfaces for our key mappings
7+
interface KeyMapping {
8+
primary: string;
9+
secondary?: string;
10+
}
11+
12+
// Type for our mapping objects
13+
export type KeyboardTypeMapping = Record<string, KeyMapping>;
14+
15+
// QWERTY layout (default) - this is just for reference as we'll keep the original labels for QWERTY
16+
export const qwertyMapping: KeyboardTypeMapping = {
17+
// We don't need to define anything here as QWERTY is the default
18+
// This is just for reference
19+
};
20+
21+
// Dvorak layout
22+
export const dvorakMapping: KeyboardTypeMapping = {
23+
// Number row remains the same
24+
// Top row
25+
'Q': { primary: "'", secondary: '"' },
26+
'W': { primary: ',', secondary: '<' },
27+
'E': { primary: '.', secondary: '>' },
28+
'R': { primary: 'P', secondary: undefined },
29+
'T': { primary: 'Y', secondary: undefined },
30+
'Y': { primary: 'F', secondary: undefined },
31+
'U': { primary: 'G', secondary: undefined },
32+
'I': { primary: 'C', secondary: undefined },
33+
'O': { primary: 'R', secondary: undefined },
34+
'P': { primary: 'L', secondary: undefined },
35+
'[': { primary: '/', secondary: '?' },
36+
']': { primary: '=', secondary: '+' },
37+
38+
// Middle row
39+
'A': { primary: 'A', secondary: undefined },
40+
'S': { primary: 'O', secondary: undefined },
41+
'D': { primary: 'E', secondary: undefined },
42+
'F': { primary: 'U', secondary: undefined },
43+
'G': { primary: 'I', secondary: undefined },
44+
'H': { primary: 'D', secondary: undefined },
45+
'J': { primary: 'H', secondary: undefined },
46+
'K': { primary: 'T', secondary: undefined },
47+
'L': { primary: 'N', secondary: undefined },
48+
';': { primary: 'S', secondary: undefined },
49+
"'": { primary: '-', secondary: '_' },
50+
51+
// Bottom row
52+
'Z': { primary: ';', secondary: ':' },
53+
'X': { primary: 'Q', secondary: undefined },
54+
'C': { primary: 'J', secondary: undefined },
55+
'V': { primary: 'K', secondary: undefined },
56+
'B': { primary: 'X', secondary: undefined },
57+
'N': { primary: 'B', secondary: undefined },
58+
'M': { primary: 'M', secondary: undefined },
59+
',': { primary: 'W', secondary: undefined },
60+
'.': { primary: 'V', secondary: undefined },
61+
'/': { primary: 'Z', secondary: undefined }
62+
};
63+
64+
// Colemak layout
65+
export const colemakMapping: KeyboardTypeMapping = {
66+
// Number row remains the same
67+
// Top row
68+
'Q': { primary: 'Q', secondary: undefined },
69+
'W': { primary: 'W', secondary: undefined },
70+
'E': { primary: 'F', secondary: undefined },
71+
'R': { primary: 'P', secondary: undefined },
72+
'T': { primary: 'G', secondary: undefined },
73+
'Y': { primary: 'J', secondary: undefined },
74+
'U': { primary: 'L', secondary: undefined },
75+
'I': { primary: 'U', secondary: undefined },
76+
'O': { primary: 'Y', secondary: undefined },
77+
'P': { primary: ';', secondary: ':' },
78+
79+
// Middle row
80+
'A': { primary: 'A', secondary: undefined },
81+
'S': { primary: 'R', secondary: undefined },
82+
'D': { primary: 'S', secondary: undefined },
83+
'F': { primary: 'T', secondary: undefined },
84+
'G': { primary: 'D', secondary: undefined },
85+
'H': { primary: 'H', secondary: undefined },
86+
'J': { primary: 'N', secondary: undefined },
87+
'K': { primary: 'E', secondary: undefined },
88+
'L': { primary: 'I', secondary: undefined },
89+
';': { primary: 'O', secondary: undefined },
90+
91+
// Bottom row
92+
'Z': { primary: 'Z', secondary: undefined },
93+
'X': { primary: 'X', secondary: undefined },
94+
'C': { primary: 'C', secondary: undefined },
95+
'V': { primary: 'V', secondary: undefined },
96+
'B': { primary: 'B', secondary: undefined },
97+
'N': { primary: 'K', secondary: undefined },
98+
'M': { primary: 'M', secondary: undefined }
99+
};
100+
101+
// Function to get the appropriate mapping based on the keyboard type
102+
export const getKeyMapping = (type: KeyboardLayoutType, key: string, defaultMapping: KeyMapping): KeyMapping => {
103+
switch (type) {
104+
case 'dvorak':
105+
return dvorakMapping[key] || defaultMapping;
106+
case 'colemak':
107+
return colemakMapping[key] || defaultMapping;
108+
case 'qwerty':
109+
default:
110+
return defaultMapping;
111+
}
112+
};

0 commit comments

Comments
 (0)