Skip to content

Commit

Permalink
chore(devenv): introduced parameterized demo HTML (#579)
Browse files Browse the repository at this point in the history
  • Loading branch information
asudoh committed May 15, 2018
1 parent 18b8687 commit 4edeba9
Show file tree
Hide file tree
Showing 165 changed files with 2,630 additions and 2,424 deletions.
3 changes: 3 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,6 @@ tests/coverage
/html
/docs/js
node_modules

# TODO: Upgrade to ESLint4 so we can apply a specific rule (one for CJS code) for below files
src/**/*.config.js
2 changes: 1 addition & 1 deletion demo/.babelrc
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@
],
"react"
],
"plugins": ["transform-class-properties", "dev-expression"]
"plugins": ["transform-class-properties", "transform-object-rest-spread", "dev-expression"]
}
34 changes: 5 additions & 29 deletions demo/js/components/CodePage/CodePage.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,60 +4,36 @@ import Markdown from 'markdown-it';

import ComponentExample from '../ComponentExample/ComponentExample';

/**
* @param {ComponentCollection|Component} metadata The component data.
* @returns {string} The HTML snippet for the component.
*/
const getContent = metadata => {
const { variants = {} } = metadata;
const { items = [] } = variants;
const variant = items[0];
return metadata.content || (variant && variant.content) || '';
};

/**
* @param {ComponentCollection|Component} metadata The component data.
* @returns {Component[]|Variant[]} The data of the component variants.
*/
const getSubItems = metadata => {
if (metadata.isCollection) {
return metadata.items;
}
if (!metadata.isCollated) {
return metadata.variants.items;
}
return [];
};

