MOVE event handlers into module init

This commit is contained in:
Norbert de Langen 2020-03-09 21:27:46 +01:00
parent 36d4802d13
commit ad8a245c85
No known key found for this signature in database
GPG Key ID: 976651DA156C2825
5 changed files with 92 additions and 91 deletions

View File

@ -13,10 +13,8 @@ import React, {
import {
SET_STORIES,
STORY_CHANGED,
SELECT_STORY,
SHARED_STATE_CHANGED,
SHARED_STATE_SET,
NAVIGATE_URL,
} from '@storybook/core-events';
import { RenderData as RouterData } from '@storybook/router';
import { Listener } from '@storybook/channels';
@ -33,16 +31,7 @@ import initNotifications, {
SubAPI as NotificationAPI,
} from './modules/notifications';
import initStories, { SubState as StoriesSubState, SubAPI as StoriesAPI } from './modules/stories';
import {
StoriesRaw,
StoriesHash,
Story,
Root,
Group,
isGroup,
isRoot,
isStory,
} from './lib/stories';
import { StoriesHash, Story, Root, Group, isGroup, isRoot, isStory } from './lib/stories';
import initLayout, {
ActiveTabs,
SubState as LayoutSubState,
@ -191,31 +180,6 @@ class ManagerProvider extends Component<ManagerProviderProps, State> {
initProviderApi({ provider, store, api });
api.on(STORY_CHANGED, (id: string) => {
const options = api.getParameters(id, 'options');
if (options) {
api.setOptions(options);
}
});
api.on(SET_STORIES, (data: { stories: StoriesRaw }) => {
api.setStories(data.stories);
const options = storyId
? api.getParameters(storyId, 'options')
: api.getParameters(Object.keys(data.stories)[0], 'options');
api.setOptions(options);
});
api.on(
SELECT_STORY,
({ kind, story, ...rest }: { kind: string; story: string; [k: string]: any }) => {
api.selectStory(kind, story, rest);
}
);
api.on(NAVIGATE_URL, (url: string, options: { [k: string]: any }) => {
api.navigateUrl(url, options);
});
this.state = state;
this.api = api;
}
@ -239,7 +203,7 @@ class ManagerProvider extends Component<ManagerProviderProps, State> {
// a chance to do things that call other modules' APIs.
this.modules.forEach(({ init }) => {
if (init) {
init({ api: this.api });
init();
}
});
}

View File

@ -24,8 +24,8 @@ export interface SubAPI {
setShortcut(action: Action, value: KeyCollection): Promise<KeyCollection>;
restoreAllDefaultShortcuts(): Promise<Shortcuts>;
restoreDefaultShortcut(action: Action): Promise<KeyCollection>;
handleKeydownEvent(api: API, event: Event): void;
handleShortcutFeature(api: API, feature: Action): void;
handleKeydownEvent(event: Event): void;
handleShortcutFeature(feature: Action): void;
}
export type KeyCollection = string[];
@ -83,7 +83,14 @@ export interface Event extends KeyboardEvent {
};
}
export default function initShortcuts({ store }: Module) {
function focusInInput(event: Event) {
return (
/input|textarea/i.test(event.target.tagName) ||
event.target.getAttribute('contenteditable') !== null
);
}
export default function initShortcuts({ store, fullAPI }: Module) {
const api: SubAPI = {
// Getting and setting shortcuts
getShortcutKeys(): Shortcuts {
@ -107,7 +114,7 @@ export default function initShortcuts({ store }: Module) {
},
// Listening to shortcut events
handleKeydownEvent(fullApi, event) {
handleKeydownEvent(event) {
const shortcut = eventToShortcut(event);
const shortcuts = api.getShortcutKeys();
const actions = keys(shortcuts);
@ -115,11 +122,11 @@ export default function initShortcuts({ store }: Module) {
shortcutMatchesShortcut(shortcut, shortcuts[feature])
);
if (matchedFeature) {
api.handleShortcutFeature(fullApi, matchedFeature);
api.handleShortcutFeature(matchedFeature);
}
},
handleShortcutFeature(fullApi, feature) {
handleShortcutFeature(feature) {
const {
layout: { isFullscreen, showNav, showPanel },
ui: { enableShortcuts },
@ -130,34 +137,34 @@ export default function initShortcuts({ store }: Module) {
switch (feature) {
case 'escape': {
if (isFullscreen) {
fullApi.toggleFullscreen();
fullAPI.toggleFullscreen();
} else if (!showNav) {
fullApi.toggleNav();
fullAPI.toggleNav();
}
break;
}
case 'focusNav': {
if (isFullscreen) {
fullApi.toggleFullscreen();
fullAPI.toggleFullscreen();
}
if (!showNav) {
fullApi.toggleNav();
fullAPI.toggleNav();
}
fullApi.focusOnUIElement(focusableUIElements.storyListMenu);
fullAPI.focusOnUIElement(focusableUIElements.storyListMenu);
break;
}
case 'search': {
if (isFullscreen) {
fullApi.toggleFullscreen();
fullAPI.toggleFullscreen();
}
if (!showNav) {
fullApi.toggleNav();
fullAPI.toggleNav();
}
setTimeout(() => {
fullApi.focusOnUIElement(focusableUIElements.storySearchField);
fullAPI.focusOnUIElement(focusableUIElements.storySearchField);
}, 0);
break;
}
@ -178,92 +185,92 @@ export default function initShortcuts({ store }: Module) {
case 'focusPanel': {
if (isFullscreen) {
fullApi.toggleFullscreen();
fullAPI.toggleFullscreen();
}
if (!showPanel) {
fullApi.togglePanel();
fullAPI.togglePanel();
}
fullApi.focusOnUIElement(focusableUIElements.storyPanelRoot);
fullAPI.focusOnUIElement(focusableUIElements.storyPanelRoot);
break;
}
case 'nextStory': {
fullApi.jumpToStory(1);
fullAPI.jumpToStory(1);
break;
}
case 'prevStory': {
fullApi.jumpToStory(-1);
fullAPI.jumpToStory(-1);
break;
}
case 'nextComponent': {
fullApi.jumpToComponent(1);
fullAPI.jumpToComponent(1);
break;
}
case 'prevComponent': {
fullApi.jumpToComponent(-1);
fullAPI.jumpToComponent(-1);
break;
}
case 'fullScreen': {
fullApi.toggleFullscreen();
fullAPI.toggleFullscreen();
break;
}
case 'togglePanel': {
if (isFullscreen) {
fullApi.toggleFullscreen();
fullApi.resetLayout();
fullAPI.toggleFullscreen();
fullAPI.resetLayout();
}
fullApi.togglePanel();
fullAPI.togglePanel();
break;
}
case 'toggleNav': {
if (isFullscreen) {
fullApi.toggleFullscreen();
fullApi.resetLayout();
fullAPI.toggleFullscreen();
fullAPI.resetLayout();
}
fullApi.toggleNav();
fullAPI.toggleNav();
break;
}
case 'toolbar': {
fullApi.toggleToolbar();
fullAPI.toggleToolbar();
break;
}
case 'panelPosition': {
if (isFullscreen) {
fullApi.toggleFullscreen();
fullAPI.toggleFullscreen();
}
if (!showPanel) {
fullApi.togglePanel();
fullAPI.togglePanel();
}
fullApi.togglePanelPosition();
fullAPI.togglePanelPosition();
break;
}
case 'aboutPage': {
fullApi.navigate('/settings/about');
fullAPI.navigate('/settings/about');
break;
}
case 'shortcutsPage': {
fullApi.navigate('/settings/shortcuts');
fullAPI.navigate('/settings/shortcuts');
break;
}
case 'collapseAll': {
fullApi.collapseAll();
fullAPI.collapseAll();
break;
}
case 'expandAll': {
fullApi.expandAll();
fullAPI.expandAll();
break;
}
default:
@ -281,26 +288,19 @@ export default function initShortcuts({ store }: Module) {
),
};
const init = ({ api: fullApi }: API) => {
function focusInInput(event: Event) {
return (
/input|textarea/i.test(event.target.tagName) ||
event.target.getAttribute('contenteditable') !== null
);
}
const init = () => {
// Listen for keydown events in the manager
document.addEventListener('keydown', (event: Event) => {
if (!focusInInput(event)) {
fullApi.handleKeydownEvent(fullApi, event);
fullAPI.handleKeydownEvent(event);
}
});
// Also listen to keydown events sent over the channel
fullApi.on(PREVIEW_KEYDOWN, (data: { event: Event }) => {
fullApi.handleKeydownEvent(fullApi, data.event);
fullAPI.on(PREVIEW_KEYDOWN, (data: { event: Event }) => {
fullAPI.handleKeydownEvent(data.event);
});
};
const result = { api, state, init };
return result;
return { api, state, init };
}

View File

@ -1,6 +1,7 @@
import { DOCS_MODE } from 'global';
import { toId, sanitize } from '@storybook/csf';
import { STORY_CHANGED, SET_STORIES, SELECT_STORY } from '@storybook/core-events';
import {
transformStoriesRawToStoriesHash,
StoriesHash,
@ -40,6 +41,7 @@ export interface SubAPI {
// When adding a group, also add all of its children, depth first
const initStoriesApi = ({
fullAPI,
store,
navigate,
provider,
@ -146,6 +148,31 @@ const initStoriesApi = ({
}
};
const init = () => {
fullAPI.on(STORY_CHANGED, (id: string) => {
const options = fullAPI.getParameters(id, 'options');
if (options) {
fullAPI.setOptions(options);
}
});
fullAPI.on(SET_STORIES, (data: { stories: StoriesRaw }) => {
const { storyId } = store.getState();
fullAPI.setStories(data.stories);
const options = storyId
? fullAPI.getParameters(storyId, 'options')
: fullAPI.getParameters(Object.keys(data.stories)[0], 'options');
fullAPI.setOptions(options);
});
fullAPI.on(
SELECT_STORY,
({ kind, story, ...rest }: { kind: string; story: string; [k: string]: any }) => {
fullAPI.selectStory(kind, story, rest);
}
);
};
// Recursively traverse storiesHash from the initial storyId until finding
// the leaf story.
const findLeafStoryId = (storiesHash: StoriesHash, storyId: string): string => {
@ -253,6 +280,7 @@ const initStoriesApi = ({
viewMode: initialViewMode,
storiesConfigured: false,
},
init,
};
};
export default initStoriesApi;

View File

@ -2,6 +2,7 @@ import { navigate as navigateRouter, NavigateOptions } from '@reach/router';
import { queryFromLocation } from '@storybook/router';
import { toId } from '@storybook/csf';
import { NAVIGATE_URL } from '@storybook/core-events';
import { Module } from '../index';
import { PanelPositions } from './layout';
@ -105,7 +106,7 @@ export interface SubAPI {
setQueryParams: (input: QueryParams) => void;
}
export default function({ store, navigate, state, provider, ...rest }: Module) {
export default function({ store, navigate, state, provider, fullAPI, ...rest }: Module) {
const api: SubAPI = {
getQueryParam: key => {
const { customQueryParams } = store.getState();
@ -146,8 +147,15 @@ export default function({ store, navigate, state, provider, ...rest }: Module) {
},
};
const init = () => {
fullAPI.on(NAVIGATE_URL, (url: string, options: { [k: string]: any }) => {
fullAPI.navigateUrl(url, options);
});
};
return {
api,
state: initialUrlSupport({ store, navigate, state, provider, ...rest }),
state: initialUrlSupport({ store, navigate, state, provider, fullAPI, ...rest }),
init,
};
}

View File

@ -46,7 +46,7 @@ export interface SubAPI {
versionUpdateAvailable: () => boolean;
}
export default function({ store, mode }: Module) {
export default function({ store, mode, fullAPI }: Module) {
const { dismissedVersionNotification } = store.getState();
const state = {
@ -106,10 +106,11 @@ export default function({ store, mode }: Module) {
};
// Grab versions from the server/local storage right away
async function init({ api: fullApi }: API) {
async function init() {
const { versions = {} } = store.getState();
const { latest, next } = getVersionCheckData();
await store.setState({
versions: { ...versions, latest, next },
});
@ -125,7 +126,7 @@ export default function({ store, mode }: Module) {
!semver.prerelease(latestVersion) &&
mode !== 'production'
) {
fullApi.addNotification({
fullAPI.addNotification({
id: 'update',
link: '/settings/about',
content: `🎉 Storybook ${latestVersion} is available!`,