diff --git a/addons/cssresources/README.md b/addons/cssresources/README.md
index 14bec5d98141..bdc7fe79efc9 100644
--- a/addons/cssresources/README.md
+++ b/addons/cssresources/README.md
@@ -35,7 +35,7 @@ import { withCssResources } from '@storybook/addon-cssresources';
addDecorator(
withCssResources({
cssresources: [{
- name: `bluetheme`,
+ id: `bluetheme`,
code: ``,
picked: false,
},
@@ -48,11 +48,11 @@ storiesOf('Addons|Cssresources', module)
.addDecorator(
withCssResources({
cssresources: [{
- name: `fontawesome`,
+ id: `fontawesome`,
code: ``,
picked: true,
}, {
- name: `whitetheme`,
+ id: `whitetheme`,
code: ``,
picked: true,
},
diff --git a/addons/cssresources/package.json b/addons/cssresources/package.json
index 7499c9f92965..cdd3afdbf687 100644
--- a/addons/cssresources/package.json
+++ b/addons/cssresources/package.json
@@ -19,13 +19,14 @@
"license": "MIT",
"author": "nm123github",
"main": "dist/index.js",
- "jsnext:main": "src/index.js",
+ "types": "dist/index.d.ts",
"scripts": {
"prepare": "node ../../scripts/prepare.js"
},
"dependencies": {
"@emotion/styled": "10.0.6",
"@storybook/addons": "5.0.0-alpha.9",
+ "@storybook/channels": "5.0.0-alpha.9",
"@storybook/components": "5.0.0-alpha.9",
"@storybook/core-events": "5.0.0-alpha.9",
"core-js": "^2.6.2",
diff --git a/addons/cssresources/src/CssResource.ts b/addons/cssresources/src/CssResource.ts
new file mode 100644
index 000000000000..0067ca677488
--- /dev/null
+++ b/addons/cssresources/src/CssResource.ts
@@ -0,0 +1,5 @@
+export interface CssResource {
+ id: string;
+ code: string;
+ picked: boolean;
+}
diff --git a/addons/cssresources/src/constants.js b/addons/cssresources/src/constants.ts
similarity index 89%
rename from addons/cssresources/src/constants.js
rename to addons/cssresources/src/constants.ts
index b8422207fb45..1a0f36540353 100644
--- a/addons/cssresources/src/constants.js
+++ b/addons/cssresources/src/constants.ts
@@ -2,7 +2,7 @@ export const ADDON_ID = 'storybook/cssresources';
export const PANEL_ID = `${ADDON_ID}/panel`;
export const PARAM_KEY = 'cssresources';
-export default {
+export const EVENTS = {
SET: `${ADDON_ID}:set`,
UNSET: `${ADDON_ID}:unset`,
};
diff --git a/addons/cssresources/src/css-resource-panel.js b/addons/cssresources/src/css-resource-panel.tsx
similarity index 52%
rename from addons/cssresources/src/css-resource-panel.js
rename to addons/cssresources/src/css-resource-panel.tsx
index 38150a87a27e..628db155807f 100644
--- a/addons/cssresources/src/css-resource-panel.js
+++ b/addons/cssresources/src/css-resource-panel.tsx
@@ -1,12 +1,30 @@
import React, { Component, Fragment } from 'react';
-import PropTypes from 'prop-types';
import { SyntaxHighlighter } from '@storybook/components';
+import events, { STORY_CHANGED } from '@storybook/core-events';
+import { EVENTS, PARAM_KEY } from './constants';
+import { Channel } from '@storybook/channels';
+import { CssResource } from './CssResource';
+import { bool, func, shape } from 'prop-types';
-import { STORY_CHANGED } from '@storybook/core-events';
-import EVENTS, { PARAM_KEY } from './constants';
+interface CssResourcePanelProps {
+ active: boolean;
+ channel: Channel;
+ api: {
+ emit: (event: any, data: any) => void;
+ on: (event: events, callback: (data: any) => void) => void;
+ off: (event: events, callback: (data: any) => void) => void;
+ getQueryParam: () => void;
+ getParameters: (id: string, paramKey: string) => any;
+ setQueryParams: () => void;
+ };
+}
+
+interface CssResourcePanelState {
+ list: CssResource[];
+}
-export default class CssResourcePanel extends Component {
- constructor(props) {
+export class CssResourcePanel extends Component {
+ constructor(props: CssResourcePanelProps) {
super(props);
this.state = {
@@ -24,9 +42,9 @@ export default class CssResourcePanel extends Component {
api.off(STORY_CHANGED, this.onStoryChange);
}
- onStoryChange = id => {
+ onStoryChange = (id: string) => {
const { api } = this.props;
- const list = api.getParameters(id, PARAM_KEY);
+ const list = api.getParameters(id, PARAM_KEY) as CssResource[];
if (list) {
const picked = list.filter(res => res.picked);
@@ -34,16 +52,16 @@ export default class CssResourcePanel extends Component {
}
};
- onChange = event => {
+ onChange = (event: any) => {
const { list: oldList } = this.state;
const list = oldList.map(i => ({
...i,
picked: i.id === event.target.id ? event.target.checked : i.picked,
}));
- this.setState({ list }, () => this.emit(list.filter(res => res.picked)));
+ this.setState({ list }, () => this.emit(list.filter((res: any) => res.picked)));
};
- emit(list) {
+ emit(list: CssResource[]) {
const { api } = this.props;
api.emit(EVENTS.SET, list);
}
@@ -73,16 +91,16 @@ export default class CssResourcePanel extends Component {
}
}
-CssResourcePanel.propTypes = {
- active: PropTypes.bool.isRequired,
- channel: PropTypes.shape({
- on: PropTypes.func,
- emit: PropTypes.func,
- removeListener: PropTypes.func,
+(CssResourcePanel as any).propTypes = {
+ active: bool.isRequired,
+ channel: shape({
+ on: func,
+ emit: func,
+ removeListener: func,
}).isRequired,
- api: PropTypes.shape({
- on: PropTypes.func,
- getQueryParam: PropTypes.func,
- setQueryParams: PropTypes.func,
+ api: shape({
+ on: func,
+ getQueryParam: func,
+ setQueryParams: func,
}).isRequired,
};
diff --git a/addons/cssresources/src/index.js b/addons/cssresources/src/index.ts
similarity index 68%
rename from addons/cssresources/src/index.js
rename to addons/cssresources/src/index.ts
index 17532d7df73e..436343c8f449 100644
--- a/addons/cssresources/src/index.js
+++ b/addons/cssresources/src/index.ts
@@ -1,8 +1,8 @@
import { document } from 'global';
-import addons, { makeDecorator } from '@storybook/addons';
-import EVENTS, { PARAM_KEY } from './constants';
+import { addons, makeDecorator } from '@storybook/addons';
+import { EVENTS, PARAM_KEY } from './constants';
-const changeMediaAttribute = (element, enabled) => {
+const changeMediaAttribute = (element: HTMLElement, enabled: boolean) => {
const current = element.getAttribute('media');
if ((enabled && !current) || (!enabled && current === 'max-width: 1px')) {
// don't do anything
@@ -19,29 +19,33 @@ const changeMediaAttribute = (element, enabled) => {
element.setAttribute('media', value);
}
};
-const createElement = (id, code) => {
- const element = document.createElement('div');
+
+const createElement = (id: string, code: string): HTMLDivElement => {
+ const element: HTMLDivElement = document.createElement('div');
element.setAttribute('id', `storybook-addon-resource_${id}`);
element.innerHTML = code;
return element;
};
-const getElement = (id, code) => {
- const found = document.querySelector(`[id="storybook-addon-resource_${id}"]`);
+
+const getElement = (id: string, code: string) => {
+ const found: Element = document.querySelector(`[id="storybook-addon-resource_${id}"]`);
return { element: found || createElement(id, code), created: !found };
};
-const updateElement = (id, code, value) => {
+
+const updateElement = (id: string, code: string, value: boolean) => {
const { element, created } = getElement(id, code);
- const tags = [...element.querySelectorAll('link'), ...element.querySelectorAll('style')];
- tags.forEach(child => changeMediaAttribute(child, value));
+ element.querySelectorAll('link').forEach(child => changeMediaAttribute(child, value));
+ element.querySelectorAll('style').forEach(child => changeMediaAttribute(child, value));
if (created) {
document.body.appendChild(element);
}
};
-const list = [];
-const setResources = resources => {
+const list: any[] = [];
+
+const setResources = (resources: Array<{ code: string; id: string }>) => {
const added = resources.filter(i => !list.find(r => r.code === i.code));
const removed = list.filter(i => !resources.find(r => r.code === i.code));
@@ -63,7 +67,7 @@ export const withCssResources = makeDecorator({
skipIfNoParametersOrOptions: true,
allowDeprecatedUsage: false,
- wrapper: (getStory, context, { options, parameters }) => {
+ wrapper: (getStory: any, context: any, { options, parameters }: any) => {
const storyOptions = parameters || options;
addons.getChannel().on(EVENTS.SET, setResources);
diff --git a/addons/cssresources/src/register.js b/addons/cssresources/src/register.tsx
similarity index 61%
rename from addons/cssresources/src/register.js
rename to addons/cssresources/src/register.tsx
index 3effb0f6a733..7a8348cc2c0b 100644
--- a/addons/cssresources/src/register.js
+++ b/addons/cssresources/src/register.tsx
@@ -1,18 +1,18 @@
import React from 'react';
-import addons, { types } from '@storybook/addons';
+import { addons, types } from '@storybook/addons';
import { ADDON_ID, PANEL_ID } from './constants';
-
-import CssResourcePanel from './css-resource-panel';
+import { CssResourcePanel } from './css-resource-panel';
addons.register(ADDON_ID, api => {
const channel = addons.getChannel();
+ // Need to cast as any as it's not matching Addon type, to investigate
addons.add(PANEL_ID, {
type: types.PANEL,
title: 'CSS resources',
// eslint-disable-next-line react/prop-types
- render: ({ active, key }) => (
+ render: ({ active, key }: any) => (
),
- });
+ } as any);
});
diff --git a/addons/cssresources/src/typings.d.ts b/addons/cssresources/src/typings.d.ts
new file mode 100644
index 000000000000..1cebcd2c971a
--- /dev/null
+++ b/addons/cssresources/src/typings.d.ts
@@ -0,0 +1,3 @@
+// TODO: following packages need definition files or a TS migration
+declare module '@storybook/components';
+declare module 'global';
diff --git a/addons/cssresources/tsconfig.json b/addons/cssresources/tsconfig.json
new file mode 100644
index 000000000000..8876bb6737a1
--- /dev/null
+++ b/addons/cssresources/tsconfig.json
@@ -0,0 +1,13 @@
+{
+ "extends": "../../tsconfig.json",
+ "compilerOptions": {
+ "rootDir": "./src",
+ "types": ["webpack-env"]
+ },
+ "include": [
+ "src/**/*"
+ ],
+ "exclude": [
+ "src/__tests__/**/*"
+ ]
+}