diff --git a/.eslintrc.js b/.eslintrc.js index 98dff193b3c1..fc1735437888 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -41,6 +41,7 @@ module.exports = { { files: [ '**/__tests__/**', + '**/__testfixtures__/**', '**/*.test.*', '**/*.stories.*', '**/storyshots/**/stories/**', diff --git a/addons/docs/docs/media/props-tables-hero.png b/addons/docs/docs/media/props-tables-hero.png new file mode 100644 index 000000000000..fad4b2355d38 Binary files /dev/null and b/addons/docs/docs/media/props-tables-hero.png differ diff --git a/addons/docs/docs/props-tables.md b/addons/docs/docs/props-tables.md new file mode 100644 index 000000000000..00ca8ca88e0e --- /dev/null +++ b/addons/docs/docs/props-tables.md @@ -0,0 +1,97 @@ +
+ +
+ +

Storybook Docs Props Tables

+ +Storybook Docs automatically generates props tables for components in supported frameworks. This document is a consolidated summary of prop tables, provides instructions for reporting bugs, and list known limitations for each framework. + +- [Usage](#usage) +- [Reporting a bug](#reporting-a-bug) +- [Known limitations](#known-limitations) + - [React](#react) + - [Vue](#vue) + - [Angular](#angular) + - [Web components](#web-components) + - [Ember](#ember) +- [More resources](#more-resources) + +## Usage + +For framework-specific setup instructions, see the framework's README: [React](../../react/README.md), [Vue](../../vue/README.md), [Angular](../../angular/README.md), [Web Components](../../web-components/README.md), [Ember](../../ember/README.md). + +To use the props table in [DocsPage](./docspage.md), simply export a component property on your stories metadata: + +```js +// MyComponent.stories.js +import { MyComponent } from './MyComponent'; + +export default { + title: 'MyComponent', + component: MyComponent, +}; +// stories etc... +``` + +To use the props table in [MDX](./mdx.md), use the `Props` block: + +```js +// MyComponent.stories.mdx +import { Props } from '@storybook/addon-docs/blocks'; +import { MyComponent } from './MyComponent'; + +# My Component! + + +``` + +## Reporting a bug + +Extracting component properties from source is a tricky problem with thousands of corner cases. We've designed this package and its tests to accurately isolate problems, since the cause could either be in this package or (likely) one of the packages it depends on. + +If you're seeing a problem with your prop table, here's what to do. + +First, look to see if there's already a test case that corresponds to your situation. If there is, it should be documented in the [Known Limitations](#known-limitations) section above. There should also be one or more corresponding test fixtures contained in this package. For example, if you are using React, look under the directory `./src/frameworks/react/__testfixtures__`. + +If your problem is not already represented here, do the following: + +1. Create a **MINIMAL** repro for your problem. Each case should be just a few lines of code. +2. Place it in the appropriate directory `./src/frameworks//__testfixtures__/`, e.g. `./src/frameworks/react/__testfixtures__/XXXX-some-description`, where `XXXX` is the corresponding github issue. +3. Run the tests for your ``, e.g. `yarn jest --testPathPattern=react-properties.test.ts --watch` +4. Inspect the output files for your test case. +5. Add the example to the appropriate stories file, e.g. `react-properties.stories.ts` for `react`, for a visual repro + +If the problem appears to be an issue with this library, file an issue and include a PR that includes your repro. + +If the problem appears to be an issue with the sub-package, please file an issue on the appropriate sub-package, document the limitation in [Known Limitations](#known-limitations) below, link to that issue, and submit a PR including the updated documentation and fixtures/snapshots. + +## Known limitations + +This package relies on a variety of sub-packages to extract property information from components. Many of the bugs in this package correspond to bugs in a sub-package. Since we don't maintain the sub-packages, the best we can do for now is (1) document these limitations, (2) provide clean reproductions to the sub-package, (3) optionally provide PRs to those packages to fix the problems. + +### React + +SB Docs for React uses `babel-plugin-react-docgen`/`react-docgen` for both JS PropTypes prop tables and, as of 6.0, TypeScript-driven props tables. + +### Vue + +SB Docs for Vue uses `vue-docgen-loader`/`vue-docgen-api` for SFC and JSX components. + +### Angular + +SB Docs for Angular uses `compodoc` for prop table information. + +### Web components + +SB Docs for Web-components uses `custom-elements.json` for prop table information. + +### Ember + +SB Docs for Ember uses `yui-doc` for prop table information. + +## More resources + +- References: [README](../README.md) / [DocsPage](docspage.md) / [MDX](mdx.md) / [FAQ](faq.md) / [Recipes](recipes.md) / [Theming](theming.md) +- Framework-specific docs: [React](../react/README.md) / [Vue](../vue/README.md) / [Angular](../angular/README.md) / [Web components](../web-components/README.md) / [Ember](../ember/README.md) +- Announcements: [Vision](https://medium.com/storybookjs/storybook-docs-sneak-peak-5be78445094a) / [DocsPage](https://medium.com/storybookjs/storybook-docspage-e185bc3622bf) / [MDX](https://medium.com/storybookjs/rich-docs-with-storybook-mdx-61bc145ae7bc) / [Framework support](https://medium.com/storybookjs/storybook-docs-for-new-frameworks-b1f6090ee0ea) +- Example: [Storybook Design System](https://github.com/storybookjs/design-system) diff --git a/addons/docs/package.json b/addons/docs/package.json index f604b1aefb7b..62a207980d8d 100644 --- a/addons/docs/package.json +++ b/addons/docs/package.json @@ -69,16 +69,25 @@ "remark-slug": "^5.1.2", "ts-dedent": "^1.1.1", "util-deprecate": "^1.0.2", - "vue-docgen-api": "^4.1.0", - "vue-docgen-loader": "^1.3.0-beta.0" + "vue-docgen-api": "^4.7.0", + "vue-docgen-loader": "^1.4.0" }, "devDependencies": { + "@storybook/react": "6.0.0-alpha.11", + "@storybook/web-components": "6.0.0-alpha.11", "@types/doctrine": "^0.0.3", "@types/enzyme": "^3.10.3", "@types/jest": "^25.1.1", "@types/prop-types": "^15.5.9", "@types/util-deprecate": "^1.0.0", - "jest-specific-snapshot": "^2.0.0" + "babel-plugin-react-docgen": "^4.1.0", + "cross-spawn": "^7.0.1", + "jest-specific-snapshot": "^2.0.0", + "lit-html": "^1.0.0", + "require-from-string": "^2.0.2", + "styled-components": "^5.0.1", + "tmp": "^0.1.0", + "web-component-analyzer": "^1.0.3" }, "peerDependencies": { "@babel/core": "^7.0.0-0", diff --git a/addons/docs/src/frameworks/angular/__testfixtures__/doc-button/compodoc.snapshot b/addons/docs/src/frameworks/angular/__testfixtures__/doc-button/compodoc.snapshot new file mode 100644 index 000000000000..677536e95e08 --- /dev/null +++ b/addons/docs/src/frameworks/angular/__testfixtures__/doc-button/compodoc.snapshot @@ -0,0 +1,1016 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`angular component properties doc-button 1`] = ` +Object { + "classes": Array [], + "components": Array [ + Object { + "accessors": Object { + "inputValue": Object { + "getSignature": Object { + "description": "

Getter for inputValue.

+", + "line": 102, + "name": "inputValue", + "returnType": "", + "type": "", + }, + "name": "inputValue", + "setSignature": Object { + "args": Array [ + Object { + "name": "value", + "type": "string", + }, + ], + "description": "

Setter for inputValue that is also an @Input.

+", + "jsdoctags": Array [ + Object { + "name": "value", + "tagName": Object { + "text": "param", + }, + "type": "string", + }, + ], + "line": 97, + "name": "inputValue", + "returnType": "void", + "type": "void", + }, + }, + "item": Object { + "name": "item", + "setSignature": Object { + "args": Array [ + Object { + "name": "item", + "type": "[]", + }, + ], + "jsdoctags": Array [ + Object { + "name": "item", + "tagName": Object { + "text": "param", + }, + "type": "[]", + }, + ], + "line": 180, + "name": "item", + "returnType": "void", + "type": "void", + }, + }, + "value": Object { + "getSignature": Object { + "description": "

Get the private value.

+", + "line": 139, + "name": "value", + "returnType": "string | number", + "type": "", + }, + "name": "value", + "setSignature": Object { + "args": Array [ + Object { + "name": "value", + "type": "", + }, + ], + "description": "

Set the private value.

+", + "jsdoctags": Array [ + Object { + "name": "value", + "tagName": Object { + "text": "param", + }, + "type": "", + }, + ], + "line": 134, + "name": "value", + "returnType": "void", + "type": "void", + }, + }, + }, + "assetsDirs": Array [], + "description": "

This is a simple button that demonstrates various JSDoc handling in Storybook Docs for Angular.

+

It supports markdown, so you can embed formatted text, +like bold, italic, and inline code.

+
+

How you like dem apples?! It's never been easier to document all your components.

+
+", + "encapsulation": Array [], + "entryComponents": Array [], + "file": "addons/docs/src/frameworks/angular/__testfixtures__/doc-button/input.ts", + "hostBindings": Array [ + Object { + "defaultValue": "false", + "line": 111, + "name": "class.focused", + }, + ], + "hostListeners": Array [ + Object { + "args": Array [ + Object { + "name": "btn", + "type": "", + }, + ], + "argsDecorator": Array [ + "$event.target", + ], + "line": 107, + "name": "click", + }, + ], + "id": "component-InputComponent-62457013911a3b491fc4b1bdc175baf8", + "inputs": Array [], + "inputsClass": Array [ + Object { + "defaultValue": "'secondary'", + "description": "

Appearance style of the button.

+", + "line": 46, + "name": "appearance", + "type": "\\"primary\\" | \\"secondary\\"", + }, + Object { + "description": "

Setter for inputValue that is also an @Input.

+", + "line": 97, + "name": "inputValue", + "type": "string", + }, + Object { + "defaultValue": "false", + "description": "

Sets the button to a disabled state.

+", + "line": 50, + "name": "isDisabled", + }, + Object { + "line": 180, + "name": "item", + "type": "[]", + }, + Object { + "description": "

The inner text of the button.

+", + "line": 58, + "name": "label", + "type": "string", + }, + Object { + "line": 177, + "name": "showKeyAlias", + "type": "", + }, + Object { + "defaultValue": "'medium'", + "description": "

Size of the button.

+", + "line": 62, + "name": "size", + "type": "ButtonSize", + }, + Object { + "defaultValue": "false", + "description": "

Some input you shouldn't use.

+", + "line": 70, + "name": "somethingYouShouldNotUse", + }, + ], + "jsdoctags": Array [ + Object { + "atToken": Object { + "end": 787, + "flags": 0, + "kind": 57, + "pos": 786, + }, + "comment": "Hello world", + "end": 794, + "flags": 0, + "kind": 288, + "pos": 786, + "tagName": Object { + "end": 793, + "escapedText": "string", + "flags": 0, + "pos": 787, + }, + }, + Object { + "atToken": Object { + "end": 810, + "flags": 0, + "kind": 57, + "pos": 809, + }, + "comment": "[Example](http://example.com)", + "end": 815, + "flags": 0, + "kind": 288, + "pos": 809, + "tagName": Object { + "end": 814, + "escapedText": "link", + "flags": 0, + "pos": 810, + }, + }, + Object { + "atToken": Object { + "end": 849, + "flags": 0, + "kind": 57, + "pos": 848, + }, + "comment": "\`ThingThing\`", + "end": 854, + "flags": 0, + "kind": 288, + "pos": 848, + "tagName": Object { + "end": 853, + "escapedText": "code", + "flags": 0, + "pos": 849, + }, + }, + Object { + "atToken": Object { + "end": 871, + "flags": 0, + "kind": 57, + "pos": 870, + }, + "comment": "aaa", + "end": 876, + "flags": 0, + "kind": 288, + "pos": 870, + "tagName": Object { + "end": 875, + "escapedText": "html", + "flags": 0, + "pos": 871, + }, + }, + ], + "methodsClass": Array [ + Object { + "args": Array [ + Object { + "name": "x", + "type": "number", + }, + Object { + "name": "y", + "type": "string | number", + }, + ], + "description": "

An internal calculation method which adds x and y together.

+", + "jsdoctags": Array [ + Object { + "comment": "

Some number you'd like to use.

+", + "name": Object { + "end": 3201, + "escapedText": "x", + "flags": 0, + "pos": 3200, + }, + "tagName": Object { + "end": 3199, + "escapedText": "param", + "flags": 0, + "pos": 3194, + }, + "type": "number", + }, + Object { + "comment": "

Some other number or string you'd like to use, will have parseInt() applied before calculation.

+", + "name": Object { + "end": 3246, + "escapedText": "y", + "flags": 0, + "pos": 3245, + }, + "tagName": Object { + "end": 3244, + "escapedText": "param", + "flags": 0, + "pos": 3239, + }, + "type": "string | number", + }, + ], + "line": 149, + "modifierKind": Array [ + 114, + ], + "name": "calc", + "optional": false, + "returnType": "number", + "typeParameters": Array [], + }, + Object { + "args": Array [ + Object { + "name": "password", + "type": "string", + }, + ], + "description": "

A private method.

+", + "jsdoctags": Array [ + Object { + "comment": "

Some password.

+", + "name": Object { + "end": 3762, + "escapedText": "password", + "flags": 0, + "pos": 3754, + }, + "tagName": Object { + "end": 3753, + "escapedText": "param", + "flags": 0, + "pos": 3748, + }, + "type": "string", + }, + ], + "line": 172, + "modifierKind": Array [ + 112, + ], + "name": "privateMethod", + "optional": false, + "returnType": "void", + "typeParameters": Array [], + }, + Object { + "args": Array [ + Object { + "name": "id", + "optional": true, + "type": "number", + }, + ], + "description": "

A protected method.

+", + "jsdoctags": Array [ + Object { + "comment": "

Some id.

+", + "name": Object { + "end": 3621, + "escapedText": "id", + "flags": 0, + "pos": 3619, + }, + "optional": true, + "tagName": Object { + "end": 3618, + "escapedText": "param", + "flags": 0, + "pos": 3613, + }, + "type": "number", + }, + ], + "line": 163, + "modifierKind": Array [ + 113, + ], + "name": "protectedMethod", + "optional": false, + "returnType": "void", + "typeParameters": Array [], + }, + Object { + "args": Array [ + Object { + "name": "things", + "type": "ISomeInterface", + }, + ], + "description": "

A public method using an interface.

+", + "jsdoctags": Array [ + Object { + "name": "things", + "tagName": Object { + "text": "param", + }, + "type": "ISomeInterface", + }, + ], + "line": 154, + "modifierKind": Array [ + 114, + ], + "name": "publicMethod", + "optional": false, + "returnType": "void", + "typeParameters": Array [], + }, + ], + "name": "InputComponent", + "outputs": Array [], + "outputsClass": Array [ + Object { + "defaultValue": "new EventEmitter()", + "description": "

Handler to be called when the button is clicked by a user.

+

Will also block the emission of the event if isDisabled is true.

+", + "line": 78, + "name": "onClick", + "type": "EventEmitter", + }, + ], + "propertiesClass": Array [ + Object { + "defaultValue": "'some value'", + "description": "", + "line": 93, + "modifierKind": Array [ + 112, + ], + "name": "_inputValue", + "optional": false, + "type": "string", + }, + Object { + "defaultValue": "'Private hello'", + "description": "

Private value.

+", + "line": 131, + "modifierKind": Array [ + 112, + ], + "name": "_value", + "optional": false, + "type": "string", + }, + Object { + "decorators": Array [ + Object { + "name": "ViewChild", + "stringifiedArguments": "'buttonRef', {static: false}", + }, + ], + "description": "", + "line": 42, + "name": "buttonRef", + "optional": false, + "type": "ElementRef", + }, + Object { + "defaultValue": "'Public hello'", + "description": "

Public value.

+", + "line": 128, + "modifierKind": Array [ + 114, + ], + "name": "internalProperty", + "optional": false, + "type": "string", + }, + Object { + "description": "", + "line": 184, + "modifierKind": Array [ + 114, + ], + "name": "processedItem", + "optional": false, + "type": "T[]", + }, + ], + "providers": Array [], + "rawdescription": "This is a simple button that demonstrates various JSDoc handling in Storybook Docs for Angular. + +It supports [markdown](https://en.wikipedia.org/wiki/Markdown), so you can embed formatted text, +like **bold**, _italic_, and \`inline code\`. + +> How you like dem apples?! It's never been easier to document all your components.", + "selector": "doc-button", + "sourceCode": "import { + Component, + EventEmitter, + Input, + Output, + ViewChild, + HostListener, + HostBinding, + ElementRef, +} from '@angular/core'; + +export const exportedConstant = 'An exported constant'; + +export type ButtonSize = 'small' | 'medium' | 'large' | 'xlarge'; + +export interface ISomeInterface { + one: string; + two: boolean; + three: any[]; +} + +/** + * This is a simple button that demonstrates various JSDoc handling in Storybook Docs for Angular. + * + * It supports [markdown](https://en.wikipedia.org/wiki/Markdown), so you can embed formatted text, + * like **bold**, _italic_, and \`inline code\`. + * + * > How you like dem apples?! It's never been easier to document all your components. + * + * @string Hello world + * @link [Example](http://example.com) + * @code \`ThingThing\` + * @html aaa + */ +@Component({ + selector: 'doc-button', +}) +export class InputComponent { + @ViewChild('buttonRef', { static: false }) buttonRef: ElementRef; + + /** Appearance style of the button. */ + @Input() + public appearance: 'primary' | 'secondary' = 'secondary'; + + /** Sets the button to a disabled state. */ + @Input() + public isDisabled = false; + + /** + * The inner text of the button. + * + * @required + */ + @Input() + public label: string; + + /** Size of the button. */ + @Input() + public size?: ButtonSize = 'medium'; + + /** + * Some input you shouldn't use. + * + * @deprecated + */ + @Input() + public somethingYouShouldNotUse = false; + + /** + * Handler to be called when the button is clicked by a user. + * + * Will also block the emission of the event if \`isDisabled\` is true. + */ + @Output() + public onClick = new EventEmitter(); + + /** + * This is an internal method that we don't want to document and have added the \`ignore\` annoation to. + * + * @ignore + */ + public handleClick(event: Event) { + event.stopPropagation(); + + if (!this.isDisabled) { + this.onClick.emit(event); + } + } + + private _inputValue = 'some value'; + + /** Setter for \`inputValue\` that is also an \`@Input\`. */ + @Input() + public set inputValue(value: string) { + this._inputValue = value; + } + + /** Getter for \`inputValue\`. */ + public get inputValue() { + return this._inputValue; + } + + @HostListener('click', ['$event.target']) + onClickListener(btn) { + console.log('button', btn); + } + + @HostBinding('class.focused') focus = false; + + /** + * Returns all the CSS classes for the button. + * + * @ignore + */ + public get classes(): string[] { + return [this.appearance, this.size].filter(_class => !!_class).map(_class => \`btn-\${_class}\`); + } + + /** + * @ignore + */ + public ignoredProperty = 'Ignore me'; + + /** Public value. */ + public internalProperty = 'Public hello'; + + /** Private value. */ + private _value = 'Private hello'; + + /** Set the private value. */ + public set value(value: string | number) { + this._value = \`\${value}\`; + } + + /** Get the private value. */ + public get value(): string | number { + return this._value; + } + + /** + * An internal calculation method which adds \`x\` and \`y\` together. + * + * @param x Some number you'd like to use. + * @param y Some other number or string you'd like to use, will have \`parseInt()\` applied before calculation. + */ + public calc(x: number, y: string | number): number { + return x + parseInt(\`\${y}\`, 10); + } + + /** A public method using an interface. */ + public publicMethod(things: ISomeInterface) { + console.log(things); + } + + /** + * A protected method. + * + * @param id Some \`id\`. + */ + protected protectedMethod(id?: number) { + console.log(id); + } + + /** + * A private method. + * + * @param password Some \`password\`. + */ + private privateMethod(password: string) { + console.log(password); + } + + @Input('showKeyAlias') + public showKey: keyof T; + + @Input() + public set item(item: T[]) { + this.processedItem = item; + } + + public processedItem: T[]; +} +", + "styleUrls": Array [], + "styleUrlsData": "", + "styles": Array [], + "stylesData": "", + "templateUrl": Array [], + "type": "component", + "viewProviders": Array [], + }, + ], + "coverage": Object { + "count": 22, + "files": Array [ + Object { + "coverageCount": "14/21", + "coveragePercent": 66, + "filePath": "addons/docs/src/frameworks/angular/__testfixtures__/doc-button/input.ts", + "linktype": "component", + "name": "InputComponent", + "status": "good", + "type": "component", + }, + Object { + "coverageCount": "0/4", + "coveragePercent": 0, + "filePath": "addons/docs/src/frameworks/angular/__testfixtures__/doc-button/input.ts", + "linktype": "interface", + "name": "ISomeInterface", + "status": "low", + "type": "interface", + }, + Object { + "coverageCount": "0/1", + "coveragePercent": 0, + "filePath": "addons/docs/src/frameworks/angular/__testfixtures__/doc-button/input.ts", + "linksubtype": "variable", + "linktype": "miscellaneous", + "name": "exportedConstant", + "status": "low", + "type": "variable", + }, + ], + "status": "low", + }, + "directives": Array [], + "injectables": Array [], + "interfaces": Array [ + Object { + "file": "addons/docs/src/frameworks/angular/__testfixtures__/doc-button/input.ts", + "id": "interface-ISomeInterface-62457013911a3b491fc4b1bdc175baf8", + "indexSignatures": Array [], + "kind": 150, + "methods": Array [], + "name": "ISomeInterface", + "properties": Array [ + Object { + "description": "", + "line": 20, + "name": "one", + "optional": false, + "type": "string", + }, + Object { + "description": "", + "line": 22, + "name": "three", + "optional": false, + "type": "any[]", + }, + Object { + "description": "", + "line": 21, + "name": "two", + "optional": false, + "type": "boolean", + }, + ], + "sourceCode": "import { + Component, + EventEmitter, + Input, + Output, + ViewChild, + HostListener, + HostBinding, + ElementRef, +} from '@angular/core'; + +export const exportedConstant = 'An exported constant'; + +export type ButtonSize = 'small' | 'medium' | 'large' | 'xlarge'; + +export interface ISomeInterface { + one: string; + two: boolean; + three: any[]; +} + +/** + * This is a simple button that demonstrates various JSDoc handling in Storybook Docs for Angular. + * + * It supports [markdown](https://en.wikipedia.org/wiki/Markdown), so you can embed formatted text, + * like **bold**, _italic_, and \`inline code\`. + * + * > How you like dem apples?! It's never been easier to document all your components. + * + * @string Hello world + * @link [Example](http://example.com) + * @code \`ThingThing\` + * @html aaa + */ +@Component({ + selector: 'doc-button', +}) +export class InputComponent { + @ViewChild('buttonRef', { static: false }) buttonRef: ElementRef; + + /** Appearance style of the button. */ + @Input() + public appearance: 'primary' | 'secondary' = 'secondary'; + + /** Sets the button to a disabled state. */ + @Input() + public isDisabled = false; + + /** + * The inner text of the button. + * + * @required + */ + @Input() + public label: string; + + /** Size of the button. */ + @Input() + public size?: ButtonSize = 'medium'; + + /** + * Some input you shouldn't use. + * + * @deprecated + */ + @Input() + public somethingYouShouldNotUse = false; + + /** + * Handler to be called when the button is clicked by a user. + * + * Will also block the emission of the event if \`isDisabled\` is true. + */ + @Output() + public onClick = new EventEmitter(); + + /** + * This is an internal method that we don't want to document and have added the \`ignore\` annoation to. + * + * @ignore + */ + public handleClick(event: Event) { + event.stopPropagation(); + + if (!this.isDisabled) { + this.onClick.emit(event); + } + } + + private _inputValue = 'some value'; + + /** Setter for \`inputValue\` that is also an \`@Input\`. */ + @Input() + public set inputValue(value: string) { + this._inputValue = value; + } + + /** Getter for \`inputValue\`. */ + public get inputValue() { + return this._inputValue; + } + + @HostListener('click', ['$event.target']) + onClickListener(btn) { + console.log('button', btn); + } + + @HostBinding('class.focused') focus = false; + + /** + * Returns all the CSS classes for the button. + * + * @ignore + */ + public get classes(): string[] { + return [this.appearance, this.size].filter(_class => !!_class).map(_class => \`btn-\${_class}\`); + } + + /** + * @ignore + */ + public ignoredProperty = 'Ignore me'; + + /** Public value. */ + public internalProperty = 'Public hello'; + + /** Private value. */ + private _value = 'Private hello'; + + /** Set the private value. */ + public set value(value: string | number) { + this._value = \`\${value}\`; + } + + /** Get the private value. */ + public get value(): string | number { + return this._value; + } + + /** + * An internal calculation method which adds \`x\` and \`y\` together. + * + * @param x Some number you'd like to use. + * @param y Some other number or string you'd like to use, will have \`parseInt()\` applied before calculation. + */ + public calc(x: number, y: string | number): number { + return x + parseInt(\`\${y}\`, 10); + } + + /** A public method using an interface. */ + public publicMethod(things: ISomeInterface) { + console.log(things); + } + + /** + * A protected method. + * + * @param id Some \`id\`. + */ + protected protectedMethod(id?: number) { + console.log(id); + } + + /** + * A private method. + * + * @param password Some \`password\`. + */ + private privateMethod(password: string) { + console.log(password); + } + + @Input('showKeyAlias') + public showKey: keyof T; + + @Input() + public set item(item: T[]) { + this.processedItem = item; + } + + public processedItem: T[]; +} +", + "type": "interface", + }, + ], + "miscellaneous": Object { + "enumerations": Array [], + "functions": Array [], + "groupedEnumerations": Object {}, + "groupedFunctions": Object {}, + "groupedTypeAliases": Object { + "addons/docs/src/frameworks/angular/__testfixtures__/doc-button/input.ts": Array [ + Object { + "ctype": "miscellaneous", + "description": "", + "file": "addons/docs/src/frameworks/angular/__testfixtures__/doc-button/input.ts", + "kind": 168, + "name": "ButtonSize", + "rawtype": "\\"small\\" | \\"medium\\" | \\"large\\" | \\"xlarge\\"", + "subtype": "typealias", + }, + ], + }, + "groupedVariables": Object { + "addons/docs/src/frameworks/angular/__testfixtures__/doc-button/input.ts": Array [ + Object { + "ctype": "miscellaneous", + "defaultValue": "'An exported constant'", + "file": "addons/docs/src/frameworks/angular/__testfixtures__/doc-button/input.ts", + "name": "exportedConstant", + "subtype": "variable", + "type": "string", + }, + ], + }, + "typealiases": Array [ + Object { + "ctype": "miscellaneous", + "description": "", + "file": "addons/docs/src/frameworks/angular/__testfixtures__/doc-button/input.ts", + "kind": 168, + "name": "ButtonSize", + "rawtype": "\\"small\\" | \\"medium\\" | \\"large\\" | \\"xlarge\\"", + "subtype": "typealias", + }, + ], + "variables": Array [ + Object { + "ctype": "miscellaneous", + "defaultValue": "'An exported constant'", + "file": "addons/docs/src/frameworks/angular/__testfixtures__/doc-button/input.ts", + "name": "exportedConstant", + "subtype": "variable", + "type": "string", + }, + ], + }, + "modules": Array [], + "pipes": Array [], + "routes": Array [], +} +`; diff --git a/addons/docs/src/frameworks/angular/__testfixtures__/doc-button/input.ts b/addons/docs/src/frameworks/angular/__testfixtures__/doc-button/input.ts new file mode 100644 index 000000000000..a76d7d54ea5d --- /dev/null +++ b/addons/docs/src/frameworks/angular/__testfixtures__/doc-button/input.ts @@ -0,0 +1,185 @@ +// @ts-nocheck +/* eslint-disable no-console */ +/* eslint-disable no-underscore-dangle */ +import { + Component, + EventEmitter, + Input, + Output, + ViewChild, + HostListener, + HostBinding, + ElementRef, +} from '@angular/core'; + +export const exportedConstant = 'An exported constant'; + +export type ButtonSize = 'small' | 'medium' | 'large' | 'xlarge'; + +export interface ISomeInterface { + one: string; + two: boolean; + three: any[]; +} + +/** + * This is a simple button that demonstrates various JSDoc handling in Storybook Docs for Angular. + * + * It supports [markdown](https://en.wikipedia.org/wiki/Markdown), so you can embed formatted text, + * like **bold**, _italic_, and `inline code`. + * + * > How you like dem apples?! It's never been easier to document all your components. + * + * @string Hello world + * @link [Example](http://example.com) + * @code `ThingThing` + * @html aaa + */ +@Component({ + selector: 'doc-button', +}) +export class InputComponent { + @ViewChild('buttonRef', { static: false }) buttonRef: ElementRef; + + /** Appearance style of the button. */ + @Input() + public appearance: 'primary' | 'secondary' = 'secondary'; + + /** Sets the button to a disabled state. */ + @Input() + public isDisabled = false; + + /** + * The inner text of the button. + * + * @required + */ + @Input() + public label: string; + + /** Size of the button. */ + @Input() + public size?: ButtonSize = 'medium'; + + /** + * Some input you shouldn't use. + * + * @deprecated + */ + @Input() + public somethingYouShouldNotUse = false; + + /** + * Handler to be called when the button is clicked by a user. + * + * Will also block the emission of the event if `isDisabled` is true. + */ + @Output() + public onClick = new EventEmitter(); + + /** + * This is an internal method that we don't want to document and have added the `ignore` annoation to. + * + * @ignore + */ + public handleClick(event: Event) { + event.stopPropagation(); + + if (!this.isDisabled) { + this.onClick.emit(event); + } + } + + private _inputValue = 'some value'; + + /** Setter for `inputValue` that is also an `@Input`. */ + @Input() + public set inputValue(value: string) { + this._inputValue = value; + } + + /** Getter for `inputValue`. */ + public get inputValue() { + return this._inputValue; + } + + @HostListener('click', ['$event.target']) + onClickListener(btn) { + console.log('button', btn); + } + + @HostBinding('class.focused') focus = false; + + /** + * Returns all the CSS classes for the button. + * + * @ignore + */ + public get classes(): string[] { + return [this.appearance, this.size].filter(_class => !!_class).map(_class => `btn-${_class}`); + } + + /** + * @ignore + */ + public ignoredProperty = 'Ignore me'; + + /** Public value. */ + public internalProperty = 'Public hello'; + + /** Private value. */ + private _value = 'Private hello'; + + /** Set the private value. */ + public set value(value: string | number) { + this._value = `${value}`; + } + + /** Get the private value. */ + public get value(): string | number { + return this._value; + } + + /** + * An internal calculation method which adds `x` and `y` together. + * + * @param x Some number you'd like to use. + * @param y Some other number or string you'd like to use, will have `parseInt()` applied before calculation. + */ + public calc(x: number, y: string | number): number { + return x + parseInt(`${y}`, 10); + } + + /** A public method using an interface. */ + public publicMethod(things: ISomeInterface) { + console.log(things); + } + + /** + * A protected method. + * + * @param id Some `id`. + */ + protected protectedMethod(id?: number) { + console.log(id); + } + + /** + * A private method. + * + * @param password Some `password`. + */ + private privateMethod(password: string) { + console.log(password); + } + + @Input('showKeyAlias') + public showKey: keyof T; + + @Input() + public set item(item: T[]) { + this.processedItem = item; + } + + public processedItem: T[]; +} diff --git a/addons/docs/src/frameworks/angular/__testfixtures__/doc-button/properties.snapshot b/addons/docs/src/frameworks/angular/__testfixtures__/doc-button/properties.snapshot new file mode 100644 index 000000000000..efd774f746b2 --- /dev/null +++ b/addons/docs/src/frameworks/angular/__testfixtures__/doc-button/properties.snapshot @@ -0,0 +1,230 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`angular component properties doc-button 1`] = ` +Object { + "sections": Object { + "inputs": Array [ + Object { + "defaultValue": Object { + "summary": "'secondary'", + }, + "description": "

Appearance style of the button.

+", + "name": "appearance", + "required": true, + "type": Object { + "summary": "\\"primary\\" | \\"secondary\\"", + }, + }, + Object { + "defaultValue": Object { + "summary": undefined, + }, + "description": "

Setter for inputValue that is also an @Input.

+", + "name": "inputValue", + "required": true, + "type": Object { + "summary": "string", + }, + }, + Object { + "defaultValue": Object { + "summary": "false", + }, + "description": "

Sets the button to a disabled state.

+", + "name": "isDisabled", + "required": true, + "type": Object { + "summary": undefined, + }, + }, + Object { + "defaultValue": Object { + "summary": undefined, + }, + "description": undefined, + "name": "item", + "required": true, + "type": Object { + "summary": "[]", + }, + }, + Object { + "defaultValue": Object { + "summary": undefined, + }, + "description": "

The inner text of the button.

+", + "name": "label", + "required": true, + "type": Object { + "summary": "string", + }, + }, + Object { + "defaultValue": Object { + "summary": undefined, + }, + "description": undefined, + "name": "showKeyAlias", + "required": true, + "type": Object { + "summary": "", + }, + }, + Object { + "defaultValue": Object { + "summary": "'medium'", + }, + "description": "

Size of the button.

+", + "name": "size", + "required": true, + "type": Object { + "summary": "ButtonSize", + }, + }, + Object { + "defaultValue": Object { + "summary": "false", + }, + "description": "

Some input you shouldn't use.

+", + "name": "somethingYouShouldNotUse", + "required": true, + "type": Object { + "summary": undefined, + }, + }, + ], + "methods": Array [ + Object { + "defaultValue": Object { + "summary": "", + }, + "description": "

An internal calculation method which adds x and y together.

+", + "name": "calc", + "required": false, + "type": Object { + "summary": "(x: number, y: string | number) => number", + }, + }, + Object { + "defaultValue": Object { + "summary": "", + }, + "description": "

A private method.

+", + "name": "privateMethod", + "required": false, + "type": Object { + "summary": "(password: string) => void", + }, + }, + Object { + "defaultValue": Object { + "summary": "", + }, + "description": "

A protected method.

+", + "name": "protectedMethod", + "required": false, + "type": Object { + "summary": "(id?: number) => void", + }, + }, + Object { + "defaultValue": Object { + "summary": "", + }, + "description": "

A public method using an interface.

+", + "name": "publicMethod", + "required": false, + "type": Object { + "summary": "(things: ISomeInterface) => void", + }, + }, + ], + "outputs": Array [ + Object { + "defaultValue": Object { + "summary": "new EventEmitter()", + }, + "description": "

Handler to be called when the button is clicked by a user.

+

Will also block the emission of the event if isDisabled is true.

+", + "name": "onClick", + "required": true, + "type": Object { + "summary": "EventEmitter", + }, + }, + ], + "properties": Array [ + Object { + "defaultValue": Object { + "summary": "'some value'", + }, + "description": "", + "name": "_inputValue", + "required": true, + "type": Object { + "summary": "string", + }, + }, + Object { + "defaultValue": Object { + "summary": "'Private hello'", + }, + "description": "

Private value.

+", + "name": "_value", + "required": true, + "type": Object { + "summary": "string", + }, + }, + Object { + "defaultValue": Object { + "summary": "'Public hello'", + }, + "description": "

Public value.

+", + "name": "internalProperty", + "required": true, + "type": Object { + "summary": "string", + }, + }, + Object { + "defaultValue": Object { + "summary": undefined, + }, + "description": "", + "name": "processedItem", + "required": true, + "type": Object { + "summary": "T[]", + }, + }, + ], + "view child": Array [ + Object { + "defaultValue": Object { + "summary": undefined, + }, + "description": "", + "name": "buttonRef", + "required": true, + "type": Object { + "summary": "ElementRef", + }, + }, + ], + }, +} +`; diff --git a/addons/docs/src/frameworks/angular/__testfixtures__/doc-button/tsconfig.json b/addons/docs/src/frameworks/angular/__testfixtures__/doc-button/tsconfig.json new file mode 100644 index 000000000000..ced6b7ae2f7c --- /dev/null +++ b/addons/docs/src/frameworks/angular/__testfixtures__/doc-button/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "rootDir": "." + }, + "include": ["./*.ts"] +} diff --git a/addons/docs/src/frameworks/angular/angular-properties.test.ts b/addons/docs/src/frameworks/angular/angular-properties.test.ts new file mode 100644 index 000000000000..c169ff0ea9f0 --- /dev/null +++ b/addons/docs/src/frameworks/angular/angular-properties.test.ts @@ -0,0 +1,50 @@ +import 'jest-specific-snapshot'; +import path from 'path'; +import fs from 'fs'; +import tmp from 'tmp'; +import { sync as spawnSync } from 'cross-spawn'; + +import { findComponentByName, extractPropsFromData } from './compodoc'; + +// File hierarchy: __testfixtures__ / some-test-case / input.* +const inputRegExp = /^input\..*$/; + +const runCompodoc = (inputPath: string) => { + const testDir = path.dirname(inputPath); + const { name: tmpDir, removeCallback } = tmp.dirSync(); + + // FIXME: for now, this requires a tsconfig.json for each test case. Tried generating + // one dynamically in tmpDir, but compodoc doesn't handle absolute paths properly + // (and screwed around with relative paths as well, but couldn't get it working) + spawnSync('compodoc', ['-p', `${testDir}/tsconfig.json`, '-e', 'json', '-d', tmpDir], { + stdio: 'inherit', + }); + const output = fs.readFileSync(`${tmpDir}/documentation.json`, 'utf8'); + removeCallback(); + return output; +}; + +describe('angular component properties', () => { + const fixturesDir = path.join(__dirname, '__testfixtures__'); + fs.readdirSync(fixturesDir, { withFileTypes: true }).forEach(testEntry => { + if (testEntry.isDirectory()) { + const testDir = path.join(fixturesDir, testEntry.name); + const testFile = fs.readdirSync(testDir).find(fileName => inputRegExp.test(fileName)); + if (testFile) { + it(testEntry.name, () => { + const inputPath = path.join(testDir, testFile); + + // snapshot the output of compodoc + const compodocOutput = runCompodoc(inputPath); + const compodocJson = JSON.parse(compodocOutput); + expect(compodocJson).toMatchSpecificSnapshot(path.join(testDir, 'compodoc.snapshot')); + + // snapshot the output of addon-docs angular-properties + const componentData = findComponentByName('InputComponent', compodocJson); + const properties = extractPropsFromData(componentData); + expect(properties).toMatchSpecificSnapshot(path.join(testDir, 'properties.snapshot')); + }); + } + } + }); +}); diff --git a/addons/docs/src/frameworks/angular/compodoc.ts b/addons/docs/src/frameworks/angular/compodoc.ts index 8362919f1755..9838966dd45a 100644 --- a/addons/docs/src/frameworks/angular/compodoc.ts +++ b/addons/docs/src/frameworks/angular/compodoc.ts @@ -71,6 +71,10 @@ const mapItemToSection = (key: string, item: Method | Property): string => { } }; +export const findComponentByName = (name: string, compodocJson: CompodocJson) => + compodocJson.components.find((c: Component) => c.name === name) || + compodocJson.directives.find((c: Directive) => c.name === name); + const getComponentData = (component: Component | Directive) => { if (!component) { return null; @@ -79,10 +83,7 @@ const getComponentData = (component: Component | Directive) => { const compodocJson = getCompdocJson(); checkValidCompodocJson(compodocJson); const { name } = component; - return ( - compodocJson.components.find((c: Component) => c.name === name) || - compodocJson.directives.find((c: Directive) => c.name === name) - ); + return findComponentByName(name, compodocJson); }; const displaySignature = (item: Method): string => { @@ -92,12 +93,7 @@ const displaySignature = (item: Method): string => { return `(${args.join(', ')}) => ${item.returnType}`; }; -export const extractProps = (component: Component | Directive) => { - const componentData = getComponentData(component); - if (!componentData) { - return null; - } - +export const extractPropsFromData = (componentData: Directive) => { const sectionToItems: Sections = {}; const compodocClasses = ['propertiesClass', 'methodsClass', 'inputsClass', 'outputsClass']; type COMPODOC_CLASS = 'propertiesClass' | 'methodsClass' | 'inputsClass' | 'outputsClass'; @@ -143,6 +139,11 @@ export const extractProps = (component: Component | Directive) => { return isEmpty(sections) ? null : { sections }; }; +export const extractProps = (component: Component | Directive) => { + const componentData = getComponentData(component); + return componentData && extractPropsFromData(componentData); +}; + export const extractComponentDescription = (component: Component | Directive) => { const componentData = getComponentData(component); if (!componentData) { diff --git a/addons/docs/src/frameworks/react/__testfixtures__/8140-js-prop-types-oneof/docgen.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/8140-js-prop-types-oneof/docgen.snapshot new file mode 100644 index 000000000000..2970f5434d36 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/8140-js-prop-types-oneof/docgen.snapshot @@ -0,0 +1,102 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 8140-js-prop-types-oneof 1`] = ` +"/* eslint-disable react/no-unused-prop-types */ + +/* eslint-disable react/require-default-props */ +import React from 'react'; +import PropTypes from 'prop-types'; + +const Alert = props => React.createElement(React.Fragment, null, JSON.stringify(props)); + +Alert.defaultProps = { + mode: 'static', + type: 'warning' +}; +Alert.propTypes = { + mode: PropTypes.oneOf(['static', 'timed']), + type: PropTypes.oneOf(['success', 'warning', 'error', 'primary']), + message: PropTypes.string.isRequired, + + /** + * No background or border if static alert + */ + blank: PropTypes.bool, + + /** + * Allows icon override, accepts material icon name + */ + icon: PropTypes.string +}; +export const component = Alert; +Alert.__docgenInfo = { + \\"description\\": \\"\\", + \\"methods\\": [], + \\"displayName\\": \\"Alert\\", + \\"props\\": { + \\"mode\\": { + \\"defaultValue\\": { + \\"value\\": \\"'static'\\", + \\"computed\\": false + }, + \\"type\\": { + \\"name\\": \\"enum\\", + \\"value\\": [{ + \\"value\\": \\"'static'\\", + \\"computed\\": false + }, { + \\"value\\": \\"'timed'\\", + \\"computed\\": false + }] + }, + \\"required\\": false, + \\"description\\": \\"\\" + }, + \\"type\\": { + \\"defaultValue\\": { + \\"value\\": \\"'warning'\\", + \\"computed\\": false + }, + \\"type\\": { + \\"name\\": \\"enum\\", + \\"value\\": [{ + \\"value\\": \\"'success'\\", + \\"computed\\": false + }, { + \\"value\\": \\"'warning'\\", + \\"computed\\": false + }, { + \\"value\\": \\"'error'\\", + \\"computed\\": false + }, { + \\"value\\": \\"'primary'\\", + \\"computed\\": false + }] + }, + \\"required\\": false, + \\"description\\": \\"\\" + }, + \\"message\\": { + \\"type\\": { + \\"name\\": \\"string\\" + }, + \\"required\\": true, + \\"description\\": \\"\\" + }, + \\"blank\\": { + \\"type\\": { + \\"name\\": \\"bool\\" + }, + \\"required\\": false, + \\"description\\": \\"No background or border if static alert\\" + }, + \\"icon\\": { + \\"type\\": { + \\"name\\": \\"string\\" + }, + \\"required\\": false, + \\"description\\": \\"Allows icon override, accepts material icon name\\" + } + } +};" +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/8140-js-prop-types-oneof/input.js b/addons/docs/src/frameworks/react/__testfixtures__/8140-js-prop-types-oneof/input.js new file mode 100644 index 000000000000..c3a1133a34a8 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/8140-js-prop-types-oneof/input.js @@ -0,0 +1,27 @@ +/* eslint-disable react/no-unused-prop-types */ +/* eslint-disable react/require-default-props */ +import React from 'react'; +import PropTypes from 'prop-types'; + +const Alert = props => <>{JSON.stringify(props)}; + +Alert.defaultProps = { + mode: 'static', + type: 'warning', +}; + +Alert.propTypes = { + mode: PropTypes.oneOf(['static', 'timed']), + type: PropTypes.oneOf(['success', 'warning', 'error', 'primary']), + message: PropTypes.string.isRequired, + /** + * No background or border if static alert + */ + blank: PropTypes.bool, + /** + * Allows icon override, accepts material icon name + */ + icon: PropTypes.string, +}; + +export const component = Alert; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/8140-js-prop-types-oneof/properties.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/8140-js-prop-types-oneof/properties.snapshot new file mode 100644 index 000000000000..fcd3cad8942c --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/8140-js-prop-types-oneof/properties.snapshot @@ -0,0 +1,64 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 8140-js-prop-types-oneof 1`] = ` +Object { + "rows": Array [ + Object { + "defaultValue": Object { + "detail": undefined, + "summary": "'static'", + }, + "description": "", + "name": "mode", + "required": false, + "type": Object { + "detail": undefined, + "summary": "'static' | 'timed'", + }, + }, + Object { + "defaultValue": Object { + "detail": undefined, + "summary": "'warning'", + }, + "description": "", + "name": "type", + "required": false, + "type": Object { + "detail": undefined, + "summary": "'success' | 'warning' | 'error' | 'primary'", + }, + }, + Object { + "defaultValue": null, + "description": "", + "name": "message", + "required": true, + "type": Object { + "detail": undefined, + "summary": "string", + }, + }, + Object { + "defaultValue": null, + "description": "No background or border if static alert", + "name": "blank", + "required": false, + "type": Object { + "detail": undefined, + "summary": "bool", + }, + }, + Object { + "defaultValue": null, + "description": "Allows icon override, accepts material icon name", + "name": "icon", + "required": false, + "type": Object { + "detail": undefined, + "summary": "string", + }, + }, + ], +} +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/8143-ts-imported-types/docgen.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/8143-ts-imported-types/docgen.snapshot new file mode 100644 index 000000000000..e07759d99ce9 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/8143-ts-imported-types/docgen.snapshot @@ -0,0 +1,22 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 8143-ts-imported-types 1`] = ` +"import React from 'react'; +export const FooComponent = foo => React.createElement(React.Fragment, null, JSON.stringify(foo)); +export const component = FooComponent; +FooComponent.__docgenInfo = { + \\"description\\": \\"\\", + \\"methods\\": [], + \\"displayName\\": \\"FooComponent\\", + \\"props\\": { + \\"bar\\": { + \\"required\\": true, + \\"tsType\\": { + \\"name\\": \\"Foo['bar']\\", + \\"raw\\": \\"Foo['bar']\\" + }, + \\"description\\": \\"\\" + } + } +};" +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/8143-ts-imported-types/input.tsx b/addons/docs/src/frameworks/react/__testfixtures__/8143-ts-imported-types/input.tsx new file mode 100644 index 000000000000..7e30066389a2 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/8143-ts-imported-types/input.tsx @@ -0,0 +1,10 @@ +import React from 'react'; +import { Foo } from './types'; + +interface FooProps { + bar: Foo['bar']; +} + +export const FooComponent = (foo: FooProps) => <>{JSON.stringify(foo)}; + +export const component = FooComponent; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/8143-ts-imported-types/properties.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/8143-ts-imported-types/properties.snapshot new file mode 100644 index 000000000000..704ca876098d --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/8143-ts-imported-types/properties.snapshot @@ -0,0 +1,21 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 8143-ts-imported-types 1`] = ` +Object { + "rows": Array [ + Object { + "defaultValue": Object { + "detail": undefined, + "summary": "0", + }, + "description": "", + "name": "bar", + "required": true, + "type": Object { + "detail": undefined, + "summary": "Foo['bar']", + }, + }, + ], +} +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/8143-ts-imported-types/types.ts b/addons/docs/src/frameworks/react/__testfixtures__/8143-ts-imported-types/types.ts new file mode 100644 index 000000000000..156212cf95ce --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/8143-ts-imported-types/types.ts @@ -0,0 +1,3 @@ +export interface Foo { + bar: number; +} diff --git a/addons/docs/src/frameworks/react/__testfixtures__/8143-ts-react-fc-generics/docgen.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/8143-ts-react-fc-generics/docgen.snapshot new file mode 100644 index 000000000000..57d22462232f --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/8143-ts-react-fc-generics/docgen.snapshot @@ -0,0 +1,24 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 8143-ts-react-fc-generics 1`] = ` +"import React from 'react'; +export const Text = ({ + padding = '0', + margin +}) => React.createElement(React.Fragment, null, \\"Text\\"); +export const component = Text; +Text.__docgenInfo = { + \\"description\\": \\"\\", + \\"methods\\": [], + \\"displayName\\": \\"Text\\", + \\"props\\": { + \\"padding\\": { + \\"defaultValue\\": { + \\"value\\": \\"'0'\\", + \\"computed\\": false + }, + \\"required\\": false + } + } +};" +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/8143-ts-react-fc-generics/input.tsx b/addons/docs/src/frameworks/react/__testfixtures__/8143-ts-react-fc-generics/input.tsx new file mode 100644 index 000000000000..9116328f1937 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/8143-ts-react-fc-generics/input.tsx @@ -0,0 +1,10 @@ +import React from 'react'; + +interface Props { + padding: string; + margin: number; +} + +export const Text: React.FC = ({ padding = '0', margin }) => <>Text; + +export const component = Text; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/8143-ts-react-fc-generics/properties.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/8143-ts-react-fc-generics/properties.snapshot new file mode 100644 index 000000000000..7e70b8104795 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/8143-ts-react-fc-generics/properties.snapshot @@ -0,0 +1,21 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 8143-ts-react-fc-generics 1`] = ` +Object { + "rows": Array [ + Object { + "defaultValue": Object { + "detail": undefined, + "summary": "'0'", + }, + "description": undefined, + "name": "padding", + "required": false, + "type": Object { + "detail": undefined, + "summary": "unknown", + }, + }, + ], +} +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/8279-js-styled-docgen/docgen.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/8279-js-styled-docgen/docgen.snapshot new file mode 100644 index 000000000000..670ab38ca25b --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/8279-js-styled-docgen/docgen.snapshot @@ -0,0 +1,24 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 8279-js-styled-docgen 1`] = ` +"import styled from 'styled-components'; +import PropTypes from 'prop-types'; +/** + * Use \`A\` to provide a regular link + */ + +const A = styled('a')({ + margin: '8px 0', + outline: 'none' +}); +A.displayName = 'Link'; +A.defaultProps = { + children: 'This is a link' +}; +A.propTypes = { + /** That should be the clickable element */ + children: PropTypes.node.isRequired +}; +export default A; +export const component = A;" +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/8279-js-styled-docgen/input.js b/addons/docs/src/frameworks/react/__testfixtures__/8279-js-styled-docgen/input.js new file mode 100644 index 000000000000..95cf14f635c8 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/8279-js-styled-docgen/input.js @@ -0,0 +1,23 @@ +import styled from 'styled-components'; +import PropTypes from 'prop-types'; + +/** + * Use `A` to provide a regular link + */ +const A = styled('a')({ + margin: '8px 0', + outline: 'none', +}); + +A.displayName = 'Link'; +A.defaultProps = { + children: 'This is a link', +}; + +A.propTypes = { + /** That should be the clickable element */ + children: PropTypes.node.isRequired, +}; +export default A; + +export const component = A; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/8279-js-styled-docgen/properties.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/8279-js-styled-docgen/properties.snapshot new file mode 100644 index 000000000000..b429f083fcc0 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/8279-js-styled-docgen/properties.snapshot @@ -0,0 +1,7 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 8279-js-styled-docgen 1`] = ` +Object { + "rows": Array [], +} +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/8428-js-static-prop-types/docgen.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/8428-js-static-prop-types/docgen.snapshot new file mode 100644 index 000000000000..fc7b04959c73 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/8428-js-static-prop-types/docgen.snapshot @@ -0,0 +1,41 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 8428-js-static-prop-types 1`] = ` +"function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +/* eslint-disable react/no-unused-prop-types */ + +/* eslint-disable react/require-default-props */ +import React from 'react'; +import PropTypes from 'prop-types'; // eslint-disable-next-line react/prefer-stateless-function + +export default class Test extends React.Component { + render() { + return React.createElement(\\"div\\", null, \\"test\\"); + } + +} + +_defineProperty(Test, \\"propTypes\\", { + /** + * Please work... + */ + test: PropTypes.string +}); + +export const component = Test; +Test.__docgenInfo = { + \\"description\\": \\"\\", + \\"methods\\": [], + \\"displayName\\": \\"Test\\", + \\"props\\": { + \\"test\\": { + \\"type\\": { + \\"name\\": \\"string\\" + }, + \\"required\\": false, + \\"description\\": \\"Please work...\\" + } + } +};" +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/8428-js-static-prop-types/input.js b/addons/docs/src/frameworks/react/__testfixtures__/8428-js-static-prop-types/input.js new file mode 100644 index 000000000000..4b416fe973a4 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/8428-js-static-prop-types/input.js @@ -0,0 +1,20 @@ +/* eslint-disable react/no-unused-prop-types */ +/* eslint-disable react/require-default-props */ +import React from 'react'; +import PropTypes from 'prop-types'; + +// eslint-disable-next-line react/prefer-stateless-function +export default class Test extends React.Component { + static propTypes = { + /** + * Please work... + */ + test: PropTypes.string, + }; + + render() { + return
test
; + } +} + +export const component = Test; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/8428-js-static-prop-types/properties.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/8428-js-static-prop-types/properties.snapshot new file mode 100644 index 000000000000..dd23348be458 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/8428-js-static-prop-types/properties.snapshot @@ -0,0 +1,18 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 8428-js-static-prop-types 1`] = ` +Object { + "rows": Array [ + Object { + "defaultValue": null, + "description": "Please work...", + "name": "test", + "required": false, + "type": Object { + "detail": undefined, + "summary": "string", + }, + }, + ], +} +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/8663-js-styled-components/docgen.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/8663-js-styled-components/docgen.snapshot new file mode 100644 index 000000000000..b8dfa2067cd5 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/8663-js-styled-components/docgen.snapshot @@ -0,0 +1,33 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 8663-js-styled-components 1`] = ` +"import React from 'react'; +import PropTypes from 'prop-types'; +import styled from 'styled-components'; +const Box = styled.div\` + background-color: \${props => props.bg}; +\`; +Box.propTypes = { + bg: PropTypes.string +}; +export const MyBox = props => React.createElement(Box, props); +MyBox.propTypes = { + // eslint-disable-next-line react/require-default-props + bg: PropTypes.string +}; +export const component = MyBox; +MyBox.__docgenInfo = { + \\"description\\": \\"\\", + \\"methods\\": [], + \\"displayName\\": \\"MyBox\\", + \\"props\\": { + \\"bg\\": { + \\"type\\": { + \\"name\\": \\"string\\" + }, + \\"required\\": false, + \\"description\\": \\"\\" + } + } +};" +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/8663-js-styled-components/input.js b/addons/docs/src/frameworks/react/__testfixtures__/8663-js-styled-components/input.js new file mode 100644 index 000000000000..493ebe783cbd --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/8663-js-styled-components/input.js @@ -0,0 +1,20 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import styled from 'styled-components'; + +const Box = styled.div` + background-color: ${props => props.bg}; +`; + +Box.propTypes = { + bg: PropTypes.string, +}; + +export const MyBox = props => ; + +MyBox.propTypes = { + // eslint-disable-next-line react/require-default-props + bg: PropTypes.string, +}; + +export const component = MyBox; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/8663-js-styled-components/properties.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/8663-js-styled-components/properties.snapshot new file mode 100644 index 000000000000..0681e3864563 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/8663-js-styled-components/properties.snapshot @@ -0,0 +1,18 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 8663-js-styled-components 1`] = ` +Object { + "rows": Array [ + Object { + "defaultValue": null, + "description": "", + "name": "bg", + "required": false, + "type": Object { + "detail": undefined, + "summary": "string", + }, + }, + ], +} +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/8740-ts-multi-props/docgen.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/8740-ts-multi-props/docgen.snapshot new file mode 100644 index 000000000000..16b8164d715e --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/8740-ts-multi-props/docgen.snapshot @@ -0,0 +1,49 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 8740-ts-multi-props 1`] = ` +"import React from 'react'; +export const Header = ({ + size = 'a', + children +}) => React.createElement(\\"div\\", { + className: size +}, children); +export const Paragraph = ({ + size, + children +}) => React.createElement(\\"div\\", { + className: size +}, children); +Paragraph.defaultProps = { + size: 'md' +}; +export const component = Header; +Header.__docgenInfo = { + \\"description\\": \\"\\", + \\"methods\\": [], + \\"displayName\\": \\"Header\\", + \\"props\\": { + \\"size\\": { + \\"defaultValue\\": { + \\"value\\": \\"'a'\\", + \\"computed\\": false + }, + \\"required\\": false + } + } +}; +Paragraph.__docgenInfo = { + \\"description\\": \\"\\", + \\"methods\\": [], + \\"displayName\\": \\"Paragraph\\", + \\"props\\": { + \\"size\\": { + \\"defaultValue\\": { + \\"value\\": \\"'md'\\", + \\"computed\\": false + }, + \\"required\\": false + } + } +};" +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/8740-ts-multi-props/input.tsx b/addons/docs/src/frameworks/react/__testfixtures__/8740-ts-multi-props/input.tsx new file mode 100644 index 000000000000..ee19cf1a8e94 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/8740-ts-multi-props/input.tsx @@ -0,0 +1,21 @@ +import React from 'react'; + +export interface ElemAProps { + size?: 'a' | 'b' | 'c' | 'd'; +} + +export const Header: React.SFC = ({ size = 'a', children }) => ( +
{children}
+); + +export interface ElemBProps { + size?: 'sm' | 'md' | 'lg'; +} + +export const Paragraph: React.SFC = ({ size, children }) => ( +
{children}
+); + +Paragraph.defaultProps = { size: 'md' }; + +export const component = Header; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/8740-ts-multi-props/properties.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/8740-ts-multi-props/properties.snapshot new file mode 100644 index 000000000000..9877ca576ceb --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/8740-ts-multi-props/properties.snapshot @@ -0,0 +1,21 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 8740-ts-multi-props 1`] = ` +Object { + "rows": Array [ + Object { + "defaultValue": Object { + "detail": undefined, + "summary": "'a'", + }, + "description": undefined, + "name": "size", + "required": false, + "type": Object { + "detail": undefined, + "summary": "unknown", + }, + }, + ], +} +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/8894-9511-ts-forward-ref/docgen.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/8894-9511-ts-forward-ref/docgen.snapshot new file mode 100644 index 000000000000..43d37ef2103a --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/8894-9511-ts-forward-ref/docgen.snapshot @@ -0,0 +1,36 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 8894-9511-ts-forward-ref 1`] = ` +"import React, { forwardRef } from 'react'; +const Button = forwardRef(({ + disabled = false, + variant = 'small', + children +}, ref) => // eslint-disable-next-line react/button-has-type +React.createElement(\\"button\\", { + disabled: disabled, + ref: ref +}, children, \\" \\", variant)); +Button.__docgenInfo = { + \\"description\\": \\"\\", + \\"methods\\": [], + \\"props\\": { + \\"disabled\\": { + \\"defaultValue\\": { + \\"value\\": \\"false\\", + \\"computed\\": false + }, + \\"required\\": false + }, + \\"variant\\": { + \\"defaultValue\\": { + \\"value\\": \\"'small'\\", + \\"computed\\": false + }, + \\"required\\": false + } + } +}; +export default Button; +export const component = Button;" +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/8894-9511-ts-forward-ref/input.tsx b/addons/docs/src/frameworks/react/__testfixtures__/8894-9511-ts-forward-ref/input.tsx new file mode 100644 index 000000000000..0878c8cd8ca3 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/8894-9511-ts-forward-ref/input.tsx @@ -0,0 +1,25 @@ +import React, { forwardRef } from 'react'; + +interface ButtonProps { + /** + * Sets the button size. + */ + variant?: 'small' | 'large'; + /** + * Disables the button. + */ + disabled?: boolean; +} + +const Button = forwardRef( + ({ disabled = false, variant = 'small', children }, ref) => ( + // eslint-disable-next-line react/button-has-type + + ) +); + +export default Button; + +export const component = Button; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/8894-9511-ts-forward-ref/properties.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/8894-9511-ts-forward-ref/properties.snapshot new file mode 100644 index 000000000000..63a04364ae3a --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/8894-9511-ts-forward-ref/properties.snapshot @@ -0,0 +1,34 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 8894-9511-ts-forward-ref 1`] = ` +Object { + "rows": Array [ + Object { + "defaultValue": Object { + "detail": undefined, + "summary": "false", + }, + "description": undefined, + "name": "disabled", + "required": false, + "type": Object { + "detail": undefined, + "summary": "unknown", + }, + }, + Object { + "defaultValue": Object { + "detail": undefined, + "summary": "'small'", + }, + "description": undefined, + "name": "variant", + "required": false, + "type": Object { + "detail": undefined, + "summary": "unknown", + }, + }, + ], +} +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9023-js-hoc/docgen.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/9023-js-hoc/docgen.snapshot new file mode 100644 index 000000000000..2bd3202c1a43 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9023-js-hoc/docgen.snapshot @@ -0,0 +1,89 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 9023-js-hoc 1`] = ` +"/* eslint-disable react/forbid-prop-types */ + +/* eslint-disable react/require-default-props */ + +/* eslint-disable react/no-unused-prop-types */ + +/* eslint-disable react/prefer-stateless-function */ +import React from 'react'; +import PropTypes from 'prop-types'; + +const withStyles = themeFn => Comp => Comp; + +class Alert extends React.Component { + render() { + return React.createElement(React.Fragment, null, \\"Alert\\"); + } + +} + +Alert.propTypes = { + variant: PropTypes.string, + dismissible: PropTypes.bool, + icon: PropTypes.elementType, + classes: PropTypes.object.isRequired +}; +Alert.defaultProps = { + variant: 'primary', + dismissible: false +}; +const StyledAlert = withStyles(theme => ({ + alert: props => ({ + backgroundColor: theme.palette[props.variant].main + }), + message: { + display: 'flex', + alignItems: 'center' + }, + icon: { + marginRight: theme.spacing(2) + } +}))(Alert); +export const component = StyledAlert; +Alert.__docgenInfo = { + \\"description\\": \\"\\", + \\"methods\\": [], + \\"displayName\\": \\"Alert\\", + \\"props\\": { + \\"variant\\": { + \\"defaultValue\\": { + \\"value\\": \\"'primary'\\", + \\"computed\\": false + }, + \\"type\\": { + \\"name\\": \\"string\\" + }, + \\"required\\": false, + \\"description\\": \\"\\" + }, + \\"dismissible\\": { + \\"defaultValue\\": { + \\"value\\": \\"false\\", + \\"computed\\": false + }, + \\"type\\": { + \\"name\\": \\"bool\\" + }, + \\"required\\": false, + \\"description\\": \\"\\" + }, + \\"icon\\": { + \\"type\\": { + \\"name\\": \\"elementType\\" + }, + \\"required\\": false, + \\"description\\": \\"\\" + }, + \\"classes\\": { + \\"type\\": { + \\"name\\": \\"object\\" + }, + \\"required\\": true, + \\"description\\": \\"\\" + } + } +};" +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9023-js-hoc/input.js b/addons/docs/src/frameworks/react/__testfixtures__/9023-js-hoc/input.js new file mode 100644 index 000000000000..46f18c7ea3df --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9023-js-hoc/input.js @@ -0,0 +1,39 @@ +/* eslint-disable react/forbid-prop-types */ +/* eslint-disable react/require-default-props */ +/* eslint-disable react/no-unused-prop-types */ +/* eslint-disable react/prefer-stateless-function */ +import React from 'react'; +import PropTypes from 'prop-types'; + +const withStyles = themeFn => Comp => Comp; + +class Alert extends React.Component { + render() { + return <>Alert; + } +} +Alert.propTypes = { + variant: PropTypes.string, + dismissible: PropTypes.bool, + icon: PropTypes.elementType, + classes: PropTypes.object.isRequired, +}; +Alert.defaultProps = { + variant: 'primary', + dismissible: false, +}; + +const StyledAlert = withStyles(theme => ({ + alert: props => ({ + backgroundColor: theme.palette[props.variant].main, + }), + message: { + display: 'flex', + alignItems: 'center', + }, + icon: { + marginRight: theme.spacing(2), + }, +}))(Alert); + +export const component = StyledAlert; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9023-js-hoc/properties.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/9023-js-hoc/properties.snapshot new file mode 100644 index 000000000000..6c8e78ce3878 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9023-js-hoc/properties.snapshot @@ -0,0 +1,54 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 9023-js-hoc 1`] = ` +Object { + "rows": Array [ + Object { + "defaultValue": Object { + "detail": undefined, + "summary": "'primary'", + }, + "description": "", + "name": "variant", + "required": false, + "type": Object { + "detail": undefined, + "summary": "string", + }, + }, + Object { + "defaultValue": Object { + "detail": undefined, + "summary": "false", + }, + "description": "", + "name": "dismissible", + "required": false, + "type": Object { + "detail": undefined, + "summary": "bool", + }, + }, + Object { + "defaultValue": null, + "description": "", + "name": "icon", + "required": false, + "type": Object { + "detail": undefined, + "summary": "elementType", + }, + }, + Object { + "defaultValue": null, + "description": "", + "name": "classes", + "required": true, + "type": Object { + "detail": undefined, + "summary": "object", + }, + }, + ], +} +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9399-js-proptypes-shape/docgen.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/9399-js-proptypes-shape/docgen.snapshot new file mode 100644 index 000000000000..700732942e9a --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9399-js-proptypes-shape/docgen.snapshot @@ -0,0 +1,47 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 9399-js-proptypes-shape 1`] = ` +"import React from 'react'; +import PropTypes from 'prop-types'; +export const Credits = ({ + areas +}) => React.createElement(React.Fragment, null, JSON.stringify(areas)); // https://github.com/storybookjs/storybook/issues/9399 + +Credits.propTypes = { + areas: PropTypes.arrayOf(PropTypes.shape({ + position: PropTypes.string.isRequired, + names: PropTypes.arrayOf(PropTypes.string).isRequired + })).isRequired +}; +export const component = Credits; +Credits.__docgenInfo = { + \\"description\\": \\"\\", + \\"methods\\": [], + \\"displayName\\": \\"Credits\\", + \\"props\\": { + \\"areas\\": { + \\"type\\": { + \\"name\\": \\"arrayOf\\", + \\"value\\": { + \\"name\\": \\"shape\\", + \\"value\\": { + \\"position\\": { + \\"name\\": \\"string\\", + \\"required\\": true + }, + \\"names\\": { + \\"name\\": \\"arrayOf\\", + \\"value\\": { + \\"name\\": \\"string\\" + }, + \\"required\\": true + } + } + } + }, + \\"required\\": true, + \\"description\\": \\"\\" + } + } +};" +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9399-js-proptypes-shape/input.js b/addons/docs/src/frameworks/react/__testfixtures__/9399-js-proptypes-shape/input.js new file mode 100644 index 000000000000..af120524fa8f --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9399-js-proptypes-shape/input.js @@ -0,0 +1,16 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +export const Credits = ({ areas }) => <>{JSON.stringify(areas)}; + +// https://github.com/storybookjs/storybook/issues/9399 +Credits.propTypes = { + areas: PropTypes.arrayOf( + PropTypes.shape({ + position: PropTypes.string.isRequired, + names: PropTypes.arrayOf(PropTypes.string).isRequired, + }) + ).isRequired, +}; + +export const component = Credits; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9399-js-proptypes-shape/properties.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/9399-js-proptypes-shape/properties.snapshot new file mode 100644 index 000000000000..193a0a5d8423 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9399-js-proptypes-shape/properties.snapshot @@ -0,0 +1,18 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 9399-js-proptypes-shape 1`] = ` +Object { + "rows": Array [ + Object { + "defaultValue": null, + "description": "", + "name": "areas", + "required": true, + "type": Object { + "detail": "[object]", + "summary": "object[]", + }, + }, + ], +} +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9465-ts-type-props/docgen.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/9465-ts-type-props/docgen.snapshot new file mode 100644 index 000000000000..58c223819ff8 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9465-ts-type-props/docgen.snapshot @@ -0,0 +1,33 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 9465-ts-type-props 1`] = ` +"import React from 'react'; + +const Component = ({ + disabled = false, + children +}) => // eslint-disable-next-line react/button-has-type +React.createElement(\\"button\\", { + disabled: disabled +}, children); + +export const component = Component; +Component.__docgenInfo = { + \\"description\\": \\"\\", + \\"methods\\": [], + \\"displayName\\": \\"Component\\", + \\"props\\": { + \\"disabled\\": { + \\"defaultValue\\": { + \\"value\\": \\"false\\", + \\"computed\\": false + }, + \\"required\\": false, + \\"tsType\\": { + \\"name\\": \\"boolean\\" + }, + \\"description\\": \\"\\" + } + } +};" +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9465-ts-type-props/input.tsx b/addons/docs/src/frameworks/react/__testfixtures__/9465-ts-type-props/input.tsx new file mode 100644 index 000000000000..e5627c8058fa --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9465-ts-type-props/input.tsx @@ -0,0 +1,12 @@ +import React from 'react'; + +type Props = React.ButtonHTMLAttributes & { + disabled?: boolean; +}; + +const Component = ({ disabled = false, children }: Props) => ( + // eslint-disable-next-line react/button-has-type + +); + +export const component = Component; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9465-ts-type-props/properties.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/9465-ts-type-props/properties.snapshot new file mode 100644 index 000000000000..67f69b4def7c --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9465-ts-type-props/properties.snapshot @@ -0,0 +1,21 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 9465-ts-type-props 1`] = ` +Object { + "rows": Array [ + Object { + "defaultValue": Object { + "detail": undefined, + "summary": "false", + }, + "description": "", + "name": "disabled", + "required": false, + "type": Object { + "detail": undefined, + "summary": "boolean", + }, + }, + ], +} +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9493-ts-display-name/docgen.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/9493-ts-display-name/docgen.snapshot new file mode 100644 index 000000000000..bfec8463a63b --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9493-ts-display-name/docgen.snapshot @@ -0,0 +1,59 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 9493-ts-display-name 1`] = ` +"import styled from '@emotion/styled'; +import React from 'react'; +const Wrapper = styled('div')(({ + theme +}) => ({ + backgroundColor: 'tomato', + color: 'white', + padding: 10 +})); + +/** + * This message should show up in the Docs panel if everything works fine. + */ +export const EmpireAlert = ({ + title = 'Code Yellow', + message +}) => React.createElement(Wrapper, null, React.createElement(\\"h1\\", null, title), React.createElement(\\"p\\", null, message)); +EmpireAlert.displayName = 'SomeOtherDisplayName'; +export const component = EmpireAlert; +EmpireAlert.__docgenInfo = { + \\"description\\": \\"This message should show up in the Docs panel if everything works fine.\\", + \\"methods\\": [], + \\"displayName\\": \\"SomeOtherDisplayName\\", + \\"props\\": { + \\"title\\": { + \\"defaultValue\\": { + \\"value\\": \\"'Code Yellow'\\", + \\"computed\\": false + }, + \\"required\\": false, + \\"tsType\\": { + \\"name\\": \\"union\\", + \\"raw\\": \\"'Code Red' | 'Code Yellow' | 'Code Green'\\", + \\"elements\\": [{ + \\"name\\": \\"literal\\", + \\"value\\": \\"'Code Red'\\" + }, { + \\"name\\": \\"literal\\", + \\"value\\": \\"'Code Yellow'\\" + }, { + \\"name\\": \\"literal\\", + \\"value\\": \\"'Code Green'\\" + }] + }, + \\"description\\": \\"A title that brings attention to the alert.\\" + }, + \\"message\\": { + \\"required\\": true, + \\"tsType\\": { + \\"name\\": \\"string\\" + }, + \\"description\\": \\"A message alerting about Empire activities.\\" + } + } +};" +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9493-ts-display-name/input.tsx b/addons/docs/src/frameworks/react/__testfixtures__/9493-ts-display-name/input.tsx new file mode 100644 index 000000000000..57155c790165 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9493-ts-display-name/input.tsx @@ -0,0 +1,37 @@ +import styled from '@emotion/styled'; +import React from 'react'; + +const Wrapper = styled('div')<{}>(({ theme }) => ({ + backgroundColor: 'tomato', + color: 'white', + padding: 10, +})); + +type AlertCode = 'Code Red' | 'Code Yellow' | 'Code Green'; + +export interface EmpireAlertProps { + /** + * A title that brings attention to the alert. + */ + title: AlertCode; + /** + * A message alerting about Empire activities. + */ + message: string; +} + +/** + * This message should show up in the Docs panel if everything works fine. + */ +export const EmpireAlert: React.FC = ({ + title = 'Code Yellow', + message, +}: EmpireAlertProps) => ( + +

{title}

+

{message}

+
+); +EmpireAlert.displayName = 'SomeOtherDisplayName'; + +export const component = EmpireAlert; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9493-ts-display-name/properties.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/9493-ts-display-name/properties.snapshot new file mode 100644 index 000000000000..395c2943f310 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9493-ts-display-name/properties.snapshot @@ -0,0 +1,34 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 9493-ts-display-name 1`] = ` +Object { + "rows": Array [ + Object { + "defaultValue": Object { + "detail": undefined, + "summary": "'Code Yellow'", + }, + "description": "A title that brings attention to the alert.", + "name": "title", + "required": false, + "type": Object { + "detail": undefined, + "summary": "union", + }, + }, + Object { + "defaultValue": Object { + "detail": undefined, + "summary": "1", + }, + "description": "A message alerting about Empire activities.", + "name": "message", + "required": true, + "type": Object { + "detail": undefined, + "summary": "string", + }, + }, + ], +} +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9556-ts-react-default-exports/docgen.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/9556-ts-react-default-exports/docgen.snapshot new file mode 100644 index 000000000000..b9dce6097f0d --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9556-ts-react-default-exports/docgen.snapshot @@ -0,0 +1,33 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 9556-ts-react-default-exports 1`] = ` +"function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } + +/* eslint-disable react/button-has-type */ +import React from 'react'; +export const Button = ({ + isDisabled = false, + ...props +}) => React.createElement(\\"button\\", _extends({ + disabled: isDisabled +}, props)); +export const component = Button; +Button.__docgenInfo = { + \\"description\\": \\"\\", + \\"methods\\": [], + \\"displayName\\": \\"Button\\", + \\"props\\": { + \\"isDisabled\\": { + \\"defaultValue\\": { + \\"value\\": \\"false\\", + \\"computed\\": false + }, + \\"required\\": false, + \\"tsType\\": { + \\"name\\": \\"boolean\\" + }, + \\"description\\": \\"\\" + } + } +};" +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9556-ts-react-default-exports/input.tsx b/addons/docs/src/frameworks/react/__testfixtures__/9556-ts-react-default-exports/input.tsx new file mode 100644 index 000000000000..3517870221b2 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9556-ts-react-default-exports/input.tsx @@ -0,0 +1,12 @@ +/* eslint-disable react/button-has-type */ +import React from 'react'; + +export interface Props extends React.ButtonHTMLAttributes { + isDisabled?: boolean; +} + +export const Button: React.FC = ({ isDisabled = false, ...props }: Props) => ( + ; +} + +Button.propTypes = { + label: PropTypes.string.isRequired, + onClick: PropTypes.func.isRequired, +}; + +const MemoButton = React.memo(Button); +export const component = MemoButton; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9586-js-react-memo/properties.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/9586-js-react-memo/properties.snapshot new file mode 100644 index 000000000000..125e28045362 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9586-js-react-memo/properties.snapshot @@ -0,0 +1,7 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 9586-js-react-memo 1`] = ` +Object { + "rows": Array [], +} +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9591-ts-import-types/Bar.tsx b/addons/docs/src/frameworks/react/__testfixtures__/9591-ts-import-types/Bar.tsx new file mode 100644 index 000000000000..990a576fd54d --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9591-ts-import-types/Bar.tsx @@ -0,0 +1,3 @@ +export type BarProps = { + foo?: string; +}; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9591-ts-import-types/docgen.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/9591-ts-import-types/docgen.snapshot new file mode 100644 index 000000000000..b4bcfd817fd2 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9591-ts-import-types/docgen.snapshot @@ -0,0 +1,23 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 9591-ts-import-types 1`] = ` +"import React from 'react'; + +const Other = props => React.createElement(\\"span\\", props, \\"Other\\"); + +export const component = Other; +Other.__docgenInfo = { + \\"description\\": \\"\\", + \\"methods\\": [], + \\"displayName\\": \\"Other\\", + \\"props\\": { + \\"other\\": { + \\"required\\": false, + \\"tsType\\": { + \\"name\\": \\"number\\" + }, + \\"description\\": \\"\\" + } + } +};" +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9591-ts-import-types/input.tsx b/addons/docs/src/frameworks/react/__testfixtures__/9591-ts-import-types/input.tsx new file mode 100644 index 000000000000..f1049b4e1acb --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9591-ts-import-types/input.tsx @@ -0,0 +1,10 @@ +import React from 'react'; +import { BarProps } from './Bar'; + +type OtherProps = BarProps & { + other?: number; +}; + +const Other = (props: OtherProps) => Other; + +export const component = Other; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9591-ts-import-types/properties.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/9591-ts-import-types/properties.snapshot new file mode 100644 index 000000000000..78d106871602 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9591-ts-import-types/properties.snapshot @@ -0,0 +1,21 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 9591-ts-import-types 1`] = ` +Object { + "rows": Array [ + Object { + "defaultValue": Object { + "detail": undefined, + "summary": "0", + }, + "description": "", + "name": "other", + "required": false, + "type": Object { + "detail": undefined, + "summary": "number", + }, + }, + ], +} +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9592-ts-styled-props/docgen.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/9592-ts-styled-props/docgen.snapshot new file mode 100644 index 000000000000..ff1f7e85421f --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9592-ts-styled-props/docgen.snapshot @@ -0,0 +1,33 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 9592-ts-styled-props 1`] = ` +"import React from 'react'; +import styled from 'styled-components'; +const StyledHello = styled.div\` + color: red; +\`; + +const Hello = ({ + title +}) => { + return React.createElement(StyledHello, { + className: \\"hello\\" + }, \\"Hello Component \\", title); +}; + +export const component = Hello; +Hello.__docgenInfo = { + \\"description\\": \\"\\", + \\"methods\\": [], + \\"displayName\\": \\"Hello\\", + \\"props\\": { + \\"title\\": { + \\"required\\": true, + \\"tsType\\": { + \\"name\\": \\"string\\" + }, + \\"description\\": \\"\\" + } + } +};" +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9592-ts-styled-props/input.tsx b/addons/docs/src/frameworks/react/__testfixtures__/9592-ts-styled-props/input.tsx new file mode 100644 index 000000000000..485bad8f10b7 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9592-ts-styled-props/input.tsx @@ -0,0 +1,16 @@ +import React from 'react'; +import styled from 'styled-components'; + +interface HelloProps { + title: string; +} + +const StyledHello = styled.div` + color: red; +`; + +const Hello = ({ title }: HelloProps) => { + return Hello Component {title}; +}; + +export const component = Hello; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9592-ts-styled-props/properties.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/9592-ts-styled-props/properties.snapshot new file mode 100644 index 000000000000..4cfc37500730 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9592-ts-styled-props/properties.snapshot @@ -0,0 +1,21 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 9592-ts-styled-props 1`] = ` +Object { + "rows": Array [ + Object { + "defaultValue": Object { + "detail": undefined, + "summary": "0", + }, + "description": "", + "name": "title", + "required": true, + "type": Object { + "detail": undefined, + "summary": "string", + }, + }, + ], +} +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9626-js-default-values/docgen.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/9626-js-default-values/docgen.snapshot new file mode 100644 index 000000000000..67528fe5cdd7 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9626-js-default-values/docgen.snapshot @@ -0,0 +1,24 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 9626-js-default-values 1`] = ` +"import React from 'react'; // eslint-disable-next-line react/prop-types + +export const Tag = ({ + title = 'Beta' +}) => React.createElement(\\"div\\", null, title); +export const component = Tag; +Tag.__docgenInfo = { + \\"description\\": \\"\\", + \\"methods\\": [], + \\"displayName\\": \\"Tag\\", + \\"props\\": { + \\"title\\": { + \\"defaultValue\\": { + \\"value\\": \\"'Beta'\\", + \\"computed\\": false + }, + \\"required\\": false + } + } +};" +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9626-js-default-values/input.js b/addons/docs/src/frameworks/react/__testfixtures__/9626-js-default-values/input.js new file mode 100644 index 000000000000..451411c1c1e4 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9626-js-default-values/input.js @@ -0,0 +1,5 @@ +import React from 'react'; + +// eslint-disable-next-line react/prop-types +export const Tag = ({ title = 'Beta' }) =>
{title}
; +export const component = Tag; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9626-js-default-values/properties.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/9626-js-default-values/properties.snapshot new file mode 100644 index 000000000000..b1043c87f419 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9626-js-default-values/properties.snapshot @@ -0,0 +1,21 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 9626-js-default-values 1`] = ` +Object { + "rows": Array [ + Object { + "defaultValue": Object { + "detail": undefined, + "summary": "'Beta'", + }, + "description": undefined, + "name": "title", + "required": false, + "type": Object { + "detail": undefined, + "summary": "unknown", + }, + }, + ], +} +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9668-js-proptypes-no-jsdoc/docgen.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/9668-js-proptypes-no-jsdoc/docgen.snapshot new file mode 100644 index 000000000000..36193a4d8e6e --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9668-js-proptypes-no-jsdoc/docgen.snapshot @@ -0,0 +1,40 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 9668-js-proptypes-no-jsdoc 1`] = ` +"/* eslint-disable react/require-default-props */ + +/* eslint-disable react/no-unused-prop-types */ + +/* eslint-disable react/forbid-prop-types */ +import React from 'react'; +import PropTypes from 'prop-types'; + +const CCTable = props => React.createElement(React.Fragment, null, JSON.stringify(props)); + +CCTable.propTypes = { + heads: PropTypes.array.isRequired, + onAddClick: PropTypes.func +}; +export const component = CCTable; +CCTable.__docgenInfo = { + \\"description\\": \\"\\", + \\"methods\\": [], + \\"displayName\\": \\"CCTable\\", + \\"props\\": { + \\"heads\\": { + \\"type\\": { + \\"name\\": \\"array\\" + }, + \\"required\\": true, + \\"description\\": \\"\\" + }, + \\"onAddClick\\": { + \\"type\\": { + \\"name\\": \\"func\\" + }, + \\"required\\": false, + \\"description\\": \\"\\" + } + } +};" +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9668-js-proptypes-no-jsdoc/input.js b/addons/docs/src/frameworks/react/__testfixtures__/9668-js-proptypes-no-jsdoc/input.js new file mode 100644 index 000000000000..738e126bd17d --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9668-js-proptypes-no-jsdoc/input.js @@ -0,0 +1,13 @@ +/* eslint-disable react/require-default-props */ +/* eslint-disable react/no-unused-prop-types */ +/* eslint-disable react/forbid-prop-types */ +import React from 'react'; +import PropTypes from 'prop-types'; + +const CCTable = props => <>{JSON.stringify(props)}; +CCTable.propTypes = { + heads: PropTypes.array.isRequired, + onAddClick: PropTypes.func, +}; + +export const component = CCTable; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9668-js-proptypes-no-jsdoc/properties.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/9668-js-proptypes-no-jsdoc/properties.snapshot new file mode 100644 index 000000000000..4dea4decbacb --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9668-js-proptypes-no-jsdoc/properties.snapshot @@ -0,0 +1,28 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 9668-js-proptypes-no-jsdoc 1`] = ` +Object { + "rows": Array [ + Object { + "defaultValue": null, + "description": "", + "name": "heads", + "required": true, + "type": Object { + "detail": undefined, + "summary": "array", + }, + }, + Object { + "defaultValue": null, + "description": "", + "name": "onAddClick", + "required": false, + "type": Object { + "detail": undefined, + "summary": "func", + }, + }, + ], +} +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9721-ts-deprecated-jsdoc/docgen.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/9721-ts-deprecated-jsdoc/docgen.snapshot new file mode 100644 index 000000000000..534f0ba1cd5b --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9721-ts-deprecated-jsdoc/docgen.snapshot @@ -0,0 +1,47 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 9721-ts-deprecated-jsdoc 1`] = ` +"import React from 'react'; + +const Foo = props => React.createElement(React.Fragment, null, JSON.stringify(props)); + +export const component = Foo; +Foo.__docgenInfo = { + \\"description\\": \\"\\", + \\"methods\\": [], + \\"displayName\\": \\"Foo\\", + \\"props\\": { + \\"width\\": { + \\"required\\": true, + \\"tsType\\": { + \\"name\\": \\"number\\" + }, + \\"description\\": \\"@deprecated Do not use! Use \`size\` instead!\\\\n\\\\nWidth of foo\\" + }, + \\"size\\": { + \\"required\\": true, + \\"tsType\\": { + \\"name\\": \\"signature\\", + \\"type\\": \\"object\\", + \\"raw\\": \\"{ width: number; height: number }\\", + \\"signature\\": { + \\"properties\\": [{ + \\"key\\": \\"width\\", + \\"value\\": { + \\"name\\": \\"number\\", + \\"required\\": true + } + }, { + \\"key\\": \\"height\\", + \\"value\\": { + \\"name\\": \\"number\\", + \\"required\\": true + } + }] + } + }, + \\"description\\": \\"The size (replaces width)\\" + } + } +};" +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9721-ts-deprecated-jsdoc/input.tsx b/addons/docs/src/frameworks/react/__testfixtures__/9721-ts-deprecated-jsdoc/input.tsx new file mode 100644 index 000000000000..1d9fa51da825 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9721-ts-deprecated-jsdoc/input.tsx @@ -0,0 +1,18 @@ +import React from 'react'; + +interface FooProps { + /** + * @deprecated Do not use! Use `size` instead! + * + * Width of foo + */ + width: number; + /** + * The size (replaces width) + */ + size: { width: number; height: number }; +} + +const Foo: React.FC = (props: FooProps) => <>{JSON.stringify(props)}; + +export const component = Foo; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9721-ts-deprecated-jsdoc/properties.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/9721-ts-deprecated-jsdoc/properties.snapshot new file mode 100644 index 000000000000..73b74b7b9d32 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9721-ts-deprecated-jsdoc/properties.snapshot @@ -0,0 +1,34 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 9721-ts-deprecated-jsdoc 1`] = ` +Object { + "rows": Array [ + Object { + "defaultValue": Object { + "detail": undefined, + "summary": "0", + }, + "description": "", + "name": "width", + "required": true, + "type": Object { + "detail": undefined, + "summary": "number", + }, + }, + Object { + "defaultValue": Object { + "detail": undefined, + "summary": "1", + }, + "description": "The size (replaces width)", + "name": "size", + "required": true, + "type": Object { + "detail": undefined, + "summary": "signature", + }, + }, + ], +} +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9764-ts-extend-props/docgen.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/9764-ts-extend-props/docgen.snapshot new file mode 100644 index 000000000000..01b9c02bc772 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9764-ts-extend-props/docgen.snapshot @@ -0,0 +1,43 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 9764-ts-extend-props 1`] = ` +"import React from 'react'; + +const Radio = props => React.createElement(React.Fragment, null, JSON.stringify(props)); + +export const component = Radio; +Radio.__docgenInfo = { + \\"description\\": \\"\\", + \\"methods\\": [], + \\"displayName\\": \\"Radio\\", + \\"props\\": { + \\"value\\": { + \\"required\\": false, + \\"tsType\\": { + \\"name\\": \\"union\\", + \\"raw\\": \\"string | number\\", + \\"elements\\": [{ + \\"name\\": \\"string\\" + }, { + \\"name\\": \\"number\\" + }] + }, + \\"description\\": \\"The input content value\\" + }, + \\"defaultChecked\\": { + \\"required\\": false, + \\"tsType\\": { + \\"name\\": \\"boolean\\" + }, + \\"description\\": \\"\\" + }, + \\"checked\\": { + \\"required\\": false, + \\"tsType\\": { + \\"name\\": \\"boolean\\" + }, + \\"description\\": \\"\\" + } + } +};" +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9764-ts-extend-props/input.tsx b/addons/docs/src/frameworks/react/__testfixtures__/9764-ts-extend-props/input.tsx new file mode 100644 index 000000000000..2abd61eed129 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9764-ts-extend-props/input.tsx @@ -0,0 +1,17 @@ +import React from 'react'; + +interface InputProps { + /** + * The input content value + */ + value?: string | number; +} + +interface RadioProps extends InputProps { + defaultChecked?: boolean; + checked?: boolean; +} + +const Radio: React.FC = (props: RadioProps) => <>{JSON.stringify(props)}; + +export const component = Radio; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9764-ts-extend-props/properties.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/9764-ts-extend-props/properties.snapshot new file mode 100644 index 000000000000..94f0778e84bd --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9764-ts-extend-props/properties.snapshot @@ -0,0 +1,47 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 9764-ts-extend-props 1`] = ` +Object { + "rows": Array [ + Object { + "defaultValue": Object { + "detail": undefined, + "summary": "0", + }, + "description": "The input content value", + "name": "value", + "required": false, + "type": Object { + "detail": undefined, + "summary": "union", + }, + }, + Object { + "defaultValue": Object { + "detail": undefined, + "summary": "1", + }, + "description": "", + "name": "defaultChecked", + "required": false, + "type": Object { + "detail": undefined, + "summary": "boolean", + }, + }, + Object { + "defaultValue": Object { + "detail": undefined, + "summary": "2", + }, + "description": "", + "name": "checked", + "required": false, + "type": Object { + "detail": undefined, + "summary": "boolean", + }, + }, + ], +} +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9827-ts-default-values/docgen.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/9827-ts-default-values/docgen.snapshot new file mode 100644 index 000000000000..6ccab5afcaa6 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9827-ts-default-values/docgen.snapshot @@ -0,0 +1,54 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 9827-ts-default-values 1`] = ` +"import React from 'react'; + +const Hello = ({ + title +}) => { + return React.createElement(\\"div\\", { + className: \\"hello\\" + }, \\"Hello Component \\", title); +}; + +Hello.defaultProps = { + title: 'this is the default :)' +}; +export const component = Hello; +Hello.__docgenInfo = { + \\"description\\": \\"\\", + \\"methods\\": [], + \\"displayName\\": \\"Hello\\", + \\"props\\": { + \\"title\\": { + \\"defaultValue\\": { + \\"value\\": \\"'this is the default :)'\\", + \\"computed\\": false + }, + \\"required\\": false, + \\"tsType\\": { + \\"name\\": \\"string\\" + }, + \\"description\\": \\"\\" + }, + \\"foo\\": { + \\"required\\": true, + \\"tsType\\": { + \\"name\\": \\"boolean\\" + }, + \\"description\\": \\"\\" + }, + \\"bar\\": { + \\"required\\": false, + \\"tsType\\": { + \\"name\\": \\"Array\\", + \\"elements\\": [{ + \\"name\\": \\"string\\" + }], + \\"raw\\": \\"string[]\\" + }, + \\"description\\": \\"\\" + } + } +};" +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9827-ts-default-values/input.tsx b/addons/docs/src/frameworks/react/__testfixtures__/9827-ts-default-values/input.tsx new file mode 100644 index 000000000000..373829aac3b3 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9827-ts-default-values/input.tsx @@ -0,0 +1,17 @@ +import React from 'react'; + +export interface HelloProps { + title: string; + foo: boolean; + bar?: string[]; +} + +const Hello = ({ title }: HelloProps) => { + return
Hello Component {title}
; +}; + +Hello.defaultProps = { + title: 'this is the default :)', +}; + +export const component = Hello; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9827-ts-default-values/properties.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/9827-ts-default-values/properties.snapshot new file mode 100644 index 000000000000..098188816e3a --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9827-ts-default-values/properties.snapshot @@ -0,0 +1,47 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 9827-ts-default-values 1`] = ` +Object { + "rows": Array [ + Object { + "defaultValue": Object { + "detail": undefined, + "summary": "'this is the default :)'", + }, + "description": "", + "name": "title", + "required": false, + "type": Object { + "detail": undefined, + "summary": "string", + }, + }, + Object { + "defaultValue": Object { + "detail": undefined, + "summary": "1", + }, + "description": "", + "name": "foo", + "required": true, + "type": Object { + "detail": undefined, + "summary": "boolean", + }, + }, + Object { + "defaultValue": Object { + "detail": undefined, + "summary": "2", + }, + "description": "", + "name": "bar", + "required": false, + "type": Object { + "detail": undefined, + "summary": "Array", + }, + }, + ], +} +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9832-ts-enum-export/docgen.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/9832-ts-enum-export/docgen.snapshot new file mode 100644 index 000000000000..f2307f88fa1d --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9832-ts-enum-export/docgen.snapshot @@ -0,0 +1,18 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 9832-ts-enum-export 1`] = ` +"import React from 'react'; +export let EnumWithExtraProps; + +(function (EnumWithExtraProps) { + EnumWithExtraProps[\\"key1\\"] = \\"key1\\"; + EnumWithExtraProps[\\"key2\\"] = \\"key2\\"; +})(EnumWithExtraProps || (EnumWithExtraProps = {})); + +export const component = () => React.createElement(\\"div\\", null, \\"hello\\"); +component.__docgenInfo = { + \\"description\\": \\"\\", + \\"methods\\": [], + \\"displayName\\": \\"component\\" +};" +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9832-ts-enum-export/input.tsx b/addons/docs/src/frameworks/react/__testfixtures__/9832-ts-enum-export/input.tsx new file mode 100644 index 000000000000..3072adb5705e --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9832-ts-enum-export/input.tsx @@ -0,0 +1,8 @@ +import React from 'react'; + +export enum EnumWithExtraProps { + key1 = 'key1', + key2 = 'key2', +} + +export const component = () =>
hello
; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/9832-ts-enum-export/properties.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/9832-ts-enum-export/properties.snapshot new file mode 100644 index 000000000000..85dec505d2c5 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/9832-ts-enum-export/properties.snapshot @@ -0,0 +1,7 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties 9832-ts-enum-export 1`] = ` +Object { + "rows": Array [], +} +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/js-class-component/docgen.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/js-class-component/docgen.snapshot new file mode 100644 index 000000000000..5952fcbc3e52 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/js-class-component/docgen.snapshot @@ -0,0 +1,45 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties js-class-component 1`] = ` +"/* eslint-disable react/prefer-stateless-function */ +import React from 'react'; +import PropTypes from 'prop-types'; +/** + * Component description + */ + +class ErrorBox extends React.Component { + render() { + const { + children + } = this.props; + return React.createElement(\\"div\\", { + className: \\"error-box\\" + }, children); + } + +} + +ErrorBox.propTypes = { + /** + * PropTypes description + */ + children: PropTypes.node.isRequired +}; +ErrorBox.__docgenInfo = { + \\"description\\": \\"Component description\\", + \\"methods\\": [], + \\"displayName\\": \\"ErrorBox\\", + \\"props\\": { + \\"children\\": { + \\"type\\": { + \\"name\\": \\"node\\" + }, + \\"required\\": true, + \\"description\\": \\"PropTypes description\\" + } + } +}; +export default ErrorBox; +export const component = ErrorBox;" +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/js-class-component/input.js b/addons/docs/src/frameworks/react/__testfixtures__/js-class-component/input.js new file mode 100644 index 000000000000..c94bb47ca22b --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/js-class-component/input.js @@ -0,0 +1,24 @@ +/* eslint-disable react/prefer-stateless-function */ +import React from 'react'; +import PropTypes from 'prop-types'; + +/** + * Component description + */ +class ErrorBox extends React.Component { + render() { + const { children } = this.props; + + return
{children}
; + } +} + +ErrorBox.propTypes = { + /** + * PropTypes description + */ + children: PropTypes.node.isRequired, +}; + +export default ErrorBox; +export const component = ErrorBox; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/js-class-component/properties.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/js-class-component/properties.snapshot new file mode 100644 index 000000000000..62dea7473922 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/js-class-component/properties.snapshot @@ -0,0 +1,18 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties js-class-component 1`] = ` +Object { + "rows": Array [ + Object { + "defaultValue": null, + "description": "PropTypes description", + "name": "children", + "required": true, + "type": Object { + "detail": undefined, + "summary": "node", + }, + }, + ], +} +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/ts-function-component/docgen.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/ts-function-component/docgen.snapshot new file mode 100644 index 000000000000..5d5fe32b98da --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/ts-function-component/docgen.snapshot @@ -0,0 +1,64 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties ts-function-component 1`] = ` +"import React from 'react'; + +/** + * The world's most _basic_ button + */ +export const Button = ({ + onClick +}) => React.createElement(\\"button\\", { + onClick: onClick, + type: \\"button\\" +}, \\"hello\\"); +Button.defaultProps = { + primary: true, + secondary: false +}; +export const component = Button; +Button.__docgenInfo = { + \\"description\\": \\"The world's most _basic_ button\\", + \\"methods\\": [], + \\"displayName\\": \\"Button\\", + \\"props\\": { + \\"primary\\": { + \\"defaultValue\\": { + \\"value\\": \\"true\\", + \\"computed\\": false + }, + \\"required\\": false, + \\"tsType\\": { + \\"name\\": \\"boolean\\" + }, + \\"description\\": \\"Is primary?\\" + }, + \\"secondary\\": { + \\"defaultValue\\": { + \\"value\\": \\"false\\", + \\"computed\\": false + }, + \\"required\\": false, + \\"tsType\\": { + \\"name\\": \\"boolean\\" + }, + \\"description\\": \\"default is false\\" + }, + \\"onClick\\": { + \\"required\\": false, + \\"tsType\\": { + \\"name\\": \\"signature\\", + \\"type\\": \\"function\\", + \\"raw\\": \\"() => void\\", + \\"signature\\": { + \\"arguments\\": [], + \\"return\\": { + \\"name\\": \\"void\\" + } + } + }, + \\"description\\": \\"Simple click handler\\" + } + } +};" +`; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/ts-function-component/input.tsx b/addons/docs/src/frameworks/react/__testfixtures__/ts-function-component/input.tsx new file mode 100644 index 000000000000..fdeea8fa6c8a --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/ts-function-component/input.tsx @@ -0,0 +1,34 @@ +import React from 'react'; + +interface ButtonProps { + /** + * Simple click handler + */ + onClick?: () => void; + + /** + * Is primary? + */ + primary?: boolean; + + /** + * default is false + */ + secondary?: boolean; +} + +/** + * The world's most _basic_ button + */ +export const Button: React.FC = ({ onClick }: ButtonProps) => ( + +); + +Button.defaultProps = { + primary: true, + secondary: false, +}; + +export const component = Button; diff --git a/addons/docs/src/frameworks/react/__testfixtures__/ts-function-component/properties.snapshot b/addons/docs/src/frameworks/react/__testfixtures__/ts-function-component/properties.snapshot new file mode 100644 index 000000000000..3577fd957656 --- /dev/null +++ b/addons/docs/src/frameworks/react/__testfixtures__/ts-function-component/properties.snapshot @@ -0,0 +1,47 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react component properties ts-function-component 1`] = ` +Object { + "rows": Array [ + Object { + "defaultValue": Object { + "detail": undefined, + "summary": "true", + }, + "description": "Is primary?", + "name": "primary", + "required": false, + "type": Object { + "detail": undefined, + "summary": "boolean", + }, + }, + Object { + "defaultValue": Object { + "detail": undefined, + "summary": "false", + }, + "description": "default is false", + "name": "secondary", + "required": false, + "type": Object { + "detail": undefined, + "summary": "boolean", + }, + }, + Object { + "defaultValue": Object { + "detail": undefined, + "summary": "2", + }, + "description": "Simple click handler", + "name": "onClick", + "required": false, + "type": Object { + "detail": undefined, + "summary": "signature", + }, + }, + ], +} +`; diff --git a/addons/docs/src/frameworks/react/propTypes/createType.ts b/addons/docs/src/frameworks/react/propTypes/createType.ts index ce3cefc186d7..f75ea0edbe4f 100644 --- a/addons/docs/src/frameworks/react/propTypes/createType.ts +++ b/addons/docs/src/frameworks/react/propTypes/createType.ts @@ -209,8 +209,8 @@ function generateShape(type: DocgenPropType, extractedProp: ExtractedProp): Type return createTypeDef({ name: PropTypesType.SHAPE, short: OBJECT_CAPTION, - compact: depth === 1 ? prettyObject(ast, true) : null, - full: prettyObject(ast), + compact: depth === 1 && ast ? prettyObject(ast, true) : null, + full: ast ? prettyObject(ast) : null, }); } diff --git a/addons/docs/src/frameworks/react/react-properties.stories.tsx b/addons/docs/src/frameworks/react/react-properties.stories.tsx new file mode 100644 index 000000000000..f94a4627c2a5 --- /dev/null +++ b/addons/docs/src/frameworks/react/react-properties.stories.tsx @@ -0,0 +1,40 @@ +import React from 'react'; +import { storiesOf } from '@storybook/react'; +import { PropsTable } from '@storybook/components'; +import { extractProps } from './extractProps'; + +const fixtures = [ + 'js-class-component', + 'ts-function-component', + '9399-js-proptypes-shape', + '8663-js-styled-components', + '9626-js-default-values', + '9668-js-proptypes-no-jsdoc', + '8143-ts-react-fc-generics', + '8143-ts-imported-types', + '8279-js-styled-docgen', + '8140-js-prop-types-oneof', + '9023-js-hoc', + '8740-ts-multi-props', + '9556-ts-react-default-exports', + '9592-ts-styled-props', + '9591-ts-import-types', + '9721-ts-deprecated-jsdoc', + '9827-ts-default-values', + '9586-js-react-memo', + '9575-ts-camel-case', + '9493-ts-display-name', + '8894-9511-ts-forward-ref', + '9465-ts-type-props', + '8428-js-static-prop-types', + '9764-ts-extend-props', +]; + +const stories = storiesOf('Properties/React', module); + +fixtures.forEach(fixture => { + // eslint-disable-next-line import/no-dynamic-require, global-require + const { component } = require(`./__testfixtures__/${fixture}/input`); + const props = extractProps(component); + stories.add(fixture, () => ); +}); diff --git a/addons/docs/src/frameworks/react/react-properties.test.ts b/addons/docs/src/frameworks/react/react-properties.test.ts new file mode 100644 index 000000000000..c996b6fdeca6 --- /dev/null +++ b/addons/docs/src/frameworks/react/react-properties.test.ts @@ -0,0 +1,67 @@ +import 'jest-specific-snapshot'; +import path from 'path'; +import fs from 'fs'; + +import { transformFileSync, transformSync } from '@babel/core'; +import requireFromString from 'require-from-string'; + +import { extractProps } from './extractProps'; +import { normalizeNewlines } from '../../lib/utils'; + +// File hierarchy: +// __testfixtures__ / some-test-case / input.* +const inputRegExp = /^input\..*$/; + +const transformToModule = (inputCode: string) => { + const options = { + presets: [ + [ + '@babel/preset-env', + { + targets: { + esmodules: true, + }, + }, + ], + ], + }; + const { code } = transformSync(inputCode, options); + return normalizeNewlines(code); +}; + +const annotateWithDocgen = (inputPath: string) => { + const options = { + presets: ['@babel/typescript', '@babel/react'], + plugins: ['babel-plugin-react-docgen', '@babel/plugin-proposal-class-properties'], + babelrc: false, + }; + const { code } = transformFileSync(inputPath, options); + return normalizeNewlines(code); +}; + +describe('react component properties', () => { + const fixturesDir = path.join(__dirname, '__testfixtures__'); + fs.readdirSync(fixturesDir, { withFileTypes: true }).forEach(testEntry => { + if (testEntry.isDirectory()) { + const testDir = path.join(fixturesDir, testEntry.name); + const testFile = fs.readdirSync(testDir).find(fileName => inputRegExp.test(fileName)); + if (testFile) { + it(testEntry.name, () => { + const inputPath = path.join(testDir, testFile); + + // snapshot the output of babel-plugin-react-docgen + const docgenPretty = annotateWithDocgen(inputPath); + expect(docgenPretty).toMatchSpecificSnapshot(path.join(testDir, 'docgen.snapshot')); + + // transform into an uglier format that's works with require-from-string + const docgenModule = transformToModule(docgenPretty); + + // snapshot the output of component-properties/react + const { component } = requireFromString(docgenModule); + const properties = extractProps(component); + expect(properties).toMatchSpecificSnapshot(path.join(testDir, 'properties.snapshot')); + }); + } + } + }); +}); diff --git a/addons/docs/src/frameworks/web-components/__testfixtures__/lit-element-demo-card/custom-elements.snapshot b/addons/docs/src/frameworks/web-components/__testfixtures__/lit-element-demo-card/custom-elements.snapshot new file mode 100644 index 000000000000..162254124055 --- /dev/null +++ b/addons/docs/src/frameworks/web-components/__testfixtures__/lit-element-demo-card/custom-elements.snapshot @@ -0,0 +1,83 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`web-components component properties lit-element-demo-card 1`] = ` +Object { + "tags": Array [ + Object { + "attributes": Array [ + Object { + "default": "false", + "description": "Indicates that the back of the card is shown", + "name": "back-side", + "type": "boolean", + }, + Object { + "default": "\\"Your Message\\"", + "description": "Header message", + "name": "header", + "type": "string", + }, + Object { + "default": "[]", + "description": "Data rows", + "name": "rows", + "type": "object", + }, + ], + "cssProperties": Array [ + Object { + "description": "Header font size", + "name": "--demo-wc-card-header-font-size", + }, + Object { + "description": "Font color for front", + "name": "--demo-wc-card-front-color", + }, + Object { + "description": "Font color for back", + "name": "--demo-wc-card-back-color", + }, + ], + "description": "This is a container looking like a card with a back and front side you can switch", + "events": Array [ + Object { + "description": "Fires whenever it switches between front/back", + "name": "side-changed", + }, + ], + "name": "input", + "path": "dummy-path-to-component", + "properties": Array [ + Object { + "attribute": "back-side", + "default": "false", + "description": "Indicates that the back of the card is shown", + "name": "backSide", + "type": "boolean", + }, + Object { + "attribute": "header", + "default": "\\"Your Message\\"", + "description": "Header message", + "name": "header", + "type": "string", + }, + Object { + "attribute": "rows", + "default": "[]", + "description": "Data rows", + "name": "rows", + "type": "object", + }, + ], + "slots": Array [ + Object { + "description": "This is an unnamed slot (the default slot)", + "name": "", + }, + ], + }, + ], + "version": "experimental", +} +`; diff --git a/addons/docs/src/frameworks/web-components/__testfixtures__/lit-element-demo-card/input.js b/addons/docs/src/frameworks/web-components/__testfixtures__/lit-element-demo-card/input.js new file mode 100644 index 000000000000..ff166aa3ba51 --- /dev/null +++ b/addons/docs/src/frameworks/web-components/__testfixtures__/lit-element-demo-card/input.js @@ -0,0 +1,198 @@ +import { CustomEvent } from 'global'; +import { LitElement, html, css } from 'lit-element'; + +const demoWcCardStyle = css` + :host { + display: block; + position: relative; + width: 250px; + height: 200px; + border-radius: 10px; + transform-style: preserve-3d; + transition: all 0.8s ease; + } + + .header { + font-weight: bold; + font-size: var(--demo-wc-card-header-font-size, 16px); + text-align: center; + } + + .content { + padding: 20px 10px 0 10px; + flex-grow: 1; + } + + .footer { + display: flex; + } + + dl { + margin: 0; + text-align: left; + } + + dd { + margin-left: 15px; + } + + button { + border-radius: 15px; + width: 30px; + height: 30px; + background: #fff; + border: 1px solid #ccc; + color: #000; + font-size: 21px; + line-height: 27px; + font-weight: bold; + cursor: pointer; + margin: 5px; + } + + .note { + flex-grow: 1; + color: #666; + font-size: 16px; + font-weight: bold; + text-align: left; + padding-top: 15px; + } + + :host([back-side]) { + transform: rotateY(180deg); + } + + #front, + #back { + position: absolute; + width: 250px; + box-sizing: border-box; + box-shadow: #ccc 3px 3px 2px 1px; + padding: 10px; + display: flex; + flex-flow: column; + top: 0; + left: 0; + height: 100%; + border-radius: 10px; + backface-visibility: hidden; + overflow: hidden; + } + + #front { + background: linear-gradient(141deg, #aaa 25%, #eee 40%, #ddd 55%); + color: var(--demo-wc-card-front-color, #000); + } + + #back { + background: linear-gradient(141deg, #333 25%, #aaa 40%, #666 55%); + color: var(--demo-wc-card-back-color, #fff); + text-align: center; + transform: rotateY(180deg) translate3d(0px, 0, 1px); + } + + #back .note { + color: #fff; + } +`; + +/** + * This is a container looking like a card with a back and front side you can switch + * + * @slot - This is an unnamed slot (the default slot) + * @fires side-changed - Fires whenever it switches between front/back + * @cssprop --demo-wc-card-header-font-size - Header font size + * @cssprop --demo-wc-card-front-color - Font color for front + * @cssprop --demo-wc-card-back-color - Font color for back + */ +export class DemoWcCard extends LitElement { + static get properties() { + return { + backSide: { + type: Boolean, + reflect: true, + attribute: 'back-side', + }, + header: { type: String }, + rows: { type: Object }, + }; + } + + static get styles() { + return demoWcCardStyle; + } + + constructor() { + super(); + + /** + * Indicates that the back of the card is shown + */ + this.backSide = false; + + /** + * Header message + */ + this.header = 'Your Message'; + + /** + * Data rows + */ + this.rows = []; + } + + toggle() { + this.backSide = !this.backSide; + } + + render() { + return html` +
+
+ ${this.header} +
+
+ +
+ +
+
+
+ ${this.header} +
+ +
+ ${this.rows.length === 0 + ? html`` + : html` +
+ ${this.rows.map( + row => html` +
${row.header}
+
${row.value}
+ ` + )} +
+ `} +
+ +
+ `; + } + + updated(changedProperties) { + if (changedProperties.has('backSide') && changedProperties.get('backSide') !== undefined) { + this.dispatchEvent(new CustomEvent('side-changed')); + } + } +} + +// eslint-disable-next-line no-undef +customElements.define('input', DemoWcCard); diff --git a/addons/docs/src/frameworks/web-components/__testfixtures__/lit-element-demo-card/properties.snapshot b/addons/docs/src/frameworks/web-components/__testfixtures__/lit-element-demo-card/properties.snapshot new file mode 100644 index 000000000000..40a878b10105 --- /dev/null +++ b/addons/docs/src/frameworks/web-components/__testfixtures__/lit-element-demo-card/properties.snapshot @@ -0,0 +1,139 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`web-components component properties lit-element-demo-card 1`] = ` +Object { + "sections": Object { + "attributes": Array [ + Object { + "defaultValue": Object { + "summary": "false", + }, + "description": "Indicates that the back of the card is shown", + "name": "back-side", + "required": "", + "type": Object { + "summary": "boolean", + }, + }, + Object { + "defaultValue": Object { + "summary": "\\"Your Message\\"", + }, + "description": "Header message", + "name": "header", + "required": "", + "type": Object { + "summary": "string", + }, + }, + Object { + "defaultValue": Object { + "summary": "[]", + }, + "description": "Data rows", + "name": "rows", + "required": "", + "type": Object { + "summary": "object", + }, + }, + ], + "css": Array [ + Object { + "defaultValue": Object { + "summary": undefined, + }, + "description": "Header font size", + "name": "--demo-wc-card-header-font-size", + "required": "", + "type": Object { + "summary": undefined, + }, + }, + Object { + "defaultValue": Object { + "summary": undefined, + }, + "description": "Font color for front", + "name": "--demo-wc-card-front-color", + "required": "", + "type": Object { + "summary": undefined, + }, + }, + Object { + "defaultValue": Object { + "summary": undefined, + }, + "description": "Font color for back", + "name": "--demo-wc-card-back-color", + "required": "", + "type": Object { + "summary": undefined, + }, + }, + ], + "events": Array [ + Object { + "defaultValue": Object { + "summary": undefined, + }, + "description": "Fires whenever it switches between front/back", + "name": "side-changed", + "required": "", + "type": Object { + "summary": undefined, + }, + }, + ], + "properties": Array [ + Object { + "defaultValue": Object { + "summary": "false", + }, + "description": "Indicates that the back of the card is shown", + "name": "backSide", + "required": "", + "type": Object { + "summary": "boolean", + }, + }, + Object { + "defaultValue": Object { + "summary": "\\"Your Message\\"", + }, + "description": "Header message", + "name": "header", + "required": "", + "type": Object { + "summary": "string", + }, + }, + Object { + "defaultValue": Object { + "summary": "[]", + }, + "description": "Data rows", + "name": "rows", + "required": "", + "type": Object { + "summary": "object", + }, + }, + ], + "slots": Array [ + Object { + "defaultValue": Object { + "summary": undefined, + }, + "description": "This is an unnamed slot (the default slot)", + "name": "", + "required": "", + "type": Object { + "summary": undefined, + }, + }, + ], + }, +} +`; diff --git a/addons/docs/src/frameworks/web-components/__testfixtures__/lit-html-welcome/custom-elements.snapshot b/addons/docs/src/frameworks/web-components/__testfixtures__/lit-html-welcome/custom-elements.snapshot new file mode 100644 index 000000000000..c1416386b1b1 --- /dev/null +++ b/addons/docs/src/frameworks/web-components/__testfixtures__/lit-html-welcome/custom-elements.snapshot @@ -0,0 +1,13 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`web-components component properties lit-html-welcome 1`] = ` +Object { + "tags": Array [ + Object { + "name": "input", + "path": "dummy-path-to-component", + }, + ], + "version": "experimental", +} +`; diff --git a/addons/docs/src/frameworks/web-components/__testfixtures__/lit-html-welcome/input.js b/addons/docs/src/frameworks/web-components/__testfixtures__/lit-html-welcome/input.js new file mode 100644 index 000000000000..30e6edec7cf2 --- /dev/null +++ b/addons/docs/src/frameworks/web-components/__testfixtures__/lit-html-welcome/input.js @@ -0,0 +1,61 @@ +import { html } from 'lit-html'; + +export const Welcome = () => html` +
+

Welcome to Storybook for Web Components

+

This is a UI component dev environment for your plain HTML snippets.

+

+ We've added some basic stories inside the stories directory. +
+ A story is a single state of one or more UI components. You can have as many stories as you + want. +
+ (Basically a story is like a visual test case.) +

+

+ See these sample + stories +

+

+ Just like that, you can add your own snippets as stories. +
+ You can also edit those snippets and see changes right away. +
+

+

+ Usually we create stories with smaller UI components in the app.
+ Have a look at the + + Writing Stories + + section in our documentation. +

+
+ + +`; + +// eslint-disable-next-line no-undef +customElements.define('input', Welcome); diff --git a/addons/docs/src/frameworks/web-components/__testfixtures__/lit-html-welcome/properties.snapshot b/addons/docs/src/frameworks/web-components/__testfixtures__/lit-html-welcome/properties.snapshot new file mode 100644 index 000000000000..3ed546fa4e29 --- /dev/null +++ b/addons/docs/src/frameworks/web-components/__testfixtures__/lit-html-welcome/properties.snapshot @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`web-components component properties lit-html-welcome 1`] = `false`; diff --git a/addons/docs/src/frameworks/web-components/config.js b/addons/docs/src/frameworks/web-components/config.js index 883c269e4e9f..c14ef2f9bfa8 100644 --- a/addons/docs/src/frameworks/web-components/config.js +++ b/addons/docs/src/frameworks/web-components/config.js @@ -1,64 +1,14 @@ /* global window */ /* eslint-disable import/no-extraneous-dependencies */ import { addParameters } from '@storybook/client-api'; -import { getCustomElements, isValidComponent, isValidMetaData } from '@storybook/web-components'; import React from 'react'; import { render } from 'lit-html'; - -function mapData(data) { - return data.map(item => ({ - name: item.name, - type: { summary: item.type }, - required: '', - description: item.description, - defaultValue: { summary: item.default !== undefined ? item.default : item.defaultValue }, - })); -} - -function isEmpty(obj) { - return Object.entries(obj).length === 0 && obj.constructor === Object; -} +import { extractProps, extractComponentDescription } from './custom-elements'; addParameters({ docs: { - extractProps: tagName => { - const customElements = getCustomElements(); - if (isValidComponent(tagName) && isValidMetaData(customElements)) { - const metaData = customElements.tags.find( - tag => tag.name.toUpperCase() === tagName.toUpperCase() - ); - const sections = {}; - if (metaData.attributes) { - sections.attributes = mapData(metaData.attributes); - } - if (metaData.properties) { - sections.properties = mapData(metaData.properties); - } - if (metaData.events) { - sections.events = mapData(metaData.events); - } - if (metaData.slots) { - sections.slots = mapData(metaData.slots); - } - if (metaData.cssProperties) { - sections.css = mapData(metaData.cssProperties); - } - return isEmpty(sections) ? false : { sections }; - } - return false; - }, - extractComponentDescription: tagName => { - const customElements = getCustomElements(); - if (isValidComponent(tagName) && isValidMetaData(customElements)) { - const metaData = customElements.tags.find( - tag => tag.name.toUpperCase() === tagName.toUpperCase() - ); - if (metaData && metaData.description) { - return metaData.description; - } - } - return false; - }, + extractProps, + extractComponentDescription, inlineStories: true, prepareForInline: storyFn => { class Story extends React.Component { diff --git a/addons/docs/src/frameworks/web-components/custom-elements.ts b/addons/docs/src/frameworks/web-components/custom-elements.ts new file mode 100644 index 000000000000..421bbcf06414 --- /dev/null +++ b/addons/docs/src/frameworks/web-components/custom-elements.ts @@ -0,0 +1,88 @@ +/* eslint-disable import/no-extraneous-dependencies */ +import { getCustomElements, isValidComponent, isValidMetaData } from '@storybook/web-components'; + +interface TagItem { + name: string; + type: string; + description: string; + default?: any; + defaultValue?: any; +} + +interface Tag { + name: string; + description: string; + attributes?: TagItem[]; + properties?: TagItem[]; + events?: TagItem[]; + slots?: TagItem[]; + cssProperties?: TagItem[]; +} + +interface CustomElements { + tags: Tag[]; +} + +interface Sections { + attributes?: any; + properties?: any; + events?: any; + slots?: any; + css?: any; +} + +function mapData(data: TagItem[]) { + return data.map(item => ({ + name: item.name, + type: { summary: item.type }, + required: '', + description: item.description, + defaultValue: { summary: item.default !== undefined ? item.default : item.defaultValue }, + })); +} + +function isEmpty(obj: object) { + return Object.entries(obj).length === 0 && obj.constructor === Object; +} + +export const extractPropsFromElements = (tagName: string, customElements: CustomElements) => { + if (!isValidComponent(tagName) || !isValidMetaData(customElements)) { + return null; + } + const metaData = customElements.tags.find( + tag => tag.name.toUpperCase() === tagName.toUpperCase() + ); + const sections: Sections = {}; + if (metaData.attributes) { + sections.attributes = mapData(metaData.attributes); + } + if (metaData.properties) { + sections.properties = mapData(metaData.properties); + } + if (metaData.events) { + sections.events = mapData(metaData.events); + } + if (metaData.slots) { + sections.slots = mapData(metaData.slots); + } + if (metaData.cssProperties) { + sections.css = mapData(metaData.cssProperties); + } + return isEmpty(sections) ? false : { sections }; +}; + +export const extractProps = (tagName: string) => { + const customElements: CustomElements = getCustomElements(); + return extractPropsFromElements(tagName, customElements); +}; + +export const extractComponentDescription = (tagName: string) => { + const customElements: CustomElements = getCustomElements(); + if (!isValidComponent(tagName) || !isValidMetaData(customElements)) { + return null; + } + const metaData = customElements.tags.find( + tag => tag.name.toUpperCase() === tagName.toUpperCase() + ); + return metaData && metaData.description; +}; diff --git a/addons/docs/src/frameworks/web-components/web-components-properties.test.ts b/addons/docs/src/frameworks/web-components/web-components-properties.test.ts new file mode 100644 index 000000000000..30a38a879a28 --- /dev/null +++ b/addons/docs/src/frameworks/web-components/web-components-properties.test.ts @@ -0,0 +1,57 @@ +import 'jest-specific-snapshot'; +import path from 'path'; +import fs from 'fs'; +import tmp from 'tmp'; +import { sync as spawnSync } from 'cross-spawn'; + +// File hierarchy: +// __testfixtures__ / some-test-case / input.* +const inputRegExp = /^input\..*$/; + +const runWebComponentsAnalyzer = (inputPath: string) => { + const { name: tmpDir, removeCallback } = tmp.dirSync(); + const customElementsFile = `${tmpDir}/custom-elements.json`; + spawnSync('wca', ['analyze', inputPath, '--outFile', customElementsFile], { + stdio: 'inherit', + }); + const output = fs.readFileSync(customElementsFile, 'utf8'); + removeCallback(); + return output; +}; + +describe('web-components component properties', () => { + // we need to mock lit-html and dynamically require custom-elements + // because lit-html is distributed as ESM not CJS + // https://github.com/Polymer/lit-html/issues/516 + jest.mock('lit-html', () => {}); + // eslint-disable-next-line global-require + const { extractPropsFromElements } = require('./custom-elements'); + + const fixturesDir = path.join(__dirname, '__testfixtures__'); + fs.readdirSync(fixturesDir, { withFileTypes: true }).forEach(testEntry => { + if (testEntry.isDirectory()) { + const testDir = path.join(fixturesDir, testEntry.name); + const testFile = fs.readdirSync(testDir).find(fileName => inputRegExp.test(fileName)); + if (testFile) { + it(testEntry.name, () => { + const inputPath = path.join(testDir, testFile); + + // snapshot the output of wca + const customElementsJson = runWebComponentsAnalyzer(inputPath); + const customElements = JSON.parse(customElementsJson); + customElements.tags.forEach((tag: any) => { + // eslint-disable-next-line no-param-reassign + tag.path = 'dummy-path-to-component'; + }); + expect(customElements).toMatchSpecificSnapshot( + path.join(testDir, 'custom-elements.snapshot') + ); + + // snapshot the properties + const properties = extractPropsFromElements('input', customElements); + expect(properties).toMatchSpecificSnapshot(path.join(testDir, 'properties.snapshot')); + }); + } + } + }); +}); diff --git a/addons/docs/src/lib/utils.ts b/addons/docs/src/lib/utils.ts index 4a0af2fb7a5b..44725a086956 100644 --- a/addons/docs/src/lib/utils.ts +++ b/addons/docs/src/lib/utils.ts @@ -14,3 +14,5 @@ export function isTooLongForDefaultValueSummary(value: string): boolean { export function createSummaryValue(summary: string, detail?: string): PropSummaryValue { return { summary, detail }; } + +export const normalizeNewlines = (string: string) => string.replace(/\\r\\n/g, '\\n'); diff --git a/addons/docs/src/typings.d.ts b/addons/docs/src/typings.d.ts index dc9928da3997..4a41c83bba2e 100644 --- a/addons/docs/src/typings.d.ts +++ b/addons/docs/src/typings.d.ts @@ -4,5 +4,10 @@ declare module '@storybook/addon-docs/blocks'; declare module 'global'; declare module 'react-is'; declare module '@egoist/vue-to-react'; -declare module "remark-slug"; -declare module "remark-external-links"; +declare module 'remark-slug'; +declare module 'remark-external-links'; +declare module 'babel-plugin-react-docgen'; +declare module 'require-from-string'; +declare module 'tmp'; +declare module 'cross-spawn'; +declare module 'styled-components'; diff --git a/addons/docs/tsconfig.json b/addons/docs/tsconfig.json index eac4a67bed71..793e61d30a1e 100644 --- a/addons/docs/tsconfig.json +++ b/addons/docs/tsconfig.json @@ -2,7 +2,7 @@ "extends": "../../tsconfig.json", "compilerOptions": { "rootDir": "./src", - "types": ["webpack-env", "jest"] + "types": ["webpack-env", "jest", "node"] }, "include": ["src/**/*"], "exclude": ["src/**.test.ts"] diff --git a/app/react/package.json b/app/react/package.json index 37f6b2115877..06f0449f6f04 100644 --- a/app/react/package.json +++ b/app/react/package.json @@ -43,7 +43,7 @@ "@types/webpack-env": "^1.15.1", "babel-plugin-add-react-displayname": "^0.0.5", "babel-plugin-named-asset-import": "^0.3.1", - "babel-plugin-react-docgen": "^4.0.0", + "babel-plugin-react-docgen": "^4.1.0", "core-js": "^3.0.1", "global": "^4.3.2", "lodash": "^4.17.15", diff --git a/examples/official-storybook/main.js b/examples/official-storybook/main.js index 0e2cf6ee5151..72365ac3100d 100644 --- a/examples/official-storybook/main.js +++ b/examples/official-storybook/main.js @@ -4,6 +4,7 @@ module.exports = { '../../lib/ui/src/**/*.stories.(js|tsx|mdx)', '../../lib/components/src/**/*.stories.(js|tsx|mdx)', './stories/**/*.stories.(js|tsx|mdx)', + './../../addons/docs/**/react-properties.stories.tsx', ], addons: [ '@storybook/addon-docs', diff --git a/yarn.lock b/yarn.lock index b94ca1ccede0..dad9ebbb2192 100644 --- a/yarn.lock +++ b/yarn.lock @@ -387,7 +387,7 @@ lodash "^4.17.13" source-map "^0.5.0" -"@babel/helper-annotate-as-pure@^7.8.3": +"@babel/helper-annotate-as-pure@^7.0.0", "@babel/helper-annotate-as-pure@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.8.3.tgz#60bc0bc657f63a0924ff9a4b4a0b24a13cf4deee" integrity sha512-6o+mJrZBxOoEX77Ezv9zwW7WV8DdluouRKNY/IR5u/YTMuKHgugHOzYWlYvYLpLA9nPsQCAAASpCIbjI9Mv+Uw== @@ -1725,7 +1725,7 @@ resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.7.4.tgz#f14932887422c9056b15a8d222a9074a7dfa2831" integrity sha512-fxfMSBMX3tlIbKUdtGKxqB1fyrH6gVrX39Gsv3y8lRYKUqlgDt3UMqQyGnR1bQMa2B8aGnhLZokZgg8vT0Le+A== -"@emotion/is-prop-valid@0.8.6", "@emotion/is-prop-valid@^0.8.6": +"@emotion/is-prop-valid@0.8.6", "@emotion/is-prop-valid@^0.8.3", "@emotion/is-prop-valid@^0.8.6": version "0.8.6" resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.6.tgz#4757646f0a58e9dec614c47c838e7147d88c263c" integrity sha512-mnZMho3Sq8BfzkYYRVc8ilQTnc8U02Ytp6J1AwM6taQStZ3AhsEJBX2LzhA/LJirNCwM2VtHL3VFIZ+sNJUgUQ== @@ -1793,12 +1793,12 @@ "@emotion/styled-base" "^10.0.27" babel-plugin-emotion "^10.0.27" -"@emotion/stylis@0.8.5": +"@emotion/stylis@0.8.5", "@emotion/stylis@^0.8.4": version "0.8.5" resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.8.5.tgz#deacb389bd6ee77d1e7fcaccce9e16c5c7e78e04" integrity sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ== -"@emotion/unitless@0.7.5": +"@emotion/unitless@0.7.5", "@emotion/unitless@^0.7.4": version "0.7.5" resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed" integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg== @@ -6208,7 +6208,7 @@ babel-plugin-named-asset-import@^0.3.1, babel-plugin-named-asset-import@^0.3.2, resolved "https://registry.yarnpkg.com/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.6.tgz#c9750a1b38d85112c9e166bf3ef7c5dbc605f4be" integrity sha512-1aGDUfL1qOOIoqk9QKGIo2lANk+C7ko/fqH0uIyC71x3PEGz0uVP8ISgfEsFuG+FKmjHTvFK/nNM8dowpmUxLA== -babel-plugin-react-docgen@^4.0.0: +babel-plugin-react-docgen@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/babel-plugin-react-docgen/-/babel-plugin-react-docgen-4.1.0.tgz#1dfa447dac9ca32d625a123df5733a9e47287c26" integrity sha512-vzpnBlfGv8XOhJM2zbPyyqw2OLEbelgZZsaaRRTpVwNKuYuc+pUg4+dy7i9gCRms0uOQn4osX571HRcCJMJCmA== @@ -6222,6 +6222,16 @@ babel-plugin-require-context-hook@^1.0.0: resolved "https://registry.yarnpkg.com/babel-plugin-require-context-hook/-/babel-plugin-require-context-hook-1.0.0.tgz#3f0e7cce87c338f53639b948632fd4e73834632d" integrity sha512-EMZD1563QUqLhzrqcThk759RhuNVX/ZJdrtGK6drwzgvnR+ARjWyXIHPbu+tUNaMGtPz/gQeAM2M6VUw2UiUeA== +"babel-plugin-styled-components@>= 1": + version "1.10.7" + resolved "https://registry.yarnpkg.com/babel-plugin-styled-components/-/babel-plugin-styled-components-1.10.7.tgz#3494e77914e9989b33cc2d7b3b29527a949d635c" + integrity sha512-MBMHGcIA22996n9hZRf/UJLVVgkEOITuR2SvjHLb5dSTUyR4ZRGn+ngITapes36FI3WLxZHfRhkA1ffHxihOrg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.0.0" + "@babel/helper-module-imports" "^7.0.0" + babel-plugin-syntax-jsx "^6.18.0" + lodash "^4.17.11" + babel-plugin-syntax-async-functions@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" @@ -9961,6 +9971,15 @@ css-to-react-native@^2.2.1: css-color-keywords "^1.0.0" postcss-value-parser "^3.3.0" +css-to-react-native@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/css-to-react-native/-/css-to-react-native-3.0.0.tgz#62dbe678072a824a689bcfee011fc96e02a7d756" + integrity sha512-Ro1yETZA813eoyUp2GDBhG2j+YggidUmzO1/v9eYBKR2EHVEniE2MI/NqpTQ954BMpTPZFsGNPm46qFB9dpaPQ== + dependencies: + camelize "^1.0.0" + css-color-keywords "^1.0.0" + postcss-value-parser "^4.0.2" + css-tree@1.0.0-alpha.29: version "1.0.0-alpha.29" resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.29.tgz#3fa9d4ef3142cbd1c301e7664c1f352bd82f5a39" @@ -13058,7 +13077,7 @@ fast-glob@^2.0.2, fast-glob@^2.2.2, fast-glob@^2.2.6: merge2 "^1.2.3" micromatch "^3.1.10" -fast-glob@^3.0.3, fast-glob@^3.1.1: +fast-glob@^3.0.3, fast-glob@^3.1.0, fast-glob@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.1.1.tgz#87ee30e9e9f3eb40d6f254a7997655da753d7c82" integrity sha512-nTCREpBY8w8r+boyFYAx21iL6faSsQynliPHM4Uf56SbkyohCNxpVPEH9xrF5TXKy+IsjkPUHDKiUkzBVRXn9g== @@ -15007,7 +15026,7 @@ hoek@4.x.x: resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.1.tgz#9634502aa12c445dd5a7c5734b572bb8738aacbb" integrity sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA== -hoist-non-react-statics@^3.3.0: +hoist-non-react-statics@^3.0.0, hoist-non-react-statics@^3.3.0: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== @@ -28086,6 +28105,22 @@ style-unit@^2.0.0: dependencies: universal-env "^2.0.0" +styled-components@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-5.0.1.tgz#57782a6471031abefb2db5820a1876ae853bc619" + integrity sha512-E0xKTRIjTs4DyvC1MHu/EcCXIj6+ENCP8hP01koyoADF++WdBUOrSGwU1scJRw7/YaYOhDvvoad6VlMG+0j53A== + dependencies: + "@babel/helper-module-imports" "^7.0.0" + "@babel/traverse" "^7.4.5" + "@emotion/is-prop-valid" "^0.8.3" + "@emotion/stylis" "^0.8.4" + "@emotion/unitless" "^0.7.4" + babel-plugin-styled-components ">= 1" + css-to-react-native "^3.0.0" + hoist-non-react-statics "^3.0.0" + shallowequal "^1.1.0" + supports-color "^5.5.0" + styled_string@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/styled_string/-/styled_string-0.0.1.tgz#d22782bd81295459bc4f1df18c4bad8e94dd124a" @@ -29131,6 +29166,11 @@ ts-simple-ast@12.4.0: tslib "^1.9.0" typescript "2.9.1" +ts-simple-type@~0.3.6: + version "0.3.7" + resolved "https://registry.yarnpkg.com/ts-simple-type/-/ts-simple-type-0.3.7.tgz#1e77222c3d90d7093f80a954e74c725fd99c911c" + integrity sha512-bDXWURwpDpe1mA5E9eldmI0Mpt9zGprhtN/ZTLOJjsAMyeMy1UT7WvGRQghYewIYBYxDZurChhe4DrsPbcCVrA== + tsconfig-paths-webpack-plugin@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-3.2.0.tgz#6e70bd42915ad0efb64d3385163f0c1270f3e04d" @@ -29343,7 +29383,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.7.5, typescript@^3.2.4, typescript@^3.4.0: +typescript@3.7.5, typescript@^3.2.4, typescript@^3.4.0, typescript@^3.5.3: version "3.7.5" resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.5.tgz#0692e21f65fd4108b9330238aac11dd2e177a1ae" integrity sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw== @@ -30267,7 +30307,7 @@ vue-class-component@^7.1.0: resolved "https://registry.yarnpkg.com/vue-class-component/-/vue-class-component-7.2.2.tgz#aecc6d28801f64c61eb04407cf3a5476da26b0c0" integrity sha512-QjVfjRffux0rUBNtxr1hvUxDrfifDvk9q/OSdB/sKIlfxAudDF2E1YTeiEC+qOYIOOBGWkgSKQSnast6H+S38w== -vue-docgen-api@^4.1.0: +vue-docgen-api@^4.7.0: version "4.7.7" resolved "https://registry.yarnpkg.com/vue-docgen-api/-/vue-docgen-api-4.7.7.tgz#685366830a8620a390d4bddd9afcd660757a7631" integrity sha512-gwoqCM8NPKY6HE39fs8orpzWp9oTXpWVVUFGMFimAO+EPraqVB1dezv/g2c9s5E21hb0qryCEkeSsNmUpoRiCA== @@ -30282,10 +30322,10 @@ vue-docgen-api@^4.1.0: ts-map "^1.0.3" vue-template-compiler "^2.0.0" -vue-docgen-loader@^1.3.0-beta.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/vue-docgen-loader/-/vue-docgen-loader-1.3.0.tgz#449c2e09b1434f65ae4d8536dc63c61dbeb640b2" - integrity sha512-K/r3IulRQlZpRIvR0Ed8vdPQCCd1WbcajOgm/4fdwtO4pWorLLX9o0YGM1rlkX3DXybqOolQ5LEh7E3kTer1qg== +vue-docgen-loader@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/vue-docgen-loader/-/vue-docgen-loader-1.4.0.tgz#24409ddcec6c353b6e04734d9035623a9c301b9c" + integrity sha512-VD06bTwsQlgs0vHVcDw5a5WhyvH5Hw5LuS9Fs7OHB0VnElUB0wKJXE9t1SXEc87VOZb29kokhBRT+q1BdDI71A== dependencies: clone "^2.1.2" jscodeshift "^0.7.0" @@ -30483,6 +30523,16 @@ wcwidth@^1.0.0, wcwidth@^1.0.1: dependencies: defaults "^1.0.3" +web-component-analyzer@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/web-component-analyzer/-/web-component-analyzer-1.0.3.tgz#da73dff15d6a8f4864311664476f0f436274e97d" + integrity sha512-QA6GVVJrKRPHLVqPv4evY0H+du1yY+E1q8c82bdY5e10+pWsRfeYA+Hsh2r8yl1EGQVC55SeV3tGvJ6+CxaH/Q== + dependencies: + fast-glob "^3.1.0" + ts-simple-type "~0.3.6" + typescript "^3.5.3" + yargs "^15.0.2" + web-namespaces@^1.0.0, web-namespaces@^1.1.2: version "1.1.4" resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-1.1.4.tgz#bc98a3de60dadd7faefc403d1076d529f5e030ec" @@ -31741,7 +31791,7 @@ yargs@^14.0.0, yargs@^14.2.2: y18n "^4.0.0" yargs-parser "^15.0.0" -yargs@^15.0.0: +yargs@^15.0.0, yargs@^15.0.2: version "15.1.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.1.0.tgz#e111381f5830e863a89550bd4b136bb6a5f37219" integrity sha512-T39FNN1b6hCW4SOIk1XyTOWxtXdcen0t+XYrysQmChzSipvhBO8Bj0nK1ozAasdk24dNWuMZvr4k24nz+8HHLg==