From 320c6226a5aa5886d1dd777fdded4c6215a77455 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Maisse?= Date: Sat, 2 Feb 2019 14:47:58 +0100 Subject: [PATCH 1/5] Add tsconfig in addons/actions --- addons/actions/tsconfig.json | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 addons/actions/tsconfig.json diff --git a/addons/actions/tsconfig.json b/addons/actions/tsconfig.json new file mode 100644 index 000000000000..8876bb6737a1 --- /dev/null +++ b/addons/actions/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "rootDir": "./src", + "types": ["webpack-env"] + }, + "include": [ + "src/**/*" + ], + "exclude": [ + "src/__tests__/**/*" + ] +} From 66c26ff91cdbe39004c7616c576934afb8294bc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Maisse?= Date: Sat, 2 Feb 2019 15:44:40 +0100 Subject: [PATCH 2/5] Migrate src of addons/actions to Typescript --- addons/actions/package.json | 6 +++- .../ActionLogger/{index.js => index.tsx} | 4 +-- .../ActionLogger/{style.js => style.ts} | 0 .../src/{constants.js => constants.ts} | 0 .../ActionLogger/{index.js => index.tsx} | 30 +++++++++++++++---- addons/actions/src/index.js | 27 ----------------- addons/actions/src/index.ts | 10 +++++++ .../actions/src/{manager.js => manager.tsx} | 5 +--- .../src/preview/{action.js => action.ts} | 6 ++-- .../src/preview/{actions.js => actions.ts} | 4 +-- ...onfigureActions.js => configureActions.ts} | 0 .../{decorateAction.js => decorateAction.ts} | 14 ++++----- .../src/preview/{index.js => index.ts} | 2 +- .../{withActions.js => withActions.ts} | 20 ++++++------- addons/actions/src/typings.d.ts | 4 +++ yarn.lock | 12 ++++++++ 16 files changed, 81 insertions(+), 63 deletions(-) rename addons/actions/src/components/ActionLogger/{index.js => index.tsx} (91%) rename addons/actions/src/components/ActionLogger/{style.js => style.ts} (100%) rename addons/actions/src/{constants.js => constants.ts} (100%) rename addons/actions/src/containers/ActionLogger/{index.js => index.tsx} (71%) delete mode 100644 addons/actions/src/index.js create mode 100644 addons/actions/src/index.ts rename addons/actions/src/{manager.js => manager.tsx} (67%) rename addons/actions/src/preview/{action.js => action.ts} (68%) rename addons/actions/src/preview/{actions.js => actions.ts} (86%) rename addons/actions/src/preview/{configureActions.js => configureActions.ts} (100%) rename addons/actions/src/preview/{decorateAction.js => decorateAction.ts} (67%) rename addons/actions/src/preview/{index.js => index.ts} (78%) rename addons/actions/src/preview/{withActions.js => withActions.ts} (71%) create mode 100644 addons/actions/src/typings.d.ts diff --git a/addons/actions/package.json b/addons/actions/package.json index c0ae38789c33..af49fd89561d 100644 --- a/addons/actions/package.json +++ b/addons/actions/package.json @@ -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" }, @@ -36,5 +36,9 @@ }, "publishConfig": { "access": "public" + }, + "devDependencies": { + "@types/lodash": "^4.14.120", + "@types/uuid": "^3.4.4" } } diff --git a/addons/actions/src/components/ActionLogger/index.js b/addons/actions/src/components/ActionLogger/index.tsx similarity index 91% rename from addons/actions/src/components/ActionLogger/index.js rename to addons/actions/src/components/ActionLogger/index.tsx index 9c0216c1ff4b..49d5486151e9 100644 --- a/addons/actions/src/components/ActionLogger/index.js +++ b/addons/actions/src/components/ActionLogger/index.tsx @@ -7,10 +7,10 @@ import { ActionBar } from '@storybook/components'; import { Actions, Action, Wrapper, InspectorContainer, Counter } from './style'; -const ActionLogger = withTheme(({ actions, onClear, theme }) => ( +export const ActionLogger = withTheme(({ actions, onClear, theme }: any) => ( - {actions.map(action => ( + {actions.map((action: any) => ( {action.count > 1 && {action.count}} diff --git a/addons/actions/src/components/ActionLogger/style.js b/addons/actions/src/components/ActionLogger/style.ts similarity index 100% rename from addons/actions/src/components/ActionLogger/style.js rename to addons/actions/src/components/ActionLogger/style.ts diff --git a/addons/actions/src/constants.js b/addons/actions/src/constants.ts similarity index 100% rename from addons/actions/src/constants.js rename to addons/actions/src/constants.ts diff --git a/addons/actions/src/containers/ActionLogger/index.js b/addons/actions/src/containers/ActionLogger/index.tsx similarity index 71% rename from addons/actions/src/containers/ActionLogger/index.js rename to addons/actions/src/containers/ActionLogger/index.tsx index de2379cb0ef4..cd9a671c1c2c 100644 --- a/addons/actions/src/containers/ActionLogger/index.js +++ b/addons/actions/src/containers/ActionLogger/index.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { Component } from 'react'; import PropTypes from 'prop-types'; import deepEqual from 'fast-deep-equal'; @@ -7,8 +7,26 @@ import { STORY_RENDERED } from '@storybook/core-events'; import ActionLoggerComponent from '../../components/ActionLogger'; import { EVENT_ID } from '../..'; -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: any[]; +} + +export default class ActionLogger extends Component { + private mounted: boolean; + + constructor(props: ActionLoggerProps) { + super(props); + + this.state = { actions: [] }; + } componentDidMount() { this.mounted = true; @@ -33,13 +51,13 @@ export default class ActionLogger extends React.Component { } }; - addAction = action => { + addAction = (action: { data: any; count: number; options: { limit: number; }; }) => { 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 @@ -63,7 +81,7 @@ export default class ActionLogger extends React.Component { } } -ActionLogger.propTypes = { +(ActionLogger as any).propTypes = { active: PropTypes.bool.isRequired, channel: PropTypes.shape({ emit: PropTypes.func, diff --git a/addons/actions/src/index.js b/addons/actions/src/index.js deleted file mode 100644 index c2af18bada5b..000000000000 --- a/addons/actions/src/index.js +++ /dev/null @@ -1,27 +0,0 @@ -import { - action, - actions, - decorate, - configureActions, - decorateAction, - withActions, -} from './preview'; - -// addons, panels and events get unique names using a prefix -import { ADDON_ID, PANEL_ID, EVENT_ID } from './constants'; - -export { - action, - actions, - decorate, - configureActions, - decorateAction, - withActions, - ADDON_ID, - PANEL_ID, - EVENT_ID, -}; - -if (module && module.hot && module.hot.decline) { - module.hot.decline(); -} diff --git a/addons/actions/src/index.ts b/addons/actions/src/index.ts new file mode 100644 index 000000000000..867028e07b35 --- /dev/null +++ b/addons/actions/src/index.ts @@ -0,0 +1,10 @@ +import { action, actions, decorate, configureActions, decorateAction, withActions } from './preview'; + +// addons, panels and events get unique names using a prefix +import { ADDON_ID, PANEL_ID, EVENT_ID } from './constants'; + +export { action, actions, decorate, configureActions, decorateAction, withActions, ADDON_ID, PANEL_ID, EVENT_ID }; + +if (module && module.hot && module.hot.decline) { + module.hot.decline(); +} diff --git a/addons/actions/src/manager.js b/addons/actions/src/manager.tsx similarity index 67% rename from addons/actions/src/manager.js rename to addons/actions/src/manager.tsx index 91bf1afc872b..4805b5435ca6 100644 --- a/addons/actions/src/manager.js +++ b/addons/actions/src/manager.tsx @@ -5,13 +5,10 @@ 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 }) => ( - - ), + render: ({ active }) => , }); }); } diff --git a/addons/actions/src/preview/action.js b/addons/actions/src/preview/action.ts similarity index 68% rename from addons/actions/src/preview/action.js rename to addons/actions/src/preview/action.ts index 6c1a60ef4634..b3c2ecfc1253 100644 --- a/addons/actions/src/preview/action.js +++ b/addons/actions/src/preview/action.ts @@ -2,13 +2,13 @@ import uuid from 'uuid/v1'; import addons from '@storybook/addons'; import { EVENT_ID } from '../constants'; -export default function action(name, options = {}) { +export default function action(name: any, options = {}) { const actionOptions = { ...options, }; - // eslint-disable-next-line no-shadow - const handler = function action(...args) { + // tslint:disable-next-line:no-shadowed-variable + const handler = function action(...args: any[]) { const channel = addons.getChannel(); const id = uuid(); channel.emit(EVENT_ID, { diff --git a/addons/actions/src/preview/actions.js b/addons/actions/src/preview/actions.ts similarity index 86% rename from addons/actions/src/preview/actions.js rename to addons/actions/src/preview/actions.ts index 4aad698453b5..f6894feb3cac 100644 --- a/addons/actions/src/preview/actions.js +++ b/addons/actions/src/preview/actions.ts @@ -1,6 +1,6 @@ import action from './action'; -export default function actions(...args) { +export default function actions(...args: any[]) { let options = {}; const names = args; // last argument can be options @@ -16,7 +16,7 @@ export default function actions(...args) { }); } - const actionsObject = {}; + const actionsObject = {} as any; Object.keys(namesObject).forEach(name => { actionsObject[name] = action(namesObject[name], options); }); diff --git a/addons/actions/src/preview/configureActions.js b/addons/actions/src/preview/configureActions.ts similarity index 100% rename from addons/actions/src/preview/configureActions.js rename to addons/actions/src/preview/configureActions.ts diff --git a/addons/actions/src/preview/decorateAction.js b/addons/actions/src/preview/decorateAction.ts similarity index 67% rename from addons/actions/src/preview/decorateAction.js rename to addons/actions/src/preview/decorateAction.ts index d61f3744874d..4672034ecf3c 100644 --- a/addons/actions/src/preview/decorateAction.js +++ b/addons/actions/src/preview/decorateAction.ts @@ -2,25 +2,25 @@ import action from './action'; import actions from './actions'; import { createDecorator } from './withActions'; -function applyDecorators(decorators, actionCallback) { - return (..._args) => { +function applyDecorators(decorators: any[], actionCallback: (...args: any) => void) { + return (..._args: any[]) => { const decorated = decorators.reduce((args, fn) => fn(args), _args); actionCallback(...decorated); }; } -export function decorateAction(decorators) { - return (name, options) => { +export function decorateAction(decorators: any[]) { + return (name: any, options: any) => { const callAction = action(name, options); return applyDecorators(decorators, callAction); }; } -export function decorate(decorators) { +export function decorate(decorators: any[]) { 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]); }); diff --git a/addons/actions/src/preview/index.js b/addons/actions/src/preview/index.ts similarity index 78% rename from addons/actions/src/preview/index.js rename to addons/actions/src/preview/index.ts index 3ac38c32c124..191d425e892e 100644 --- a/addons/actions/src/preview/index.js +++ b/addons/actions/src/preview/index.ts @@ -2,4 +2,4 @@ export { default as action } from './action'; export { default as actions } from './actions'; export { configureActions } from './configureActions'; export { decorateAction, decorate } from './decorateAction'; -export { default as withActions } from './withActions'; +export { withActions } from './withActions'; diff --git a/addons/actions/src/preview/withActions.js b/addons/actions/src/preview/withActions.ts similarity index 71% rename from addons/actions/src/preview/withActions.js rename to addons/actions/src/preview/withActions.ts index 106659b936b0..5aba2479b92e 100644 --- a/addons/actions/src/preview/withActions.js +++ b/addons/actions/src/preview/withActions.ts @@ -6,8 +6,8 @@ import Events from '@storybook/core-events'; import actions from './actions'; -let lastSubscription; -let lastArgs; +let lastSubscription: () => () => void; +let lastArgs: any[]; const delegateEventSplitter = /^(\S+)\s*(.*)$/; @@ -16,7 +16,7 @@ const matchesMethod = isIE ? 'msMatchesSelector' : 'matches'; const root = document && document.getElementById('root'); -const hasMatchInAncestry = (element, selector) => { +const hasMatchInAncestry = (element: any, selector: any): boolean => { if (element[matchesMethod](selector)) { return true; } @@ -27,14 +27,14 @@ const hasMatchInAncestry = (element, selector) => { return hasMatchInAncestry(parent, selector); }; -const createHandlers = (actionsFn, ...args) => { +const createHandlers = (actionsFn: (...arg: any[]) => object, ...args: any[]) => { const actionsObject = actionsFn(...args); return Object.entries(actionsObject).map(([key, action]) => { // eslint-disable-next-line no-unused-vars const [_, eventName, selector] = key.match(delegateEventSplitter); return { eventName, - handler: e => { + handler: (e: { target: any }) => { if (!selector || hasMatchInAncestry(e.target, selector)) { action(e); } @@ -43,24 +43,24 @@ const createHandlers = (actionsFn, ...args) => { }); }; -const actionsSubscription = (...args) => { +const actionsSubscription = (...args: any[]) => { if (!isEqual(args, lastArgs)) { lastArgs = args; + // @ts-ignore const handlers = createHandlers(...args); lastSubscription = () => { handlers.forEach(({ eventName, handler }) => root.addEventListener(eventName, handler)); - return () => - handlers.forEach(({ eventName, handler }) => root.removeEventListener(eventName, handler)); + return () => handlers.forEach(({ eventName, handler }) => root.removeEventListener(eventName, handler)); }; } return lastSubscription; }; -export const createDecorator = actionsFn => (...args) => story => { +export const createDecorator = (actionsFn: any) => (...args: any[]) => (story: () => any) => { if (root != null) { addons.getChannel().emit(Events.REGISTER_SUBSCRIPTION, actionsSubscription(actionsFn, ...args)); } return story(); }; -export default createDecorator(actions); +export const withActions = createDecorator(actions); diff --git a/addons/actions/src/typings.d.ts b/addons/actions/src/typings.d.ts new file mode 100644 index 000000000000..71fa74c16e2a --- /dev/null +++ b/addons/actions/src/typings.d.ts @@ -0,0 +1,4 @@ +// TODO: following packages need definition files or a TS migration +declare module '@storybook/components'; +declare module 'global'; +declare module 'react-inspector'; diff --git a/yarn.lock b/yarn.lock index 675b6de2bca5..aefe6d0c538a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2107,6 +2107,11 @@ version "0.0.29" resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" +"@types/lodash@^4.14.120": + version "4.14.120" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.120.tgz#cf265d06f6c7a710db087ed07523ab8c1a24047b" + integrity sha512-jQ21kQ120mo+IrDs1nFNVm/AsdFxIx2+vZ347DbogHJPd/JzKNMOqU6HCYin1W6v8l5R9XSO2/e9cxmn7HAnVw== + "@types/node@*", "@types/node@^10.11.7", "@types/node@^10.12.19", "@types/node@~10.12.19": version "10.12.19" resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.19.tgz#ca1018c26be01f07e66ac7fefbeb6407e4490c61" @@ -2191,6 +2196,13 @@ version "1.0.0" resolved "https://registry.yarnpkg.com/@types/util-deprecate/-/util-deprecate-1.0.0.tgz#341d0815fe5a661b94e3ea738d182b4c359e3958" +"@types/uuid@^3.4.4": + version "3.4.4" + resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-3.4.4.tgz#7af69360fa65ef0decb41fd150bf4ca5c0cefdf5" + integrity sha512-tPIgT0GUmdJQNSHxp0X2jnpQfBSTfGxUMc/2CXBU2mnyTFVYVa2ojpoQ74w0U2yn2vw3jnC640+77lkFFpdVDw== + dependencies: + "@types/node" "*" + "@types/vfile-message@*": version "1.0.1" resolved "https://registry.yarnpkg.com/@types/vfile-message/-/vfile-message-1.0.1.tgz#e1e9895cc6b36c462d4244e64e6d0b6eaf65355a" From 8ef5b1e51547446a572028c897591ab7397d1223 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Maisse?= Date: Sat, 2 Feb 2019 15:53:55 +0100 Subject: [PATCH 3/5] Refactor import/export to use named export instead of `default` export --- .../src/components/ActionLogger/index.tsx | 2 -- .../src/containers/ActionLogger/index.tsx | 4 ++-- addons/actions/src/index.ts | 8 ++------ addons/actions/src/preview/action.ts | 4 ++-- addons/actions/src/preview/actions.ts | 4 ++-- addons/actions/src/preview/configureActions.ts | 4 ++-- addons/actions/src/preview/decorateAction.ts | 16 ++++++++-------- addons/actions/src/preview/index.ts | 10 +++++----- addons/actions/src/preview/withActions.ts | 6 +++--- 9 files changed, 26 insertions(+), 32 deletions(-) diff --git a/addons/actions/src/components/ActionLogger/index.tsx b/addons/actions/src/components/ActionLogger/index.tsx index 49d5486151e9..df861ab4e570 100644 --- a/addons/actions/src/components/ActionLogger/index.tsx +++ b/addons/actions/src/components/ActionLogger/index.tsx @@ -42,5 +42,3 @@ ActionLogger.propTypes = { }) ).isRequired, }; - -export default ActionLogger; diff --git a/addons/actions/src/containers/ActionLogger/index.tsx b/addons/actions/src/containers/ActionLogger/index.tsx index cd9a671c1c2c..80f7720b8117 100644 --- a/addons/actions/src/containers/ActionLogger/index.tsx +++ b/addons/actions/src/containers/ActionLogger/index.tsx @@ -4,7 +4,7 @@ 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 '../..'; interface ActionLoggerProps { @@ -51,7 +51,7 @@ export default class ActionLogger extends Component { + addAction = (action: { data: any; count: number; options: { limit: number } }) => { let { actions = [] } = this.state; actions = [...actions]; diff --git a/addons/actions/src/index.ts b/addons/actions/src/index.ts index 867028e07b35..8a6ce711f9b8 100644 --- a/addons/actions/src/index.ts +++ b/addons/actions/src/index.ts @@ -1,9 +1,5 @@ -import { action, actions, decorate, configureActions, decorateAction, withActions } from './preview'; - -// addons, panels and events get unique names using a prefix -import { ADDON_ID, PANEL_ID, EVENT_ID } from './constants'; - -export { action, actions, decorate, configureActions, decorateAction, withActions, ADDON_ID, PANEL_ID, EVENT_ID }; +export * from './constants'; +export * from './preview'; if (module && module.hot && module.hot.decline) { module.hot.decline(); diff --git a/addons/actions/src/preview/action.ts b/addons/actions/src/preview/action.ts index b3c2ecfc1253..da2090cf2646 100644 --- a/addons/actions/src/preview/action.ts +++ b/addons/actions/src/preview/action.ts @@ -1,8 +1,8 @@ import uuid from 'uuid/v1'; -import addons from '@storybook/addons'; +import { addons } from '@storybook/addons'; import { EVENT_ID } from '../constants'; -export default function action(name: any, options = {}) { +export function action(name: any, options = {}) { const actionOptions = { ...options, }; diff --git a/addons/actions/src/preview/actions.ts b/addons/actions/src/preview/actions.ts index f6894feb3cac..d51882c252ca 100644 --- a/addons/actions/src/preview/actions.ts +++ b/addons/actions/src/preview/actions.ts @@ -1,6 +1,6 @@ -import action from './action'; +import { action } from './action'; -export default function actions(...args: any[]) { +export function actions(...args: any[]) { let options = {}; const names = args; // last argument can be options diff --git a/addons/actions/src/preview/configureActions.ts b/addons/actions/src/preview/configureActions.ts index 2e5d0ddcf866..8c617c160fdc 100644 --- a/addons/actions/src/preview/configureActions.ts +++ b/addons/actions/src/preview/configureActions.ts @@ -4,6 +4,6 @@ export const config = { limit: 50, }; -export function configureActions(options = {}) { +export const configureActions = (options = {}) => { Object.assign(config, options); -} +}; diff --git a/addons/actions/src/preview/decorateAction.ts b/addons/actions/src/preview/decorateAction.ts index 4672034ecf3c..48c391878801 100644 --- a/addons/actions/src/preview/decorateAction.ts +++ b/addons/actions/src/preview/decorateAction.ts @@ -1,22 +1,22 @@ -import action from './action'; -import actions from './actions'; +import { action } from './action'; +import { actions } from './actions'; import { createDecorator } from './withActions'; -function applyDecorators(decorators: any[], actionCallback: (...args: any) => void) { +const applyDecorators = (decorators: any[], actionCallback: (...args: any) => void) => { return (..._args: any[]) => { const decorated = decorators.reduce((args, fn) => fn(args), _args); actionCallback(...decorated); }; -} +}; -export function decorateAction(decorators: any[]) { +export const decorateAction = (decorators: any[]) => { return (name: any, options: any) => { const callAction = action(name, options); return applyDecorators(decorators, callAction); }; -} +}; -export function decorate(decorators: any[]) { +export const decorate = (decorators: any[]) => { const decorated = decorateAction(decorators); const decoratedActions = (...args: any[]) => { const rawActions = actions(...args); @@ -31,4 +31,4 @@ export function decorate(decorators: any[]) { actions: decoratedActions, withActions: createDecorator(decoratedActions), }; -} +}; diff --git a/addons/actions/src/preview/index.ts b/addons/actions/src/preview/index.ts index 191d425e892e..b5358d2c4441 100644 --- a/addons/actions/src/preview/index.ts +++ b/addons/actions/src/preview/index.ts @@ -1,5 +1,5 @@ -export { default as action } from './action'; -export { default as actions } from './actions'; -export { configureActions } from './configureActions'; -export { decorateAction, decorate } from './decorateAction'; -export { withActions } from './withActions'; +export * from './action'; +export * from './actions'; +export * from './configureActions'; +export * from './decorateAction'; +export * from './withActions'; diff --git a/addons/actions/src/preview/withActions.ts b/addons/actions/src/preview/withActions.ts index 5aba2479b92e..efd121936694 100644 --- a/addons/actions/src/preview/withActions.ts +++ b/addons/actions/src/preview/withActions.ts @@ -1,10 +1,10 @@ // Based on http://backbonejs.org/docs/backbone.html#section-164 import { document, Element } from 'global'; -import isEqual from 'lodash/isEqual'; -import addons from '@storybook/addons'; +import { isEqual } from 'lodash'; +import { addons } from '@storybook/addons'; import Events from '@storybook/core-events'; -import actions from './actions'; +import { actions } from './actions'; let lastSubscription: () => () => void; let lastArgs: any[]; From c3e56a98cb093e5a5d68b46a91c1e5e4d6a39727 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Maisse?= Date: Sat, 2 Feb 2019 16:57:55 +0100 Subject: [PATCH 4/5] Add some interfaces and types to really use TS capabilities --- addons/actions/src/components/ActionLogger/index.tsx | 3 ++- addons/actions/src/containers/ActionLogger/index.tsx | 10 +++------- addons/actions/src/manager.tsx | 1 - addons/actions/src/models/ActionDisplay.ts | 11 +++++++++++ addons/actions/src/models/ActionOptions.ts | 5 +++++ addons/actions/src/models/ActionsMap.ts | 5 +++++ addons/actions/src/models/DecoratorFunction.ts | 1 + addons/actions/src/models/HandlerFunction.ts | 1 + addons/actions/src/models/index.ts | 5 +++++ addons/actions/src/preview/action.ts | 9 ++++++--- addons/actions/src/preview/actions.ts | 7 ++++--- addons/actions/src/preview/configureActions.ts | 6 ++++-- addons/actions/src/preview/decorateAction.ts | 9 +++++---- 13 files changed, 52 insertions(+), 21 deletions(-) create mode 100644 addons/actions/src/models/ActionDisplay.ts create mode 100644 addons/actions/src/models/ActionOptions.ts create mode 100644 addons/actions/src/models/ActionsMap.ts create mode 100644 addons/actions/src/models/DecoratorFunction.ts create mode 100644 addons/actions/src/models/HandlerFunction.ts create mode 100644 addons/actions/src/models/index.ts diff --git a/addons/actions/src/components/ActionLogger/index.tsx b/addons/actions/src/components/ActionLogger/index.tsx index df861ab4e570..094e21cae953 100644 --- a/addons/actions/src/components/ActionLogger/index.tsx +++ b/addons/actions/src/components/ActionLogger/index.tsx @@ -6,11 +6,12 @@ import { withTheme } from '@storybook/theming'; import { ActionBar } from '@storybook/components'; import { Actions, Action, Wrapper, InspectorContainer, Counter } from './style'; +import { ActionDisplay } from '../../models'; export const ActionLogger = withTheme(({ actions, onClear, theme }: any) => ( - {actions.map((action: any) => ( + {actions.map((action: ActionDisplay) => ( {action.count > 1 && {action.count}} diff --git a/addons/actions/src/containers/ActionLogger/index.tsx b/addons/actions/src/containers/ActionLogger/index.tsx index 80f7720b8117..0f949e9bb0e1 100644 --- a/addons/actions/src/containers/ActionLogger/index.tsx +++ b/addons/actions/src/containers/ActionLogger/index.tsx @@ -6,6 +6,7 @@ import { STORY_RENDERED } from '@storybook/core-events'; import { ActionLogger as ActionLoggerComponent } from '../../components/ActionLogger'; import { EVENT_ID } from '../..'; +import { ActionDisplay } from '../../models'; interface ActionLoggerProps { active: boolean; @@ -16,7 +17,7 @@ interface ActionLoggerProps { } interface ActionLoggerState { - actions: any[]; + actions: ActionDisplay[]; } export default class ActionLogger extends Component { @@ -51,7 +52,7 @@ export default class ActionLogger extends Component { + addAction = (action: ActionDisplay) => { let { actions = [] } = this.state; actions = [...actions]; @@ -83,11 +84,6 @@ export default class ActionLogger extends Component { addons.addPanel(PANEL_ID, { title: 'Actions', - // eslint-disable-next-line react/prop-types render: ({ active }) => , }); }); diff --git a/addons/actions/src/models/ActionDisplay.ts b/addons/actions/src/models/ActionDisplay.ts new file mode 100644 index 000000000000..c3039db325fe --- /dev/null +++ b/addons/actions/src/models/ActionDisplay.ts @@ -0,0 +1,11 @@ +import { ActionOptions } from './ActionOptions'; + +export interface ActionDisplay { + id: string; + data: { + name: string; + args: any[]; + }; + count: number; + options: ActionOptions; +} diff --git a/addons/actions/src/models/ActionOptions.ts b/addons/actions/src/models/ActionOptions.ts new file mode 100644 index 000000000000..548c9c5075bb --- /dev/null +++ b/addons/actions/src/models/ActionOptions.ts @@ -0,0 +1,5 @@ +export interface ActionOptions { + depth?: number; + clearOnStoryChange?: boolean; + limit?: number; +} diff --git a/addons/actions/src/models/ActionsMap.ts b/addons/actions/src/models/ActionsMap.ts new file mode 100644 index 000000000000..d7d1b6f05a37 --- /dev/null +++ b/addons/actions/src/models/ActionsMap.ts @@ -0,0 +1,5 @@ +import { HandlerFunction } from './HandlerFunction'; + +export interface ActionsMap { + [key: string]: HandlerFunction; +} diff --git a/addons/actions/src/models/DecoratorFunction.ts b/addons/actions/src/models/DecoratorFunction.ts new file mode 100644 index 000000000000..9ea17af0ec5d --- /dev/null +++ b/addons/actions/src/models/DecoratorFunction.ts @@ -0,0 +1 @@ +export type DecoratorFunction = (args: any[]) => any[]; diff --git a/addons/actions/src/models/HandlerFunction.ts b/addons/actions/src/models/HandlerFunction.ts new file mode 100644 index 000000000000..fc96f4d2af59 --- /dev/null +++ b/addons/actions/src/models/HandlerFunction.ts @@ -0,0 +1 @@ +export type HandlerFunction = (...args: any[]) => void; diff --git a/addons/actions/src/models/index.ts b/addons/actions/src/models/index.ts new file mode 100644 index 000000000000..eb72774241b1 --- /dev/null +++ b/addons/actions/src/models/index.ts @@ -0,0 +1,5 @@ +export * from './ActionDisplay'; +export * from './ActionOptions'; +export * from './ActionsMap'; +export * from './DecoratorFunction'; +export * from './HandlerFunction'; diff --git a/addons/actions/src/preview/action.ts b/addons/actions/src/preview/action.ts index da2090cf2646..5b46c92f2739 100644 --- a/addons/actions/src/preview/action.ts +++ b/addons/actions/src/preview/action.ts @@ -1,8 +1,9 @@ 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: any, options = {}) { +export function action(name: string, options: ActionOptions = {}): HandlerFunction { const actionOptions = { ...options, }; @@ -11,11 +12,13 @@ export function action(name: any, options = {}) { const handler = function action(...args: any[]) { const channel = addons.getChannel(); const id = uuid(); - channel.emit(EVENT_ID, { + const actionDisplayToEmit: ActionDisplay = { id, + count: 0, data: { name, args }, options: actionOptions, - }); + }; + channel.emit(EVENT_ID, actionDisplayToEmit); }; return handler; diff --git a/addons/actions/src/preview/actions.ts b/addons/actions/src/preview/actions.ts index d51882c252ca..0c330962adbb 100644 --- a/addons/actions/src/preview/actions.ts +++ b/addons/actions/src/preview/actions.ts @@ -1,7 +1,8 @@ import { action } from './action'; +import { ActionOptions, ActionsMap } from '../models'; -export function actions(...args: any[]) { - 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') { @@ -16,7 +17,7 @@ export function actions(...args: any[]) { }); } - const actionsObject = {} as any; + const actionsObject: ActionsMap = {}; Object.keys(namesObject).forEach(name => { actionsObject[name] = action(namesObject[name], options); }); diff --git a/addons/actions/src/preview/configureActions.ts b/addons/actions/src/preview/configureActions.ts index 8c617c160fdc..24a31b5d60b1 100644 --- a/addons/actions/src/preview/configureActions.ts +++ b/addons/actions/src/preview/configureActions.ts @@ -1,9 +1,11 @@ -export const config = { +import { ActionOptions } from '../models'; + +export const config: ActionOptions = { depth: 10, clearOnStoryChange: true, limit: 50, }; -export const configureActions = (options = {}) => { +export const configureActions = (options: ActionOptions = {}): void => { Object.assign(config, options); }; diff --git a/addons/actions/src/preview/decorateAction.ts b/addons/actions/src/preview/decorateAction.ts index 48c391878801..df7764e51a2e 100644 --- a/addons/actions/src/preview/decorateAction.ts +++ b/addons/actions/src/preview/decorateAction.ts @@ -1,22 +1,23 @@ import { action } from './action'; import { actions } from './actions'; import { createDecorator } from './withActions'; +import { ActionOptions, DecoratorFunction, HandlerFunction } from '../models'; -const applyDecorators = (decorators: any[], actionCallback: (...args: any) => void) => { +const applyDecorators = (decorators: DecoratorFunction[], actionCallback: HandlerFunction) => { return (..._args: any[]) => { const decorated = decorators.reduce((args, fn) => fn(args), _args); actionCallback(...decorated); }; }; -export const decorateAction = (decorators: any[]) => { - return (name: any, options: any) => { +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 const decorate = (decorators: any[]) => { +export const decorate = (decorators: DecoratorFunction[]) => { const decorated = decorateAction(decorators); const decoratedActions = (...args: any[]) => { const rawActions = actions(...args); From 82f527a50a1315e59a5cb73fa462fc0f40b36cc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Maisse?= Date: Sat, 9 Feb 2019 16:32:07 +0100 Subject: [PATCH 5/5] Remove reference to `prop-types` as components are written in TS --- addons/actions/package.json | 1 - .../src/components/ActionLogger/index.tsx | 22 ++++++------------- .../src/containers/ActionLogger/index.tsx | 10 --------- 3 files changed, 7 insertions(+), 26 deletions(-) diff --git a/addons/actions/package.json b/addons/actions/package.json index af49fd89561d..f18a8ddbd1db 100644 --- a/addons/actions/package.json +++ b/addons/actions/package.json @@ -29,7 +29,6 @@ "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" diff --git a/addons/actions/src/components/ActionLogger/index.tsx b/addons/actions/src/components/ActionLogger/index.tsx index 094e21cae953..d2b829445884 100644 --- a/addons/actions/src/components/ActionLogger/index.tsx +++ b/addons/actions/src/components/ActionLogger/index.tsx @@ -1,4 +1,3 @@ -import PropTypes from 'prop-types'; import React from 'react'; import Inspector from 'react-inspector'; @@ -8,7 +7,13 @@ import { ActionBar } from '@storybook/components'; import { Actions, Action, Wrapper, InspectorContainer, Counter } from './style'; import { ActionDisplay } from '../../models'; -export const ActionLogger = withTheme(({ actions, onClear, theme }: any) => ( +interface ActionLoggerProps { + actions: ActionDisplay[]; + onClear: () => void; + theme: any; +} + +export const ActionLogger = withTheme(({ actions, onClear, theme }: ActionLoggerProps) => ( {actions.map((action: ActionDisplay) => ( @@ -30,16 +35,3 @@ export const ActionLogger = withTheme(({ actions, onClear, theme }: any) => ( )); - -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, -}; diff --git a/addons/actions/src/containers/ActionLogger/index.tsx b/addons/actions/src/containers/ActionLogger/index.tsx index 0f949e9bb0e1..be59226c96e5 100644 --- a/addons/actions/src/containers/ActionLogger/index.tsx +++ b/addons/actions/src/containers/ActionLogger/index.tsx @@ -1,5 +1,4 @@ import React, { Component } from 'react'; -import PropTypes from 'prop-types'; import deepEqual from 'fast-deep-equal'; import { STORY_RENDERED } from '@storybook/core-events'; @@ -81,12 +80,3 @@ export default class ActionLogger extends Component : null; } } - -(ActionLogger as any).propTypes = { - active: PropTypes.bool.isRequired, - api: PropTypes.shape({ - on: PropTypes.func, - getQueryParam: PropTypes.func, - setQueryParams: PropTypes.func, - }).isRequired, -};