Skip to content

Commit

Permalink
Merge pull request #5459 from gaetanmaisse/ts-migration/addon-actions
Browse files Browse the repository at this point in the history
Migrate addon actions to TS
  • Loading branch information
ndelangen committed Feb 9, 2019
2 parents 2b2144a + 48169db commit 0b55a32
Show file tree
Hide file tree
Showing 26 changed files with 175 additions and 138 deletions.
7 changes: 5 additions & 2 deletions addons/actions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
},
"license": "MIT",
"main": "dist/index.js",
"jsnext:main": "src/index.js",
"types": "dist/index.d.ts",
"scripts": {
"prepare": "node ../../scripts/prepare.js"
},
Expand All @@ -29,12 +29,15 @@
"global": "^4.3.2",
"lodash": "^4.17.11",
"make-error": "^1.3.5",
"prop-types": "^15.6.2",
"react": "^16.8.1",
"react-inspector": "^2.3.0",
"uuid": "^3.3.2"
},
"publishConfig": {
"access": "public"
},
"devDependencies": {
"@types/lodash": "^4.14.120",
"@types/uuid": "^3.4.4"
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
import PropTypes from 'prop-types';
import React from 'react';
import Inspector from 'react-inspector';

import { withTheme } from '@storybook/theming';
import { ActionBar } from '@storybook/components';

import { Actions, Action, Wrapper, InspectorContainer, Counter } from './style';
import { ActionDisplay } from '../../models';

const ActionLogger = withTheme(({ actions, onClear, theme }) => (
interface ActionLoggerProps {
actions: ActionDisplay[];
onClear: () => void;
theme: any;
}

export const ActionLogger = withTheme(({ actions, onClear, theme }: ActionLoggerProps) => (
<Wrapper>
<Actions>
{actions.map(action => (
{actions.map((action: ActionDisplay) => (
<Action key={action.id}>
{action.count > 1 && <Counter>{action.count}</Counter>}
<InspectorContainer>
Expand All @@ -29,18 +35,3 @@ const ActionLogger = withTheme(({ actions, onClear, theme }) => (
<ActionBar actionItems={[{ title: 'Clear', onClick: onClear }]} />
</Wrapper>
));

ActionLogger.propTypes = {
onClear: PropTypes.func.isRequired,
actions: PropTypes.arrayOf(
PropTypes.shape({
count: PropTypes.node,
data: PropTypes.shape({
name: PropTypes.node.isRequired,
args: PropTypes.any,
}),
})
).isRequired,
};

export default ActionLogger;
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,14 +1,32 @@
import React from 'react';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import deepEqual from 'fast-deep-equal';

import { STORY_RENDERED } from '@storybook/core-events';

import ActionLoggerComponent from '../../components/ActionLogger';
import { ActionLogger as ActionLoggerComponent } from '../../components/ActionLogger';
import { EVENT_ID } from '../..';
import { ActionDisplay } from '../../models';

export default class ActionLogger extends React.Component {
state = { actions: [] };
interface ActionLoggerProps {
active: boolean;
api: {
on(event: string, callback: (data: any) => void): void;
off(event: string, callback: (data: any) => void): void;
};
}

interface ActionLoggerState {
actions: ActionDisplay[];
}

export default class ActionLogger extends Component<ActionLoggerProps, ActionLoggerState> {
private mounted: boolean;

constructor(props: ActionLoggerProps) {
super(props);

this.state = { actions: [] };
}

componentDidMount() {
this.mounted = true;
Expand All @@ -33,13 +51,13 @@ export default class ActionLogger extends React.Component {
}
};

addAction = action => {
addAction = (action: ActionDisplay) => {
let { actions = [] } = this.state;
actions = [...actions];

const previous = actions.length && actions[0];

if (previous && deepEqual(previous.data, action.data, { strict: true })) {
if (previous && deepEqual(previous.data, action.data)) {
previous.count++; // eslint-disable-line
} else {
action.count = 1; // eslint-disable-line
Expand All @@ -62,17 +80,3 @@ export default class ActionLogger extends React.Component {
return active ? <ActionLoggerComponent {...props} /> : null;
}
}

ActionLogger.propTypes = {
active: PropTypes.bool.isRequired,
channel: PropTypes.shape({
emit: PropTypes.func,
on: PropTypes.func,
removeListener: PropTypes.func,
}).isRequired,
api: PropTypes.shape({
on: PropTypes.func,
getQueryParam: PropTypes.func,
setQueryParams: PropTypes.func,
}).isRequired,
};
27 changes: 0 additions & 27 deletions addons/actions/src/index.js

This file was deleted.

6 changes: 6 additions & 0 deletions addons/actions/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export * from './constants';
export * from './preview';

if (module && module.hot && module.hot.decline) {
module.hot.decline();
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,9 @@ import { ADDON_ID, PANEL_ID } from '.';

export function register() {
addons.register(ADDON_ID, api => {
const channel = addons.getChannel();
addons.addPanel(PANEL_ID, {
title: 'Actions',
// eslint-disable-next-line react/prop-types
render: ({ active, key }) => (
<ActionLogger key={key} channel={channel} api={api} active={active} />
),
render: ({ active }) => <ActionLogger api={api} active={active} />,
});
});
}
11 changes: 11 additions & 0 deletions addons/actions/src/models/ActionDisplay.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { ActionOptions } from './ActionOptions';

export interface ActionDisplay {
id: string;
data: {
name: string;
args: any[];
};
count: number;
options: ActionOptions;
}
5 changes: 5 additions & 0 deletions addons/actions/src/models/ActionOptions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface ActionOptions {
depth?: number;
clearOnStoryChange?: boolean;
limit?: number;
}
5 changes: 5 additions & 0 deletions addons/actions/src/models/ActionsMap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { HandlerFunction } from './HandlerFunction';

export interface ActionsMap {
[key: string]: HandlerFunction;
}
1 change: 1 addition & 0 deletions addons/actions/src/models/DecoratorFunction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type DecoratorFunction = (args: any[]) => any[];
1 change: 1 addition & 0 deletions addons/actions/src/models/HandlerFunction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type HandlerFunction = (...args: any[]) => void;
5 changes: 5 additions & 0 deletions addons/actions/src/models/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export * from './ActionDisplay';
export * from './ActionOptions';
export * from './ActionsMap';
export * from './DecoratorFunction';
export * from './HandlerFunction';
22 changes: 0 additions & 22 deletions addons/actions/src/preview/action.js

This file was deleted.

25 changes: 25 additions & 0 deletions addons/actions/src/preview/action.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import uuid from 'uuid/v1';
import { addons } from '@storybook/addons';
import { EVENT_ID } from '../constants';
import { ActionDisplay, ActionOptions, HandlerFunction } from '../models';

export function action(name: string, options: ActionOptions = {}): HandlerFunction {
const actionOptions = {
...options,
};

// tslint:disable-next-line:no-shadowed-variable
const handler = function action(...args: any[]) {
const channel = addons.getChannel();
const id = uuid();
const actionDisplayToEmit: ActionDisplay = {
id,
count: 0,
data: { name, args },
options: actionOptions,
};
channel.emit(EVENT_ID, actionDisplayToEmit);
};

return handler;
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import action from './action';
import { action } from './action';
import { ActionOptions, ActionsMap } from '../models';

export default function actions(...args) {
let options = {};
export function actions(...args: any[]): ActionsMap {
let options: ActionOptions = {};
const names = args;
// last argument can be options
if (names.length !== 1 && typeof args[args.length - 1] !== 'string') {
Expand All @@ -16,7 +17,7 @@ export default function actions(...args) {
});
}

const actionsObject = {};
const actionsObject: ActionsMap = {};
Object.keys(namesObject).forEach(name => {
actionsObject[name] = action(namesObject[name], options);
});
Expand Down
9 changes: 0 additions & 9 deletions addons/actions/src/preview/configureActions.js

This file was deleted.

11 changes: 11 additions & 0 deletions addons/actions/src/preview/configureActions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { ActionOptions } from '../models';

export const config: ActionOptions = {
depth: 10,
clearOnStoryChange: true,
limit: 50,
};

export const configureActions = (options: ActionOptions = {}): void => {
Object.assign(config, options);
};
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
import action from './action';
import actions from './actions';
import { action } from './action';
import { actions } from './actions';
import { createDecorator } from './withActions';
import { ActionOptions, DecoratorFunction, HandlerFunction } from '../models';

function applyDecorators(decorators, actionCallback) {
return (..._args) => {
const applyDecorators = (decorators: DecoratorFunction[], actionCallback: HandlerFunction) => {
return (..._args: any[]) => {
const decorated = decorators.reduce((args, fn) => fn(args), _args);
actionCallback(...decorated);
};
}
};

export function decorateAction(decorators) {
return (name, options) => {
export const decorateAction = (decorators: DecoratorFunction[]): ((name: string, options?: ActionOptions) => HandlerFunction) => {
return (name: string, options?: ActionOptions) => {
const callAction = action(name, options);
return applyDecorators(decorators, callAction);
};
}
};

export function decorate(decorators) {
export const decorate = (decorators: DecoratorFunction[]) => {
const decorated = decorateAction(decorators);
const decoratedActions = (...args) => {
const decoratedActions = (...args: any[]) => {
const rawActions = actions(...args);
const actionsObject = {};
const actionsObject = {} as any;
Object.keys(rawActions).forEach(name => {
actionsObject[name] = applyDecorators(decorators, rawActions[name]);
});
Expand All @@ -31,4 +32,4 @@ export function decorate(decorators) {
actions: decoratedActions,
withActions: createDecorator(decoratedActions),
};
}
};
5 changes: 0 additions & 5 deletions addons/actions/src/preview/index.js

This file was deleted.

5 changes: 5 additions & 0 deletions addons/actions/src/preview/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export * from './action';
export * from './actions';
export * from './configureActions';
export * from './decorateAction';
export * from './withActions';

0 comments on commit 0b55a32

Please sign in to comment.