diff --git a/packages/patternfly-4/react-core/src/components/Button/examples/LinkButton.js b/packages/patternfly-4/react-core/src/components/Button/examples/LinkButton.js index 76ed1c0e559..3139d2b7f1b 100644 --- a/packages/patternfly-4/react-core/src/components/Button/examples/LinkButton.js +++ b/packages/patternfly-4/react-core/src/components/Button/examples/LinkButton.js @@ -2,7 +2,7 @@ import React from 'react'; import { Button } from '@patternfly/react-core'; import getContainerProps from './common/getContainerProps'; -class LinkButtons extends React.Component { +class LinkButton extends React.Component { static title = 'Links'; static description = `Links with button styling. Semantic buttons and links are important for usability as well as accessibility. Using an "a" instead of a "button" element to perform user initiated actions should be avoided, unless absolutely necessary.`; static getContainerProps = getContainerProps; @@ -21,4 +21,4 @@ class LinkButtons extends React.Component { } } -export default LinkButtons; +export default LinkButton; diff --git a/packages/patternfly-4/react-core/src/components/Dropdown/examples/DirectionUpDropdown.js b/packages/patternfly-4/react-core/src/components/Dropdown/examples/DirectionUpDropdown.js index 17b8e0fa9ae..c733b6f67f3 100644 --- a/packages/patternfly-4/react-core/src/components/Dropdown/examples/DirectionUpDropdown.js +++ b/packages/patternfly-4/react-core/src/components/Dropdown/examples/DirectionUpDropdown.js @@ -1,7 +1,7 @@ import React, { Component } from 'react'; import { Dropdown, DropdownToggle, DropdownItem, DropdownSeparator, DropdownDirection } from '@patternfly/react-core'; -export default class ExampleDropdown extends Component { +export default class DirectionUpDropdown extends Component { static title = 'Dropdown - direction up'; constructor(props) { @@ -13,14 +13,12 @@ export default class ExampleDropdown extends Component { onToggle = isOpen => { this.setState({ - ...this.state, isOpen }); }; onSelect = event => { this.setState({ - ...this.state, isOpen: !this.state.isOpen }); }; diff --git a/packages/patternfly-4/react-core/src/components/Dropdown/examples/KebabDropdown.js b/packages/patternfly-4/react-core/src/components/Dropdown/examples/KebabDropdown.js index d370e93def2..cd426eb235d 100644 --- a/packages/patternfly-4/react-core/src/components/Dropdown/examples/KebabDropdown.js +++ b/packages/patternfly-4/react-core/src/components/Dropdown/examples/KebabDropdown.js @@ -1,7 +1,7 @@ import React, { Component } from 'react'; import { Dropdown, KebabToggle, DropdownItem, DropdownSeparator } from '@patternfly/react-core'; -export default class ExampleDropdown extends Component { +export default class KebabDropdown extends Component { static title = 'Kebab'; constructor(props) { @@ -13,14 +13,12 @@ export default class ExampleDropdown extends Component { onToggle = isOpen => { this.setState({ - ...this.state, isOpen }); }; onSelect = event => { this.setState({ - ...this.state, isOpen: !this.state.isOpen }); }; diff --git a/packages/patternfly-4/react-core/src/components/Dropdown/examples/PositionRightDropdown.js b/packages/patternfly-4/react-core/src/components/Dropdown/examples/PositionRightDropdown.js index ed3c251d204..6c17c68269b 100644 --- a/packages/patternfly-4/react-core/src/components/Dropdown/examples/PositionRightDropdown.js +++ b/packages/patternfly-4/react-core/src/components/Dropdown/examples/PositionRightDropdown.js @@ -1,7 +1,7 @@ import React, { Component } from 'react'; import { Dropdown, DropdownToggle, DropdownItem, DropdownSeparator, DropdownPosition } from '@patternfly/react-core'; -export default class ExampleDropdown extends Component { +export default class PositionRightDropdown extends Component { static title = 'Dropdown - position right'; constructor(props) { @@ -13,14 +13,12 @@ export default class ExampleDropdown extends Component { onToggle = isOpen => { this.setState({ - ...this.state, isOpen }); }; onSelect = event => { this.setState({ - ...this.state, isOpen: !this.state.isOpen }); }; diff --git a/packages/patternfly-4/react-core/src/components/Dropdown/examples/SimpleDropdown.js b/packages/patternfly-4/react-core/src/components/Dropdown/examples/SimpleDropdown.js index 58e2cc0613a..883c4ce504a 100644 --- a/packages/patternfly-4/react-core/src/components/Dropdown/examples/SimpleDropdown.js +++ b/packages/patternfly-4/react-core/src/components/Dropdown/examples/SimpleDropdown.js @@ -1,7 +1,7 @@ import React, { Component } from 'react'; import { Dropdown, DropdownToggle, DropdownItem, DropdownSeparator } from '@patternfly/react-core'; -export default class ExampleDropdown extends Component { +export default class SimpleDropdown extends Component { static title = 'Simple dropdown'; constructor(props) { @@ -13,14 +13,12 @@ export default class ExampleDropdown extends Component { onToggle = isOpen => { this.setState({ - ...this.state, isOpen }); }; onSelect = event => { this.setState({ - ...this.state, isOpen: !this.state.isOpen }); }; diff --git a/packages/patternfly-4/react-docs/.env.development b/packages/patternfly-4/react-docs/.env.development new file mode 100644 index 00000000000..4c70de32003 --- /dev/null +++ b/packages/patternfly-4/react-docs/.env.development @@ -0,0 +1 @@ +LIVE_EXAMPLES=true diff --git a/packages/patternfly-4/react-docs/.env.production b/packages/patternfly-4/react-docs/.env.production new file mode 100644 index 00000000000..4c70de32003 --- /dev/null +++ b/packages/patternfly-4/react-docs/.env.production @@ -0,0 +1 @@ +LIVE_EXAMPLES=true diff --git a/packages/patternfly-4/react-docs/gatsby-node.js b/packages/patternfly-4/react-docs/gatsby-node.js index 5efca0108c5..61347c8f0b6 100644 --- a/packages/patternfly-4/react-docs/gatsby-node.js +++ b/packages/patternfly-4/react-docs/gatsby-node.js @@ -54,10 +54,11 @@ exports.onCreateNode = ({ node, boundActionCreators }) => { exports.createPages = async ({ boundActionCreators, graphql }) => { const { - data: { docs, examples } + data: { docs, examples, exampleImages } } = await graphql(` fragment DocFile on File { relativePath + relativeDirectory absolutePath base name @@ -78,17 +79,47 @@ exports.createPages = async ({ boundActionCreators, graphql }) => { } } } + exampleImages: allFile(filter: { extension: { regex: "/(png|svg)/" } }) { + edges { + node { + ...DocFile + } + } + } } `); const docsComponentPath = path.resolve(__dirname, './src/components/componentDocs'); docs.edges.forEach(({ node: doc }) => { const filePath = path.resolve(__dirname, '.tmp', doc.base); + + const rawExamples = []; + examples.edges.forEach(({ node: example }) => { + if ( + example.relativeDirectory + .split('/') + .slice(0, 2) + .join('/') === doc.relativeDirectory + ) { + // e.g. components/Alert/examples/DangerAlert.js + const examplePath = `../../react-core/src/${example.relativePath}`; + rawExamples.push(`{name: '${example.name}', path: '${examplePath}', file: require('!!raw!${examplePath}')}`); + } + }); + const allImages = []; + exampleImages.edges.forEach(({ node: image }) => { + const imagePath = `../../react-core/src/${image.relativePath}`; + allImages.push(`{name: '${image.base}', file: require('${imagePath}')}`); + }); + const content = ` import React from 'react'; import docs from '${doc.absolutePath}'; import ComponentDocs from '${docsComponentPath}'; + + const rawExamples = [${rawExamples}]; + const images = [${allImages}]; - export default () => + export default () => `; fs.outputFileSync(filePath, content); boundActionCreators.createPage({ diff --git a/packages/patternfly-4/react-docs/package.json b/packages/patternfly-4/react-docs/package.json index 0024e7c6bfc..1fba26f464d 100644 --- a/packages/patternfly-4/react-docs/package.json +++ b/packages/patternfly-4/react-docs/package.json @@ -12,7 +12,7 @@ "@patternfly/react-icons": "*", "@patternfly/react-styles": "^2.0.0", "@patternfly/react-tokens": "^1.0.0", - "babel-plugin-react-docgen": "^v1.9.0", + "babel-standalone": "^6.26.0", "emotion": "^9.2.9", "emotion-server": "^9.2.9", "gatsby": "^1.9.247", @@ -27,7 +27,8 @@ "prop-types": "^15.6.1", "react": "^16.3.2", "react-dom": "^16.3.2", - "react-helmet": "^5.2.0" + "react-helmet": "^5.2.0", + "react-live": "^1.11.0" }, "keywords": [ "gatsby" diff --git a/packages/patternfly-4/react-docs/src/components/componentDocs/componentDocs.js b/packages/patternfly-4/react-docs/src/components/componentDocs/componentDocs.js index 2471a5f1b19..4ac63ff3c05 100644 --- a/packages/patternfly-4/react-docs/src/components/componentDocs/componentDocs.js +++ b/packages/patternfly-4/react-docs/src/components/componentDocs/componentDocs.js @@ -13,31 +13,41 @@ const propTypes = { description: PropTypes.string, examples: PropTypes.arrayOf(PropTypes.func), components: PropTypes.objectOf(PropTypes.func), - enumValues: PropTypes.objectOf(PropTypes.arrayOf(PropTypes.any)) + enumValues: PropTypes.objectOf(PropTypes.arrayOf(PropTypes.any)), + rawExamples: PropTypes.array, + images: PropTypes.array }; const defaultProps = { description: '', examples: [], components: {}, - enumValues: {} + enumValues: {}, + rawExamples: [], + images: [] }; -const ComponentDocs = ({ title, description, examples, components, enumValues }) => ( +const ComponentDocs = ({ title, description, examples, components, enumValues, rawExamples, images }) => ( {title} {Boolean(description) &&

{description}

}
- {examples.map((ComponentExample, i) => ( - - - - ))} + {examples.map((ComponentExample, i) => { + const { __docgenInfo: componentDocs } = ComponentExample; + const rawExample = rawExamples.find(example => example.name === componentDocs.displayName); + return ( + + + + ); + })}
{Object.entries(components).map(([componentName, { __docgenInfo: componentDocs }]) => ( diff --git a/packages/patternfly-4/react-docs/src/components/example/example.js b/packages/patternfly-4/react-docs/src/components/example/example.js index 57e0bfb8873..bdbd61a4a7d 100644 --- a/packages/patternfly-4/react-docs/src/components/example/example.js +++ b/packages/patternfly-4/react-docs/src/components/example/example.js @@ -3,26 +3,37 @@ import { css } from '@patternfly/react-styles'; import styles from './example.styles'; import PropTypes from 'prop-types'; import { Title } from '@patternfly/react-core'; +import LiveDemo from './liveDemo'; const propTypes = { children: PropTypes.node.isRequired, title: PropTypes.string.isRequired, description: PropTypes.string, - className: PropTypes.string + className: PropTypes.string, + raw: PropTypes.string, + images: PropTypes.array }; const defaultProps = { className: '', - description: '' + description: '', + raw: '', + images: [] }; -const Example = ({ children, title, className, description, ...props }) => ( +const LIVE_EXAMPLES = /true/i.test(process.env.LIVE_EXAMPLES); + +const Example = ({ children, title, className, description, raw, images, ...props }) => (
- {title} + {title} {Boolean(description) &&

{description}

} -
- {children} -
+ {LIVE_EXAMPLES ? ( + + ) : ( +
+ {children} +
+ )}
); diff --git a/packages/patternfly-4/react-docs/src/components/example/liveDemo.js b/packages/patternfly-4/react-docs/src/components/example/liveDemo.js new file mode 100644 index 00000000000..d9affdd27bd --- /dev/null +++ b/packages/patternfly-4/react-docs/src/components/example/liveDemo.js @@ -0,0 +1,67 @@ +import React from 'react'; +import { css } from '@patternfly/react-styles'; +import styles from './example.styles'; +import PropTypes from 'prop-types'; +import * as CoreComponents from '@patternfly/react-core'; +import * as CoreIcons from '@patternfly/react-icons'; +import { LiveProvider, LiveEditor, LiveError, LivePreview, withLive } from 'react-live'; +import { transform } from 'babel-standalone'; + +const propTypes = { + className: PropTypes.string, + raw: PropTypes.string.isRequired, + images: PropTypes.array +}; + +const defaultProps = { + className: '', + images: [] +}; + +const scopePlayground = { React, ...CoreComponents, ...CoreIcons }; + +const transformCode = code => { + try { + // LiveEditor doesn't work properly with these so need to remove + code = code.replace(/^\s*import.*$/gm, ''); + code = code.replace(/^\s*export default class/gm, 'class'); + code = code.replace(/extends Component/gm, 'extends React.Component'); + code = code.replace(/^\s*export.*$/gm, ''); + code = code.replace(/^\s*static.*$/gm, ''); + const transformedCode = transform(code, { + presets: ['react', 'stage-2'] + }).code; + return transformedCode; + } catch (e) { + console.log(e); + // todo: handle error + return code; + } +}; + +const LiveDemo = ({ className, raw, images, ...props }) => { + const scope = { + ...scopePlayground + }; + for (const image of images) { + const searchIndex = raw.search(image.name); + if (searchIndex > -1) { + const startIndex = raw.lastIndexOf('import', searchIndex); + const importName = raw.substring(startIndex, searchIndex).split(' ')[1]; + scope[importName] = image.file; + } + } + + return ( + + + + + + ); +}; + +LiveDemo.propTypes = propTypes; +LiveDemo.defaultProps = defaultProps; + +export default withLive(LiveDemo); diff --git a/packages/patternfly-4/react-docs/src/layouts/index.js b/packages/patternfly-4/react-docs/src/layouts/index.js index 53aadf56eb8..8acb0d4d1c5 100644 --- a/packages/patternfly-4/react-docs/src/layouts/index.js +++ b/packages/patternfly-4/react-docs/src/layouts/index.js @@ -32,12 +32,13 @@ const Layout = ({ children, data }) => { return ( - + + + + + + + } diff --git a/yarn.lock b/yarn.lock index 41a808f1e8f..8c92b4a5e53 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1927,7 +1927,7 @@ babel-plugin-minify-type-constructors@^0.3.0: dependencies: babel-helper-is-void-0 "^0.3.0" -babel-plugin-react-docgen@^1.9.0, babel-plugin-react-docgen@^v1.9.0: +babel-plugin-react-docgen@^1.9.0: version "1.9.0" resolved "https://registry.yarnpkg.com/babel-plugin-react-docgen/-/babel-plugin-react-docgen-1.9.0.tgz#2e79aeed2f93b53a172398f93324fdcf9f02e01f" dependencies: @@ -3058,6 +3058,19 @@ btoa-lite@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/btoa-lite/-/btoa-lite-1.0.0.tgz#337766da15801210fdd956c22e9c6891ab9d0337" +buble@^0.19.3: + version "0.19.3" + resolved "https://registry.yarnpkg.com/buble/-/buble-0.19.3.tgz#01e9412062cff1da6f20342b6ecd72e7bf699d02" + dependencies: + acorn "^5.4.1" + acorn-dynamic-import "^3.0.0" + acorn-jsx "^4.1.1" + chalk "^2.3.1" + magic-string "^0.22.4" + minimist "^1.2.0" + os-homedir "^1.0.1" + vlq "^1.0.0" + buffer-alloc-unsafe@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" @@ -3337,7 +3350,7 @@ chalk@2.4.0: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@2.4.1, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.2, chalk@^2.4.1: +chalk@2.4.1, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.3.2, chalk@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" dependencies: @@ -3553,6 +3566,14 @@ cli-width@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" +clipboard@^1.5.5: + version "1.7.1" + resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-1.7.1.tgz#360d6d6946e99a7a1fef395e42ba92b5e9b5a16b" + dependencies: + good-listener "^1.2.2" + select "^1.1.2" + tiny-emitter "^2.0.0" + clipboard@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-2.0.1.tgz#a12481e1c13d8a50f5f036b0560fe5d16d74e46a" @@ -3828,6 +3849,14 @@ component-inherit@0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143" +component-props@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/component-props/-/component-props-1.1.1.tgz#f9b7df9b9927b6e6d97c9bd272aa867670f34944" + +component-xor@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/component-xor/-/component-xor-0.0.4.tgz#c55d83ccc1b94cd5089a4e93fa7891c7263e59aa" + compressible@~2.0.13: version "2.0.13" resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.13.tgz#0d1020ab924b2fdb4d6279875c7d6daba6baa7a9" @@ -4988,6 +5017,13 @@ dom-helpers@^3.2.0, dom-helpers@^3.2.1, dom-helpers@^3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.3.1.tgz#fc1a4e15ffdf60ddde03a480a9c0fece821dd4a6" +dom-iterator@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/dom-iterator/-/dom-iterator-1.0.0.tgz#9c09899846ec41c2d257adc4d6015e4759ef05ad" + dependencies: + component-props "1.1.1" + component-xor "0.0.4" + dom-serializer@0, dom-serializer@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" @@ -9812,6 +9848,12 @@ ltcdr@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ltcdr/-/ltcdr-2.2.1.tgz#5ab87ad1d4c1dab8e8c08bbf037ee0c1902287cf" +magic-string@^0.22.4: + version "0.22.5" + resolved "http://registry.npmjs.org/magic-string/-/magic-string-0.22.5.tgz#8e9cf5afddf44385c1da5bc2a6a0dbd10b03657e" + dependencies: + vlq "^0.2.2" + make-dir@^1.0.0: version "1.3.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" @@ -12225,6 +12267,12 @@ pretty-format@^23.6.0: ansi-regex "^3.0.0" ansi-styles "^3.2.0" +prismjs@1.6: + version "1.6.0" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.6.0.tgz#118d95fb7a66dba2272e343b345f5236659db365" + optionalDependencies: + clipboard "^1.5.5" + prismjs@^1.8.4, prismjs@~1.14.0: version "1.14.0" resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.14.0.tgz#bbccfdb8be5d850d26453933cb50122ca0362ae0" @@ -12769,6 +12817,17 @@ react-lifecycles-compat@^3.0.0: version "3.0.4" resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" +react-live@^1.11.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/react-live/-/react-live-1.11.0.tgz#257b54abb64df250bc40b0572c21acd600ecdd5c" + dependencies: + buble "^0.19.3" + core-js "^2.4.1" + dom-iterator "^1.0.0" + prismjs "1.6" + prop-types "^15.5.8" + unescape "^0.2.0" + react-modal@^3.3.2: version "3.4.4" resolved "https://registry.yarnpkg.com/react-modal/-/react-modal-3.4.4.tgz#e9dde25e9e85a59c76831f2a2b468712a546aded" @@ -15527,6 +15586,10 @@ underscore@~1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.6.0.tgz#8b38b10cacdef63337b8b24e4ff86d45aea529a8" +unescape@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/unescape/-/unescape-0.2.0.tgz#b78b9b60c86f1629df181bf53eee3bc8d6367ddf" + unherit@^1.0.4: version "1.1.1" resolved "https://registry.yarnpkg.com/unherit/-/unherit-1.1.1.tgz#132748da3e88eab767e08fabfbb89c5e9d28628c" @@ -15854,6 +15917,14 @@ viewport-dimensions@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/viewport-dimensions/-/viewport-dimensions-0.2.0.tgz#de740747db5387fd1725f5175e91bac76afdf36c" +vlq@^0.2.2: + version "0.2.3" + resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26" + +vlq@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/vlq/-/vlq-1.0.0.tgz#8101be90843422954c2b13eb27f2f3122bdcc806" + vm-browserify@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73"