Skip to content

Commit 33a930b

Browse files
alt up/down for demo selections (including full screen)
1 parent 3fa768f commit 33a930b

6 files changed

Lines changed: 106 additions & 10 deletions

File tree

src/components/hotkeys/hotKeyBuilder.test.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,9 @@ describe('hotKeyBuilder', () => {
1616
const altF5 = hotKeyFromString('Alt F5');
1717
expect(altF5).toEqual({code: 'F5', shift: false, meta: false, ctrl: false, alt: true});
1818
});
19+
20+
it('maps arrow keys', () => {
21+
const shiftArrow = hotKeyFromString('Shift Down');
22+
expect(shiftArrow).toEqual({code: 'ArrowDown', shift: true, meta: false, ctrl: false, alt: false});
23+
});
1924
});

src/components/hotkeys/hotKeyBuilder.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,11 @@ function createKeyMapping() {
6565
'/': 'Slash',
6666
'-': 'Minus',
6767
'=': 'Equal',
68-
'`': 'Backquote'
68+
'`': 'Backquote',
69+
'DOWN': 'ArrowDown',
70+
'UP': 'ArrowUp',
71+
'LEFT': 'ArrowLeft',
72+
'RIGHT': 'ArrowRight',
6973
};
7074
}
7175

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import * as React from 'react';
2+
3+
import { Registry } from './Registry';
4+
5+
describe('Registry', () => {
6+
const registry = new Registry('widgets');
7+
registry.registerAsRows('demo one', registerDemo);
8+
registry.registerAsRows('demo two', registerDemo);
9+
registry.registerAsRows('demo three', registerDemo);
10+
11+
it('should find demo by name', () => {
12+
const byName = registry.findDemoByName('demo two');
13+
expect(byName!.name).toEqual('demo two');
14+
15+
const notFound = registry.findDemoByName('demo 2');
16+
expect(notFound).toEqual(null);
17+
});
18+
19+
it('should find next demo by current name', () => {
20+
const byName = registry.findNextDemoByCurrentName('demo two');
21+
expect(byName!.name).toEqual('demo three');
22+
});
23+
24+
it('should return last demo when no next demo is available', () => {
25+
const byName = registry.findNextDemoByCurrentName('demo three');
26+
expect(byName!.name).toEqual('demo three');
27+
});
28+
29+
it('should find prev demo by current name', () => {
30+
const byName = registry.findPrevDemoByCurrentName('demo two');
31+
expect(byName!.name).toEqual('demo one');
32+
});
33+
34+
it('should return first demo when no prev demo is available', () => {
35+
const byName = registry.findPrevDemoByCurrentName('demo one');
36+
expect(byName!.name).toEqual('demo one');
37+
});
38+
});
39+
40+
function registerDemo(registry: Registry) {
41+
registry.add('demo entry', () => <div/>);
42+
}

src/components/registry/Registry.ts

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -106,16 +106,34 @@ class Registry {
106106
return byUrl.length > 0 ? byUrl[0] : null;
107107
}
108108

109-
findByName(name: string): DemoEntry | null {
110-
const byName = this.demoEntries
111-
.filter(entry => entry.name === name);
109+
findDemoByName(name: string): DemoEntry | null {
110+
const found = findDemoAndReturn(this.demoEntries, name, idx => this.demoEntries[idx]);
111+
return found ? found : null;
112+
}
112113

113-
if (byName.length === 0) {
114-
return null;
115-
}
114+
findNextDemoByCurrentName(name: string): DemoEntry {
115+
const found = findDemoAndReturn(this.demoEntries, name, idx => this.demoEntries[idx + 1]);
116+
return found ? found : this.demoEntries[this.demoEntries.length - 1];
117+
}
118+
119+
findPrevDemoByCurrentName(name: string): DemoEntry {
120+
const found = findDemoAndReturn(this.demoEntries, name, idx => this.demoEntries[idx - 1]);
121+
return found ? found : this.demoEntries[0];
122+
}
123+
}
116124

117-
return byName[0];
125+
function findDemoAndReturn(demos: DemoEntry[],
126+
currentDemoName: string,
127+
returnFunc: (idx: number) => DemoEntry | null) {
128+
let idx = 0;
129+
for (const demo of demos) {
130+
if (demo.name === currentDemoName) {
131+
return returnFunc(idx);
132+
}
133+
idx++;
118134
}
135+
136+
return undefined;
119137
}
120138

121139
export { Registry };

src/components/viewer/ComponentViewer.tsx

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ class ComponentViewer extends Component<Props, ComponentViewerState> {
4545
this.state = this.stateFromUrl();
4646
this.hotKeyBoundActions = {
4747
'Alt F': this.onFullScreenToggle,
48+
'Alt Down': this.onNextDemo,
49+
'Alt Up': this.onPrevDemo,
4850
...this.dropDownKeyBoundActions()
4951
};
5052
}
@@ -56,7 +58,7 @@ class ComponentViewer extends Component<Props, ComponentViewerState> {
5658
} = this.state;
5759

5860
const registry = this.findSelectedRegistry();
59-
const demoEntry = registry ? registry.findByName(demoName) : null;
61+
const demoEntry = registry ? registry.findDemoByName(demoName) : null;
6062

6163
const rendered = demoEntry && (demoEntry.isMiniApp() || isFullScreen) ?
6264
this.renderDemo(demoEntry, true) :
@@ -204,6 +206,31 @@ class ComponentViewer extends Component<Props, ComponentViewerState> {
204206
this.state.selectedToolbarItem);
205207
}
206208

209+
private onNextDemo = () => {
210+
this.withRegistryAndDemoNameWhenPresent(((registry, demoName) => {
211+
const nextDemo = registry.findNextDemoByCurrentName(demoName);
212+
this.selectDemo(nextDemo.name);
213+
}));
214+
}
215+
216+
private onPrevDemo = () => {
217+
this.withRegistryAndDemoNameWhenPresent(((registry, demoName) => {
218+
const prevDemo = registry.findPrevDemoByCurrentName(demoName);
219+
this.selectDemo(prevDemo.name);
220+
}));
221+
}
222+
223+
private withRegistryAndDemoNameWhenPresent = (code: (registry: Registry, demoName: string) => void) => {
224+
const registry = this.findSelectedRegistry();
225+
const {demoName} = this.state;
226+
227+
if (!registry) {
228+
return;
229+
}
230+
231+
code(registry, demoName);
232+
}
233+
207234
private selectRegistry = (registryName: string) => {
208235
this.pushUrl(
209236
registryName,

src/components/viewer/ComponentViewerStateCreator.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export class ComponentViewerStateCreator {
2020
}
2121

2222
private static firstTitleByDemoName(registry: Registry | null, name: string) {
23-
const demoEntry = registry ? registry.findByName(name) : null;
23+
const demoEntry = registry ? registry.findDemoByName(name) : null;
2424
return demoEntry ? demoEntry.firstEntryTitle : '';
2525
}
2626

0 commit comments

Comments
 (0)