mirror of
https://github.com/storybookjs/storybook.git
synced 2025-04-09 00:19:13 +08:00
Addon-docs: Support jsdoc params to describe function signature (#8660)
Addon-docs: Support jsdoc params to describe function signature
This commit is contained in:
commit
4aed2feec4
@ -14,6 +14,8 @@ scripts/storage
|
||||
*.d.ts
|
||||
examples/ember-cli/.storybook/preview-head.html
|
||||
examples/official-storybook/tests/addon-jest.test.js
|
||||
examples/cra-ts-kitchen-sink/*.json
|
||||
examples/cra-ts-kitchen-sink/public/*.json
|
||||
|
||||
!.remarkrc.js
|
||||
!.babelrc.js
|
||||
|
@ -51,6 +51,7 @@
|
||||
"@storybook/source-loader": "5.3.0-alpha.35",
|
||||
"@storybook/theming": "5.3.0-alpha.35",
|
||||
"core-js": "^3.0.1",
|
||||
"doctrine": "^3.0.0",
|
||||
"global": "^4.3.2",
|
||||
"js-string-escape": "^1.0.1",
|
||||
"lodash": "^4.17.15",
|
||||
@ -59,6 +60,9 @@
|
||||
"ts-dedent": "^1.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/doctrine": "^0.0.3",
|
||||
"@types/enzyme": "^3.10.3",
|
||||
"@types/jest": "^24.0.11",
|
||||
"@types/prop-types": "^15.5.9",
|
||||
"@types/util-deprecate": "^1.0.0",
|
||||
"@types/webpack-env": "^1.14.0"
|
||||
|
@ -1,8 +1,12 @@
|
||||
/* eslint-disable no-underscore-dangle,react/forbid-foreign-prop-types */
|
||||
import PropTypes from 'prop-types';
|
||||
import { isForwardRef, isMemo } from 'react-is';
|
||||
import { PropDef } from '@storybook/components';
|
||||
import { PropDefGetter, PropsExtractor, propsFromDocgen, hasDocgen } from '../../lib/docgenUtils';
|
||||
import {
|
||||
PropDefGetter,
|
||||
PropsExtractor,
|
||||
extractPropsFromDocgen,
|
||||
hasDocgen,
|
||||
} from '../../lib/docgenUtils';
|
||||
|
||||
export interface PropDefMap {
|
||||
[p: string]: PropDef;
|
||||
@ -18,47 +22,6 @@ Object.keys(PropTypes).forEach(typeName => {
|
||||
propTypesMap.set(type.isRequired, typeName);
|
||||
});
|
||||
|
||||
const propsFromPropTypes: PropDefGetter = (type, section) => {
|
||||
const props: PropDefMap = {};
|
||||
|
||||
if (type.propTypes) {
|
||||
Object.keys(type.propTypes).forEach(property => {
|
||||
const typeInfo = type.propTypes[property];
|
||||
const required = typeInfo.isRequired === undefined;
|
||||
const docgenInfo =
|
||||
type.__docgenInfo && type.__docgenInfo[section] && type.__docgenInfo[section][property];
|
||||
const description = docgenInfo ? docgenInfo.description : null;
|
||||
let propType = propTypesMap.get(typeInfo) || 'other';
|
||||
|
||||
if (propType === 'other') {
|
||||
if (docgenInfo && docgenInfo.type) {
|
||||
propType = docgenInfo.type.name;
|
||||
}
|
||||
}
|
||||
|
||||
props[property] = { name: property, type: propType, required, description };
|
||||
});
|
||||
}
|
||||
|
||||
if (type.defaultProps) {
|
||||
Object.keys(type.defaultProps).forEach(property => {
|
||||
const value = type.defaultProps[property];
|
||||
|
||||
if (value === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!props[property]) {
|
||||
props[property] = { name: property, type: 'any', required: false };
|
||||
}
|
||||
|
||||
props[property].defaultValue = value;
|
||||
});
|
||||
}
|
||||
|
||||
return Object.values(props);
|
||||
};
|
||||
|
||||
export const getPropDefs: PropDefGetter = (type, section) => {
|
||||
let processedType = type;
|
||||
if (!hasDocgen(type) && !type.propTypes) {
|
||||
@ -70,9 +33,8 @@ export const getPropDefs: PropDefGetter = (type, section) => {
|
||||
processedType = type.type().type;
|
||||
}
|
||||
}
|
||||
return hasDocgen(processedType)
|
||||
? propsFromDocgen(processedType, section)
|
||||
: propsFromPropTypes(processedType, section);
|
||||
|
||||
return extractPropsFromDocgen(processedType, section);
|
||||
};
|
||||
|
||||
export const extractProps: PropsExtractor = component => ({
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { PropDef } from '@storybook/components';
|
||||
import { PropsExtractor, propsFromDocgen, hasDocgen } from '../../lib/docgenUtils';
|
||||
import { PropsExtractor, extractPropsFromDocgen, hasDocgen } from '../../lib/docgenUtils';
|
||||
|
||||
const SECTIONS = ['props', 'events', 'slots'];
|
||||
|
||||
@ -9,7 +9,7 @@ export const extractProps: PropsExtractor = component => {
|
||||
}
|
||||
const sections: Record<string, PropDef[]> = {};
|
||||
SECTIONS.forEach(section => {
|
||||
sections[section] = propsFromDocgen(component, section);
|
||||
sections[section] = extractPropsFromDocgen(component, section);
|
||||
});
|
||||
return { sections };
|
||||
};
|
||||
|
@ -1,10 +1,11 @@
|
||||
/* eslint-disable no-underscore-dangle */
|
||||
import { PropDef, PropsTableProps } from '@storybook/components';
|
||||
import { Component } from '../blocks/shared';
|
||||
import { getTypeSystemHandler, getPropTypeSystem } from './type-system-handlers';
|
||||
|
||||
export type PropsExtractor = (component: Component) => PropsTableProps | null;
|
||||
|
||||
export type PropDefGetter = (type: Component, section: string) => PropDef[] | null;
|
||||
export type PropDefGetter = (type: Component, section: string) => PropDef[];
|
||||
|
||||
export const str = (o: any) => {
|
||||
if (!o) {
|
||||
@ -23,25 +24,28 @@ export const hasDocgenSection = (obj: any, section: string) =>
|
||||
obj.__docgenInfo[section] &&
|
||||
Object.keys(obj.__docgenInfo[section]).length > 0;
|
||||
|
||||
export const propsFromDocgen: PropDefGetter = (type, section) => {
|
||||
export const extractPropsFromDocgen: PropDefGetter = (type, section) => {
|
||||
const props: Record<string, PropDef> = {};
|
||||
|
||||
const docgenInfoProps = type.__docgenInfo[section];
|
||||
if (!docgenInfoProps) {
|
||||
return null;
|
||||
return [];
|
||||
}
|
||||
|
||||
Object.keys(docgenInfoProps).forEach(property => {
|
||||
const docgenInfoProp = docgenInfoProps[property];
|
||||
const defaultValueDesc = docgenInfoProp.defaultValue || {};
|
||||
const propType = docgenInfoProp.flowType || docgenInfoProp.type || 'other';
|
||||
const propKeys = Object.keys(docgenInfoProps);
|
||||
if (propKeys.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
props[property] = {
|
||||
name: property,
|
||||
type: propType,
|
||||
required: docgenInfoProp.required,
|
||||
description: docgenInfoProp.description,
|
||||
defaultValue: defaultValueDesc.value,
|
||||
};
|
||||
// Assuming the props for a given type will all have the same type system.
|
||||
const typeSystem = getPropTypeSystem(docgenInfoProps[propKeys[0]]);
|
||||
const typeSystemHandler = getTypeSystemHandler(typeSystem);
|
||||
|
||||
propKeys.forEach(propKey => {
|
||||
const docgenInfoProp = docgenInfoProps[propKey];
|
||||
|
||||
const propDef = typeSystemHandler(propKey, docgenInfoProp);
|
||||
props[propKey] = propDef;
|
||||
});
|
||||
|
||||
return Object.values(props);
|
||||
|
24
addons/docs/src/lib/jsdoc-parser.ts
Normal file
24
addons/docs/src/lib/jsdoc-parser.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import doctrine from 'doctrine';
|
||||
|
||||
export interface JsDocAst {
|
||||
description?: string;
|
||||
tags: any[];
|
||||
}
|
||||
|
||||
export function parseComment(comment: string): JsDocAst {
|
||||
let ast;
|
||||
|
||||
try {
|
||||
ast = doctrine.parse(comment, {
|
||||
tags: ['param', 'arg', 'argument', 'returns'],
|
||||
sloppy: true,
|
||||
});
|
||||
} catch (e) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(e);
|
||||
|
||||
throw new Error('Cannot parse JSDoc tags.');
|
||||
}
|
||||
|
||||
return ast;
|
||||
}
|
717
addons/docs/src/lib/type-system-handlers.test.ts
Normal file
717
addons/docs/src/lib/type-system-handlers.test.ts
Normal file
@ -0,0 +1,717 @@
|
||||
import { propTypesHandler, tsHandler, flowHandler, DocgenInfo } from './type-system-handlers';
|
||||
|
||||
const DEFAULT_PROP_NAME = 'propName';
|
||||
|
||||
const PROP_TYPE_FUNC_TYPE = {
|
||||
name: 'func',
|
||||
};
|
||||
|
||||
function createPropTypesDocgenInfo(overrides: Record<string, any> = {}): DocgenInfo {
|
||||
return {
|
||||
type: { name: 'string' },
|
||||
required: true,
|
||||
description: 'A string prop',
|
||||
defaultValue: {
|
||||
value: 'default string',
|
||||
},
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
function createTypeScriptDocgenInfo(overrides: Record<string, any> = {}): DocgenInfo {
|
||||
return {
|
||||
tsType: { name: 'string' },
|
||||
required: true,
|
||||
description: 'A string prop',
|
||||
defaultValue: {
|
||||
value: 'default string',
|
||||
},
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
function createFlowDocgenInfo(overrides: Record<string, any> = {}): DocgenInfo {
|
||||
return {
|
||||
flowType: { name: 'string' },
|
||||
required: true,
|
||||
description: 'A string prop',
|
||||
defaultValue: {
|
||||
value: 'default string',
|
||||
},
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
describe('prop-types handler', () => {
|
||||
it('should map defaults docgen info properly', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo();
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.name).toBe(DEFAULT_PROP_NAME);
|
||||
expect(propDef.type.name).toBe(docgenInfo.type.name);
|
||||
expect(propDef.description).toBe(docgenInfo.description);
|
||||
expect(propDef.required).toBe(docgenInfo.required);
|
||||
expect(propDef.defaultValue).toBe(docgenInfo.defaultValue.value);
|
||||
});
|
||||
|
||||
describe('when the prop is not a function', () => {
|
||||
it('should handle prop without a description', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
description: undefined,
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.description).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should clean the description', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: {
|
||||
name: 'string',
|
||||
},
|
||||
description: 'onClick description\n@param {SyntheticEvent} event',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
|
||||
it('should have an empty description when the description only contains JSDoc', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: {
|
||||
name: 'string',
|
||||
},
|
||||
description: '@param event',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.description).toBe('');
|
||||
});
|
||||
|
||||
it('should not remove newline characters of multilines description without JSDoc tags', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: {
|
||||
name: 'string',
|
||||
},
|
||||
description: 'onClick description\nis a\nmulti-lines\ndescription',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.description).toBe('onClick description\nis a\nmulti-lines\ndescription');
|
||||
});
|
||||
|
||||
it('should not remove newline characters of multilines description with JSDoc tags', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: {
|
||||
name: 'string',
|
||||
},
|
||||
description: 'onClick description\nis a\nmulti-lines\ndescription\n@param event',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.description).toBe('onClick description\nis a\nmulti-lines\ndescription');
|
||||
});
|
||||
|
||||
it('should not remove markdown from description without JSDoc tags', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: {
|
||||
name: 'string',
|
||||
},
|
||||
description: 'onClick *emphasis*, **strong**, `formatted` description.',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.description).toBe('onClick *emphasis*, **strong**, `formatted` description.');
|
||||
});
|
||||
|
||||
it('should not remove markdown from description with JSDoc tags', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: {
|
||||
name: 'string',
|
||||
},
|
||||
description: 'onClick *emphasis*, **strong**, `formatted` description.\n@param event',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.description).toBe('onClick *emphasis*, **strong**, `formatted` description.');
|
||||
});
|
||||
|
||||
it('should not remove @ characters that does not match JSDoc tags', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: {
|
||||
name: 'string',
|
||||
},
|
||||
description: 'onClick @description@',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.description).toBe('onClick @description@');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the prop is a function', () => {
|
||||
it("should have func as type when the props doesn't have a description", () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description: undefined,
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.description).toBeUndefined();
|
||||
expect(propDef.type.name).toBe('func');
|
||||
});
|
||||
|
||||
it('should have func as type when the prop have a description without JSDoc', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description: 'onClick description',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('func');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
|
||||
it('should have an empty description when the description only contains JSDoc', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description: '@param event',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.description).toBe('');
|
||||
});
|
||||
|
||||
describe('when the description contains a @param tag', () => {
|
||||
it('should have func as type when it is an invalid @param tag', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description: 'onClick description\n@param',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('func');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
|
||||
it('should have a func signature with a single arg as type when it is a @param tag with a name', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description: 'onClick description\n@param event',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('(event)');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
|
||||
it('should have a func signature with a single arg as type when it is a @param tag with a name and a type', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description: 'onClick description\n@param {SyntheticEvent} event',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('(event: SyntheticEvent)');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
|
||||
it('should have a func signature with a single arg as type when it is a @param tag with a name, a type and a desc', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description:
|
||||
'onClick description\n@param {SyntheticEvent} event - Original SyntheticEvent',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('(event: SyntheticEvent)');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
|
||||
it('should have func as type when it is @param tag without a name 1', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description: 'onClick description\n@param - Original SyntheticEvent',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('func');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
|
||||
it('should have func as type when it is @param tag without a name 2', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description: 'onClick description\n@param {SyntheticEvent} - Original SyntheticEvent',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('func');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
|
||||
it('should support param of record type with a single field', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description: 'onClick description\n@param {{a: number}} event',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('(event: ({a: number}))');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
|
||||
it('should support param of record type with multiple fields', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description: 'onClick description\n@param {{a: number, b: string}} event',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('(event: ({a: number, b: string}))');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
|
||||
it('should support param of record type with a field having only a name', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description: 'onClick description\n@param {{a}} event',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('(event: ({a}))');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
|
||||
it('should support param of union type', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description: 'onClick description\n@param {(number|boolean)} event',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('(event: (number|boolean))');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
|
||||
it('should support param of array type', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description: 'onClick description\n@param {number[]} event',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('(event: number[])');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
|
||||
it('should support param of untyped array type', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description: 'onClick description\n@param {[]} event',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('(event: [])');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
|
||||
it('should support param with a nullable type', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description: 'onClick description\n@param {?number} event',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('(event: number)');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
|
||||
it('should support param with a non nullable type', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description: 'onClick description\n@param {!number} event',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('(event: number)');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
|
||||
it('should support optional param 1', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description: 'onClick description\n@param {number} [event]',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('(event: number)');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
|
||||
it('should support optional param 2', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description: 'onClick description\n@param {number=} event',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('(event: number)');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
|
||||
it('should support param of type any', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description: 'onClick description\n@param {*} event',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('(event: any)');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
|
||||
it('should support multilines description when there is a @param', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description: 'onClick description\nis a\nmulti-lines\ndescription\n@param event',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('(event)');
|
||||
expect(propDef.description).toBe('onClick description\nis a\nmulti-lines\ndescription');
|
||||
});
|
||||
|
||||
it('should support multilines @param description', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description:
|
||||
'onClick description\n@param event - This is my param\nmultiline description\n@param customData',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('(event, customData)');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
|
||||
it('should autofix missing space between the param name and the description separator', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description:
|
||||
'onClick description\n@param {SyntheticEvent} event- Original SyntheticEvent',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('(event: SyntheticEvent)');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
|
||||
it('should autofix param name ending with . followed by a @returns tag', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description: 'onClick description\n@param {SyntheticEvent} event.\n',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('(event: SyntheticEvent)');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the description contains multiple @param tags', () => {
|
||||
it('should have a func signature with multiple args as type', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description:
|
||||
'onClick description\n@param {SyntheticEvent} event\n@param {string} customData',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('(event: SyntheticEvent, customData: string)');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
|
||||
it('should ignore invalid @param tags', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description:
|
||||
'onClick description\n@param {SyntheticEvent} event\n@param {string} customData\n@param {SyntheticEvent} - Original event',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('(event: SyntheticEvent, customData: string)');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
});
|
||||
|
||||
it('should support @arg alias', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description: 'onClick description\n@arg event',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('(event)');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
|
||||
it('should support @argument alias', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description: 'onClick description\n@argument event',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('(event)');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
|
||||
describe('when the description contains a @returns tag', () => {
|
||||
it('should have func as type when it is an invalid @returns tag', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description: 'onClick description\n@returns',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('func');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
|
||||
it('should have a func signature with a return type as type when it is a @returns tag with a type', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description: 'onClick description\n@returns {string}',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('() => string');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
|
||||
it('should have a func signature with a return type as type when it is a @returns tag with a type and a description', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description: 'onClick description\n@returns {string} - A custom return type',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('() => string');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
|
||||
it('should have func as type when it is a @returns tag without a type and there is no params.', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description: 'onClick description\n@returns - A custom return type',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('func');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
|
||||
it('should have no return type when it is a @returns tag without a type and there is params.', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description: 'onClick description\n@param event\n@returns - A custom return type',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('(event)');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
|
||||
it('should have a full signature as type when there is a @param and a @returns tag 1', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description:
|
||||
'onClick description\n@param {SyntheticEvent} event - Original event.\n@returns {string}',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('(event: SyntheticEvent) => string');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
|
||||
it('should have a full signature as type when there is a @param and a @returns tag 2', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description:
|
||||
'onClick description\n@param {SyntheticEvent} event - Original event.\n@param {string} customData\n@returns {string}',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('(event: SyntheticEvent, customData: string) => string');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
|
||||
it('should only consider the last @returns tag when there is more than one', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description: 'onClick description\n@returns {string}\n@returns {integer}',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('() => integer');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
|
||||
it('should support returns of record type', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description: 'onClick description\n@returns {{a: number, b: string}}',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('() => ({a: number, b: string})');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
|
||||
it('should support returns of array type', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description: 'onClick description\n@returns {integer[]}',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('() => integer[]');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
|
||||
it('should support returns of union type', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description: 'onClick description\n@returns {(number|boolean)}',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('() => (number|boolean)');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
|
||||
it('should support returns of type any', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description: 'onClick description\n@returns {*}',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('() => any');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
|
||||
it('should support returns of type void', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description: 'onClick description\n@returns {void}',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('() => void');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
});
|
||||
|
||||
it('should remove extra newline characters between tags', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description:
|
||||
'onClick description\n@param {SyntheticEvent} event - Original event.\n \n \n \n@returns {string}',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('(event: SyntheticEvent) => string');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
|
||||
it('should ignore unsupported JSDoc tags', () => {
|
||||
const docgenInfo = createPropTypesDocgenInfo({
|
||||
type: PROP_TYPE_FUNC_TYPE,
|
||||
description:
|
||||
'onClick description\n@param {SyntheticEvent} event\n@type {number}\n@returns {string}\n@version 2',
|
||||
});
|
||||
|
||||
const propDef = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.type.name).toBe('(event: SyntheticEvent) => string');
|
||||
expect(propDef.description).toBe('onClick description');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('ts handler', () => {
|
||||
it('should map defaults docgen info properly', () => {
|
||||
const docgenInfo = createTypeScriptDocgenInfo();
|
||||
const propDef = tsHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.name).toBe(DEFAULT_PROP_NAME);
|
||||
expect(propDef.type.name).toBe(docgenInfo.tsType.name);
|
||||
expect(propDef.description).toBe(docgenInfo.description);
|
||||
expect(propDef.required).toBe(docgenInfo.required);
|
||||
expect(propDef.defaultValue).toBe(docgenInfo.defaultValue.value);
|
||||
});
|
||||
});
|
||||
|
||||
describe('flow handler', () => {
|
||||
it('should map defaults docgen info properly', () => {
|
||||
const docgenInfo = createFlowDocgenInfo();
|
||||
const propDef = flowHandler(DEFAULT_PROP_NAME, docgenInfo);
|
||||
|
||||
expect(propDef.name).toBe(DEFAULT_PROP_NAME);
|
||||
expect(propDef.type.name).toBe(docgenInfo.flowType.name);
|
||||
expect(propDef.description).toBe(docgenInfo.description);
|
||||
expect(propDef.required).toBe(docgenInfo.required);
|
||||
expect(propDef.defaultValue).toBe(docgenInfo.defaultValue.value);
|
||||
});
|
||||
});
|
259
addons/docs/src/lib/type-system-handlers.ts
Normal file
259
addons/docs/src/lib/type-system-handlers.ts
Normal file
@ -0,0 +1,259 @@
|
||||
import { PropDef } from '@storybook/components';
|
||||
import { isNil } from 'lodash';
|
||||
import { parseComment, JsDocAst } from './jsdoc-parser';
|
||||
|
||||
export interface DocgenInfo {
|
||||
type?: {
|
||||
name: string;
|
||||
};
|
||||
flowType?: any;
|
||||
tsType?: any;
|
||||
required: boolean;
|
||||
description?: string;
|
||||
defaultValue?: {
|
||||
value: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface JsDocParamTag {
|
||||
name: string;
|
||||
type?: string;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
interface JsDocReturnsTag {
|
||||
type?: string;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
interface ExtractedJsDocTags {
|
||||
params: JsDocParamTag[];
|
||||
returns?: JsDocReturnsTag;
|
||||
}
|
||||
|
||||
export const TypeSystem = {
|
||||
Flow: 'Flow',
|
||||
TypeScript: 'TypeScript',
|
||||
PropTypes: 'PropTypes',
|
||||
Unknown: 'Unknown',
|
||||
};
|
||||
|
||||
export type TypeSystemHandler = (propName: string, docgenInfo: DocgenInfo) => PropDef;
|
||||
|
||||
function createDefaultPropDef(propName: string, docgenInfo: DocgenInfo): PropDef {
|
||||
const { description, required, defaultValue } = docgenInfo;
|
||||
|
||||
return {
|
||||
name: propName,
|
||||
type: null,
|
||||
required,
|
||||
description,
|
||||
defaultValue: isNil(defaultValue) ? null : defaultValue.value,
|
||||
};
|
||||
}
|
||||
|
||||
export const propTypesHandler: TypeSystemHandler = (propName: string, docgenInfo: DocgenInfo) => {
|
||||
const propDef = createDefaultPropDef(propName, docgenInfo);
|
||||
propDef.type = docgenInfo.type;
|
||||
|
||||
if (!isNil(propDef.description)) {
|
||||
if (propDef.description.includes('@')) {
|
||||
const jsDocAst = parseComment(propDef.description);
|
||||
|
||||
// Always use the parsed description to ensure JSDoc is removed from the description.
|
||||
if (!isNil(jsDocAst.description)) {
|
||||
propDef.description = jsDocAst.description;
|
||||
}
|
||||
|
||||
if (propDef.type.name === 'func') {
|
||||
const tags = extractJsDocTags(jsDocAst);
|
||||
const hasParams = tags.params.length > 0;
|
||||
const hasReturnType = !isNil(tags.returns) && !isNil(tags.returns.type);
|
||||
|
||||
if (hasParams || hasReturnType) {
|
||||
const funcParts = [];
|
||||
|
||||
if (hasParams) {
|
||||
const funcParams = tags.params.map((x: any) => {
|
||||
if (x.name && x.type) {
|
||||
return `${x.name}: ${x.type}`;
|
||||
}
|
||||
|
||||
if (x.name) {
|
||||
return x.name;
|
||||
}
|
||||
|
||||
return x.type;
|
||||
});
|
||||
|
||||
funcParts.push(`(${funcParams.join(', ')})`);
|
||||
} else {
|
||||
funcParts.push('()');
|
||||
}
|
||||
|
||||
if (hasReturnType) {
|
||||
funcParts.push(`=> ${tags.returns.type}`);
|
||||
}
|
||||
|
||||
propDef.type = {
|
||||
name: funcParts.join(' '),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return propDef;
|
||||
};
|
||||
|
||||
function extractJsDocTags(ast: JsDocAst): Record<string, any> {
|
||||
const tags: ExtractedJsDocTags = {
|
||||
params: [],
|
||||
returns: null,
|
||||
};
|
||||
|
||||
ast.tags.forEach(tag => {
|
||||
// arg & argument are aliases for param.
|
||||
if (tag.title === 'param' || tag.title === 'arg' || tag.title === 'argument') {
|
||||
// When the @param doesn't have a name but have a type and a description, "null-null" is returned.
|
||||
if (tag.name !== 'null-null') {
|
||||
let paramName = tag.name;
|
||||
|
||||
if (paramName.includes('null')) {
|
||||
// There is a few cases in which the returned param name contains "null".
|
||||
// - @param {SyntheticEvent} event- Original SyntheticEvent
|
||||
// - @param {SyntheticEvent} event.\n@returns {string}
|
||||
paramName = paramName.replace('-null', '').replace('.null', '');
|
||||
}
|
||||
|
||||
let paramType;
|
||||
|
||||
if (!isNil(tag.type)) {
|
||||
const extractedTypeName = extractJsDocTypeName(tag.type);
|
||||
|
||||
if (!isNil(extractedTypeName)) {
|
||||
paramType = extractedTypeName;
|
||||
}
|
||||
}
|
||||
|
||||
tags.params.push({
|
||||
name: paramName,
|
||||
type: paramType,
|
||||
description: tag.description,
|
||||
});
|
||||
}
|
||||
} else if (tag.title === 'returns') {
|
||||
if (!isNil(tag.type)) {
|
||||
tags.returns = {
|
||||
type: extractJsDocTypeName(tag.type),
|
||||
description: tag.description,
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return tags;
|
||||
}
|
||||
|
||||
function extractJsDocTypeName(type: any): string {
|
||||
if (type.type === 'NameExpression') {
|
||||
return type.name;
|
||||
}
|
||||
|
||||
if (type.type === 'RecordType') {
|
||||
const recordFields = type.fields.map((field: any) => {
|
||||
if (!isNil(field.value)) {
|
||||
const valueTypeName = extractJsDocTypeName(field.value);
|
||||
|
||||
return `${field.key}: ${valueTypeName}`;
|
||||
}
|
||||
|
||||
return field.key;
|
||||
});
|
||||
|
||||
return `({${recordFields.join(', ')}})`;
|
||||
}
|
||||
|
||||
if (type.type === 'UnionType') {
|
||||
const unionElements = type.elements.map(extractJsDocTypeName);
|
||||
|
||||
return `(${unionElements.join('|')})`;
|
||||
}
|
||||
|
||||
// Only support untyped array: []. Might add more support later if required.
|
||||
if (type.type === 'ArrayType') {
|
||||
return '[]';
|
||||
}
|
||||
|
||||
if (type.type === 'TypeApplication') {
|
||||
if (!isNil(type.expression)) {
|
||||
if (type.expression.name === 'Array') {
|
||||
const arrayType = extractJsDocTypeName(type.applications[0]);
|
||||
|
||||
return `${arrayType}[]`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
type.type === 'NullableType' ||
|
||||
type.type === 'NonNullableType' ||
|
||||
type.type === 'OptionalType'
|
||||
) {
|
||||
return extractJsDocTypeName(type.expression);
|
||||
}
|
||||
|
||||
if (type.type === 'AllLiteral') {
|
||||
return 'any';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export const tsHandler: TypeSystemHandler = (propName: string, docgenInfo: DocgenInfo) => {
|
||||
const propDef = createDefaultPropDef(propName, docgenInfo);
|
||||
propDef.type = docgenInfo.tsType;
|
||||
|
||||
return propDef;
|
||||
};
|
||||
|
||||
export const flowHandler: TypeSystemHandler = (propName: string, docgenInfo: DocgenInfo) => {
|
||||
const propDef = createDefaultPropDef(propName, docgenInfo);
|
||||
propDef.type = docgenInfo.flowType;
|
||||
|
||||
return propDef;
|
||||
};
|
||||
|
||||
export const unknownHandler: TypeSystemHandler = (propName: string, docgenInfo: DocgenInfo) => {
|
||||
const propDef = createDefaultPropDef(propName, docgenInfo);
|
||||
propDef.type = { name: 'unknown' };
|
||||
|
||||
return propDef;
|
||||
};
|
||||
|
||||
export const TypeSystemHandlers: Record<string, TypeSystemHandler> = {
|
||||
[TypeSystem.Flow]: flowHandler,
|
||||
[TypeSystem.TypeScript]: tsHandler,
|
||||
[TypeSystem.PropTypes]: propTypesHandler,
|
||||
[TypeSystem.Unknown]: unknownHandler,
|
||||
};
|
||||
|
||||
export const getPropTypeSystem = (docgenInfo: DocgenInfo): string => {
|
||||
if (!isNil(docgenInfo.flowType)) {
|
||||
return TypeSystem.Flow;
|
||||
}
|
||||
|
||||
if (!isNil(docgenInfo.tsType)) {
|
||||
return TypeSystem.TypeScript;
|
||||
}
|
||||
|
||||
if (!isNil(docgenInfo.type)) {
|
||||
return TypeSystem.PropTypes;
|
||||
}
|
||||
|
||||
return TypeSystem.Unknown;
|
||||
};
|
||||
|
||||
export const getTypeSystemHandler = (typeSystem: string): TypeSystemHandler => {
|
||||
return TypeSystemHandlers[typeSystem];
|
||||
};
|
@ -2,7 +2,7 @@
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"types": ["webpack-env"]
|
||||
"types": ["webpack-env", "jest"]
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["src/**.test.ts"]
|
||||
|
@ -1,3 +1,3 @@
|
||||
import '@storybook/addon-actions/register';
|
||||
import '@storybook/addon-options/register';
|
||||
import '@storybook/addon-links/register';
|
||||
import '@storybook/addon-a11y/register';
|
@ -1,20 +0,0 @@
|
||||
import { configure, addDecorator, addParameters } from '@storybook/react';
|
||||
import { withInfo } from '@storybook/addon-info';
|
||||
import { withA11y } from '@storybook/addon-a11y';
|
||||
|
||||
addDecorator(withA11y);
|
||||
addParameters({
|
||||
options: {
|
||||
brandTitle: 'CRA TypeScript Kitchen Sink',
|
||||
brandUrl: 'https://github.com/storybookjs/storybook/tree/master/examples/cra-ts-kitchen-sink',
|
||||
},
|
||||
});
|
||||
addDecorator(withInfo());
|
||||
|
||||
function loadStories() {
|
||||
// automatically import all story js files that end with *.stories.tsx
|
||||
const req = require.context('../src', true, /\.stories\.tsx$/);
|
||||
req.keys().forEach(filename => req(filename));
|
||||
}
|
||||
|
||||
configure(loadStories, module);
|
13
examples/cra-ts-kitchen-sink/.storybook/config.ts
Normal file
13
examples/cra-ts-kitchen-sink/.storybook/config.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { configure, addParameters, addDecorator } from '@storybook/react';
|
||||
import { withA11y } from '@storybook/addon-a11y';
|
||||
|
||||
addDecorator(withA11y);
|
||||
addParameters({
|
||||
options: {
|
||||
brandTitle: 'CRA TypeScript Kitchen Sink',
|
||||
brandUrl: 'https://github.com/storybookjs/storybook/tree/master/examples/cra-ts-kitchen-sink',
|
||||
},
|
||||
});
|
||||
|
||||
// automatically import all files ending in *.stories.(tsx|jsx)
|
||||
configure(require.context('../src/stories', true, /\.stories\.(mdx|[tj]sx?)$/), module);
|
18
examples/cra-ts-kitchen-sink/.storybook/presets.js
Normal file
18
examples/cra-ts-kitchen-sink/.storybook/presets.js
Normal file
@ -0,0 +1,18 @@
|
||||
const path = require('path');
|
||||
|
||||
module.exports = [
|
||||
{
|
||||
name: '@storybook/preset-create-react-app',
|
||||
options: {
|
||||
tsDocgenLoaderOptions: {
|
||||
tsconfigPath: path.resolve(__dirname, '../tsconfig.json'),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '@storybook/addon-docs/react/preset',
|
||||
options: {
|
||||
sourceLoaderOptions: null,
|
||||
},
|
||||
},
|
||||
];
|
@ -1,10 +0,0 @@
|
||||
const path = require('path');
|
||||
|
||||
module.exports = async ({ config }) => {
|
||||
config.module.rules.push({
|
||||
test: /\.tsx?$/,
|
||||
include: path.resolve(__dirname, '../src'),
|
||||
use: [require.resolve('react-docgen-typescript-loader')],
|
||||
});
|
||||
return config;
|
||||
};
|
@ -1,17 +0,0 @@
|
||||
const config = require('../../jest.config');
|
||||
|
||||
module.exports = {
|
||||
...config,
|
||||
roots: [__dirname],
|
||||
moduleNameMapper: {
|
||||
'\\.(jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
|
||||
'<rootDir>/__mocks__/fileMock.js',
|
||||
'\\.(css|scss)$': '<rootDir>/__mocks__/styleMock.js',
|
||||
'\\.(md)$': '<rootDir>/__mocks__/htmlMock.js',
|
||||
},
|
||||
transform: {
|
||||
...config.transform,
|
||||
'^.+\\.svg$': '<rootDir>/node_modules/react-scripts/config/jest/fileTransform.js',
|
||||
},
|
||||
moduleDirectories: ['<rootDir>/node_modules', 'src'],
|
||||
};
|
@ -3,33 +3,46 @@
|
||||
"version": "5.3.0-alpha.35",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "react-scripts build",
|
||||
"build-storybook": "build-storybook -s public",
|
||||
"eject": "react-scripts eject",
|
||||
"lint": "tslint src/**/*.ts{,x}",
|
||||
"storybook": "start-storybook -p 9010 -s public",
|
||||
"test": "react-scripts test --env=jsdom"
|
||||
"start": "react-scripts start",
|
||||
"storybook": "start-storybook -p 9009 -s public",
|
||||
"test": "react-scripts test"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "react-app"
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "^16.8.3",
|
||||
"react-dom": "^16.8.3"
|
||||
"@types/jest": "24.0.19",
|
||||
"@types/node": "12.11.1",
|
||||
"@types/react": "16.9.9",
|
||||
"@types/react-dom": "16.9.2",
|
||||
"react": "^16.10.2",
|
||||
"react-dom": "^16.10.2",
|
||||
"react-scripts": "3.2.0",
|
||||
"typescript": "3.6.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@storybook/addon-a11y": "5.3.0-alpha.35",
|
||||
"@storybook/addon-actions": "5.3.0-alpha.35",
|
||||
"@storybook/addon-info": "5.3.0-alpha.35",
|
||||
"@storybook/addon-options": "5.3.0-alpha.35",
|
||||
"@storybook/addon-docs": "5.3.0-alpha.35",
|
||||
"@storybook/addon-links": "5.3.0-alpha.35",
|
||||
"@storybook/addons": "5.3.0-alpha.35",
|
||||
"@storybook/react": "5.3.0-alpha.35",
|
||||
"@types/enzyme": "^3.9.0",
|
||||
"@types/react": "^16.8.14",
|
||||
"@types/react-dom": "^16.8.2",
|
||||
"enzyme": "^3.9.0",
|
||||
"enzyme-adapter-react-16": "^1.9.1",
|
||||
"enzyme-to-json": "^3.4.1",
|
||||
"fork-ts-checker-webpack-plugin": "^3.0.1",
|
||||
"react-docgen-typescript-loader": "^3.0.1",
|
||||
"react-scripts": "^3.0.1",
|
||||
"tslint": "^5.14.0",
|
||||
"tslint-config-airbnb": "^5.11.1",
|
||||
"typescript": "^3.4.0"
|
||||
"@storybook/preset-create-react-app": "^1.2.0",
|
||||
"@storybook/react": "5.3.0-alpha.35"
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 22 KiB |
@ -2,12 +2,24 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Web site created using create-react-app"
|
||||
/>
|
||||
<link rel="apple-touch-icon" href="logo192.png" />
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tag above.
|
||||
manifest.json provides metadata used when your web app is installed on a
|
||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||
-->
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
Only files inside the `public` folder can be referenced from the HTML.
|
||||
|
||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
@ -15,14 +27,17 @@
|
||||
<title>React App</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
<!--
|
||||
This HTML file is a template.
|
||||
If you open it directly in the browser, you will see an empty page.
|
||||
|
||||
You can add webfonts, meta tags, or analytics to this file.
|
||||
The build step will place the bundled scripts into the <body> tag.
|
||||
To begin the development, run `npm start`.
|
||||
To create a production bundle, use `npm run build`.
|
||||
|
||||
To begin the development, run `npm start` or `yarn start`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
-->
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
BIN
examples/cra-ts-kitchen-sink/public/logo192.png
Normal file
BIN
examples/cra-ts-kitchen-sink/public/logo192.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.4 KiB |
BIN
examples/cra-ts-kitchen-sink/public/logo512.png
Normal file
BIN
examples/cra-ts-kitchen-sink/public/logo512.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
25
examples/cra-ts-kitchen-sink/public/manifest.json
Normal file
25
examples/cra-ts-kitchen-sink/public/manifest.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"short_name": "React App",
|
||||
"name": "Create React App Sample",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
},
|
||||
{
|
||||
"src": "logo192.png",
|
||||
"type": "image/png",
|
||||
"sizes": "192x192"
|
||||
},
|
||||
{
|
||||
"src": "logo512.png",
|
||||
"type": "image/png",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
],
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff"
|
||||
}
|
22
examples/cra-ts-kitchen-sink/src/App.css
Normal file
22
examples/cra-ts-kitchen-sink/src/App.css
Normal file
@ -0,0 +1,22 @@
|
||||
.App {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.App-logo {
|
||||
height: 40vmin;
|
||||
}
|
||||
|
||||
.App-header {
|
||||
background-color: #282c34;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: calc(10px + 2vmin);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.App-link {
|
||||
color: #09d3ac;
|
||||
}
|
26
examples/cra-ts-kitchen-sink/src/App.tsx
Normal file
26
examples/cra-ts-kitchen-sink/src/App.tsx
Normal file
@ -0,0 +1,26 @@
|
||||
import React from 'react';
|
||||
import logo from './logo.svg';
|
||||
import './App.css';
|
||||
|
||||
const App: React.FC = () => {
|
||||
return (
|
||||
<div className="App">
|
||||
<header className="App-header">
|
||||
<img src={logo} className="App-logo" alt="logo" />
|
||||
<p>
|
||||
Edit <code>src/App.tsx</code> and save to reload.
|
||||
</p>
|
||||
<a
|
||||
className="App-link"
|
||||
href="https://reactjs.org"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Learn React
|
||||
</a>
|
||||
</header>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
@ -1,12 +0,0 @@
|
||||
import * as React from 'react';
|
||||
import { storiesOf } from '@storybook/react';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import Button from './Button';
|
||||
|
||||
storiesOf('Button', module).add(
|
||||
'simple button',
|
||||
() => <Button onClick={action('button clicked')}>OK</Button>,
|
||||
{
|
||||
info: { inline: true },
|
||||
}
|
||||
);
|
@ -1,23 +0,0 @@
|
||||
import * as React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import Button from './Button';
|
||||
|
||||
describe('Button', () => {
|
||||
it('renders', () => {
|
||||
const wrapper = shallow(<Button>OK</Button>);
|
||||
expect(wrapper).toMatchInlineSnapshot(`
|
||||
<button
|
||||
type="button"
|
||||
>
|
||||
OK
|
||||
</button>
|
||||
`);
|
||||
});
|
||||
|
||||
it('calls onClick on button click', () => {
|
||||
const handleClick = jest.fn();
|
||||
const wrapper = shallow(<Button onClick={handleClick}>OK</Button>);
|
||||
wrapper.find('button').simulate('click');
|
||||
expect(handleClick).toHaveBeenCalled();
|
||||
});
|
||||
});
|
@ -1,17 +0,0 @@
|
||||
import React, { FunctionComponent } from 'react';
|
||||
|
||||
interface Props {
|
||||
/**
|
||||
* Click event handler
|
||||
* @default null
|
||||
*/
|
||||
onClick?: () => void;
|
||||
}
|
||||
|
||||
const Button: FunctionComponent<Props> = ({ children, onClick }) => (
|
||||
<button type="button" onClick={onClick}>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
|
||||
export default Button;
|
13
examples/cra-ts-kitchen-sink/src/index.css
Normal file
13
examples/cra-ts-kitchen-sink/src/index.css
Normal file
@ -0,0 +1,13 @@
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||
sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||
monospace;
|
||||
}
|
12
examples/cra-ts-kitchen-sink/src/index.tsx
Normal file
12
examples/cra-ts-kitchen-sink/src/index.tsx
Normal file
@ -0,0 +1,12 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import './index.css';
|
||||
import App from './App';
|
||||
import * as serviceWorker from './serviceWorker';
|
||||
|
||||
ReactDOM.render(<App />, document.getElementById('root'));
|
||||
|
||||
// If you want your app to work offline and load faster, you can change
|
||||
// unregister() to register() below. Note this comes with some pitfalls.
|
||||
// Learn more about service workers: https://bit.ly/CRA-PWA
|
||||
serviceWorker.unregister();
|
1
examples/cra-ts-kitchen-sink/src/logo.svg
Normal file
1
examples/cra-ts-kitchen-sink/src/logo.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 8.0 KiB |
143
examples/cra-ts-kitchen-sink/src/serviceWorker.ts
Normal file
143
examples/cra-ts-kitchen-sink/src/serviceWorker.ts
Normal file
@ -0,0 +1,143 @@
|
||||
// This optional code is used to register a service worker.
|
||||
// register() is not called by default.
|
||||
|
||||
// This lets the app load faster on subsequent visits in production, and gives
|
||||
// it offline capabilities. However, it also means that developers (and users)
|
||||
// will only see deployed updates on subsequent visits to a page, after all the
|
||||
// existing tabs open on the page have been closed, since previously cached
|
||||
// resources are updated in the background.
|
||||
|
||||
// To learn more about the benefits of this model and instructions on how to
|
||||
// opt-in, read https://bit.ly/CRA-PWA
|
||||
|
||||
const isLocalhost = Boolean(
|
||||
window.location.hostname === 'localhost' ||
|
||||
// [::1] is the IPv6 localhost address.
|
||||
window.location.hostname === '[::1]' ||
|
||||
// 127.0.0.1/8 is considered localhost for IPv4.
|
||||
window.location.hostname.match(
|
||||
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
|
||||
)
|
||||
);
|
||||
|
||||
type Config = {
|
||||
onSuccess?: (registration: ServiceWorkerRegistration) => void;
|
||||
onUpdate?: (registration: ServiceWorkerRegistration) => void;
|
||||
};
|
||||
|
||||
export function register(config?: Config) {
|
||||
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
|
||||
// The URL constructor is available in all browsers that support SW.
|
||||
const publicUrl = new URL(
|
||||
(process as { env: { [key: string]: string } }).env.PUBLIC_URL,
|
||||
window.location.href
|
||||
);
|
||||
if (publicUrl.origin !== window.location.origin) {
|
||||
// Our service worker won't work if PUBLIC_URL is on a different origin
|
||||
// from what our page is served on. This might happen if a CDN is used to
|
||||
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
|
||||
return;
|
||||
}
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
|
||||
|
||||
if (isLocalhost) {
|
||||
// This is running on localhost. Let's check if a service worker still exists or not.
|
||||
checkValidServiceWorker(swUrl, config);
|
||||
|
||||
// Add some additional logging to localhost, pointing developers to the
|
||||
// service worker/PWA documentation.
|
||||
navigator.serviceWorker.ready.then(() => {
|
||||
console.log(
|
||||
'This web app is being served cache-first by a service ' +
|
||||
'worker. To learn more, visit https://bit.ly/CRA-PWA'
|
||||
);
|
||||
});
|
||||
} else {
|
||||
// Is not localhost. Just register service worker
|
||||
registerValidSW(swUrl, config);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function registerValidSW(swUrl: string, config?: Config) {
|
||||
navigator.serviceWorker
|
||||
.register(swUrl)
|
||||
.then(registration => {
|
||||
registration.onupdatefound = () => {
|
||||
const installingWorker = registration.installing;
|
||||
if (installingWorker == null) {
|
||||
return;
|
||||
}
|
||||
installingWorker.onstatechange = () => {
|
||||
if (installingWorker.state === 'installed') {
|
||||
if (navigator.serviceWorker.controller) {
|
||||
// At this point, the updated precached content has been fetched,
|
||||
// but the previous service worker will still serve the older
|
||||
// content until all client tabs are closed.
|
||||
console.log(
|
||||
'New content is available and will be used when all ' +
|
||||
'tabs for this page are closed. See https://bit.ly/CRA-PWA.'
|
||||
);
|
||||
|
||||
// Execute callback
|
||||
if (config && config.onUpdate) {
|
||||
config.onUpdate(registration);
|
||||
}
|
||||
} else {
|
||||
// At this point, everything has been precached.
|
||||
// It's the perfect time to display a
|
||||
// "Content is cached for offline use." message.
|
||||
console.log('Content is cached for offline use.');
|
||||
|
||||
// Execute callback
|
||||
if (config && config.onSuccess) {
|
||||
config.onSuccess(registration);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error during service worker registration:', error);
|
||||
});
|
||||
}
|
||||
|
||||
function checkValidServiceWorker(swUrl: string, config?: Config) {
|
||||
// Check if the service worker can be found. If it can't reload the page.
|
||||
fetch(swUrl)
|
||||
.then(response => {
|
||||
// Ensure service worker exists, and that we really are getting a JS file.
|
||||
const contentType = response.headers.get('content-type');
|
||||
if (
|
||||
response.status === 404 ||
|
||||
(contentType != null && contentType.indexOf('javascript') === -1)
|
||||
) {
|
||||
// No service worker found. Probably a different app. Reload the page.
|
||||
navigator.serviceWorker.ready.then(registration => {
|
||||
registration.unregister().then(() => {
|
||||
window.location.reload();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// Service worker found. Proceed as normal.
|
||||
registerValidSW(swUrl, config);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
console.log(
|
||||
'No internet connection found. App is running in offline mode.'
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export function unregister() {
|
||||
if ('serviceWorker' in navigator) {
|
||||
navigator.serviceWorker.ready.then(registration => {
|
||||
registration.unregister();
|
||||
});
|
||||
}
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
import Enzyme from 'enzyme';
|
||||
import Adapter from 'enzyme-adapter-react-16';
|
||||
|
||||
Enzyme.configure({ adapter: new Adapter() });
|
@ -0,0 +1,14 @@
|
||||
import React from 'react';
|
||||
import { linkTo } from '@storybook/addon-links';
|
||||
import { Welcome } from '@storybook/react/demo';
|
||||
|
||||
export default {
|
||||
title: 'Welcome',
|
||||
component: Welcome,
|
||||
};
|
||||
|
||||
export const toStorybook = () => <Welcome showApp={linkTo('Button')} />;
|
||||
|
||||
toStorybook.story = {
|
||||
name: 'to Storybook',
|
||||
};
|
@ -0,0 +1,20 @@
|
||||
import React from "react";
|
||||
import { action } from "@storybook/addon-actions";
|
||||
import { Button } from "./Button";
|
||||
|
||||
export default {
|
||||
title: "Button",
|
||||
component: Button,
|
||||
};
|
||||
|
||||
export const text = () => (
|
||||
<Button onClick={action("clicked")}>Hello Button</Button>
|
||||
);
|
||||
|
||||
export const emoji = () => (
|
||||
<Button onClick={action("clicked")}>
|
||||
<span role="img" aria-label="so cool">
|
||||
😀 😎 👍 💯
|
||||
</span>
|
||||
</Button>
|
||||
);
|
17
examples/cra-ts-kitchen-sink/src/stories/Button.tsx
Normal file
17
examples/cra-ts-kitchen-sink/src/stories/Button.tsx
Normal file
@ -0,0 +1,17 @@
|
||||
import React, { FC } from "react";
|
||||
|
||||
interface ButtonProps {
|
||||
/**
|
||||
* Simple click handler
|
||||
*/
|
||||
onClick?: () => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* The world's most _basic_ button
|
||||
*/
|
||||
export const Button: FC<ButtonProps> = ({ children, onClick }) => (
|
||||
<button onClick={onClick} type="button">
|
||||
{children}
|
||||
</button>
|
||||
);
|
18
examples/cra-ts-kitchen-sink/src/stories/Test.stories.mdx
Normal file
18
examples/cra-ts-kitchen-sink/src/stories/Test.stories.mdx
Normal file
@ -0,0 +1,18 @@
|
||||
import { Meta, Story, Preview, Props } from '@storybook/addon-docs/blocks';
|
||||
import { Button } from './Button';
|
||||
|
||||
<Meta title="Test" />
|
||||
|
||||
Here's some _markdown_!
|
||||
|
||||
# Preview
|
||||
|
||||
<Preview>
|
||||
<Story name="button">
|
||||
<Button>hello</Button>
|
||||
</Story>
|
||||
</Preview>
|
||||
|
||||
# Props
|
||||
|
||||
<Props of={Button} />
|
@ -0,0 +1,75 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
/**
|
||||
* Button functional component
|
||||
*/
|
||||
export const ButtonFn = ({ onClick, children }) => <button onClick={onClick}>{children}</button>;
|
||||
ButtonFn.propTypes = {
|
||||
/**
|
||||
* onClick description
|
||||
*/
|
||||
onClick: PropTypes.func
|
||||
};
|
||||
ButtonFn.defaultProps = {
|
||||
onClick: null,
|
||||
};
|
||||
|
||||
/**
|
||||
* Button class React.Component
|
||||
*/
|
||||
export class ButtonReactComponent extends React.Component {
|
||||
render() {
|
||||
const { onClick, children } = this.props;
|
||||
return <button onClick={onClick}>{children}</button>;
|
||||
}
|
||||
}
|
||||
ButtonReactComponent.propTypes = {
|
||||
/**
|
||||
* onClick description
|
||||
*/
|
||||
onClick: PropTypes.func,
|
||||
};
|
||||
ButtonReactComponent.defaultProps = {
|
||||
onClick: null,
|
||||
};
|
||||
|
||||
/**
|
||||
* Button class Component
|
||||
*/
|
||||
export class ButtonComponent extends Component {
|
||||
render() {
|
||||
const { onClick, children } = this.props;
|
||||
return <button onClick={onClick}>{children}</button>;
|
||||
}
|
||||
}
|
||||
ButtonComponent.propTypes = {
|
||||
/**
|
||||
* onClick description
|
||||
*/
|
||||
onClick: PropTypes.func,
|
||||
};
|
||||
ButtonComponent.defaultProps = {
|
||||
onClick: null,
|
||||
};
|
||||
|
||||
/**
|
||||
* Button class static props
|
||||
*/
|
||||
export class ButtonStaticProps extends Component {
|
||||
static propTypes = {
|
||||
/**
|
||||
* onClick description
|
||||
*/
|
||||
onClick: PropTypes.func,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
onClick: null,
|
||||
};
|
||||
|
||||
render() {
|
||||
const { onClick, children } = this.props;
|
||||
return <button onClick={onClick}>{children}</button>;
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
import React, { FC, FunctionComponent, SyntheticEvent } from 'react';
|
||||
|
||||
interface ButtonProps {
|
||||
/**
|
||||
* onClick description
|
||||
*/
|
||||
onClick?: (e: SyntheticEvent) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Button functional component (React.FC)
|
||||
*/
|
||||
export const ButtonReactFC: React.FC<ButtonProps> = ({ onClick, children }) => (
|
||||
<button onClick={onClick}>{children}</button>
|
||||
);
|
||||
// @ts-ignore
|
||||
ButtonReactFC.defaultProps = {
|
||||
onClick: null,
|
||||
};
|
||||
|
||||
/**
|
||||
* Button functional component (FC)
|
||||
*/
|
||||
export const ButtonFC: FC<ButtonProps> = ({ onClick, children }) => (
|
||||
<button onClick={onClick}>{children}</button>
|
||||
);
|
||||
// @ts-ignore
|
||||
ButtonFC.defaultProps = {
|
||||
onClick: null,
|
||||
};
|
||||
|
||||
/**
|
||||
* Button functional component (FunctionComponent)
|
||||
*/
|
||||
export const ButtonFunctionComponent: FunctionComponent<ButtonProps> = ({ onClick, children }) => (
|
||||
<button onClick={onClick}>{children}</button>
|
||||
);
|
||||
// @ts-ignore
|
||||
ButtonFunctionComponent.defaultProps = {
|
||||
onClick: null,
|
||||
};
|
@ -0,0 +1,29 @@
|
||||
import { Meta, Props, Description } from '@storybook/addon-docs/blocks';
|
||||
import * as DocgenJS from './DocgenJS';
|
||||
import * as DocgenTS from './DocgenTS';
|
||||
|
||||
<Meta title="Docgen|Props" />
|
||||
|
||||
export const DescriptionProps = ({ of }) => (
|
||||
<>
|
||||
<h2>{of.displayName}</h2>
|
||||
<Description of={of} />
|
||||
<Props of={of} />
|
||||
</>
|
||||
);
|
||||
|
||||
# React Docgen Test Cases
|
||||
|
||||
<div>
|
||||
{Object.entries(DocgenJS).map(([key, val]) => (
|
||||
<DescriptionProps key={key} of={val} />
|
||||
))}
|
||||
</div>
|
||||
|
||||
# React Typescript Docgen Test Cases
|
||||
|
||||
<div>
|
||||
{Object.entries(DocgenTS).map(([key, val]) => (
|
||||
<DescriptionProps key={key} of={val} />
|
||||
))}
|
||||
</div>
|
@ -0,0 +1,465 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
export const ButtonTooManyProps = ({ onClick, children }) => <button onClick={onClick}>{children}</button>;
|
||||
ButtonTooManyProps.propTypes = {
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick1: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick2: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick3: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick4: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick5: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick6: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick7: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick8: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick9: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick10: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick11: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick12: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick13: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick14: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick15: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick16: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick17: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick18: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick19: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick20: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick21: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick22: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick23: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick24: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick25: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick26: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick27: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick28: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick29: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick30: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick31: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick32: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick33: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick34: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick35: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick36: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick37: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick38: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick39: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick40: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick41: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick42: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick43: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick44: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick45: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick46: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick47: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick48: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick49: PropTypes.func,
|
||||
/**
|
||||
* onClick description
|
||||
* @param {SyntheticEvent} event - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event1 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event2 - React's original SyntheticEvent.
|
||||
* @param {SyntheticEvent} event3 - React's original SyntheticEvent.
|
||||
* @returns {void}
|
||||
*/
|
||||
onClick50: PropTypes.func
|
||||
};
|
@ -0,0 +1,10 @@
|
||||
import { Meta, Props } from '@storybook/addon-docs/blocks';
|
||||
import { ButtonTooManyProps } from "./jsdoc-perfo";
|
||||
|
||||
<Meta title="Docgen|Prop types/jsdoc-perfo" />
|
||||
|
||||
## Render 150 props with JSDoc tags
|
||||
|
||||
<Props of={ButtonTooManyProps} />
|
||||
<Props of={ButtonTooManyProps} />
|
||||
<Props of={ButtonTooManyProps} />
|
@ -0,0 +1,232 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
export const JsDocProps = () => <div>JSDoc Props!</div>;
|
||||
JsDocProps.propTypes = {
|
||||
/**
|
||||
* simple description.
|
||||
*/
|
||||
case1: PropTypes.string,
|
||||
/**
|
||||
* multi
|
||||
* lines
|
||||
* description
|
||||
*/
|
||||
case2: PropTypes.string,
|
||||
/**
|
||||
* *description* **with** `formatting`
|
||||
*/
|
||||
case3: PropTypes.string,
|
||||
/**
|
||||
* simple description and dummy JSDoc tag.
|
||||
* @param event
|
||||
*/
|
||||
case4: PropTypes.string,
|
||||
/**
|
||||
* @param event
|
||||
*/
|
||||
case5: PropTypes.string,
|
||||
/**
|
||||
* simple description with a @.
|
||||
*/
|
||||
case6: PropTypes.string,
|
||||
case7: PropTypes.func,
|
||||
/**
|
||||
* func with a simple description.
|
||||
*/
|
||||
case8: PropTypes.func,
|
||||
/**
|
||||
* @param event
|
||||
*/
|
||||
case9: PropTypes.func,
|
||||
/**
|
||||
* param with name
|
||||
* @param event
|
||||
*/
|
||||
case10: PropTypes.func,
|
||||
/**
|
||||
* param with name & type
|
||||
* @param {SyntheticEvent} event
|
||||
*/
|
||||
case11: PropTypes.func,
|
||||
/**
|
||||
* param with name, type & description
|
||||
* @param {SyntheticEvent} event - React's original event
|
||||
*/
|
||||
case12: PropTypes.func,
|
||||
/**
|
||||
* param with type
|
||||
* @param {SyntheticEvent}
|
||||
*/
|
||||
case13: PropTypes.func,
|
||||
/**
|
||||
* param with type & description
|
||||
* @param {SyntheticEvent} - React's original event
|
||||
*/
|
||||
case14: PropTypes.func,
|
||||
/**
|
||||
* param with name & description
|
||||
* @param event - React's original event
|
||||
*/
|
||||
case15: PropTypes.func,
|
||||
/**
|
||||
* autofix event-
|
||||
* @param event- React's original event
|
||||
*/
|
||||
case16: PropTypes.func,
|
||||
/**
|
||||
* autofix event.
|
||||
* @param event.
|
||||
* @returns {string}
|
||||
*/
|
||||
case17: PropTypes.func,
|
||||
/**
|
||||
* with an empty param.
|
||||
* @param
|
||||
*/
|
||||
case18: PropTypes.func,
|
||||
/**
|
||||
* with multiple empty params.
|
||||
* @param
|
||||
* @param
|
||||
* @param
|
||||
*/
|
||||
case19: PropTypes.func,
|
||||
/**
|
||||
* with arg alias.
|
||||
* @arg event
|
||||
*/
|
||||
case20: PropTypes.func,
|
||||
/**
|
||||
* with argument alias.
|
||||
* @argument event
|
||||
*/
|
||||
case21: PropTypes.func,
|
||||
/**
|
||||
* with multiple params.
|
||||
* @param {SyntheticEvent} event
|
||||
* @param {string} stringValue
|
||||
* @param {number} numberValue
|
||||
*/
|
||||
case22: PropTypes.func,
|
||||
/**
|
||||
* with an empty returns
|
||||
* @returns
|
||||
*/
|
||||
case23: PropTypes.func,
|
||||
/**
|
||||
* with a returns with a type
|
||||
* @returns {SyntheticEvent}
|
||||
*/
|
||||
case24: PropTypes.func,
|
||||
/**
|
||||
* with a returns with a type & description
|
||||
* @returns {SyntheticEvent} - React's original event
|
||||
*/
|
||||
case25: PropTypes.func,
|
||||
/**
|
||||
* single param and a returns
|
||||
* @param {string} stringValue
|
||||
* @returns {SyntheticEvent} - React's original event
|
||||
*/
|
||||
case26: PropTypes.func,
|
||||
/**
|
||||
* multiple params and a returns
|
||||
* @param {string} stringValue
|
||||
* @param {number} numberValue
|
||||
* @returns {SyntheticEvent} - React's original event
|
||||
*/
|
||||
case27: PropTypes.func,
|
||||
/**
|
||||
* multiple returns
|
||||
* @returns {SyntheticEvent} - React's original event
|
||||
* @returns {string} - Second returns
|
||||
*/
|
||||
case28: PropTypes.func,
|
||||
/**
|
||||
* param with unsupported JSDoc tags
|
||||
* @param {SyntheticEvent} event - React's original event
|
||||
* @type {number}
|
||||
* @version 2
|
||||
*/
|
||||
case29: PropTypes.func,
|
||||
/**
|
||||
* param record type
|
||||
* @param {{a: number, b: string}} myType
|
||||
*/
|
||||
case30: PropTypes.func,
|
||||
/**
|
||||
* param array type
|
||||
* @param {string[]} myType
|
||||
*/
|
||||
case31: PropTypes.func,
|
||||
/**
|
||||
* param union type
|
||||
* @param {(number|boolean)} myType
|
||||
*/
|
||||
case32: PropTypes.func,
|
||||
/**
|
||||
* param any type
|
||||
* @param {*} myType
|
||||
*/
|
||||
case33: PropTypes.func,
|
||||
/**
|
||||
* param repeatable type
|
||||
* @param {...number} myType
|
||||
*/
|
||||
case34: PropTypes.func,
|
||||
/**
|
||||
* optional param
|
||||
* @param {number} [myType]
|
||||
*/
|
||||
case35: PropTypes.func,
|
||||
/**
|
||||
* optional param
|
||||
* @param {number} [myType]
|
||||
*/
|
||||
case36: PropTypes.func,
|
||||
/**
|
||||
* dot in param name
|
||||
* @param {number} my.type
|
||||
*/
|
||||
case37: PropTypes.func,
|
||||
/**
|
||||
* returns record type
|
||||
* @returns {{a: number, b: string}}
|
||||
*/
|
||||
case38: PropTypes.func,
|
||||
/**
|
||||
* returns array type
|
||||
* @returns {string[]}
|
||||
*/
|
||||
case39: PropTypes.func,
|
||||
/**
|
||||
* returns union type
|
||||
* @returns {(number|boolean)}
|
||||
*/
|
||||
case40: PropTypes.func,
|
||||
/**
|
||||
* returns any type
|
||||
* @returns {*}
|
||||
*/
|
||||
case41: PropTypes.func,
|
||||
/**
|
||||
* returns primitive
|
||||
* @returns {string}
|
||||
*/
|
||||
case42: PropTypes.func,
|
||||
/**
|
||||
* returns void
|
||||
* @returns {void}
|
||||
*/
|
||||
case43: PropTypes.func,
|
||||
};
|
||||
|
||||
export const FailingJsDocProps = () => <div>Failing JSDoc Props!</div>;
|
||||
FailingJsDocProps.propTypes = {
|
||||
/**
|
||||
* autofix event.
|
||||
* @param event.
|
||||
*/
|
||||
case: PropTypes.func,
|
||||
};
|
@ -0,0 +1,7 @@
|
||||
import { Meta, Props } from '@storybook/addon-docs/blocks';
|
||||
import { JsDocProps, FailingJsDocProps } from "./jsdoc";
|
||||
|
||||
<Meta title="Docgen|Prop types/jsdoc" />
|
||||
|
||||
<Props of={JsDocProps} />
|
||||
<Props of={FailingJsDocProps} />
|
@ -1,8 +0,0 @@
|
||||
export const addDecorator: any;
|
||||
export const addParameters: any;
|
||||
export const configure: any;
|
||||
export const forceReRender: any;
|
||||
export const getStorybook: any;
|
||||
export const raw: any;
|
||||
export const setAddon: any;
|
||||
export const storiesOf: any;
|
@ -1,25 +1,25 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": "src",
|
||||
"paths": { "*": ["types/*"] },
|
||||
"target": "es5",
|
||||
"module": "esnext",
|
||||
"lib" : ["esnext", "dom"],
|
||||
"jsx": "preserve",
|
||||
"moduleResolution": "node",
|
||||
"esModuleInterop": true,
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"esnext"
|
||||
],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": false,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react"
|
||||
},
|
||||
"include": [
|
||||
"src"
|
||||
],
|
||||
"exclude": [
|
||||
"src/setupTests.js"
|
||||
]
|
||||
}
|
||||
|
@ -97,6 +97,12 @@ export const PropRow: FC<PropRowProps> = ({
|
||||
<PrettyPropType type={type} />
|
||||
</StyledPropDef>
|
||||
</td>
|
||||
<td>{defaultValue === undefined ? '-' : <PrettyPropVal value={defaultValue} />}</td>
|
||||
<td>
|
||||
{defaultValue === null || defaultValue === undefined ? (
|
||||
'-'
|
||||
) : (
|
||||
<PrettyPropVal value={defaultValue} />
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
|
@ -138,6 +138,8 @@
|
||||
"@storybook/eslint-config-storybook": "^2.0.0",
|
||||
"@storybook/linter-config": "^2.0.0",
|
||||
"@testing-library/react": "^9.2.0",
|
||||
"@types/doctrine": "^0.0.3",
|
||||
"@types/enzyme": "^3.10.3",
|
||||
"@types/jest": "^24.0.11",
|
||||
"@types/lodash": "^4.14.129",
|
||||
"@types/node": "^12.7.9",
|
||||
|
194
yarn.lock
194
yarn.lock
@ -2080,25 +2080,6 @@
|
||||
webpack-dev-server "3.2.0"
|
||||
xmldom "0.1.27"
|
||||
|
||||
"@fimbul/bifrost@^0.21.0":
|
||||
version "0.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@fimbul/bifrost/-/bifrost-0.21.0.tgz#d0fafa25938fda475657a6a1e407a21bbe02c74e"
|
||||
integrity sha512-ou8VU+nTmOW1jeg+FT+sn+an/M0Xb9G16RucrfhjXGWv1Q97kCoM5CG9Qj7GYOSdu7km72k7nY83Eyr53Bkakg==
|
||||
dependencies:
|
||||
"@fimbul/ymir" "^0.21.0"
|
||||
get-caller-file "^2.0.0"
|
||||
tslib "^1.8.1"
|
||||
tsutils "^3.5.0"
|
||||
|
||||
"@fimbul/ymir@^0.21.0":
|
||||
version "0.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@fimbul/ymir/-/ymir-0.21.0.tgz#8525726787aceeafd4e199472c0d795160b5d4a1"
|
||||
integrity sha512-T/y7WqPsm4n3zhT08EpB5sfdm2Kvw3gurAxr2Lr5dQeLi8ZsMlNT/Jby+ZmuuAAd1PnXYzKp+2SXgIkQIIMCUg==
|
||||
dependencies:
|
||||
inversify "^5.0.0"
|
||||
reflect-metadata "^0.1.12"
|
||||
tslib "^1.8.1"
|
||||
|
||||
"@glimmer/di@^0.2.0":
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@glimmer/di/-/di-0.2.1.tgz#5286b6b32040232b751138f6d006130c728d4b3d"
|
||||
@ -3382,6 +3363,25 @@
|
||||
remark-lint "^6.0.4"
|
||||
remark-preset-lint-recommended "^3.0.2"
|
||||
|
||||
"@storybook/node-logger@^5.2.4":
|
||||
version "5.2.5"
|
||||
resolved "https://registry.yarnpkg.com/@storybook/node-logger/-/node-logger-5.2.5.tgz#87f53de795db6eed912b54d3cca82fd7b7857771"
|
||||
integrity sha512-UNyXGOhOr4Bn9wKwBTZABTBXQzrgvGxPLSmvAFZuMx9ZhqoT/EXAuLUl0/wiJtkyuYpoOOskNwIdKxLBdTKS2w==
|
||||
dependencies:
|
||||
chalk "^2.4.2"
|
||||
core-js "^3.0.1"
|
||||
npmlog "^4.1.2"
|
||||
pretty-hrtime "^1.0.3"
|
||||
regenerator-runtime "^0.12.1"
|
||||
|
||||
"@storybook/preset-create-react-app@^1.2.0":
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@storybook/preset-create-react-app/-/preset-create-react-app-1.2.0.tgz#081fe3d66a97721d9e82e6cf198f0f9d57bc489c"
|
||||
integrity sha512-SvfHsEJ0wA+9goJOci2P2CvI0K9AQEOuPzdB092ts21PIxOj2KQUiTdR/UjodNUcKguHZzPeMOjJr23EFLf4qA==
|
||||
dependencies:
|
||||
"@storybook/node-logger" "^5.2.4"
|
||||
react-docgen-typescript-loader "^3.3.0"
|
||||
|
||||
"@svgr/babel-plugin-add-jsx-attribute@^4.2.0":
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-4.2.0.tgz#dadcb6218503532d6884b210e7f3c502caaa44b1"
|
||||
@ -3628,7 +3628,12 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/core-js/-/core-js-2.5.2.tgz#d4c25420044d4a5b65e00a82fc04b7824b62691f"
|
||||
integrity sha512-+NPqjXgyA02xTHKJDeDca9u8Zr42ts6jhdND4C3PrPeQ35RJa0dmfAedXW7a9K4N1QcBbuWI1nSfGK4r1eVFCQ==
|
||||
|
||||
"@types/enzyme@^3.9.0":
|
||||
"@types/doctrine@^0.0.3":
|
||||
version "0.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/doctrine/-/doctrine-0.0.3.tgz#e892d293c92c9c1d3f9af72c15a554fbc7e0895a"
|
||||
integrity sha1-6JLSk8ksnB0/mvcsFaVU+8fgiVo=
|
||||
|
||||
"@types/enzyme@^3.10.3":
|
||||
version "3.10.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/enzyme/-/enzyme-3.10.3.tgz#02b6c5ac7d0472005944a652e79045e2f6c66804"
|
||||
integrity sha512-f/Kcb84sZOSZiBPCkr4He9/cpuSLcKRyQaEE20Q30Prx0Dn6wcyMAWI0yofL6yvd9Ht9G7EVkQeRqK0n5w8ILw==
|
||||
@ -3739,6 +3744,13 @@
|
||||
dependencies:
|
||||
"@types/jest-diff" "*"
|
||||
|
||||
"@types/jest@24.0.19":
|
||||
version "24.0.19"
|
||||
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.0.19.tgz#f7036058d2a5844fe922609187c0ad8be430aff5"
|
||||
integrity sha512-YYiqfSjocv7lk5H/T+v5MjATYjaTMsUkbDnjGqSMoO88jWdtJXJV4ST/7DKZcoMHMBvB2SeSfyOzZfkxXHR5xg==
|
||||
dependencies:
|
||||
"@types/jest-diff" "*"
|
||||
|
||||
"@types/jest@^23.0.2", "@types/jest@^23.3.1":
|
||||
version "23.3.14"
|
||||
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-23.3.14.tgz#37daaf78069e7948520474c87b80092ea912520a"
|
||||
@ -3793,6 +3805,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.7.tgz#57682a9771a3f7b09c2497f28129a0462966524a"
|
||||
integrity sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA==
|
||||
|
||||
"@types/node@12.11.1":
|
||||
version "12.11.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.1.tgz#1fd7b821f798b7fa29f667a1be8f3442bb8922a3"
|
||||
integrity sha512-TJtwsqZ39pqcljJpajeoofYRfeZ7/I/OMUQ5pR4q5wOKf2ocrUvBAZUMhWsOvKx3dVc/aaV5GluBivt0sWqA5A==
|
||||
|
||||
"@types/node@^6.0.0":
|
||||
version "6.14.8"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-6.14.8.tgz#faf07db8ccc3dec8cb4d301869c1ad872b9663a1"
|
||||
@ -3874,13 +3891,20 @@
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react-dom@*", "@types/react-dom@^16.8.2":
|
||||
"@types/react-dom@*":
|
||||
version "16.9.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.3.tgz#4006ff0e13958af91313869077c04cb20d9b9d04"
|
||||
integrity sha512-FUuZKXPr9qlzUT9lhuzrZgLjH63TvNn28Ch3MvKG4B+F52zQtO8DtE0Opbncy3xaucNZM2WIPfuNTgkbKx5Brg==
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react-dom@16.9.2":
|
||||
version "16.9.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.2.tgz#90f9e6c161850be1feb31d2f448121be2a4f3b47"
|
||||
integrity sha512-hgPbBoI1aTSTvZwo8HYw35UaTldW6n2ETLvHAcfcg1FaOuBV3olmyCe5eMpx2WybWMBPv0MdU2t5GOcQhP+3zA==
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react-lifecycles-compat@^3.0.1":
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-lifecycles-compat/-/react-lifecycles-compat-3.0.1.tgz#a0b1fe18cfb9435bd52737829a69cbe93faf32e2"
|
||||
@ -3944,6 +3968,14 @@
|
||||
"@types/prop-types" "*"
|
||||
csstype "^2.2.0"
|
||||
|
||||
"@types/react@16.9.9":
|
||||
version "16.9.9"
|
||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.9.tgz#a62c6f40f04bc7681be5e20975503a64fe783c3a"
|
||||
integrity sha512-L+AudFJkDukk+ukInYvpoAPyJK5q1GanFOINOJnM0w6tUgITuWvJ4jyoBPFL7z4/L8hGLd+K/6xR5uUjXu0vVg==
|
||||
dependencies:
|
||||
"@types/prop-types" "*"
|
||||
csstype "^2.2.0"
|
||||
|
||||
"@types/selenium-webdriver@^3.0.0":
|
||||
version "3.0.16"
|
||||
resolved "https://registry.yarnpkg.com/@types/selenium-webdriver/-/selenium-webdriver-3.0.16.tgz#50a4755f8e33edacd9c406729e9b930d2451902a"
|
||||
@ -7950,11 +7982,6 @@ buffer@^5.0.2, buffer@^5.1.0:
|
||||
base64-js "^1.0.2"
|
||||
ieee754 "^1.1.4"
|
||||
|
||||
builtin-modules@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
|
||||
integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=
|
||||
|
||||
builtin-status-codes@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
|
||||
@ -9000,7 +9027,7 @@ commander@2.8.x:
|
||||
dependencies:
|
||||
graceful-readlink ">= 1.0.0"
|
||||
|
||||
commander@^2.11.0, commander@^2.12.1, commander@^2.15.1, commander@^2.18.0, commander@^2.19.0, commander@^2.20.0, commander@^2.6.0, commander@^2.8.1, commander@^2.9.0, commander@~2.20.3:
|
||||
commander@^2.11.0, commander@^2.15.1, commander@^2.18.0, commander@^2.19.0, commander@^2.20.0, commander@^2.6.0, commander@^2.8.1, commander@^2.9.0, commander@~2.20.3:
|
||||
version "2.20.3"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
|
||||
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
|
||||
@ -10649,14 +10676,6 @@ dns-txt@^2.0.2:
|
||||
dependencies:
|
||||
buffer-indexof "^1.0.0"
|
||||
|
||||
doctrine@0.7.2:
|
||||
version "0.7.2"
|
||||
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-0.7.2.tgz#7cb860359ba3be90e040b26b729ce4bfa654c523"
|
||||
integrity sha1-fLhgNZujvpDgQLJrcpzkv6ZUxSM=
|
||||
dependencies:
|
||||
esutils "^1.1.6"
|
||||
isarray "0.0.1"
|
||||
|
||||
doctrine@1.5.0:
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa"
|
||||
@ -12195,11 +12214,6 @@ estree-walker@^0.6.1:
|
||||
resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.6.1.tgz#53049143f40c6eb918b23671d1fe3219f3a1b362"
|
||||
integrity sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==
|
||||
|
||||
esutils@^1.1.6:
|
||||
version "1.1.6"
|
||||
resolved "https://registry.yarnpkg.com/esutils/-/esutils-1.1.6.tgz#c01ccaa9ae4b897c6d0c3e210ae52f3c7a844375"
|
||||
integrity sha1-wBzKqa5LiXxtDD4hCuUvPHqEQ3U=
|
||||
|
||||
esutils@^2.0.0, esutils@^2.0.2:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
|
||||
@ -14055,7 +14069,7 @@ get-caller-file@^1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a"
|
||||
integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==
|
||||
|
||||
get-caller-file@^2.0.0, get-caller-file@^2.0.1, get-caller-file@^2.0.5:
|
||||
get-caller-file@^2.0.1, get-caller-file@^2.0.5:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
|
||||
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
|
||||
@ -15909,11 +15923,6 @@ invariant@2.2.4, invariant@^2.2.1, invariant@^2.2.2, invariant@^2.2.3, invariant
|
||||
dependencies:
|
||||
loose-envify "^1.0.0"
|
||||
|
||||
inversify@^5.0.0:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/inversify/-/inversify-5.0.1.tgz#500d709b1434896ce5a0d58915c4a4210e34fb6e"
|
||||
integrity sha512-Ieh06s48WnEYGcqHepdsJUIJUXpwH5o5vodAX+DK2JA/gjy4EbEcQZxw+uFfzysmKjiLXGYwNG3qDZsKVMcINQ==
|
||||
|
||||
invert-kv@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6"
|
||||
@ -24629,7 +24638,7 @@ react-devtools-core@^3.4.2, react-devtools-core@^3.6.0:
|
||||
shell-quote "^1.6.1"
|
||||
ws "^3.3.1"
|
||||
|
||||
react-docgen-typescript-loader@^3.0.1:
|
||||
react-docgen-typescript-loader@^3.3.0:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/react-docgen-typescript-loader/-/react-docgen-typescript-loader-3.3.0.tgz#c1f5c1db9a2b6a6bca220bc50fee0a071bc75499"
|
||||
integrity sha512-gC0TeWTz7s7OMyeABppQGbbrtSNi0yl/gBgZJElBtaBFNSJlHH1sfgQybHZmlZqFcn4UBa+8DOGT6wEJKWTV6g==
|
||||
@ -24667,7 +24676,7 @@ react-dom@^15.4.2:
|
||||
object-assign "^4.1.0"
|
||||
prop-types "^15.5.10"
|
||||
|
||||
react-dom@^16.8.3, react-dom@^16.8.4:
|
||||
react-dom@^16.10.2, react-dom@^16.8.3, react-dom@^16.8.4:
|
||||
version "16.11.0"
|
||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.11.0.tgz#7e7c4a5a85a569d565c2462f5d345da2dd849af5"
|
||||
integrity sha512-nrRyIUE1e7j8PaXSPtyRKtz+2y9ubW/ghNgqKFHHAHaeP0fpF5uXR+sq8IMRHC+ZUxw7W9NyCDTBtwWxvkb0iA==
|
||||
@ -25112,7 +25121,7 @@ react-scripts@3.0.1:
|
||||
optionalDependencies:
|
||||
fsevents "2.0.6"
|
||||
|
||||
react-scripts@^3.0.1:
|
||||
react-scripts@3.2.0, react-scripts@^3.0.1:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-3.2.0.tgz#58ccd6b4ffa27f1b4d2986cbdcaa916660e9e33c"
|
||||
integrity sha512-6LzuKbE2B4eFQG6i1FnTScn9HDcWBfXXnOwW9xKFPJ/E3rK8i1ufbOZ0ocKyRPxJAKdN7iqg3i7lt0+oxkSVOA==
|
||||
@ -25259,7 +25268,7 @@ react-transition-group@^2.2.1:
|
||||
prop-types "^15.6.2"
|
||||
react-lifecycles-compat "^3.0.4"
|
||||
|
||||
react@*, react@^16.6.0, react@^16.8.3, react@^16.8.4:
|
||||
react@*, react@^16.10.2, react@^16.6.0, react@^16.8.3, react@^16.8.4:
|
||||
version "16.11.0"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-16.11.0.tgz#d294545fe62299ccee83363599bf904e4a07fdbb"
|
||||
integrity sha512-M5Y8yITaLmU0ynd0r1Yvfq98Rmll6q8AxaEe88c8e7LxO8fZ2cNgmFt0aGAS9wzf1Ao32NKXtCl+/tVVtkxq6g==
|
||||
@ -25644,7 +25653,7 @@ redux@^4.0.0, redux@^4.0.1:
|
||||
loose-envify "^1.4.0"
|
||||
symbol-observable "^1.2.0"
|
||||
|
||||
reflect-metadata@^0.1.12, reflect-metadata@^0.1.2:
|
||||
reflect-metadata@^0.1.2:
|
||||
version "0.1.13"
|
||||
resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.13.tgz#67ae3ca57c972a2aa1642b10fe363fe32d49dc08"
|
||||
integrity sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==
|
||||
@ -25690,6 +25699,11 @@ regenerator-runtime@^0.11.0:
|
||||
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
|
||||
integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==
|
||||
|
||||
regenerator-runtime@^0.12.1:
|
||||
version "0.12.1"
|
||||
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de"
|
||||
integrity sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==
|
||||
|
||||
regenerator-transform@^0.10.0:
|
||||
version "0.10.1"
|
||||
resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd"
|
||||
@ -29502,84 +29516,12 @@ tsconfig-paths@^3.4.0:
|
||||
minimist "^1.2.0"
|
||||
strip-bom "^3.0.0"
|
||||
|
||||
tslib@1.10.0, tslib@^1.7.1, tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
|
||||
tslib@1.10.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
|
||||
version "1.10.0"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a"
|
||||
integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==
|
||||
|
||||
tslib@1.9.0:
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.0.tgz#e37a86fda8cbbaf23a057f473c9f4dc64e5fc2e8"
|
||||
integrity sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ==
|
||||
|
||||
tslint-config-airbnb@^5.11.1:
|
||||
version "5.11.2"
|
||||
resolved "https://registry.yarnpkg.com/tslint-config-airbnb/-/tslint-config-airbnb-5.11.2.tgz#2f3d239fa3923be8e7a4372217a7ed552671528f"
|
||||
integrity sha512-mUpHPTeeCFx8XARGG/kzYP4dPSOgoCqNiYbGHh09qTH8q+Y1ghsOgaeZKYYQT7IyxMos523z/QBaiv2zKNBcow==
|
||||
dependencies:
|
||||
tslint-consistent-codestyle "^1.14.1"
|
||||
tslint-eslint-rules "^5.4.0"
|
||||
tslint-microsoft-contrib "~5.2.1"
|
||||
|
||||
tslint-consistent-codestyle@^1.14.1:
|
||||
version "1.16.0"
|
||||
resolved "https://registry.yarnpkg.com/tslint-consistent-codestyle/-/tslint-consistent-codestyle-1.16.0.tgz#52348ea899a7e025b37cc6545751c6a566a19077"
|
||||
integrity sha512-ebR/xHyMEuU36hGNOgCfjGBNYxBPixf0yU1Yoo6s3BrpBRFccjPOmIVaVvQsWAUAMdmfzHOCihVkcaMfimqvHw==
|
||||
dependencies:
|
||||
"@fimbul/bifrost" "^0.21.0"
|
||||
tslib "^1.7.1"
|
||||
tsutils "^2.29.0"
|
||||
|
||||
tslint-eslint-rules@^5.4.0:
|
||||
version "5.4.0"
|
||||
resolved "https://registry.yarnpkg.com/tslint-eslint-rules/-/tslint-eslint-rules-5.4.0.tgz#e488cc9181bf193fe5cd7bfca213a7695f1737b5"
|
||||
integrity sha512-WlSXE+J2vY/VPgIcqQuijMQiel+UtmXS+4nvK4ZzlDiqBfXse8FAvkNnTcYhnQyOTW5KFM+uRRGXxYhFpuBc6w==
|
||||
dependencies:
|
||||
doctrine "0.7.2"
|
||||
tslib "1.9.0"
|
||||
tsutils "^3.0.0"
|
||||
|
||||
tslint-microsoft-contrib@~5.2.1:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.yarnpkg.com/tslint-microsoft-contrib/-/tslint-microsoft-contrib-5.2.1.tgz#a6286839f800e2591d041ea2800c77487844ad81"
|
||||
integrity sha512-PDYjvpo0gN9IfMULwKk0KpVOPMhU6cNoT9VwCOLeDl/QS8v8W2yspRpFFuUS7/c5EIH/n8ApMi8TxJAz1tfFUA==
|
||||
dependencies:
|
||||
tsutils "^2.27.2 <2.29.0"
|
||||
|
||||
tslint@^5.14.0:
|
||||
version "5.20.0"
|
||||
resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.20.0.tgz#fac93bfa79568a5a24e7be9cdde5e02b02d00ec1"
|
||||
integrity sha512-2vqIvkMHbnx8acMogAERQ/IuINOq6DFqgF8/VDvhEkBqQh/x6SP0Y+OHnKth9/ZcHQSroOZwUQSN18v8KKF0/g==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.0.0"
|
||||
builtin-modules "^1.1.1"
|
||||
chalk "^2.3.0"
|
||||
commander "^2.12.1"
|
||||
diff "^4.0.1"
|
||||
glob "^7.1.1"
|
||||
js-yaml "^3.13.1"
|
||||
minimatch "^3.0.4"
|
||||
mkdirp "^0.5.1"
|
||||
resolve "^1.3.2"
|
||||
semver "^5.3.0"
|
||||
tslib "^1.8.0"
|
||||
tsutils "^2.29.0"
|
||||
|
||||
"tsutils@^2.27.2 <2.29.0":
|
||||
version "2.28.0"
|
||||
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.28.0.tgz#6bd71e160828f9d019b6f4e844742228f85169a1"
|
||||
integrity sha512-bh5nAtW0tuhvOJnx1GLRn5ScraRLICGyJV5wJhtRWOLsxW70Kk5tZtpK3O/hW6LDnqKS9mlUMPZj9fEMJ0gxqA==
|
||||
dependencies:
|
||||
tslib "^1.8.1"
|
||||
|
||||
tsutils@^2.29.0:
|
||||
version "2.29.0"
|
||||
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.29.0.tgz#32b488501467acbedd4b85498673a0812aca0b99"
|
||||
integrity sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==
|
||||
dependencies:
|
||||
tslib "^1.8.1"
|
||||
|
||||
tsutils@^3.0.0, tsutils@^3.17.1, tsutils@^3.5.0, tsutils@^3.7.0:
|
||||
tsutils@^3.17.1, tsutils@^3.7.0:
|
||||
version "3.17.1"
|
||||
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759"
|
||||
integrity sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==
|
||||
@ -29678,7 +29620,7 @@ typescript@3.5.3:
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.3.tgz#c830f657f93f1ea846819e929092f5fe5983e977"
|
||||
integrity sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==
|
||||
|
||||
typescript@^3.2.2, typescript@^3.4.0:
|
||||
typescript@3.6.4, typescript@^3.2.2, typescript@^3.4.0:
|
||||
version "3.6.4"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.6.4.tgz#b18752bb3792bc1a0281335f7f6ebf1bbfc5b91d"
|
||||
integrity sha512-unoCll1+l+YK4i4F8f22TaNVPRHcD9PA3yCuZ8g5e0qGqlVlJ/8FSateOLLSagn+Yg5+ZwuPkL8LFUc0Jcvksg==
|
||||
|
Loading…
x
Reference in New Issue
Block a user