/**
* The page to show the component demo, its code as well as its README.
*/
const CodePage = ({ metadata, hideViewFullRender }) => {
const md = new Markdown({ html: true });
const subItems = getSubItems(metadata).filter(item => !item.isHidden);
const subItems = (metadata.items || []).filter(item => !item.isHidden);
/* eslint-disable react/no-danger */
const componentContent =
!metadata.isCollection && subItems.length <= 1 ? (
<ComponentExample
hideViewFullRender={hideViewFullRender}
component={metadata.name}
htmlFile={getContent(metadata)}
htmlFile={metadata.renderedContent}
useIframe={metadata.useIframe}
/>
) : (
subItems.map(item => (
<div key={item.id} className="component-variation">
<h2 className="component-variation__name">{item.label}</h2>
{item.notes && metadata.notes !== item.notes && <p>{item.notes}</p>}
<ComponentExample
variant={item.handle.replace(/--default$/, '')}
component={metadata.name}
htmlFile={getContent(item)}
htmlFile={item.renderedContent}
useIframe={metadata.useIframe}
/>
</div>
))
);

/* eslint-disable react/no-danger */
return (
<div className="page code-page test">
{componentContent}
Expand Down
3 changes: 2 additions & 1 deletion demo/js/components/ComponentExample/ComponentExample.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,8 @@ class ComponentExample extends Component {
});

const codepenLink = codepenSlug && `https://codepen.io/team/carbon/full/${codepenSlug}/`;
const componentLink = variant ? `/component/${component}/${variant}` : `/component/${component}`;
const variantSuffix = (component === variant && '--default') || '';
const componentLink = variant ? `/component/${variant}${variantSuffix}` : `/component/${component}`;

const viewFullRender = hideViewFullRender ? null : (
<Link className="component-example__view-full-render" target="_blank" href={codepenLink || componentLink}>
Expand Down
95 changes: 89 additions & 6 deletions demo/js/components/RootPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,67 @@ import SideNav from './SideNav';
import PageHeader from './PageHeader/PageHeader';
import SideNavToggle from './SideNavToggle/SideNavToggle';

const checkStatus = response => {
if (response.status >= 200 && response.status < 400) {
return response;
}

const error = new Error(response.statusText);
error.response = response;
throw error;
};

const load = (componentItems, selectedNavItemId) => {
const metadata = componentItems && componentItems.find(item => item.id === selectedNavItemId);
const subItems = metadata.items || [];
const hasRenderedContent =
!metadata.isCollection && subItems.length <= 1 ? metadata.renderedContent : subItems.every(item => item.renderedContent);
if (!hasRenderedContent) {
return fetch(`/code/${metadata.name}`)
.then(checkStatus)
.then(response => {
const contentType = response.headers.get('content-type');
return contentType && contentType.includes('application/json') ? response.json() : response.text();
})
.then(responseContent => {
if (Object(responseContent) === responseContent) {
return componentItems.map(item => {
if (item.id !== selectedNavItemId) {
return item;
}
return !item.items
? {
...item,
renderedContent: responseContent[`${item.handle}--default`],
}
: {
...item,
items: item.items.map(
subItem =>
!responseContent[subItem.handle]
? subItem
: {
...subItem,
renderedContent: responseContent[subItem.handle],
}
),
};
});
}
return componentItems.map(
item =>
item.id !== selectedNavItemId
? item
: {
...item,
renderedContent: responseContent,
}
);
});
}
return Promise.resolve(null);
};

/**
* The top-most React component for dev env page.
*/
Expand All @@ -22,9 +83,19 @@ class RootPage extends Component {
docItems: PropTypes.arrayOf(PropTypes.shape()).isRequired, // eslint-disable-line react/no-unused-prop-types
};

constructor() {
constructor(props) {
super();
this.state = {};

const { componentItems } = props;

this.state = {
/**
* The array of component data.
* @type {Object[]}
*/
componentItems,
};

window.addEventListener('popstate', evt => {
this.switchTo(evt.state.name);
});
Expand All @@ -42,6 +113,13 @@ class RootPage extends Component {
}
}

componentWillReceiveProps(props) {
const { componentItems } = props;
if (this.props.componentItems !== componentItems) {
this.setState({ componentItems });
}
}

/**
* The handler for changing in the state of side nav's toggle button.
*/
Expand All @@ -53,7 +131,7 @@ class RootPage extends Component {
* The handler for the `click` event on the side nav for changing selection.
*/
onSideNavItemClick = evt => {
const { componentItems } = this.props;
const { componentItems } = this.state;
const selectedNavItem = componentItems && componentItems.find(item => item.id === evt.target.dataset.navId);
if (selectedNavItem) {
this.switchTo(selectedNavItem.id);
Expand All @@ -64,7 +142,7 @@ class RootPage extends Component {
* @returns The component data that is currently selected.
*/
getCurrentComponentItem() {
const { componentItems } = this.props;
const { componentItems } = this.state;
return componentItems && componentItems.find(item => item.id === this.state.selectedNavItemId);
}

Expand All @@ -74,17 +152,22 @@ class RootPage extends Component {
*/
switchTo(selectedNavItemId) {
this.setState({ selectedNavItemId }, () => {
const { componentItems } = this.props;
const { componentItems } = this.state;
const selectedNavItem = componentItems && componentItems.find(item => item.id === selectedNavItemId);
const { name } = selectedNavItem || {};
if (name) {
history.pushState({ name }, name, `/demo/${name}`);
}
load(componentItems, selectedNavItemId).then(newComponentItems => {
if (newComponentItems) {
this.setState({ componentItems: newComponentItems });
}
});
});
}

render() {
const { componentItems } = this.props;
const { componentItems } = this.state;
const metadata = this.getCurrentComponentItem();
const { name, label } = metadata || {};
const classNames = classnames({
Expand Down
44 changes: 0 additions & 44 deletions demo/views/demo-live.dust

This file was deleted.

15 changes: 15 additions & 0 deletions demo/views/demo-nav-data.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<script>
var needIframe = [
'detail-page-header',
'footer',
'grid',
'unified-header',
];
var componentItems = {{{JSONstringify componentItems}}}.map(function (item) {
if (needIframe.indexOf(item.name) >= 0) {
item.useIframe = true;
}
return item;
});
var docItems = {{{JSONstringify docItems}}};
</script>
16 changes: 1 addition & 15 deletions demo/views/demo-nav.dust → demo/views/layouts/demo-nav.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,7 @@
<body>
<div data-renderroot></div>
<input aria-label="inpute-text-offleft" type="text" class="offleft" />
<script>
var needIframe = [
'detail-page-header',
'footer',
'grid',
'unified-header',
];
var componentItems = {componentItems|js|s}.map(function (item) {
if (needIframe.indexOf(item.name) >= 0) {
item.useIframe = true;
}
return item;
});
var docItems = {docItems|js|s};
</script>
{{{body}}}
<script src="/demo/demo.js"></script>
</body>
</html>
42 changes: 42 additions & 0 deletions demo/views/layouts/preview.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<!DOCTYPE html>
<html lang="en">
<head>
<base href="/">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<title>Carbon Components</title>
<style>
.demo--container {
display: none;
}
.offleft {
position: absolute;
top: 0;
left: -10000px;
width: 1px;
height: 1px;
overflow: hidden;
}
</style>
</head>

<body class="bx--body demo--container" data-floating-menu-container>
<div class="demo--container__panel" data-card-list>
{{{body}}}
</div>

<!-- Pseudo element to demonstrate focus-wrap behavior (focus trap) -->
<input aria-label="inpute-text-offleft" type="text" class="offleft" />

<!-- Scripts -->
<!-- <script src="/carbon-components.min.js"></script> -->
<script src="/demo/demo.js"></script>
<!-- Disable Auto Init with this flag -->
<!-- true = JavaScript will not initialize automatically -->
<!-- false = JavaScript will initialize automatically -->
<script>
CarbonComponents.settings.disableAutoInit = false;
</script>
</body>
</html>
Loading

0 comments on commit 4edeba9

Please sign in to comment.