Skip to content

Commit

Permalink
[changed] deprecate ModalTrigger
Browse files Browse the repository at this point in the history
  • Loading branch information
jquense committed Jun 30, 2015
1 parent 83b4cbc commit 1b1af04
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 42 deletions.
2 changes: 1 addition & 1 deletion docs/generate-metadata.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ let isLiteral = str => (/^('|")/).test(str.trim());
* @param {ComponentMetadata|PropMetadata} obj
*/
function parseDoclets(obj){
obj.doclets = metadata.parseDoclets(obj.desc || '');
obj.doclets = metadata.parseDoclets(obj.desc || '') || {};
obj.desc = cleanDoclets(obj.desc || '');
obj.descHtml = marked(obj.desc || '');
}
Expand Down
92 changes: 61 additions & 31 deletions docs/src/PropTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,46 @@ import Label from '../../src/Label';
import Table from '../../src/Table';


let cleanDocletValue = str => str.replace(/^\{|\}$/g, '');
let cleanDocletValue = str => str.trim().replace(/^\{/, '').replace(/\}$/, '');

function getPropsData(componentData, metadata){

let props = componentData.props || {};

if (componentData.composes) {
componentData.composes.forEach( other => {
props = merge({}, getPropsData(metadata[other] || {}, metadata), props);

});
}

if (componentData.mixins) {
componentData.mixins.forEach( other => {
if ( componentData.composes.indexOf(other) === -1) {
props = merge({}, getPropsData(metadata[other] || {}, metadata), props);
}
});
}

return props;
}

const PropTable = React.createClass({

contextTypes: {
metadata: React.PropTypes.object
},

componentWillMount(){
let componentData = this.context.metadata[this.props.component] || {};

this.propsData = getPropsData(componentData, this.context.metadata);
},

render(){
let metadata = this.context.metadata[this.props.component] || {};
let propsData = this.propsData;

if ( !Object.keys(metadata.props || {}).length){
if ( !Object.keys(propsData).length){
return <span/>;
}

Expand All @@ -31,46 +59,36 @@ const PropTable = React.createClass({
</tr>
</thead>
<tbody>
{ this._renderRows() }
{ this._renderRows(propsData) }
</tbody>
</Table>
);
},

_renderRows(){
let metadata = this.context.metadata[this.props.component] || {};
let props = metadata.props || {};
_renderRows(propsData){

if (metadata.composes) {
metadata.composes.forEach( other => {
props = merge(props, (this.context.metadata[other] || {}).props);
});
}

if (metadata.mixins) {
metadata.mixins.forEach( other => {
if ( metadata.composes.indexOf(other) === -1) {
props = merge(props, (this.context.metadata[other] || {}).props);
}
});
}

return Object.keys(props)
return Object.keys(propsData)
.sort()
.filter(propName => props[propName].type && !props[propName].doclets.private )
.filter(propName => propsData[propName].type && !propsData[propName].doclets.private )
.map(propName => {
let prop = props[propName];
let propData = propsData[propName];

return (
<tr key={propName} className='prop-table-row'>
<td>
{propName} {this.renderRequiredLabel(prop)}
{propName} {this.renderRequiredLabel(propData)}
</td>
<td>
<div>{this.getType(prop)}</div>
<div>{this.getType(propData)}</div>
</td>
<td>{propData.defaultValue}</td>

<td>
{ propData.doclets.deprecated
&& <div><strong className='text-danger'>{'Deprecated: ' + propData.doclets.deprecated + ' '}</strong></div>
}
<div dangerouslySetInnerHTML={{__html: propData.descHtml }} />
</td>
<td>{prop.defaultValue}</td>
<td dangerouslySetInnerHTML={{__html: prop.descHtml }}></td>
</tr>
);
});
Expand All @@ -87,17 +105,29 @@ const PropTable = React.createClass({
},

getType(prop) {
let type = prop.type;
let type = prop.type || {};
let name = this.getDisplayTypeName(type.name);
let doclets = prop.doclets || {};

switch (name) {
case 'object':
return name;
case 'union':
return type.value.map(val => this.getType({ type: val })).join(' | ');
return type.value.reduce((current, val, i, list) => {
let item = this.getType({ type: val });

if (React.isValidElement(item)) {
item = React.cloneElement(item, {key: i});
}

current = current.concat(item);

return i === (list.length - 1) ? current : current.concat(' | ');
}, []);
case 'array':
return `array<${this.getDisplayTypeName(type.value.name)}>`;
let child = this.getType({ type: type.value });

return <span>{'array<'}{ child }{'>'}</span>;
case 'enum':
return this.renderEnum(type);
case 'custom':
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@
"phantomjs": "^1.9.17",
"portfinder": "^0.4.0",
"react": "^0.13.1",
"react-component-metadata": "^1.1.1",
"react-component-metadata": "^1.2.1",
"react-hot-loader": "^1.2.7",
"react-router": "^0.13.1",
"rimraf": "^2.3.2",
Expand Down
58 changes: 49 additions & 9 deletions src/ModalTrigger.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
import React, { cloneElement } from 'react';
import OverlayMixin from './OverlayMixin';

import deprecationWarning from './utils/deprecationWarning';

import createChainedFunction from './utils/createChainedFunction';
import createContextWrapper from './utils/createContextWrapper';

function createHideDepreciationWrapper(hide){
return function(...args){
deprecationWarning(
'The Modal prop `onRequestHide`', 'the `onHide` prop');

return hide(...args);
};
}

const ModalTrigger = React.createClass({
mixins: [OverlayMixin],

propTypes: {
modal: React.PropTypes.node.isRequired,
Expand Down Expand Up @@ -39,15 +48,31 @@ const ModalTrigger = React.createClass({
});
},

renderOverlay() {
if (!this.state.isOverlayShown) {
return <span />;
}
componentDidMount(){
this._overlay = document.createElement('div');
React.render(this.getOverlay(), this._overlay);
},

componentWillUnmount() {
React.unmountComponentAtNode(this._overlay);
this._overlay = null;
clearTimeout(this._hoverDelay);
},

componentDidUpdate(){
React.render(this.getOverlay(), this._overlay);
},

getOverlay() {
let modal = this.props.modal;

return cloneElement(
this.props.modal,
modal,
{
onRequestHide: this.hide
show: this.state.isOverlayShown,
onHide: this.hide,
onRequestHide: createHideDepreciationWrapper(this.hide),
container: modal.props.container || this.props.container
}
);
},
Expand Down Expand Up @@ -82,4 +107,19 @@ const ModalTrigger = React.createClass({
*/
ModalTrigger.withContext = createContextWrapper(ModalTrigger, 'modal');

export default ModalTrigger;
let DepreciatedModalTrigger = React.createClass({
componentWillMount(){
deprecationWarning(
'The `ModalTrigger` component', 'the `Modal` component directly'
, 'http://react-bootstrap.github.io/components.html#modals');
},

render(){
return (<ModalTrigger {...this.props}/>);
}
});

DepreciatedModalTrigger.withContext = ModalTrigger.withContext;
DepreciatedModalTrigger.ModalTrigger = ModalTrigger;

export default DepreciatedModalTrigger;
2 changes: 2 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import NavItem from './NavItem';
import ModalTrigger from './ModalTrigger';
import OverlayTrigger from './OverlayTrigger';
import OverlayMixin from './OverlayMixin';
import Overlay from './Overlay';
import PageHeader from './PageHeader';
import Pagination from './Pagination';
import Panel from './Panel';
Expand Down Expand Up @@ -100,6 +101,7 @@ export default {
Navbar,
NavItem,
ModalTrigger,
Overlay,
OverlayTrigger,
OverlayMixin,
PageHeader,
Expand Down
19 changes: 19 additions & 0 deletions test/ModalTriggerSpec.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,27 @@
import React from 'react';
import ReactTestUtils from 'react/lib/ReactTestUtils';
import ModalTrigger from '../src/ModalTrigger';
import { shouldWarn } from './helpers';


describe('ModalTrigger', function() {

afterEach(()=> {
if ( console.warn.called ) {
shouldWarn('The `ModalTrigger` component is deprecated');
}
});

it('Should warn about deprecated Component', function() {
ReactTestUtils.renderIntoDocument(
<ModalTrigger modal={<div>test</div>}>
<button>button</button>
</ModalTrigger>
);

shouldWarn('The `ModalTrigger` component is deprecated');
});

it('Should create ModalTrigger element', function() {
const instance = ReactTestUtils.renderIntoDocument(
<ModalTrigger modal={<div>test</div>}>
Expand Down

0 comments on commit 1b1af04

Please sign in to comment.