├── codecov.yml ├── docs ├── assets │ ├── logo.png │ ├── carousel.png │ ├── favicon.ico │ ├── thumbnail.png │ ├── thumbnaildiv.png │ └── CodeMirror.css ├── examples │ ├── Badge.js │ ├── Well.js │ ├── ProgressBarBasic.js │ ├── ProgressBarAnimated.js │ ├── PanelWithFooter.js │ ├── ImageResponsive.js │ ├── ProgressBarWithLabel.js │ ├── PageHeader.js │ ├── ProgressBarScreenreaderLabel.js │ ├── ButtonTagTypes.js │ ├── AlertBasic.js │ ├── WellSizes.js │ ├── PagerDefault.js │ ├── ButtonGroupBasic.js │ ├── ButtonGroupBlock.js │ ├── PagerAligned.js │ ├── PagerDisabled.js │ ├── PanelBasic.js │ ├── ButtonActive.js │ ├── ButtonDisabled.js │ ├── ListGroupDefault.js │ ├── PanelGroupUncontrolled.js │ ├── ResponsiveEmbed.js │ ├── ListGroupActive.js │ ├── ProgressBarContextual.js │ ├── ProgressBarStacked.js │ ├── PanelWithHeading.js │ ├── Label.js │ ├── ProgressBarStriped.js │ ├── TabsUncontrolled.js │ ├── Jumbotron.js │ ├── ButtonBlock.js │ ├── TabsNoAnimation.js │ ├── PopoverBasic.js │ ├── ListGroupHeader.js │ ├── CustomButtonStyle.js │ ├── ListGroupStyle.js │ ├── ButtonGroupToggleCheckbox.js │ ├── ButtonGroupNested.js │ ├── ButtonGroupToggleRadio.js │ ├── Breadcrumb.js │ ├── PanelListGroupFill.js │ ├── ButtonGroupJustified.js │ ├── LabelVariations.js │ ├── ListGroupLinked.js │ ├── SplitButtonRight.js │ ├── FormInputSizes.js │ ├── NavBasic.js │ ├── NavStacked.js │ ├── ImageShape.js │ ├── ThumbnailAnchor.js │ ├── DropdownButtonNoCaret.js │ ├── ButtonToolbarBasic.js │ ├── ModalStatic.js │ ├── NavbarTextLink.js │ ├── NavbarForm.js │ ├── TooltipBasic.js │ ├── ListGroupCustom.js │ ├── FormInline.js │ ├── PanelGroupControlled.js │ ├── PaginationAdvanced.js │ ├── TabsControlled.js │ ├── DropdownButtonBasic.js │ ├── PanelContextual.js │ ├── SplitButtonBasic.js │ ├── PanelCollapsible.js │ ├── MenuItem.js │ ├── TableBasic.js │ ├── Fade.js │ ├── Collapse.js │ ├── NavbarBasic.js │ ├── ButtonSizes.js │ ├── LeftTabs.js │ ├── ButtonLoading.js │ ├── Glyphicon.js │ ├── TooltipPositioned.js │ ├── ButtonGroupVertical.js │ ├── NavJustified.js │ ├── PopoverContained.js │ ├── ButtonTypes.js │ ├── NavDropdown.js │ ├── PaginationBasic.js │ ├── GridBasic.js │ ├── FormHorizontal.js │ ├── ButtonGroupSizes.js │ ├── SplitButtonDropup.js │ ├── CarouselUncontrolled.js │ ├── NavbarCollapsible.js │ ├── GridWithoutClearfix.js │ ├── FormBasic.js │ ├── AlertDismissable.js │ ├── TableResponsive.js │ ├── ThumbnailDiv.js │ ├── GridWithClearfix.js │ ├── DropdownButtonCustom.js │ ├── Overlay.js │ ├── PopoverPositioned.js │ ├── OverlayCustom.js │ ├── PopoverTriggerBehaviors.js │ ├── ModalContained.js │ ├── TooltipInCopy.js │ └── TabsWithDropdown.js ├── .eslintrc ├── src │ ├── PageHeader.js │ ├── defaultPropDescriptions.js │ ├── Anchor.js │ ├── NotFoundPage.js │ ├── CodeExample.js │ ├── sections │ │ ├── GlyphiconSection.js │ │ ├── JumbotronSection.js │ │ ├── CustomStylesSection.js │ │ ├── AlertsSection.js │ │ ├── PageHeaderSection.js │ │ ├── WellSection.js │ │ ├── LabelSection.js │ │ ├── BadgeSection.js │ │ ├── ImageSection.js │ │ ├── TableSection.js │ │ ├── ResponsiveEmbedSection.js │ │ ├── FormValidationSection.js │ │ ├── ThumbnailSection.js │ │ ├── PaginationSection.js │ │ ├── BreadcrumbSection.js │ │ ├── OverlaySection.js │ │ ├── PagerSection.js │ │ ├── TooltipSection.js │ │ ├── CarouselSection.js │ │ ├── MenuItemSection.js │ │ ├── FormLayoutSection.js │ │ ├── GridSection.js │ │ └── NavSection.js │ └── Routes.js ├── README.docs.md └── client.js ├── .projections.json ├── src ├── utils │ ├── capitalize.js │ ├── index.js │ ├── splitComponentProps.js │ ├── StyleConfig.js │ ├── createChainedFunction.js │ └── deprecationWarning.js ├── PageItem.js ├── Accordion.js ├── SplitToggle.js ├── HelpBlock.js ├── MediaList.js ├── MediaListItem.js ├── InputGroupAddon.js ├── InputGroupButton.js ├── CloseButton.js ├── PageHeader.js ├── Well.js ├── ButtonToolbar.js ├── Breadcrumb.js ├── NavbarHeader.js ├── Row.js ├── NavbarCollapse.js ├── InputGroup.js ├── Jumbotron.js ├── MediaBody.js ├── ModalBody.js ├── ModalTitle.js ├── ModalFooter.js ├── MediaHeading.js ├── CarouselCaption.js ├── Tab.js ├── FormControlStatic.js ├── Glyphicon.js ├── NavbarBrand.js ├── MediaLeft.js ├── MediaRight.js ├── Thumbnail.js ├── Pager.js ├── Grid.js ├── Label.js ├── Form.js ├── BreadcrumbItem.js ├── Media.js ├── DropdownButton.js ├── Alert.js ├── Badge.js ├── ToggleButton.js ├── Image.js ├── ModalDialog.js └── ControlLabel.js ├── tools ├── .eslintrc ├── promisify.js ├── dist │ └── build.js ├── constants.js ├── amd │ ├── bower.json │ ├── README.md │ └── build.js ├── lib │ └── build.js ├── build.js ├── es │ └── build.js ├── fs-utils.js ├── build-cli.js ├── exec.js └── buildBabel.js ├── webpack.docs.js ├── webpack.config.js ├── nodemon.json ├── .gitignore ├── .ackrc ├── .editorconfig ├── .babelrc ├── .travis.yml ├── test ├── utils │ └── deprecationWarningSpec.js ├── .eslintrc ├── HelpBlockSpec.js ├── server │ └── ModalSpec.js ├── PageHeaderSpec.js ├── ButtonToolbarSpec.js ├── GlyphiconSpec.js ├── PopoverSpec.js ├── WellSpec.js ├── FormSpec.js ├── NavbarBrandSpec.js ├── FormControlStaticSpec.js ├── JumbotronSpec.js ├── helpers.js ├── RowSpec.js ├── InputGroupSpec.js ├── LabelSpec.js ├── MediaListSpec.js ├── MediaListItemSpec.js ├── CarouselCaptionSpec.js ├── ControlLabelSpec.js ├── GridSpec.js ├── MediaSpec.js ├── TooltipSpec.js ├── ModalBodySpec.js ├── ModalTitleSpec.js └── MediaBodySpec.js ├── appveyor.yml ├── webpack ├── webpack.config.js └── base.config.js ├── .eslintrc ├── LICENSE └── karma.conf.js /codecov.yml: -------------------------------------------------------------------------------- 1 | comment: off 2 | -------------------------------------------------------------------------------- /docs/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/functions/react-bootstrap/master/docs/assets/logo.png -------------------------------------------------------------------------------- /docs/assets/carousel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/functions/react-bootstrap/master/docs/assets/carousel.png -------------------------------------------------------------------------------- /docs/assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/functions/react-bootstrap/master/docs/assets/favicon.ico -------------------------------------------------------------------------------- /docs/assets/thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/functions/react-bootstrap/master/docs/assets/thumbnail.png -------------------------------------------------------------------------------- /docs/assets/thumbnaildiv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/functions/react-bootstrap/master/docs/assets/thumbnaildiv.png -------------------------------------------------------------------------------- /.projections.json: -------------------------------------------------------------------------------- 1 | { 2 | "src/*.js": { "alternate": "test/{}Spec.js" }, 3 | "test/*Spec.js": { "alternate": "src/{}.js" } 4 | } 5 | -------------------------------------------------------------------------------- /docs/examples/Badge.js: -------------------------------------------------------------------------------- 1 | const badgeInstance = ( 2 |

Badges 42

3 | ); 4 | 5 | ReactDOM.render(badgeInstance, mountNode); 6 | -------------------------------------------------------------------------------- /docs/examples/Well.js: -------------------------------------------------------------------------------- 1 | const wellInstance = ( 2 | Look I'm in a well! 3 | ); 4 | 5 | ReactDOM.render(wellInstance, mountNode); 6 | -------------------------------------------------------------------------------- /src/utils/capitalize.js: -------------------------------------------------------------------------------- 1 | export default function capitalize(string) { 2 | return `${string.charAt(0).toUpperCase()}${string.slice(1)}`; 3 | } 4 | -------------------------------------------------------------------------------- /docs/examples/ProgressBarBasic.js: -------------------------------------------------------------------------------- 1 | const progressInstance = ( 2 | 3 | ); 4 | 5 | ReactDOM.render(progressInstance, mountNode); 6 | -------------------------------------------------------------------------------- /tools/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "node": true 4 | }, 5 | "parser": "babel-eslint", 6 | "rules": { 7 | "no-console": 0 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /docs/examples/ProgressBarAnimated.js: -------------------------------------------------------------------------------- 1 | const progressInstance = ( 2 | 3 | ); 4 | 5 | ReactDOM.render(progressInstance, mountNode); 6 | -------------------------------------------------------------------------------- /webpack.docs.js: -------------------------------------------------------------------------------- 1 | /* eslint no-var: 0, vars-on-top: 0 */ 2 | require('babel-register'); 3 | var config = require('./webpack/docs.config'); 4 | module.exports = config; 5 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | /* eslint no-var: 0, vars-on-top: 0 */ 2 | require('babel-register'); 3 | var config = require('./webpack/webpack.config'); 4 | module.exports = config; 5 | -------------------------------------------------------------------------------- /docs/examples/PanelWithFooter.js: -------------------------------------------------------------------------------- 1 | const panelInstance = ( 2 | 3 | Panel content 4 | 5 | ); 6 | 7 | ReactDOM.render(panelInstance, mountNode); 8 | -------------------------------------------------------------------------------- /docs/examples/ImageResponsive.js: -------------------------------------------------------------------------------- 1 | const imageResponsiveInstance = ( 2 | 3 | ); 4 | 5 | ReactDOM.render(imageResponsiveInstance, mountNode); 6 | -------------------------------------------------------------------------------- /docs/examples/ProgressBarWithLabel.js: -------------------------------------------------------------------------------- 1 | const now = 60; 2 | 3 | const progressInstance = ( 4 | 5 | ); 6 | 7 | ReactDOM.render(progressInstance, mountNode); 8 | -------------------------------------------------------------------------------- /src/utils/index.js: -------------------------------------------------------------------------------- 1 | export * as bootstrapUtils from './bootstrapUtils'; 2 | export createChainedFunction from './createChainedFunction'; 3 | export ValidComponentChildren from './ValidComponentChildren'; 4 | -------------------------------------------------------------------------------- /docs/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "comma-spacing": 0, 4 | "react/no-multi-comp": 0, 5 | "react/prop-types": 0 6 | }, 7 | "globals": { 8 | "CodeMirror": true 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /docs/examples/PageHeader.js: -------------------------------------------------------------------------------- 1 | const pageHeaderInstance = ( 2 | Example page header Subtext for header 3 | ); 4 | 5 | ReactDOM.render(pageHeaderInstance, mountNode); 6 | -------------------------------------------------------------------------------- /docs/examples/ProgressBarScreenreaderLabel.js: -------------------------------------------------------------------------------- 1 | const now = 60; 2 | 3 | const progressInstance = ( 4 | 5 | ); 6 | 7 | ReactDOM.render(progressInstance, mountNode); 8 | -------------------------------------------------------------------------------- /src/PageItem.js: -------------------------------------------------------------------------------- 1 | import PagerItem from './PagerItem'; 2 | import deprecationWarning from './utils/deprecationWarning'; 3 | 4 | export default deprecationWarning.wrapper(PagerItem, 5 | '``', 6 | '``' 7 | ); 8 | -------------------------------------------------------------------------------- /docs/examples/ButtonTagTypes.js: -------------------------------------------------------------------------------- 1 | const buttonsInstance = ( 2 | 3 | 4 | 5 | 6 | ); 7 | 8 | ReactDOM.render(buttonsInstance, mountNode); 9 | -------------------------------------------------------------------------------- /nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "restartable": "rs", 3 | "ignore": [ 4 | "tmp-bower-repo", 5 | "tmp-docs-repo", 6 | "docs-built", 7 | "amd", 8 | "lib", 9 | "dist", 10 | ".coverage", 11 | "tools" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /docs/examples/AlertBasic.js: -------------------------------------------------------------------------------- 1 | const alertInstance = ( 2 | 3 | Holy guacamole! Best check yo self, you're not looking too good. 4 | 5 | ); 6 | 7 | ReactDOM.render(alertInstance, mountNode); 8 | -------------------------------------------------------------------------------- /docs/examples/WellSizes.js: -------------------------------------------------------------------------------- 1 | const wellInstance = ( 2 |
3 | Look I'm in a large well! 4 | Look I'm in a small well! 5 |
6 | ); 7 | 8 | ReactDOM.render(wellInstance, mountNode); 9 | -------------------------------------------------------------------------------- /docs/examples/PagerDefault.js: -------------------------------------------------------------------------------- 1 | const pagerInstance = ( 2 | 3 | Previous 4 | {' '} 5 | Next 6 | 7 | ); 8 | 9 | ReactDOM.render(pagerInstance, mountNode); 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | .DS_Store 3 | npm-debug.log* 4 | node_modules 5 | amd/ 6 | !tools/amd/ 7 | lib/ 8 | !tools/lib/ 9 | es/ 10 | !tools/es/ 11 | dist/ 12 | !tools/dist/ 13 | docs-built/ 14 | tmp-bower-repo/ 15 | tmp-docs-repo/ 16 | .babel-cache/ 17 | coverage/ 18 | -------------------------------------------------------------------------------- /docs/examples/ButtonGroupBasic.js: -------------------------------------------------------------------------------- 1 | const buttonGroupInstance = ( 2 | 3 | 4 | 5 | 6 | 7 | ); 8 | 9 | ReactDOM.render(buttonGroupInstance, mountNode); 10 | -------------------------------------------------------------------------------- /docs/examples/ButtonGroupBlock.js: -------------------------------------------------------------------------------- 1 | const buttonGroupInstance = ( 2 | 3 | 4 | 5 | 6 | ); 7 | 8 | ReactDOM.render(buttonGroupInstance, mountNode); 9 | -------------------------------------------------------------------------------- /docs/examples/PagerAligned.js: -------------------------------------------------------------------------------- 1 | const pagerInstance = ( 2 | 3 | ← Previous Page 4 | Next Page → 5 | 6 | ); 7 | 8 | ReactDOM.render(pagerInstance, mountNode); 9 | -------------------------------------------------------------------------------- /docs/examples/PagerDisabled.js: -------------------------------------------------------------------------------- 1 | const pagerInstance = ( 2 | 3 | ← Previous 4 | Next → 5 | 6 | ); 7 | 8 | ReactDOM.render(pagerInstance, mountNode); 9 | -------------------------------------------------------------------------------- /docs/examples/PanelBasic.js: -------------------------------------------------------------------------------- 1 | function handleClick() { 2 | alert('You have clicked on me'); 3 | } 4 | 5 | const panelInstance = ( 6 | 7 | Basic panel example 8 | 9 | ); 10 | 11 | ReactDOM.render(panelInstance, mountNode); 12 | -------------------------------------------------------------------------------- /docs/examples/ButtonActive.js: -------------------------------------------------------------------------------- 1 | const buttonsInstance = ( 2 | 3 | 4 | 5 | 6 | ); 7 | 8 | ReactDOM.render(buttonsInstance, mountNode); 9 | -------------------------------------------------------------------------------- /docs/examples/ButtonDisabled.js: -------------------------------------------------------------------------------- 1 | const buttonsInstance = ( 2 | 3 | 4 | 5 | 6 | ); 7 | 8 | ReactDOM.render(buttonsInstance, mountNode); 9 | -------------------------------------------------------------------------------- /docs/examples/ListGroupDefault.js: -------------------------------------------------------------------------------- 1 | const listgroupInstance = ( 2 | 3 | Item 1 4 | Item 2 5 | ... 6 | 7 | ); 8 | 9 | ReactDOM.render(listgroupInstance, mountNode); 10 | -------------------------------------------------------------------------------- /.ackrc: -------------------------------------------------------------------------------- 1 | --ignore-dir=.coverage 2 | --ignore-dir=lib 3 | --ignore-dir=dist 4 | --ignore-dir=amd 5 | --ignore-dir=test-built 6 | --ignore-dir=docs-built 7 | --ignore-dir=tmp-docs-repo 8 | --ignore-dir=tmp-bower-repo 9 | --ignore-file=match:test_bundle.js 10 | --ignore-file=match:components.html 11 | --ignore-file=match:.orig 12 | -------------------------------------------------------------------------------- /docs/examples/PanelGroupUncontrolled.js: -------------------------------------------------------------------------------- 1 | const panelGroupInstance = ( 2 | 3 | Panel 1 content 4 | Panel 2 content 5 | 6 | ); 7 | 8 | ReactDOM.render(panelGroupInstance, mountNode); 9 | -------------------------------------------------------------------------------- /docs/examples/ResponsiveEmbed.js: -------------------------------------------------------------------------------- 1 | const responsiveEmbedInstance = ( 2 |
3 | 4 | 5 | 6 |
7 | ); 8 | 9 | ReactDOM.render(responsiveEmbedInstance, mountNode); 10 | -------------------------------------------------------------------------------- /docs/examples/ListGroupActive.js: -------------------------------------------------------------------------------- 1 | const listgroupInstance = ( 2 | 3 | Link 1 4 | Link 2 5 | Link 3 6 | 7 | ); 8 | 9 | ReactDOM.render(listgroupInstance, mountNode); 10 | -------------------------------------------------------------------------------- /src/Accordion.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import PanelGroup from './PanelGroup'; 4 | 5 | class Accordion extends React.Component { 6 | render() { 7 | return ( 8 | 9 | {this.props.children} 10 | 11 | ); 12 | } 13 | } 14 | 15 | export default Accordion; 16 | -------------------------------------------------------------------------------- /docs/examples/ProgressBarContextual.js: -------------------------------------------------------------------------------- 1 | const progressInstance = ( 2 |
3 | 4 | 5 | 6 | 7 |
8 | ); 9 | 10 | ReactDOM.render(progressInstance, mountNode); 11 | -------------------------------------------------------------------------------- /docs/assets/CodeMirror.css: -------------------------------------------------------------------------------- 1 | .cm-s-solarized.CodeMirror { 2 | -moz-box-shadow: none; 3 | -webkit-box-shadow: none; 4 | box-shadow: none; 5 | } 6 | 7 | .highlight, .code-toggle.open { 8 | background-color: #fdf6e3; 9 | } 10 | 11 | .cm-s-solarized .cm-comment { color: #93a1a1; } 12 | 13 | .CodeMirror, .CodeMirror-scroll { 14 | height: auto; 15 | } 16 | -------------------------------------------------------------------------------- /docs/examples/ProgressBarStacked.js: -------------------------------------------------------------------------------- 1 | const progressInstance = ( 2 | 3 | 4 | 5 | 6 | 7 | ); 8 | 9 | ReactDOM.render(progressInstance, mountNode); 10 | -------------------------------------------------------------------------------- /tools/promisify.js: -------------------------------------------------------------------------------- 1 | export default function promisify(fn) { 2 | return (...args) => { 3 | return new Promise((resolve, reject) => { 4 | function finish(err, result) { 5 | if (err) { 6 | return reject(err); 7 | } 8 | resolve(result); 9 | } 10 | 11 | fn.apply(null, args.concat(finish)); 12 | }); 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /docs/examples/PanelWithHeading.js: -------------------------------------------------------------------------------- 1 | const title = ( 2 |

Panel title

3 | ); 4 | 5 | const panelsInstance = ( 6 |
7 | 8 | Panel content 9 | 10 | 11 | Panel content 12 | 13 |
14 | ); 15 | 16 | ReactDOM.render(panelsInstance, mountNode); 17 | -------------------------------------------------------------------------------- /docs/examples/Label.js: -------------------------------------------------------------------------------- 1 | const labelInstance = ( 2 |
3 |

Label

4 |

Label

5 |

Label

6 |

Label

7 |
Label
8 |

Label

9 |
10 | ); 11 | 12 | ReactDOM.render(labelInstance, mountNode); 13 | -------------------------------------------------------------------------------- /docs/examples/ProgressBarStriped.js: -------------------------------------------------------------------------------- 1 | const progressInstance = ( 2 |
3 | 4 | 5 | 6 | 7 |
8 | ); 9 | 10 | ReactDOM.render(progressInstance, mountNode); 11 | -------------------------------------------------------------------------------- /docs/examples/TabsUncontrolled.js: -------------------------------------------------------------------------------- 1 | const tabsInstance = ( 2 | 3 | Tab 1 content 4 | Tab 2 content 5 | Tab 3 content 6 | 7 | ); 8 | 9 | ReactDOM.render(tabsInstance, mountNode); 10 | -------------------------------------------------------------------------------- /docs/examples/Jumbotron.js: -------------------------------------------------------------------------------- 1 | const jumbotronInstance = ( 2 | 3 |

Hello, world!

4 |

This is a simple hero unit, a simple jumbotron-style component for calling extra attention to featured content or information.

5 |

6 |
7 | ); 8 | 9 | ReactDOM.render(jumbotronInstance, mountNode); 10 | -------------------------------------------------------------------------------- /docs/examples/ButtonBlock.js: -------------------------------------------------------------------------------- 1 | const wellStyles = {maxWidth: 400, margin: '0 auto 10px'}; 2 | 3 | const buttonsInstance = ( 4 |
5 | 6 | 7 |
8 | ); 9 | 10 | ReactDOM.render(buttonsInstance, mountNode); 11 | -------------------------------------------------------------------------------- /docs/examples/TabsNoAnimation.js: -------------------------------------------------------------------------------- 1 | const tabsInstance = ( 2 | 3 | Tab 1 content 4 | Tab 2 content 5 | Tab 3 content 6 | 7 | ); 8 | 9 | ReactDOM.render(tabsInstance, mountNode); 10 | -------------------------------------------------------------------------------- /docs/examples/PopoverBasic.js: -------------------------------------------------------------------------------- 1 | ReactDOM.render(( 2 |
3 | 10 | And here's some amazing content. It's very engaging. right? 11 | 12 |
13 | ), mountNode); 14 | -------------------------------------------------------------------------------- /docs/examples/ListGroupHeader.js: -------------------------------------------------------------------------------- 1 | const listgroupInstance = ( 2 | 3 | Some body text 4 | Linked item 5 | Danger styling 6 | 7 | ); 8 | 9 | ReactDOM.render(listgroupInstance, mountNode); 10 | -------------------------------------------------------------------------------- /docs/examples/CustomButtonStyle.js: -------------------------------------------------------------------------------- 1 | bootstrapUtils.addStyle(Button, 'custom'); 2 | 3 | const customButtonStyle = ( 4 |
5 | 11 | 12 |
13 | ); 14 | 15 | ReactDOM.render(customButtonStyle, mountNode); 16 | -------------------------------------------------------------------------------- /docs/examples/ListGroupStyle.js: -------------------------------------------------------------------------------- 1 | const listgroupInstance = ( 2 | 3 | Success 4 | Info 5 | Warning 6 | Danger 7 | 8 | ); 9 | 10 | ReactDOM.render(listgroupInstance, mountNode); 11 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = lf 9 | insert_final_newline = true 10 | 11 | [*.js] 12 | charset = utf-8 13 | indent_style = space 14 | indent_size = 2 15 | 16 | [{package.json,.travis.yml}] 17 | indent_style = space 18 | indent_size = 2 19 | -------------------------------------------------------------------------------- /docs/src/PageHeader.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const PageHeader = React.createClass({ 4 | render() { 5 | return ( 6 |
7 |
8 |

{this.props.title}

9 |

{this.props.subTitle}

10 |
11 |
12 | ); 13 | } 14 | }); 15 | 16 | export default PageHeader; 17 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["es2015", { "loose": true }], 4 | "stage-1", 5 | "react" 6 | ], 7 | "plugins": [ 8 | "dev-expression", 9 | "transform-runtime", 10 | "transform-es3-member-expression-literals", 11 | "transform-es3-property-literals", 12 | "add-module-exports" 13 | ], 14 | 15 | "env": { 16 | "test": { 17 | "plugins": ["istanbul"] 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /docs/examples/ButtonGroupToggleCheckbox.js: -------------------------------------------------------------------------------- 1 | const toggleButtonGroup = ( 2 | 3 | Checkbox 1 (pre-checked) 4 | Checkbox 3 5 | 6 | Checkbox 3 (pre-checked) 7 | 8 | ); 9 | 10 | ReactDOM.render(toggleButtonGroup, mountNode); 11 | -------------------------------------------------------------------------------- /docs/examples/ButtonGroupNested.js: -------------------------------------------------------------------------------- 1 | const buttonGroupInstance = ( 2 | 3 | 4 | 5 | 6 | Dropdown link 7 | Dropdown link 8 | 9 | 10 | ); 11 | 12 | ReactDOM.render(buttonGroupInstance, mountNode); 13 | -------------------------------------------------------------------------------- /docs/examples/ButtonGroupToggleRadio.js: -------------------------------------------------------------------------------- 1 | const buttonGroupInstance = ( 2 | 3 | 4 | Radio 1 (pre-checked) 5 | 6 | Radio 3 7 | 8 | Radio 3 9 | 10 | ); 11 | 12 | ReactDOM.render(buttonGroupInstance, mountNode); 13 | -------------------------------------------------------------------------------- /docs/examples/Breadcrumb.js: -------------------------------------------------------------------------------- 1 | const breadcrumbInstance = ( 2 | 3 | 4 | Home 5 | 6 | 7 | Library 8 | 9 | 10 | Data 11 | 12 | 13 | ); 14 | 15 | ReactDOM.render(breadcrumbInstance, mountNode); 16 | -------------------------------------------------------------------------------- /docs/src/defaultPropDescriptions.js: -------------------------------------------------------------------------------- 1 | 2 | export default { 3 | bsClass: 4 | 'Base CSS class and prefix for the component. Generally one should only ' + 5 | 'change `bsClass` to provide new, non-Bootstrap, CSS styles for a ' + 6 | 'component.', 7 | bsStyle: 'Component visual or contextual style variants.', 8 | bsSize: 'Component size variations.', 9 | componentClass: 'You can use a custom element type for this component.', 10 | }; 11 | -------------------------------------------------------------------------------- /src/SplitToggle.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import DropdownToggle from './DropdownToggle'; 4 | 5 | class SplitToggle extends React.Component { 6 | render() { 7 | return ( 8 | 13 | ); 14 | } 15 | } 16 | 17 | SplitToggle.defaultProps = DropdownToggle.defaultProps; 18 | 19 | export default SplitToggle; 20 | -------------------------------------------------------------------------------- /tools/dist/build.js: -------------------------------------------------------------------------------- 1 | import { exec } from '../exec'; 2 | import { distRoot } from '../constants'; 3 | 4 | export default function BuildDistributable() { 5 | console.log('Building: '.cyan + 'distributable'.green); 6 | 7 | return exec(`rimraf ${distRoot}`) 8 | .then(() => Promise.all([ 9 | exec(`webpack --bail`), 10 | exec(`webpack --bail -p`) 11 | ])) 12 | .then(() => console.log('Built: '.cyan + 'distributable'.green)); 13 | } 14 | -------------------------------------------------------------------------------- /tools/constants.js: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | 3 | export const repoRoot = path.resolve(__dirname, '../'); 4 | 5 | export const srcRoot = path.join(repoRoot, 'src/'); 6 | export const distRoot = path.join(repoRoot, 'dist/'); 7 | export const libRoot = path.join(repoRoot, 'lib/'); 8 | export const esRoot = path.join(repoRoot, 'es/'); 9 | export const bowerRoot = path.join(repoRoot, 'amd/'); 10 | export const docsRoot = path.join(repoRoot, 'docs-built/'); 11 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: node_js 4 | node_js: 5 | - stable 6 | 7 | env: 8 | - BROWSER=ChromeCi 9 | - BROWSER=Firefox 10 | 11 | cache: 12 | directories: 13 | - node_modules 14 | 15 | before_install: 16 | - export CHROME_BIN=chromium-browser 17 | - export DISPLAY=:99.0 18 | - sh -e /etc/init.d/xvfb start 19 | 20 | after_success: 21 | - node_modules/.bin/codecov 22 | 23 | branches: 24 | only: 25 | - master 26 | - next 27 | -------------------------------------------------------------------------------- /docs/examples/PanelListGroupFill.js: -------------------------------------------------------------------------------- 1 | const panelInstance = ( 2 | 3 | Some default panel content here. 4 | 5 | Item 1 6 | Item 2 7 | 8 | 9 | Some more panel content here. 10 | 11 | ); 12 | 13 | ReactDOM.render(panelInstance, mountNode); 14 | -------------------------------------------------------------------------------- /docs/examples/ButtonGroupJustified.js: -------------------------------------------------------------------------------- 1 | const buttonGroupInstance = ( 2 | 3 | 4 | 5 | 6 | Dropdown link 7 | Dropdown link 8 | 9 | 10 | ); 11 | 12 | ReactDOM.render(buttonGroupInstance, mountNode); 13 | -------------------------------------------------------------------------------- /docs/examples/LabelVariations.js: -------------------------------------------------------------------------------- 1 | const labelVariationInstance = ( 2 |
3 |   4 |   5 |   6 |   7 |   8 | 9 |
10 | ); 11 | 12 | ReactDOM.render(labelVariationInstance, mountNode); 13 | -------------------------------------------------------------------------------- /docs/examples/ListGroupLinked.js: -------------------------------------------------------------------------------- 1 | function alertClicked() { 2 | alert('You clicked the third ListGroupItem'); 3 | } 4 | 5 | const listgroupInstance = ( 6 | 7 | Link 1 8 | Link 2 9 | 10 | Trigger an alert 11 | 12 | 13 | ); 14 | 15 | ReactDOM.render(listgroupInstance, mountNode); 16 | -------------------------------------------------------------------------------- /docs/examples/SplitButtonRight.js: -------------------------------------------------------------------------------- 1 | const buttonsInstance = ( 2 | 3 | Action 4 | Another action 5 | Something else here 6 | 7 | Separated link 8 | 9 | ); 10 | 11 | ReactDOM.render(buttonsInstance, mountNode); 12 | -------------------------------------------------------------------------------- /docs/examples/FormInputSizes.js: -------------------------------------------------------------------------------- 1 | const formInstance = ( 2 |
3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | ); 14 | 15 | ReactDOM.render(formInstance, mountNode); 16 | -------------------------------------------------------------------------------- /docs/examples/NavBasic.js: -------------------------------------------------------------------------------- 1 | function handleSelect(selectedKey) { 2 | alert('selected ' + selectedKey); 3 | } 4 | 5 | const navInstance = ( 6 | 11 | ); 12 | 13 | ReactDOM.render(navInstance, mountNode); 14 | -------------------------------------------------------------------------------- /test/utils/deprecationWarningSpec.js: -------------------------------------------------------------------------------- 1 | import deprecationWarning from '../../src/utils/deprecationWarning'; 2 | 3 | import { shouldWarn } from '../helpers'; 4 | 5 | describe('deprecationWarning', () => { 6 | it('warns exactly once', () => { 7 | // console.error has already been stubbed out by test setup. 8 | shouldWarn('deprecated'); 9 | deprecationWarning('foo', 'bar'); 10 | 11 | // No second warning. 12 | deprecationWarning('foo', 'bar'); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: '{build}' 2 | 3 | # Install scripts. (runs after repo cloning) 4 | install: 5 | # Get the latest stable version of io.js 6 | - ps: Install-Product node '' 7 | - npm -g install npm@latest 8 | - set PATH=%APPDATA%\npm;%PATH% 9 | - node --version 10 | - npm --version 11 | - npm install 12 | 13 | # No need for MSBuild on this project 14 | build: off 15 | 16 | test_script: 17 | - npm test 18 | 19 | branches: 20 | only: 21 | - master 22 | - next 23 | -------------------------------------------------------------------------------- /docs/examples/NavStacked.js: -------------------------------------------------------------------------------- 1 | function handleSelect(selectedKey) { 2 | alert('selected ' + selectedKey); 3 | } 4 | 5 | const navInstance = ( 6 | 11 | ); 12 | 13 | ReactDOM.render(navInstance, mountNode); 14 | -------------------------------------------------------------------------------- /docs/examples/ImageShape.js: -------------------------------------------------------------------------------- 1 | const imageShapeInstance = ( 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | ); 16 | 17 | ReactDOM.render(imageShapeInstance, mountNode); 18 | -------------------------------------------------------------------------------- /docs/README.docs.md: -------------------------------------------------------------------------------- 1 | # React-Bootstrap Documentation Website 2 | 3 | This website is single page app built on 4 | [React](http://facebook.github.io/react/), with styles and structure taken from 5 | the [Bootstrap](http://getbootstrap.com/) docs website. The app is statically 6 | generated to HTML via node and then hosted it by pushing HTML to [GitHub 7 | Pages](http://pages.github.com/). 8 | 9 | Source can be found in the 10 | [react-bootstrap](https://github.com/react-bootstrap/react-bootstrap) repo. 11 | -------------------------------------------------------------------------------- /test/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "mocha": true 4 | }, 5 | "globals": { 6 | "assert": true, 7 | "expect": true, 8 | "sinon": true 9 | }, 10 | "plugins": [ 11 | "mocha" 12 | ], 13 | "rules": { 14 | "no-script-url": 0, 15 | "no-unused-expressions": 0, 16 | "padded-blocks": 0, 17 | "react/no-multi-comp": 0, 18 | "react/prop-types": 0, 19 | "mocha/no-exclusive-tests": 2, 20 | "no-unused-vars": [2, { "varsIgnorePattern": "^_$" }] 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/utils/splitComponentProps.js: -------------------------------------------------------------------------------- 1 | export default function splitComponentProps(props, Component) { 2 | const componentPropTypes = Component.propTypes; 3 | 4 | const parentProps = {}; 5 | const childProps = {}; 6 | 7 | Object.entries(props).forEach(([propName, propValue]) => { 8 | if (componentPropTypes[propName]) { 9 | parentProps[propName] = propValue; 10 | } else { 11 | childProps[propName] = propValue; 12 | } 13 | }); 14 | 15 | return [parentProps, childProps]; 16 | } 17 | -------------------------------------------------------------------------------- /tools/amd/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "<%= pkg.name %>", 3 | "version": "<%= pkg.version %>", 4 | "homepage": "<%= pkg.homepage %>", 5 | "author": "<%= pkg.author %>", 6 | "license": "<%= pkg.license %>", 7 | "main": [ 8 | "react-bootstrap.js" 9 | ], 10 | "keywords": [ 11 | <%= pkg.keywords.map(keyword => `"${keyword}"`).join(',\n ') %> 12 | ], 13 | "ignore": [ 14 | "**/.*" 15 | ], 16 | "dependencies": { 17 | "react": "<%= pkg.peerDependencies.react %>" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /docs/examples/ThumbnailAnchor.js: -------------------------------------------------------------------------------- 1 | const thumbnailInstance = ( 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | ); 16 | 17 | ReactDOM.render(thumbnailInstance, mountNode); 18 | -------------------------------------------------------------------------------- /tools/lib/build.js: -------------------------------------------------------------------------------- 1 | import 'colors'; 2 | import { exec } from '../exec'; 3 | import fsp from 'fs-promise'; 4 | import { srcRoot, libRoot } from '../constants'; 5 | import buildBabel from '../buildBabel'; 6 | 7 | export default function BuildCommonJs() { 8 | console.log('Building: '.cyan + 'npm module'.green); 9 | 10 | return exec(`rimraf ${libRoot}`) 11 | .then(() => fsp.mkdirs(libRoot)) 12 | .then(() => buildBabel(srcRoot, libRoot)) 13 | .then(() => console.log('Built: '.cyan + 'npm module'.green)); 14 | } 15 | -------------------------------------------------------------------------------- /test/HelpBlockSpec.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import $ from 'teaspoon'; 3 | 4 | import HelpBlock from '../src/HelpBlock'; 5 | 6 | describe('', () => { 7 | it('should render correctly', () => { 8 | expect( 9 | $( 10 | 11 | Help contents 12 | 13 | ) 14 | .shallowRender() 15 | .single('#foo.help-block.my-help-block') 16 | .text() 17 | ).to.equal('Help contents'); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /docs/src/Anchor.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | const Anchor = React.createClass({ 5 | propTypes: { 6 | id: PropTypes.oneOfType([ 7 | PropTypes.string, 8 | PropTypes.number 9 | ]) 10 | }, 11 | render() { 12 | return ( 13 | 14 | # 15 | {this.props.children} 16 | 17 | ); 18 | } 19 | }); 20 | 21 | export default Anchor; 22 | -------------------------------------------------------------------------------- /docs/examples/DropdownButtonNoCaret.js: -------------------------------------------------------------------------------- 1 | const buttonInstance = ( 2 | 3 | 4 | Action 5 | Another action 6 | Something else here 7 | 8 | Separated link 9 | 10 | 11 | ); 12 | 13 | ReactDOM.render(buttonInstance, mountNode); 14 | -------------------------------------------------------------------------------- /docs/examples/ButtonToolbarBasic.js: -------------------------------------------------------------------------------- 1 | const buttonGroupInstance = ( 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | ); 21 | 22 | ReactDOM.render(buttonGroupInstance, mountNode); 23 | -------------------------------------------------------------------------------- /docs/examples/ModalStatic.js: -------------------------------------------------------------------------------- 1 | 2 | const modalInstance = ( 3 |
4 | 5 | 6 | Modal title 7 | 8 | 9 | 10 | One fine body... 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | ); 21 | 22 | ReactDOM.render(modalInstance, mountNode); 23 | -------------------------------------------------------------------------------- /docs/src/NotFoundPage.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import NavMain from './NavMain'; 4 | import PageHeader from './PageHeader'; 5 | import PageFooter from './PageFooter'; 6 | 7 | const NotFoundPage = React.createClass({ 8 | render() { 9 | return ( 10 |
11 | 12 | 13 | 16 | 17 | 18 |
19 | ); 20 | } 21 | }); 22 | 23 | export default NotFoundPage; 24 | -------------------------------------------------------------------------------- /test/server/ModalSpec.js: -------------------------------------------------------------------------------- 1 | import {assert} from 'chai'; 2 | import React from 'react'; 3 | import ReactDOMServer from 'react-dom/server'; 4 | 5 | import Modal from '../../src/Modal.js'; 6 | 7 | describe('Modal', () => { 8 | it('Should be rendered on the server side', () => { 9 | let noOp = () => {}; 10 | 11 | assert.doesNotThrow(function renderOnServerSide() { 12 | return ReactDOMServer.renderToString( 13 | 14 | Message 15 | 16 | ); 17 | }); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /docs/examples/NavbarTextLink.js: -------------------------------------------------------------------------------- 1 | const navbarInstance = ( 2 | 3 | 4 | 5 | Brand 6 | 7 | 8 | 9 | 10 | 11 | Signed in as: Mark Otto 12 | 13 | 14 | Have a great day! 15 | 16 | 17 | 18 | ); 19 | 20 | ReactDOM.render(navbarInstance, mountNode); 21 | -------------------------------------------------------------------------------- /docs/examples/NavbarForm.js: -------------------------------------------------------------------------------- 1 | const navbarInstance = ( 2 | 3 | 4 | 5 | Brand 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | {' '} 15 | 16 | 17 | 18 | 19 | ); 20 | 21 | ReactDOM.render(navbarInstance, mountNode); 22 | -------------------------------------------------------------------------------- /docs/examples/TooltipBasic.js: -------------------------------------------------------------------------------- 1 | const tooltipInstance = ( 2 |
3 | 4 | Tooltip right 5 | 6 | 7 | 8 | Tooltip top 9 | 10 | 11 | 12 | Tooltip left 13 | 14 | 15 | 16 | Tooltip bottom 17 | 18 |
19 | ); 20 | 21 | ReactDOM.render(tooltipInstance, mountNode); 22 | -------------------------------------------------------------------------------- /docs/examples/ListGroupCustom.js: -------------------------------------------------------------------------------- 1 | const CustomComponent = React.createClass({ 2 | render() { 3 | return ( 4 |
  • {}}> 7 | {this.props.children} 8 |
  • 9 | ); 10 | } 11 | }); 12 | 13 | const listgroupInstance = ( 14 | 15 | Custom Child 1 16 | Custom Child 2 17 | Custom Child 3 18 | 19 | ); 20 | 21 | ReactDOM.render(listgroupInstance, mountNode); 22 | -------------------------------------------------------------------------------- /src/HelpBlock.js: -------------------------------------------------------------------------------- 1 | import classNames from 'classnames'; 2 | import React from 'react'; 3 | 4 | import { bsClass, getClassSet, splitBsProps } from './utils/bootstrapUtils'; 5 | 6 | class HelpBlock extends React.Component { 7 | render() { 8 | const { className, ...props } = this.props; 9 | const [bsProps, elementProps] = splitBsProps(props); 10 | 11 | const classes = getClassSet(bsProps); 12 | 13 | return ( 14 | 18 | ); 19 | } 20 | } 21 | 22 | export default bsClass('help-block', HelpBlock); 23 | -------------------------------------------------------------------------------- /src/MediaList.js: -------------------------------------------------------------------------------- 1 | import classNames from 'classnames'; 2 | import React from 'react'; 3 | 4 | import { bsClass, getClassSet, splitBsProps } from './utils/bootstrapUtils'; 5 | 6 | class MediaList extends React.Component { 7 | render() { 8 | const { className, ...props } = this.props; 9 | const [bsProps, elementProps] = splitBsProps(props); 10 | 11 | const classes = getClassSet(bsProps); 12 | 13 | return ( 14 |
      18 | ); 19 | } 20 | } 21 | 22 | export default bsClass('media-list', MediaList); 23 | -------------------------------------------------------------------------------- /docs/src/CodeExample.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | 4 | export default class CodeExample extends React.Component { 5 | render() { 6 | return ( 7 |
       8 |         
       9 |           {this.props.codeText}
      10 |         
      11 |       
      12 | ); 13 | } 14 | 15 | componentDidMount() { 16 | if (CodeMirror === undefined) { 17 | return; 18 | } 19 | 20 | CodeMirror.runMode( 21 | this.props.codeText, 22 | this.props.mode, 23 | ReactDOM.findDOMNode(this).children[0] 24 | ); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/MediaListItem.js: -------------------------------------------------------------------------------- 1 | import classNames from 'classnames'; 2 | import React from 'react'; 3 | 4 | import { bsClass, getClassSet, splitBsProps } from './utils/bootstrapUtils'; 5 | 6 | class MediaListItem extends React.Component { 7 | render() { 8 | const { className, ...props } = this.props; 9 | const [bsProps, elementProps] = splitBsProps(props); 10 | 11 | const classes = getClassSet(bsProps); 12 | 13 | return ( 14 |
    • 18 | ); 19 | } 20 | } 21 | 22 | export default bsClass('media', MediaListItem); 23 | -------------------------------------------------------------------------------- /docs/examples/FormInline.js: -------------------------------------------------------------------------------- 1 | const formInstance = ( 2 |
      3 | 4 | Name 5 | {' '} 6 | 7 | 8 | {' '} 9 | 10 | Email 11 | {' '} 12 | 13 | 14 | {' '} 15 | 18 |
      19 | ); 20 | 21 | ReactDOM.render(formInstance, mountNode); 22 | -------------------------------------------------------------------------------- /src/InputGroupAddon.js: -------------------------------------------------------------------------------- 1 | import classNames from 'classnames'; 2 | import React from 'react'; 3 | 4 | import { bsClass, getClassSet, splitBsProps } from './utils/bootstrapUtils'; 5 | 6 | class InputGroupAddon extends React.Component { 7 | render() { 8 | const { className, ...props } = this.props; 9 | const [bsProps, elementProps] = splitBsProps(props); 10 | 11 | const classes = getClassSet(bsProps); 12 | 13 | return ( 14 | 18 | ); 19 | } 20 | } 21 | 22 | export default bsClass('input-group-addon', InputGroupAddon); 23 | -------------------------------------------------------------------------------- /src/InputGroupButton.js: -------------------------------------------------------------------------------- 1 | import classNames from 'classnames'; 2 | import React from 'react'; 3 | 4 | import { bsClass, getClassSet, splitBsProps } from './utils/bootstrapUtils'; 5 | 6 | class InputGroupButton extends React.Component { 7 | render() { 8 | const { className, ...props } = this.props; 9 | const [bsProps, elementProps] = splitBsProps(props); 10 | 11 | const classes = getClassSet(bsProps); 12 | 13 | return ( 14 | 18 | ); 19 | } 20 | } 21 | 22 | export default bsClass('input-group-btn', InputGroupButton); 23 | -------------------------------------------------------------------------------- /tools/amd/README.md: -------------------------------------------------------------------------------- 1 | # react-bootstrap-bower 2 | 3 | [Bootstrap 3](http://getbootstrap.com) components built with [React](http://facebook.github.io/react/) 4 | 5 | This repo contains built AMD modules and standalone browser globals. 6 | 7 | There is a separate [source repo](https://github.com/react-bootstrap/react-bootstrap). 8 | 9 | A [docs site](http://react-bootstrap.github.io) with live editable examples. 10 | 11 | [![Build Status](https://travis-ci.org/react-bootstrap/react-bootstrap.svg)](https://travis-ci.org/react-bootstrap/react-bootstrap) [![Bower version](https://badge.fury.io/bo/react-bootstrap.svg)](http://badge.fury.io/bo/react-bootstrap) 12 | -------------------------------------------------------------------------------- /docs/examples/PanelGroupControlled.js: -------------------------------------------------------------------------------- 1 | const ControlledPanelGroup = React.createClass({ 2 | getInitialState() { 3 | return { 4 | activeKey: '1' 5 | }; 6 | }, 7 | 8 | handleSelect(activeKey) { 9 | this.setState({ activeKey }); 10 | }, 11 | 12 | render() { 13 | return ( 14 | 15 | Panel 1 content 16 | Panel 2 content 17 | 18 | ); 19 | } 20 | }); 21 | 22 | ReactDOM.render(, mountNode); 23 | -------------------------------------------------------------------------------- /src/CloseButton.js: -------------------------------------------------------------------------------- 1 | import * as PropTypes from 'prop-types'; 2 | import React from 'react'; 3 | 4 | const propTypes = { 5 | label: PropTypes.string.isRequired, 6 | onClick: PropTypes.func, 7 | }; 8 | 9 | class CloseButton extends React.Component { 10 | render() { 11 | const { label, onClick } = this.props; 12 | return ( 13 | 21 | ); 22 | } 23 | } 24 | 25 | CloseButton.propTypes = propTypes; 26 | 27 | export default CloseButton; 28 | -------------------------------------------------------------------------------- /src/utils/StyleConfig.js: -------------------------------------------------------------------------------- 1 | export const Size = { 2 | LARGE: 'large', 3 | SMALL: 'small', 4 | XSMALL: 'xsmall', 5 | }; 6 | 7 | export const SIZE_MAP = { 8 | large: 'lg', 9 | medium: 'md', 10 | small: 'sm', 11 | xsmall: 'xs', 12 | lg: 'lg', 13 | md: 'md', 14 | sm: 'sm', 15 | xs: 'xs', 16 | }; 17 | 18 | export const DEVICE_SIZES = [ 19 | 'lg', 20 | 'md', 21 | 'sm', 22 | 'xs', 23 | ]; 24 | 25 | export const State = { 26 | SUCCESS: 'success', 27 | WARNING: 'warning', 28 | DANGER: 'danger', 29 | INFO: 'info', 30 | }; 31 | 32 | export const Style = { 33 | DEFAULT: 'default', 34 | PRIMARY: 'primary', 35 | LINK: 'link', 36 | INVERSE: 'inverse', 37 | }; 38 | -------------------------------------------------------------------------------- /docs/examples/PaginationAdvanced.js: -------------------------------------------------------------------------------- 1 | const PaginationAdvanced = React.createClass({ 2 | getInitialState() { 3 | return { 4 | activePage: 1 5 | }; 6 | }, 7 | 8 | handleSelect(eventKey) { 9 | this.setState({ 10 | activePage: eventKey 11 | }); 12 | }, 13 | 14 | render() { 15 | return ( 16 | 27 | ); 28 | } 29 | }); 30 | 31 | ReactDOM.render(, mountNode); 32 | -------------------------------------------------------------------------------- /docs/examples/TabsControlled.js: -------------------------------------------------------------------------------- 1 | const ControlledTabs = React.createClass({ 2 | getInitialState() { 3 | return { 4 | key: 1 5 | }; 6 | }, 7 | 8 | handleSelect(key) { 9 | alert('selected ' + key); 10 | this.setState({key}); 11 | }, 12 | 13 | render() { 14 | return ( 15 | 16 | Tab 1 content 17 | Tab 2 content 18 | Tab 3 content 19 | 20 | ); 21 | } 22 | }); 23 | 24 | ReactDOM.render(, mountNode); 25 | -------------------------------------------------------------------------------- /src/PageHeader.js: -------------------------------------------------------------------------------- 1 | import classNames from 'classnames'; 2 | import React from 'react'; 3 | 4 | import { bsClass, getClassSet, splitBsProps } from './utils/bootstrapUtils'; 5 | 6 | class PageHeader extends React.Component { 7 | render() { 8 | const { className, children, ...props } = this.props; 9 | const [bsProps, elementProps] = splitBsProps(props); 10 | 11 | const classes = getClassSet(bsProps); 12 | 13 | return ( 14 |
      18 |

      19 | {children} 20 |

      21 |
      22 | ); 23 | } 24 | } 25 | 26 | export default bsClass('page-header', PageHeader); 27 | -------------------------------------------------------------------------------- /src/Well.js: -------------------------------------------------------------------------------- 1 | import classNames from 'classnames'; 2 | import React from 'react'; 3 | 4 | import { bsClass, bsSizes, getClassSet, splitBsProps } 5 | from './utils/bootstrapUtils'; 6 | import { Size } from './utils/StyleConfig'; 7 | 8 | class Well extends React.Component { 9 | render() { 10 | const { className, ...props } = this.props; 11 | const [bsProps, elementProps] = splitBsProps(props); 12 | 13 | const classes = getClassSet(bsProps); 14 | 15 | return ( 16 |
      20 | ); 21 | } 22 | } 23 | 24 | export default bsClass('well', 25 | bsSizes([Size.LARGE, Size.SMALL], Well) 26 | ); 27 | -------------------------------------------------------------------------------- /src/ButtonToolbar.js: -------------------------------------------------------------------------------- 1 | import classNames from 'classnames'; 2 | import React from 'react'; 3 | 4 | import Button from './Button'; 5 | import { bsClass, bsSizes, getClassSet, splitBsProps } 6 | from './utils/bootstrapUtils'; 7 | 8 | class ButtonToolbar extends React.Component { 9 | render() { 10 | const { className, ...props } = this.props; 11 | const [bsProps, elementProps] = splitBsProps(props); 12 | 13 | const classes = getClassSet(bsProps); 14 | 15 | return ( 16 |
      21 | ); 22 | } 23 | } 24 | 25 | export default bsClass('btn-toolbar', 26 | bsSizes(Button.SIZES, ButtonToolbar) 27 | ); 28 | -------------------------------------------------------------------------------- /docs/examples/DropdownButtonBasic.js: -------------------------------------------------------------------------------- 1 | const BUTTONS = ['Default', 'Primary', 'Success', 'Info', 'Warning', 'Danger']; 2 | 3 | function renderDropdownButton(title, i) { 4 | return ( 5 | 6 | Action 7 | Another action 8 | Active Item 9 | 10 | Separated link 11 | 12 | ); 13 | } 14 | 15 | const buttonsInstance = ( 16 | {BUTTONS.map(renderDropdownButton)} 17 | ); 18 | 19 | ReactDOM.render(buttonsInstance, mountNode); 20 | -------------------------------------------------------------------------------- /docs/examples/PanelContextual.js: -------------------------------------------------------------------------------- 1 | const title = ( 2 |

      Panel title

      3 | ); 4 | 5 | const panelsInstance = ( 6 |
      7 | 8 | Panel content 9 | 10 | 11 | 12 | Panel content 13 | 14 | 15 | 16 | Panel content 17 | 18 | 19 | 20 | Panel content 21 | 22 | 23 | 24 | Panel content 25 | 26 | 27 | 28 | Panel content 29 | 30 |
      31 | ); 32 | 33 | ReactDOM.render(panelsInstance, mountNode); 34 | -------------------------------------------------------------------------------- /docs/examples/SplitButtonBasic.js: -------------------------------------------------------------------------------- 1 | const BUTTONS = ['Default', 'Primary', 'Success', 'Info', 'Warning', 'Danger']; 2 | 3 | function renderDropdownButton(title, i) { 4 | return ( 5 | 6 | Action 7 | Another action 8 | Something else here 9 | 10 | Separated link 11 | 12 | ); 13 | } 14 | 15 | const buttonsInstance = ( 16 | {BUTTONS.map(renderDropdownButton)} 17 | ); 18 | 19 | ReactDOM.render(buttonsInstance, mountNode); 20 | -------------------------------------------------------------------------------- /docs/examples/PanelCollapsible.js: -------------------------------------------------------------------------------- 1 | class Example extends React.Component { 2 | constructor(...args) { 3 | super(...args); 4 | this.state = { 5 | open: true 6 | }; 7 | } 8 | 9 | render() { 10 | return ( 11 |
      12 | 15 | 16 | Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 17 | Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. 18 | 19 |
      20 | ); 21 | } 22 | } 23 | 24 | ReactDOM.render(, mountNode); 25 | -------------------------------------------------------------------------------- /docs/examples/MenuItem.js: -------------------------------------------------------------------------------- 1 | function onSelectAlert(eventKey) { 2 | alert(`Alert from menu item.\neventKey: ${eventKey}`); 3 | } 4 | 5 | const MenuItems = ( 6 | 7 |
        8 | Header 9 | link 10 | 11 | Header 12 | link 13 | disabled 14 | 15 | link with title 16 | 17 | 18 | link that alerts 19 | 20 |
      21 |
      22 | ); 23 | 24 | ReactDOM.render(MenuItems, mountNode); 25 | -------------------------------------------------------------------------------- /src/Breadcrumb.js: -------------------------------------------------------------------------------- 1 | import classNames from 'classnames'; 2 | import React from 'react'; 3 | 4 | import BreadcrumbItem from './BreadcrumbItem'; 5 | import { bsClass, getClassSet, splitBsProps } from './utils/bootstrapUtils'; 6 | 7 | class Breadcrumb extends React.Component { 8 | render() { 9 | const { className, ...props } = this.props; 10 | const [bsProps, elementProps] = splitBsProps(props); 11 | 12 | const classes = getClassSet(bsProps); 13 | 14 | return ( 15 |
        21 | ); 22 | } 23 | } 24 | 25 | Breadcrumb.Item = BreadcrumbItem; 26 | 27 | export default bsClass('breadcrumb', Breadcrumb); 28 | -------------------------------------------------------------------------------- /src/NavbarHeader.js: -------------------------------------------------------------------------------- 1 | import classNames from 'classnames'; 2 | import React from 'react'; 3 | import PropTypes from 'prop-types'; 4 | 5 | import { prefix } from './utils/bootstrapUtils'; 6 | 7 | const contextTypes = { 8 | $bs_navbar: PropTypes.shape({ 9 | bsClass: PropTypes.string, 10 | }), 11 | }; 12 | 13 | class NavbarHeader extends React.Component { 14 | render() { 15 | const { className, ...props } = this.props; 16 | const navbarProps = this.context.$bs_navbar || { bsClass: 'navbar' }; 17 | 18 | const bsClassName = prefix(navbarProps, 'header'); 19 | 20 | return ( 21 |
        22 | ); 23 | } 24 | } 25 | 26 | NavbarHeader.contextTypes = contextTypes; 27 | 28 | export default NavbarHeader; 29 | -------------------------------------------------------------------------------- /docs/examples/TableBasic.js: -------------------------------------------------------------------------------- 1 | const tableInstance = ( 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
        #First NameLast NameUsername
        1MarkOtto@mdo
        2JacobThornton@fat
        3Larry the Bird@twitter
        31 | ); 32 | 33 | ReactDOM.render(tableInstance, mountNode); 34 | -------------------------------------------------------------------------------- /docs/src/sections/GlyphiconSection.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Anchor from '../Anchor'; 4 | import PropTable from '../PropTable'; 5 | import ReactPlayground from '../ReactPlayground'; 6 | import Samples from '../Samples'; 7 | 8 | export default function GlyphiconSection() { 9 | return ( 10 |
        11 |

        12 | Glyphicons Glyphicon 13 |

        14 | 15 |

        Use them in buttons, button groups for a toolbar, navigation, or prepended form inputs.

        16 | 17 | 18 |

        Props

        19 | 20 |
        21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /webpack/webpack.config.js: -------------------------------------------------------------------------------- 1 | import baseConfig, { options } from './base.config'; 2 | 3 | export default { 4 | ...baseConfig, 5 | 6 | entry: { 7 | 'react-bootstrap': './src/index.js', 8 | }, 9 | 10 | output: { 11 | path: './dist', 12 | filename: options.optimizeMinimize ? '[name].min.js' : '[name].js', 13 | library: 'ReactBootstrap', 14 | libraryTarget: 'umd', 15 | }, 16 | 17 | externals: [ 18 | { 19 | react: { 20 | root: 'React', 21 | commonjs2: 'react', 22 | commonjs: 'react', 23 | amd: 'react', 24 | }, 25 | }, 26 | { 27 | 'react-dom': { 28 | root: 'ReactDOM', 29 | commonjs2: 'react-dom', 30 | commonjs: 'react-dom', 31 | amd: 'react-dom', 32 | }, 33 | }, 34 | ], 35 | }; 36 | -------------------------------------------------------------------------------- /docs/examples/Fade.js: -------------------------------------------------------------------------------- 1 | 2 | class Example extends React.Component { 3 | 4 | constructor(...args) { 5 | super(...args); 6 | this.state = {}; 7 | } 8 | 9 | render() { 10 | return ( 11 |
        12 | 15 | 16 |
        17 | 18 | Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 19 | Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. 20 | 21 |
        22 |
        23 |
        24 | ); 25 | } 26 | } 27 | 28 | ReactDOM.render(, mountNode); 29 | -------------------------------------------------------------------------------- /docs/examples/Collapse.js: -------------------------------------------------------------------------------- 1 | class Example extends React.Component { 2 | constructor(...args) { 3 | super(...args); 4 | 5 | this.state = {}; 6 | } 7 | 8 | render() { 9 | return ( 10 |
        11 | 14 | 15 |
        16 | 17 | Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 18 | Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. 19 | 20 |
        21 |
        22 |
        23 | ); 24 | } 25 | } 26 | 27 | ReactDOM.render(, mountNode); 28 | -------------------------------------------------------------------------------- /docs/examples/NavbarBasic.js: -------------------------------------------------------------------------------- 1 | const navbarInstance = ( 2 | 3 | 4 | 5 | React-Bootstrap 6 | 7 | 8 | 19 | 20 | ); 21 | 22 | ReactDOM.render(navbarInstance, mountNode); 23 | -------------------------------------------------------------------------------- /docs/src/sections/JumbotronSection.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Anchor from '../Anchor'; 4 | import PropTable from '../PropTable'; 5 | import ReactPlayground from '../ReactPlayground'; 6 | import Samples from '../Samples'; 7 | 8 | export default function JumbotronSection() { 9 | return ( 10 |
        11 |

        12 | Jumbotron Jumbotron 13 |

        14 | 15 |

        A lightweight, flexible component that can optionally extend the entire viewport to showcase key content on your site.

        16 | 17 | 18 |

        Props

        19 | 20 |
        21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /docs/examples/ButtonSizes.js: -------------------------------------------------------------------------------- 1 | const buttonsInstance = ( 2 |
        3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
        20 | ); 21 | 22 | ReactDOM.render(buttonsInstance, mountNode); 23 | -------------------------------------------------------------------------------- /docs/examples/LeftTabs.js: -------------------------------------------------------------------------------- 1 | const tabsInstance = ( 2 | 3 | 4 | 5 | 13 | 14 | 15 | 16 | 17 | Tab 1 content 18 | 19 | 20 | Tab 2 content 21 | 22 | 23 | 24 | 25 | 26 | ); 27 | 28 | ReactDOM.render(tabsInstance, mountNode); 29 | -------------------------------------------------------------------------------- /tools/build.js: -------------------------------------------------------------------------------- 1 | import 'colors'; 2 | import bower from './amd/build'; 3 | import lib from './lib/build'; 4 | import es from './es/build'; 5 | import dist from './dist/build'; 6 | import { copy } from './fs-utils'; 7 | import { distRoot, bowerRoot } from './constants'; 8 | import { exec } from './exec'; 9 | 10 | function forkAndBuildDocs({verbose}) { 11 | console.log('Building: '.cyan + 'docs'.green); 12 | 13 | const verboseOption = verbose ? '--verbose' : ''; 14 | 15 | return exec(`npm run docs-build -- ${verboseOption}`) 16 | .then(() => console.log('Built: '.cyan + 'docs'.green)); 17 | } 18 | 19 | export default function Build(options) { 20 | return Promise.all([ 21 | lib(), 22 | es(), 23 | bower(), 24 | dist(), 25 | forkAndBuildDocs(options) 26 | ]) 27 | .then(() => copy(distRoot, bowerRoot)); 28 | } 29 | -------------------------------------------------------------------------------- /src/utils/createChainedFunction.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Safe chained function 3 | * 4 | * Will only create a new function if needed, 5 | * otherwise will pass back existing functions or null. 6 | * 7 | * @param {function} functions to chain 8 | * @returns {function|null} 9 | */ 10 | function createChainedFunction(...funcs) { 11 | return funcs 12 | .filter(f => f != null) 13 | .reduce((acc, f) => { 14 | if (typeof f !== 'function') { 15 | throw new Error('Invalid Argument Type, must only provide functions, undefined, or null.'); 16 | } 17 | 18 | if (acc === null) { 19 | return f; 20 | } 21 | 22 | return function chainedFunction(...args) { 23 | acc.apply(this, args); 24 | f.apply(this, args); 25 | }; 26 | }, null); 27 | } 28 | 29 | export default createChainedFunction; 30 | -------------------------------------------------------------------------------- /test/PageHeaderSpec.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactTestUtils from 'react-addons-test-utils'; 3 | import ReactDOM from 'react-dom'; 4 | 5 | import PageHeader from '../src/PageHeader'; 6 | 7 | describe('PageHeader', () => { 8 | it('Should output a div with content', () => { 9 | let instance = ReactTestUtils.renderIntoDocument( 10 | 11 | Content 12 | 13 | ); 14 | assert.ok(ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'strong')); 15 | }); 16 | 17 | it('Should have a page-header class', () => { 18 | let instance = ReactTestUtils.renderIntoDocument( 19 | 20 | Content 21 | 22 | ); 23 | assert.ok(ReactDOM.findDOMNode(instance).className.match(/\bpage-header\b/)); 24 | }); 25 | 26 | }); 27 | -------------------------------------------------------------------------------- /docs/examples/ButtonLoading.js: -------------------------------------------------------------------------------- 1 | const LoadingButton = React.createClass({ 2 | getInitialState() { 3 | return { 4 | isLoading: false 5 | }; 6 | }, 7 | 8 | render() { 9 | let isLoading = this.state.isLoading; 10 | return ( 11 | 17 | ); 18 | }, 19 | 20 | handleClick() { 21 | this.setState({isLoading: true}); 22 | 23 | // This probably where you would have an `ajax` call 24 | setTimeout(() => { 25 | // Completed of async action, set loading state back 26 | this.setState({isLoading: false}); 27 | }, 2000); 28 | } 29 | }); 30 | 31 | ReactDOM.render(, mountNode); 32 | -------------------------------------------------------------------------------- /test/ButtonToolbarSpec.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactTestUtils from 'react-addons-test-utils'; 3 | import ReactDOM from 'react-dom'; 4 | 5 | import Button from '../src/Button'; 6 | import ButtonGroup from '../src/ButtonGroup'; 7 | import ButtonToolbar from '../src/ButtonToolbar'; 8 | 9 | describe('ButtonToolbar', () => { 10 | it('Should output a button toolbar', () => { 11 | let instance = ReactTestUtils.renderIntoDocument( 12 | 13 | 14 | 17 | 18 | 19 | ); 20 | let node = ReactDOM.findDOMNode(instance); 21 | assert.equal(node.nodeName, 'DIV'); 22 | assert.ok(node.className.match(/\bbtn-toolbar\b/)); 23 | assert.equal(node.getAttribute('role'), 'toolbar'); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /docs/examples/Glyphicon.js: -------------------------------------------------------------------------------- 1 | const glyphInstance = ( 2 |
        3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
        20 | ); 21 | 22 | ReactDOM.render(glyphInstance, mountNode); 23 | -------------------------------------------------------------------------------- /test/GlyphiconSpec.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactTestUtils from 'react-addons-test-utils'; 3 | import ReactDOM from 'react-dom'; 4 | 5 | import Glyphicon from '../src/Glyphicon'; 6 | 7 | describe('', () => { 8 | it('Should have correct class', () => { 9 | let instance = ReactTestUtils.renderIntoDocument( 10 | 11 | ); 12 | assert.ok(ReactDOM.findDOMNode(instance).className.match(/\bglyphicon\b/)); 13 | assert.ok(ReactDOM.findDOMNode(instance).className.match(/\bglyphicon-star\b/)); 14 | }); 15 | 16 | it('renders without the .form-control-feedback class', () => { 17 | let instance = ReactTestUtils.renderIntoDocument( 18 | 19 | ); 20 | 21 | assert.notOk(ReactDOM.findDOMNode(instance).className.match(/\bform-control-feedback\b/)); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /test/PopoverSpec.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactTestUtils from 'react-addons-test-utils'; 3 | import ReactDOM from 'react-dom'; 4 | 5 | import Popover from '../src/Popover'; 6 | 7 | describe('Popover', () => { 8 | it('Should output a popover title and content', () => { 9 | let instance = ReactTestUtils.renderIntoDocument( 10 | 11 | Popover Content 12 | 13 | ); 14 | 15 | assert.ok(ReactTestUtils.findRenderedDOMComponentWithClass(instance, 'popover-title')); 16 | assert.ok(ReactTestUtils.findRenderedDOMComponentWithClass(instance, 'popover-content')); 17 | 18 | assert.ok(ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'strong')); 19 | 20 | assert.equal(ReactDOM.findDOMNode(instance).style.display, 'block'); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /tools/es/build.js: -------------------------------------------------------------------------------- 1 | import 'colors'; 2 | import { exec } from '../exec'; 3 | import fsp from 'fs-promise'; 4 | import { srcRoot, esRoot } from '../constants'; 5 | import buildBabel from '../buildBabel'; 6 | 7 | export default function BuildES() { 8 | console.log('Building: '.cyan + 'es module'.green); 9 | 10 | return exec(`rimraf ${esRoot}`) 11 | .then(() => fsp.mkdirs(esRoot)) 12 | .then(() => buildBabel(srcRoot, esRoot, { 13 | babelrc: false, 14 | presets: [ 15 | ['es2015', { loose: true, modules: false }], 16 | 'stage-1', 17 | 'react' 18 | ], 19 | plugins: [ 20 | 'dev-expression', 21 | 'transform-runtime', 22 | 'transform-es3-member-expression-literals', 23 | 'transform-es3-property-literals' 24 | ] 25 | })) 26 | .then(() => console.log('Built: '.cyan + 'es module'.green)); 27 | } 28 | -------------------------------------------------------------------------------- /tools/fs-utils.js: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import fsp from 'fs-promise'; 3 | import fse from 'fs-extra'; 4 | 5 | export function copy(src, dest, options) { 6 | options = options || {}; 7 | 8 | return Promise.all([ 9 | fsp.stat(src), 10 | fsp.exists(dest) 11 | .then(exists => { 12 | if (!exists) { 13 | return false; 14 | } 15 | 16 | return fsp.stat(dest); 17 | }) 18 | ]) 19 | .then(([srcStat, destStat]) => { 20 | if (srcStat.isFile() && destStat && destStat.isDirectory()) { 21 | let filename = path.basename(src); 22 | dest = path.join(dest, filename); 23 | } 24 | 25 | return new Promise((resolve, reject) => { 26 | fse.copy(src, dest, options, err => { 27 | if (err) { 28 | reject(err); 29 | } 30 | 31 | resolve(); 32 | }); 33 | }); 34 | }); 35 | } 36 | -------------------------------------------------------------------------------- /docs/src/Routes.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {IndexRoute, Route} from 'react-router'; 3 | 4 | import ComponentsPage from './ComponentsPage'; 5 | import GettingStartedPage from './GettingStartedPage'; 6 | import HomePage from './HomePage'; 7 | import IntroductionPage from './IntroductionPage'; 8 | import NotFoundPage from './NotFoundPage'; 9 | import Root from './Root'; 10 | import SupportPage from './SupportPage'; 11 | 12 | export default ( 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | ); 23 | -------------------------------------------------------------------------------- /docs/src/sections/CustomStylesSection.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Anchor from '../Anchor'; 4 | import ReactPlayground from '../ReactPlayground'; 5 | import Samples from '../Samples'; 6 | 7 | export default function CustomStylesSection() { 8 | return ( 9 |
        10 |

        11 | Custom Styles 12 |

        13 | 14 |

        The bsStyle prop, available in many components in React-Bootstrap, is used to map to a Bootstrap class for styling; for example, the Bootstrap class used for Button is `btn-${'{'}bsStyle{'}'}`. Use bootstrapUtils to create a custom class that is used in lieu of the classes provided by Bootstrap:

        15 | 16 | 17 |
        18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /docs/examples/TooltipPositioned.js: -------------------------------------------------------------------------------- 1 | 2 | const tooltip = ( 3 | Holy guacamole! Check this info. 4 | ); 5 | 6 | const positionerInstance = ( 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | ); 25 | 26 | ReactDOM.render(positionerInstance, mountNode); 27 | -------------------------------------------------------------------------------- /src/Row.js: -------------------------------------------------------------------------------- 1 | import classNames from 'classnames'; 2 | import React from 'react'; 3 | import elementType from 'prop-types-extra/lib/elementType'; 4 | 5 | import { bsClass, getClassSet, splitBsProps } from './utils/bootstrapUtils'; 6 | 7 | const propTypes = { 8 | componentClass: elementType, 9 | }; 10 | 11 | const defaultProps = { 12 | componentClass: 'div', 13 | }; 14 | 15 | class Row extends React.Component { 16 | render() { 17 | const { componentClass: Component, className, ...props } = this.props; 18 | const [bsProps, elementProps] = splitBsProps(props); 19 | 20 | const classes = getClassSet(bsProps); 21 | 22 | return ( 23 | 27 | ); 28 | } 29 | } 30 | 31 | Row.propTypes = propTypes; 32 | Row.defaultProps = defaultProps; 33 | 34 | export default bsClass('row', Row); 35 | -------------------------------------------------------------------------------- /src/NavbarCollapse.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | import Collapse from './Collapse'; 5 | import { prefix } from './utils/bootstrapUtils'; 6 | 7 | const contextTypes = { 8 | $bs_navbar: PropTypes.shape({ 9 | bsClass: PropTypes.string, 10 | expanded: PropTypes.bool, 11 | }), 12 | }; 13 | 14 | class NavbarCollapse extends React.Component { 15 | render() { 16 | const { children, ...props } = this.props; 17 | const navbarProps = this.context.$bs_navbar || { bsClass: 'navbar' }; 18 | 19 | const bsClassName = prefix(navbarProps, 'collapse'); 20 | 21 | return ( 22 | 23 |
        24 | {children} 25 |
        26 |
        27 | ); 28 | } 29 | } 30 | 31 | NavbarCollapse.contextTypes = contextTypes; 32 | 33 | export default NavbarCollapse; 34 | -------------------------------------------------------------------------------- /docs/src/sections/AlertsSection.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Anchor from '../Anchor'; 4 | import PropTable from '../PropTable'; 5 | import ReactPlayground from '../ReactPlayground'; 6 | import Samples from '../Samples'; 7 | 8 | export default function AlertsSection() { 9 | return ( 10 |
        11 |

        12 | Alert messages Alert 13 |

        14 | 15 |

        Basic alert styles.

        16 | 17 | 18 |

        Closeable alerts

        19 |

        just pass in a onDismiss function.

        20 | 21 | 22 |

        Props

        23 | 24 |
        25 | ); 26 | } 27 | -------------------------------------------------------------------------------- /src/InputGroup.js: -------------------------------------------------------------------------------- 1 | import classNames from 'classnames'; 2 | import React from 'react'; 3 | 4 | import InputGroupAddon from './InputGroupAddon'; 5 | import InputGroupButton from './InputGroupButton'; 6 | import { bsClass, bsSizes, getClassSet, splitBsProps } 7 | from './utils/bootstrapUtils'; 8 | import { Size } from './utils/StyleConfig'; 9 | 10 | class InputGroup extends React.Component { 11 | render() { 12 | const { className, ...props } = this.props; 13 | const [bsProps, elementProps] = splitBsProps(props); 14 | 15 | const classes = getClassSet(bsProps); 16 | 17 | return ( 18 | 22 | ); 23 | } 24 | } 25 | 26 | InputGroup.Addon = InputGroupAddon; 27 | InputGroup.Button = InputGroupButton; 28 | 29 | export default bsClass('input-group', 30 | bsSizes([Size.LARGE, Size.SMALL], InputGroup) 31 | ); 32 | -------------------------------------------------------------------------------- /docs/examples/ButtonGroupVertical.js: -------------------------------------------------------------------------------- 1 | const buttonGroupInstance = ( 2 | 3 | 4 | 5 | 6 | Dropdown link 7 | Dropdown link 8 | 9 | 10 | 11 | 12 | Dropdown link 13 | Dropdown link 14 | 15 | 16 | Dropdown link 17 | Dropdown link 18 | 19 | 20 | ); 21 | 22 | ReactDOM.render(buttonGroupInstance, mountNode); 23 | -------------------------------------------------------------------------------- /webpack/base.config.js: -------------------------------------------------------------------------------- 1 | import webpack from 'webpack'; 2 | import yargs from 'yargs'; 3 | 4 | export const options = yargs 5 | .alias('p', 'optimize-minimize') 6 | .alias('d', 'debug') 7 | .option('port', { 8 | default: '8080', 9 | type: 'string' 10 | }) 11 | .argv; 12 | 13 | export const jsLoader = 'babel?cacheDirectory'; 14 | 15 | const baseConfig = { 16 | entry: undefined, 17 | 18 | output: undefined, 19 | 20 | externals: undefined, 21 | 22 | module: { 23 | loaders: [ 24 | { test: /\.js/, loader: jsLoader, exclude: /node_modules/ } 25 | ] 26 | }, 27 | 28 | plugins: [ 29 | new webpack.DefinePlugin({ 30 | 'process.env': { 31 | NODE_ENV: JSON.stringify(options.optimizeMinimize ? 'production' : 'development') 32 | } 33 | }) 34 | ] 35 | }; 36 | 37 | if (options.optimizeMinimize) { 38 | baseConfig.devtool = 'source-map'; 39 | } 40 | 41 | export default baseConfig; 42 | -------------------------------------------------------------------------------- /src/Jumbotron.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classNames from 'classnames'; 3 | import elementType from 'prop-types-extra/lib/elementType'; 4 | 5 | import { bsClass, getClassSet, splitBsProps } from './utils/bootstrapUtils'; 6 | 7 | const propTypes = { 8 | componentClass: elementType, 9 | }; 10 | 11 | const defaultProps = { 12 | componentClass: 'div', 13 | }; 14 | 15 | class Jumbotron extends React.Component { 16 | render() { 17 | const { componentClass: Component, className, ...props } = this.props; 18 | const [bsProps, elementProps] = splitBsProps(props); 19 | 20 | const classes = getClassSet(bsProps); 21 | 22 | return ( 23 | 27 | ); 28 | } 29 | } 30 | 31 | Jumbotron.propTypes = propTypes; 32 | Jumbotron.defaultProps = defaultProps; 33 | 34 | export default bsClass('jumbotron', Jumbotron); 35 | -------------------------------------------------------------------------------- /src/MediaBody.js: -------------------------------------------------------------------------------- 1 | import classNames from 'classnames'; 2 | import React from 'react'; 3 | import elementType from 'prop-types-extra/lib/elementType'; 4 | 5 | import { bsClass, getClassSet, splitBsProps } from './utils/bootstrapUtils'; 6 | 7 | const propTypes = { 8 | componentClass: elementType, 9 | }; 10 | 11 | const defaultProps = { 12 | componentClass: 'div', 13 | }; 14 | 15 | class MediaBody extends React.Component { 16 | render() { 17 | const { componentClass: Component, className, ...props } = this.props; 18 | const [bsProps, elementProps] = splitBsProps(props); 19 | 20 | const classes = getClassSet(bsProps); 21 | 22 | return ( 23 | 27 | ); 28 | } 29 | } 30 | 31 | MediaBody.propTypes = propTypes; 32 | MediaBody.defaultProps = defaultProps; 33 | 34 | export default bsClass('media-body', MediaBody); 35 | -------------------------------------------------------------------------------- /src/ModalBody.js: -------------------------------------------------------------------------------- 1 | import classNames from 'classnames'; 2 | import React from 'react'; 3 | import elementType from 'prop-types-extra/lib/elementType'; 4 | 5 | import { bsClass, getClassSet, splitBsProps } from './utils/bootstrapUtils'; 6 | 7 | const propTypes = { 8 | componentClass: elementType, 9 | }; 10 | 11 | const defaultProps = { 12 | componentClass: 'div', 13 | }; 14 | 15 | class ModalBody extends React.Component { 16 | render() { 17 | const { componentClass: Component, className, ...props } = this.props; 18 | const [bsProps, elementProps] = splitBsProps(props); 19 | 20 | const classes = getClassSet(bsProps); 21 | 22 | return ( 23 | 27 | ); 28 | } 29 | } 30 | 31 | ModalBody.propTypes = propTypes; 32 | ModalBody.defaultProps = defaultProps; 33 | 34 | export default bsClass('modal-body', ModalBody); 35 | -------------------------------------------------------------------------------- /src/ModalTitle.js: -------------------------------------------------------------------------------- 1 | import classNames from 'classnames'; 2 | import React from 'react'; 3 | import elementType from 'prop-types-extra/lib/elementType'; 4 | 5 | import { bsClass, getClassSet, splitBsProps } from './utils/bootstrapUtils'; 6 | 7 | const propTypes = { 8 | componentClass: elementType, 9 | }; 10 | 11 | const defaultProps = { 12 | componentClass: 'h4', 13 | }; 14 | 15 | class ModalTitle extends React.Component { 16 | render() { 17 | const { componentClass: Component, className, ...props } = this.props; 18 | const [bsProps, elementProps] = splitBsProps(props); 19 | 20 | const classes = getClassSet(bsProps); 21 | 22 | return ( 23 | 27 | ); 28 | } 29 | } 30 | 31 | ModalTitle.propTypes = propTypes; 32 | ModalTitle.defaultProps = defaultProps; 33 | 34 | export default bsClass('modal-title', ModalTitle); 35 | -------------------------------------------------------------------------------- /docs/src/sections/PageHeaderSection.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Anchor from '../Anchor'; 4 | import PropTable from '../PropTable'; 5 | import ReactPlayground from '../ReactPlayground'; 6 | import Samples from '../Samples'; 7 | 8 | export default function PageHeaderSection() { 9 | return ( 10 |
        11 |

        12 | Page header PageHeader 13 |

        14 | 15 |

        A simple shell for an h1 to appropriately space out and segment sections of content on a page. It can utilize the h1’s default small element, as well as most other components (with additional styles).

        16 | 17 | 18 |

        Props

        19 | 20 |
        21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /src/ModalFooter.js: -------------------------------------------------------------------------------- 1 | import classNames from 'classnames'; 2 | import React from 'react'; 3 | import elementType from 'prop-types-extra/lib/elementType'; 4 | 5 | import { bsClass, getClassSet, splitBsProps } from './utils/bootstrapUtils'; 6 | 7 | const propTypes = { 8 | componentClass: elementType, 9 | }; 10 | 11 | const defaultProps = { 12 | componentClass: 'div', 13 | }; 14 | 15 | class ModalFooter extends React.Component { 16 | render() { 17 | const { componentClass: Component, className, ...props } = this.props; 18 | const [bsProps, elementProps] = splitBsProps(props); 19 | 20 | const classes = getClassSet(bsProps); 21 | 22 | return ( 23 | 27 | ); 28 | } 29 | } 30 | 31 | ModalFooter.propTypes = propTypes; 32 | ModalFooter.defaultProps = defaultProps; 33 | 34 | export default bsClass('modal-footer', ModalFooter); 35 | -------------------------------------------------------------------------------- /src/MediaHeading.js: -------------------------------------------------------------------------------- 1 | import classNames from 'classnames'; 2 | import React from 'react'; 3 | import elementType from 'prop-types-extra/lib/elementType'; 4 | 5 | import { bsClass, getClassSet, splitBsProps } from './utils/bootstrapUtils'; 6 | 7 | const propTypes = { 8 | componentClass: elementType, 9 | }; 10 | 11 | const defaultProps = { 12 | componentClass: 'h4', 13 | }; 14 | 15 | class MediaHeading extends React.Component { 16 | render() { 17 | const { componentClass: Component, className, ...props } = this.props; 18 | const [bsProps, elementProps] = splitBsProps(props); 19 | 20 | const classes = getClassSet(bsProps); 21 | 22 | return ( 23 | 27 | ); 28 | } 29 | } 30 | 31 | MediaHeading.propTypes = propTypes; 32 | MediaHeading.defaultProps = defaultProps; 33 | 34 | export default bsClass('media-heading', MediaHeading); 35 | -------------------------------------------------------------------------------- /docs/src/sections/WellSection.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Anchor from '../Anchor'; 4 | import PropTable from '../PropTable'; 5 | import ReactPlayground from '../ReactPlayground'; 6 | import Samples from '../Samples'; 7 | 8 | export default function WellSection() { 9 | return ( 10 |
        11 |

        12 | Wells Well 13 |

        14 | 15 |

        Use the well as a simple effect on an element to give it an inset effect.

        16 | 17 | 18 |

        Optional classes

        19 |

        Control padding and rounded corners with two optional modifier classes.

        20 | 21 | 22 |

        Props

        23 | 24 |
        25 | ); 26 | } 27 | -------------------------------------------------------------------------------- /src/CarouselCaption.js: -------------------------------------------------------------------------------- 1 | import classNames from 'classnames'; 2 | import React from 'react'; 3 | import elementType from 'prop-types-extra/lib/elementType'; 4 | 5 | import { bsClass, getClassSet, splitBsProps } from './utils/bootstrapUtils'; 6 | 7 | const propTypes = { 8 | componentClass: elementType, 9 | }; 10 | 11 | const defaultProps = { 12 | componentClass: 'div', 13 | }; 14 | 15 | class CarouselCaption extends React.Component { 16 | render() { 17 | const { componentClass: Component, className, ...props } = this.props; 18 | const [bsProps, elementProps] = splitBsProps(props); 19 | 20 | const classes = getClassSet(bsProps); 21 | 22 | return ( 23 | 27 | ); 28 | } 29 | } 30 | 31 | CarouselCaption.propTypes = propTypes; 32 | CarouselCaption.defaultProps = defaultProps; 33 | 34 | export default bsClass('carousel-caption', CarouselCaption); 35 | -------------------------------------------------------------------------------- /docs/examples/NavJustified.js: -------------------------------------------------------------------------------- 1 | const NavJustified = React.createClass({ 2 | handleSelect(selectedKey) { 3 | alert('selected ' + selectedKey); 4 | }, 5 | 6 | render() { 7 | return ( 8 |
        9 | 14 |
        15 | 20 |
        21 | ); 22 | } 23 | }); 24 | 25 | ReactDOM.render(, mountNode); 26 | -------------------------------------------------------------------------------- /docs/examples/PopoverContained.js: -------------------------------------------------------------------------------- 1 | class Example extends React.Component { 2 | constructor(props, context) { 3 | super(props, context); 4 | 5 | this.handleClick = e => { 6 | this.setState({ target: e.target, show: !this.state.show }); 7 | }; 8 | 9 | this.state = { show: false }; 10 | } 11 | 12 | render() { 13 | return ( 14 | 15 | 18 | 19 | 26 | 27 | Holy guacamole! Check this info. 28 | 29 | 30 | 31 | ); 32 | } 33 | } 34 | 35 | ReactDOM.render(, mountNode); 36 | -------------------------------------------------------------------------------- /src/Tab.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | import TabContainer from './TabContainer'; 5 | import TabContent from './TabContent'; 6 | import TabPane from './TabPane'; 7 | 8 | const propTypes = { 9 | ...TabPane.propTypes, 10 | 11 | disabled: PropTypes.bool, 12 | 13 | title: PropTypes.node, 14 | 15 | /** 16 | * tabClassName is used as className for the associated NavItem 17 | */ 18 | tabClassName: PropTypes.string 19 | }; 20 | 21 | class Tab extends React.Component { 22 | render() { 23 | const props = { ...this.props }; 24 | 25 | // These props are for the parent `` rather than the ``. 26 | delete props.title; 27 | delete props.disabled; 28 | delete props.tabClassName; 29 | 30 | return ; 31 | } 32 | } 33 | 34 | Tab.propTypes = propTypes; 35 | 36 | Tab.Container = TabContainer; 37 | Tab.Content = TabContent; 38 | Tab.Pane = TabPane; 39 | 40 | export default Tab; 41 | -------------------------------------------------------------------------------- /src/FormControlStatic.js: -------------------------------------------------------------------------------- 1 | import classNames from 'classnames'; 2 | import React from 'react'; 3 | import elementType from 'prop-types-extra/lib/elementType'; 4 | 5 | import { bsClass, getClassSet, splitBsProps } from './utils/bootstrapUtils'; 6 | 7 | const propTypes = { 8 | componentClass: elementType, 9 | }; 10 | 11 | const defaultProps = { 12 | componentClass: 'p', 13 | }; 14 | 15 | class FormControlStatic extends React.Component { 16 | render() { 17 | const { componentClass: Component, className, ...props } = this.props; 18 | const [bsProps, elementProps] = splitBsProps(props); 19 | 20 | const classes = getClassSet(bsProps); 21 | 22 | return ( 23 | 27 | ); 28 | } 29 | } 30 | 31 | FormControlStatic.propTypes = propTypes; 32 | FormControlStatic.defaultProps = defaultProps; 33 | 34 | export default bsClass('form-control-static', FormControlStatic); 35 | -------------------------------------------------------------------------------- /docs/src/sections/LabelSection.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Anchor from '../Anchor'; 4 | import PropTable from '../PropTable'; 5 | import ReactPlayground from '../ReactPlayground'; 6 | import Samples from '../Samples'; 7 | 8 | export default function LabelSection() { 9 | return ( 10 |
        11 |

        12 | Labels Label 13 |

        14 | 15 |

        Create a {""} to highlight information

        16 | 17 | 18 |

        Available variations

        19 |

        Add any of the below mentioned modifier classes to change the appearance of a label.

        20 | 21 | 22 |

        Props

        23 | 24 |
        25 | ); 26 | } 27 | -------------------------------------------------------------------------------- /src/Glyphicon.js: -------------------------------------------------------------------------------- 1 | import classNames from 'classnames'; 2 | import React from 'react'; 3 | import PropTypes from 'prop-types'; 4 | 5 | import { bsClass, getClassSet, prefix, splitBsProps } 6 | from './utils/bootstrapUtils'; 7 | 8 | const propTypes = { 9 | /** 10 | * An icon name without "glyphicon-" prefix. See e.g. http://getbootstrap.com/components/#glyphicons 11 | */ 12 | glyph: PropTypes.string.isRequired, 13 | }; 14 | 15 | class Glyphicon extends React.Component { 16 | render() { 17 | const { glyph, className, ...props } = this.props; 18 | const [bsProps, elementProps] = splitBsProps(props); 19 | 20 | const classes = { 21 | ...getClassSet(bsProps), 22 | [prefix(bsProps, glyph)]: true, 23 | }; 24 | 25 | return ( 26 | 30 | ); 31 | } 32 | } 33 | 34 | Glyphicon.propTypes = propTypes; 35 | 36 | export default bsClass('glyphicon', Glyphicon); 37 | -------------------------------------------------------------------------------- /docs/examples/ButtonTypes.js: -------------------------------------------------------------------------------- 1 | const buttonsInstance = ( 2 | 3 | {/* Standard button */} 4 | 5 | 6 | {/* Provides extra visual weight and identifies the primary action in a set of buttons */} 7 | 8 | 9 | {/* Indicates a successful or positive action */} 10 | 11 | 12 | {/* Contextual button for informational alert messages */} 13 | 14 | 15 | {/* Indicates caution should be taken with this action */} 16 | 17 | 18 | {/* Indicates a dangerous or potentially negative action */} 19 | 20 | 21 | {/* Deemphasize a button by making it look like a link while maintaining button behavior */} 22 | 23 | 24 | ); 25 | 26 | ReactDOM.render(buttonsInstance, mountNode); 27 | -------------------------------------------------------------------------------- /docs/src/sections/BadgeSection.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Anchor from '../Anchor'; 4 | import PropTable from '../PropTable'; 5 | import ReactPlayground from '../ReactPlayground'; 6 | import Samples from '../Samples'; 7 | 8 | export default function BadgeSection() { 9 | return ( 10 |
        11 |

        12 | Badges Badge 13 |

        14 | 15 |

        Easily highlight new or unread items by adding a {""} to links, Bootstrap navs, and more.

        16 | 17 |
        18 |

        Cross-browser compatibility

        19 |

        Unlike in regular Bootstrap, badges self collapse even in Internet Explorer 8.

        20 |
        21 | 22 |

        Props

        23 | 24 |
        25 | ); 26 | } 27 | -------------------------------------------------------------------------------- /docs/examples/NavDropdown.js: -------------------------------------------------------------------------------- 1 | const NavDropdownExample = React.createClass({ 2 | handleSelect(eventKey) { 3 | event.preventDefault(); 4 | alert(`selected ${eventKey}`); 5 | }, 6 | 7 | render() { 8 | return ( 9 | 21 | ); 22 | } 23 | }); 24 | 25 | ReactDOM.render(, mountNode); 26 | -------------------------------------------------------------------------------- /docs/examples/PaginationBasic.js: -------------------------------------------------------------------------------- 1 | const PaginationBasic = React.createClass({ 2 | getInitialState() { 3 | return { 4 | activePage: 1 5 | }; 6 | }, 7 | 8 | handleSelect(eventKey) { 9 | this.setState({ 10 | activePage: eventKey 11 | }); 12 | }, 13 | 14 | render() { 15 | return ( 16 |
        17 | 22 |
        23 | 24 | 29 |
        30 | 31 | 36 |
        37 | ); 38 | } 39 | }); 40 | 41 | ReactDOM.render(, mountNode); 42 | -------------------------------------------------------------------------------- /docs/examples/GridBasic.js: -------------------------------------------------------------------------------- 1 | const gridInstance = ( 2 | 3 | 4 | <{'Col xs={12} md={8}'} /> 5 | <{'Col xs={6} md={4}'} /> 6 | 7 | 8 | 9 | <{'Col xs={6} md={4}'} /> 10 | <{'Col xs={6} md={4}'} /> 11 | <{'Col xsHidden md={4}'} /> 12 | 13 | 14 | 15 | <{'Col xs={6} xsOffset={6}'} /> 16 | 17 | 18 | 19 | <{'Col md={6} mdPush={6}'} /> 20 | <{'Col md={6} mdPull={6}'} /> 21 | 22 | 23 | ); 24 | 25 | ReactDOM.render(gridInstance, mountNode); 26 | -------------------------------------------------------------------------------- /docs/examples/FormHorizontal.js: -------------------------------------------------------------------------------- 1 | const formInstance = ( 2 |
        3 | 4 | 5 | Email 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | Password 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Remember me 24 | 25 | 26 | 27 | 28 | 29 | 32 | 33 | 34 |
        35 | ); 36 | 37 | ReactDOM.render(formInstance, mountNode); 38 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["eslint-config-airbnb"], 3 | "env": { 4 | "browser": true, 5 | "node": true 6 | }, 7 | "ecmaFeatures": { 8 | "jsx": true 9 | }, 10 | "parser": "babel-eslint", 11 | "plugins": [ 12 | "react", 13 | "babel" 14 | ], 15 | "rules": { 16 | "constructor-super": 2, 17 | "comma-dangle": 0, 18 | "eqeqeq": [2, "allow-null"], 19 | "id-length": 0, 20 | "indent": [2, 2, { "SwitchCase": 1, "VariableDeclarator": 1 }], 21 | "no-eq-null": 0, 22 | "one-var": [2, { "initialized": "never" }], 23 | "prefer-const": 0, 24 | "no-param-reassign": 0, 25 | "no-this-before-super": 2, 26 | "babel/object-shorthand": 2, 27 | "react/jsx-boolean-value": 2, 28 | "react/jsx-no-duplicate-props": 2, 29 | "react/sort-comp": 0, 30 | "react/prop-types": [2, { "ignore": [ 31 | "children", 32 | "className", 33 | "style", 34 | "bsStyle", 35 | "bsClass", 36 | "bsSize" 37 | ] 38 | }] 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /docs/examples/ButtonGroupSizes.js: -------------------------------------------------------------------------------- 1 | const buttonGroupInstance = ( 2 |
        3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 |
        35 | ); 36 | 37 | ReactDOM.render(buttonGroupInstance, mountNode); 38 | -------------------------------------------------------------------------------- /docs/examples/SplitButtonDropup.js: -------------------------------------------------------------------------------- 1 | const buttonsInstance = ( 2 |
        3 | 4 | 5 | Action 6 | Another action 7 | Something else here 8 | 9 | Separated link 10 | 11 | 12 | 13 | 14 | 15 | Action 16 | Another action 17 | Something else here 18 | 19 | Separated link 20 | 21 | 22 |
        23 | ); 24 | 25 | ReactDOM.render(buttonsInstance, mountNode); 26 | -------------------------------------------------------------------------------- /src/utils/deprecationWarning.js: -------------------------------------------------------------------------------- 1 | import warning from 'warning'; 2 | 3 | let warned = {}; 4 | 5 | function deprecationWarning(oldname, newname, link) { 6 | let message; 7 | 8 | if (typeof oldname === 'object') { 9 | message = oldname.message; 10 | } else { 11 | message = `${oldname} is deprecated. Use ${newname} instead.`; 12 | 13 | if (link) { 14 | message += `\nYou can read more about it at ${link}`; 15 | } 16 | } 17 | 18 | if (warned[message]) { 19 | return; 20 | } 21 | 22 | warning(false, message); 23 | warned[message] = true; 24 | } 25 | 26 | 27 | deprecationWarning.wrapper = (Component, ...args) => { 28 | return class DeprecatedComponent extends Component { 29 | componentWillMount(...methodArgs) { 30 | deprecationWarning(...args); 31 | 32 | if (super.componentWillMount) { 33 | super.componentWillMount(...methodArgs); 34 | } 35 | } 36 | }; 37 | }; 38 | 39 | export default deprecationWarning; 40 | 41 | export function _resetWarned() { 42 | warned = {}; 43 | } 44 | -------------------------------------------------------------------------------- /tools/build-cli.js: -------------------------------------------------------------------------------- 1 | /* eslint no-process-exit: 0 */ 2 | 3 | import 'colors'; 4 | import build from './build'; 5 | import docs from '../docs/build'; 6 | import { setExecOptions } from './exec'; 7 | 8 | import yargs from 'yargs'; 9 | 10 | const argv = yargs 11 | .help('h') 12 | .option('docs-only', { 13 | demand: false, 14 | default: false 15 | }) 16 | .option('verbose', { 17 | demand: false, 18 | default: false, 19 | describe: 'Increased debug output' 20 | }) 21 | .option('dev', { 22 | demand: false, 23 | default: false, 24 | describe: 'Only used when supplied with the --docs-only flag' 25 | }) 26 | .argv; 27 | 28 | setExecOptions(argv); 29 | 30 | let buildProcess; 31 | 32 | if (argv.docsOnly) { 33 | buildProcess = docs(argv); 34 | } else { 35 | buildProcess = build(argv); 36 | } 37 | 38 | buildProcess 39 | .catch(err => { 40 | if (err.stack) { 41 | console.error(err.stack.red); 42 | } else { 43 | console.error(err.toString().red); 44 | } 45 | process.exit(1); 46 | }); 47 | -------------------------------------------------------------------------------- /test/WellSpec.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactTestUtils from 'react-addons-test-utils'; 3 | import ReactDOM from 'react-dom'; 4 | 5 | import Well from '../src/Well'; 6 | 7 | describe('Well', () => { 8 | it('Should output a well with content', () => { 9 | let instance = ReactTestUtils.renderIntoDocument( 10 | 11 | Content 12 | 13 | ); 14 | assert.ok(ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'strong')); 15 | }); 16 | 17 | it('Should have a well class', () => { 18 | let instance = ReactTestUtils.renderIntoDocument( 19 | 20 | Content 21 | 22 | ); 23 | assert.ok(ReactDOM.findDOMNode(instance).className.match(/\bwell\b/)); 24 | }); 25 | 26 | it('Should accept bsSize arguments', () => { 27 | let instance = ReactTestUtils.renderIntoDocument( 28 | 29 | Content 30 | 31 | ); 32 | assert.ok(ReactDOM.findDOMNode(instance).className.match(/\bwell-sm\b/)); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /src/NavbarBrand.js: -------------------------------------------------------------------------------- 1 | import classNames from 'classnames'; 2 | import React from 'react'; 3 | import PropTypes from 'prop-types'; 4 | 5 | import { prefix } from './utils/bootstrapUtils'; 6 | 7 | const contextTypes = { 8 | $bs_navbar: PropTypes.shape({ 9 | bsClass: PropTypes.string, 10 | }), 11 | }; 12 | 13 | class NavbarBrand extends React.Component { 14 | render() { 15 | const { className, children, ...props } = this.props; 16 | const navbarProps = this.context.$bs_navbar || { bsClass: 'navbar' }; 17 | 18 | const bsClassName = prefix(navbarProps, 'brand'); 19 | 20 | if (React.isValidElement(children)) { 21 | return React.cloneElement(children, { 22 | className: classNames( 23 | children.props.className, className, bsClassName 24 | ) 25 | }); 26 | } 27 | 28 | return ( 29 | 30 | {children} 31 | 32 | ); 33 | } 34 | } 35 | 36 | NavbarBrand.contextTypes = contextTypes; 37 | 38 | export default NavbarBrand; 39 | -------------------------------------------------------------------------------- /docs/client.js: -------------------------------------------------------------------------------- 1 | import CodeMirror from 'codemirror'; 2 | import 'codemirror/addon/runmode/runmode'; 3 | import 'codemirror/mode/jsx/jsx'; 4 | 5 | import React from 'react'; 6 | import ReactDOM from 'react-dom'; 7 | import {Router, browserHistory} from 'react-router'; 8 | 9 | import Root from './src/Root'; 10 | import routes from './src/Routes'; 11 | 12 | import 'bootstrap/less/bootstrap.less'; 13 | 14 | import './assets/docs.css'; 15 | import './assets/style.css'; 16 | 17 | import 'codemirror/lib/codemirror.css'; 18 | import 'codemirror/theme/solarized.css'; 19 | import './assets/CodeMirror.css'; 20 | 21 | import './assets/carousel.png'; 22 | import './assets/logo.png'; 23 | import './assets/favicon.ico'; 24 | import './assets/thumbnail.png'; 25 | import './assets/thumbnaildiv.png'; 26 | import './assets/TheresaKnott_castle.svg'; 27 | 28 | global.CodeMirror = CodeMirror; 29 | 30 | Root.assetBaseUrl = window.ASSET_BASE_URL; 31 | Root.propData = window.PROP_DATA; 32 | 33 | ReactDOM.render( 34 | , 35 | document 36 | ); 37 | -------------------------------------------------------------------------------- /docs/src/sections/ImageSection.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Anchor from '../Anchor'; 4 | import PropTable from '../PropTable'; 5 | import ReactPlayground from '../ReactPlayground'; 6 | import Samples from '../Samples'; 7 | 8 | export default function ImageSection() { 9 | return ( 10 |
        11 |

        12 | Images Image 13 |

        14 | 15 |

        Shape

        16 |

        Use the rounded, circle and thumbnail props to customise the image.

        17 | 18 | 19 |

        Responsive

        20 |

        Use the responsive to scale image nicely to the parent element.

        21 | 22 | 23 |

        Props

        24 | 25 |
        26 | ); 27 | } 28 | -------------------------------------------------------------------------------- /docs/examples/CarouselUncontrolled.js: -------------------------------------------------------------------------------- 1 | const carouselInstance = ( 2 | 3 | 4 | 900x500 5 | 6 |

        First slide label

        7 |

        Nulla vitae elit libero, a pharetra augue mollis interdum.

        8 |
        9 |
        10 | 11 | 900x500 12 | 13 |

        Second slide label

        14 |

        Lorem ipsum dolor sit amet, consectetur adipiscing elit.

        15 |
        16 |
        17 | 18 | 900x500 19 | 20 |

        Third slide label

        21 |

        Praesent commodo cursus magna, vel scelerisque nisl consectetur.

        22 |
        23 |
        24 |
        25 | ); 26 | 27 | ReactDOM.render(carouselInstance, mountNode); 28 | -------------------------------------------------------------------------------- /test/FormSpec.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import $ from 'teaspoon'; 3 | 4 | import Form from '../src/Form'; 5 | import FormGroup from '../src/FormGroup'; 6 | 7 | describe('
        ', () => { 8 | it('should support horizontal', () => { 9 | $( 10 | 11 | 12 | 13 | ) 14 | .shallowRender() 15 | .single('form.form-horizontal.my-form') 16 | .single(FormGroup); 17 | }); 18 | 19 | it('should support inline', () => { 20 | $( 21 |
        22 | 23 | 24 | ) 25 | .shallowRender() 26 | .single('form.form-inline.my-form') 27 | .single(FormGroup); 28 | }); 29 | 30 | it('should support custom componentClass', () => { 31 | $( 32 |
        33 | 34 | 35 | ) 36 | .shallowRender() 37 | .single('fieldset.form-horizontal.my-form') 38 | .single(FormGroup); 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /test/NavbarBrandSpec.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactTestUtils from 'react-addons-test-utils'; 3 | import ReactDOM from 'react-dom'; 4 | 5 | import NavbarBrand from '../src/NavbarBrand'; 6 | 7 | describe('', () => { 8 | 9 | it('Should create NavbarBrand SPAN element', () => { 10 | const instance = ReactTestUtils.renderIntoDocument( 11 | Brand 12 | ); 13 | 14 | const brand = ReactDOM.findDOMNode(instance); 15 | 16 | assert.equal(brand.nodeName, 'SPAN'); 17 | assert.ok(brand.className.match(/\bnavbar-brand\b/)); 18 | assert.equal(brand.textContent, 'Brand'); 19 | }); 20 | 21 | it('Should create NavbarBrand A (link) element', () => { 22 | const instance = ReactTestUtils.renderIntoDocument( 23 | BrandLink 24 | ); 25 | 26 | const brand = ReactDOM.findDOMNode(instance); 27 | 28 | assert.equal(brand.nodeName, 'A'); 29 | assert.ok(brand.className.match(/\bnavbar-brand\b/)); 30 | assert.equal(brand.textContent, 'BrandLink'); 31 | }); 32 | 33 | }); 34 | -------------------------------------------------------------------------------- /docs/examples/NavbarCollapsible.js: -------------------------------------------------------------------------------- 1 | const navbarInstance = ( 2 | 3 | 4 | 5 | React-Bootstrap 6 | 7 | 8 | 9 | 10 | 21 | 25 | 26 | 27 | ); 28 | 29 | ReactDOM.render(navbarInstance, mountNode); 30 | -------------------------------------------------------------------------------- /src/MediaLeft.js: -------------------------------------------------------------------------------- 1 | import classNames from 'classnames'; 2 | import React from 'react'; 3 | import PropTypes from 'prop-types'; 4 | 5 | import Media from './Media'; 6 | import { bsClass, getClassSet, prefix, splitBsProps } 7 | from './utils/bootstrapUtils'; 8 | 9 | const propTypes = { 10 | /** 11 | * Align the media to the top, middle, or bottom of the media object. 12 | */ 13 | align: PropTypes.oneOf(['top', 'middle', 'bottom']), 14 | }; 15 | 16 | class MediaLeft extends React.Component { 17 | render() { 18 | const { align, className, ...props } = this.props; 19 | const [bsProps, elementProps] = splitBsProps(props); 20 | 21 | const classes = getClassSet(bsProps); 22 | 23 | if (align) { 24 | // The class is e.g. `media-top`, not `media-left-top`. 25 | classes[prefix(Media.defaultProps, align)] = true; 26 | } 27 | 28 | return ( 29 |
        33 | ); 34 | } 35 | } 36 | 37 | MediaLeft.propTypes = propTypes; 38 | 39 | export default bsClass('media-left', MediaLeft); 40 | -------------------------------------------------------------------------------- /test/FormControlStaticSpec.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import $ from 'teaspoon'; 3 | 4 | import FormControl from '../src/FormControl'; 5 | 6 | describe('', () => { 7 | it('should render correctly', () => { 8 | expect( 9 | $( 10 | 11 | Static text 12 | 13 | ) 14 | .shallowRender() 15 | .single('.form-control-static.my-form-control-static') 16 | .text() 17 | ).to.equal('Static text'); 18 | }); 19 | 20 | it('should support custom componentClass', () => { 21 | function MyComponent({ children, ...props }) { 22 | return ( 23 |
        {children}
        24 | ); 25 | } 26 | 27 | expect( 28 | $( 29 | 30 | Static text 31 | 32 | ) 33 | .shallowRender() 34 | .single($.s`${MyComponent}.form-control-static`) 35 | .text() 36 | ).to.equal('Static text'); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /src/MediaRight.js: -------------------------------------------------------------------------------- 1 | import classNames from 'classnames'; 2 | import React from 'react'; 3 | import PropTypes from 'prop-types'; 4 | 5 | import Media from './Media'; 6 | import { bsClass, getClassSet, prefix, splitBsProps } 7 | from './utils/bootstrapUtils'; 8 | 9 | const propTypes = { 10 | /** 11 | * Align the media to the top, middle, or bottom of the media object. 12 | */ 13 | align: PropTypes.oneOf(['top', 'middle', 'bottom']), 14 | }; 15 | 16 | class MediaRight extends React.Component { 17 | render() { 18 | const { align, className, ...props } = this.props; 19 | const [bsProps, elementProps] = splitBsProps(props); 20 | 21 | const classes = getClassSet(bsProps); 22 | 23 | if (align) { 24 | // The class is e.g. `media-top`, not `media-right-top`. 25 | classes[prefix(Media.defaultProps, align)] = true; 26 | } 27 | 28 | return ( 29 |
        33 | ); 34 | } 35 | } 36 | 37 | MediaRight.propTypes = propTypes; 38 | 39 | export default bsClass('media-right', MediaRight); 40 | -------------------------------------------------------------------------------- /docs/examples/GridWithoutClearfix.js: -------------------------------------------------------------------------------- 1 | const dummySentences = ['Lorem ipsum dolor sit amet, consectetuer adipiscing elit.', 'Donec hendrerit tempor tellus.', 'Donec pretium posuere tellus.', 'Proin quam nisl, tincidunt et, mattis eget, convallis nec, purus.', 'Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.', 'Nulla posuere.', 'Donec vitae dolor.', 'Nullam tristique diam non turpis.', 'Cras placerat accumsan nulla.', 'Nullam rutrum.', 'Nam vestibulum accumsan nisl.']; 2 | 3 | const gridInstance = ( 4 | 5 | 6 | <{'Col sm={6} md={3}'} />
        {dummySentences.slice(0, 6).join(' ')} 7 | <{'Col sm={6} md={3}'} />
        {dummySentences.slice(0, 4).join(' ')} 8 | <{'Col sm={6} md={3}'} />
        {dummySentences.slice(0, 6).join(' ')} 9 | <{'Col sm={6} md={3}'} />
        {dummySentences.slice(0, 2).join(' ')} 10 |
        11 |
        12 | ); 13 | 14 | ReactDOM.render(gridInstance, mountNode); 15 | -------------------------------------------------------------------------------- /docs/src/sections/TableSection.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Anchor from '../Anchor'; 4 | import PropTable from '../PropTable'; 5 | import ReactPlayground from '../ReactPlayground'; 6 | import Samples from '../Samples'; 7 | 8 | export default function TableSection() { 9 | return ( 10 |
        11 |

        12 | Tables Table 13 |

        14 | 15 |

        Use the striped, bordered, condensed and hover props to customise the table.

        16 | 17 | 18 |

        Responsive

        19 |

        Add responsive prop to make them scroll horizontally up to small devices (under 768px). When viewing on anything larger than 768px wide, you will not see any difference in these tables.

        20 | 21 | 22 |

        Props

        23 | 24 |
        25 | ); 26 | } 27 | -------------------------------------------------------------------------------- /src/Thumbnail.js: -------------------------------------------------------------------------------- 1 | import classNames from 'classnames'; 2 | import React from 'react'; 3 | import PropTypes from 'prop-types'; 4 | 5 | import SafeAnchor from './SafeAnchor'; 6 | import { bsClass, getClassSet, splitBsProps } from './utils/bootstrapUtils'; 7 | 8 | const propTypes = { 9 | src: PropTypes.string, 10 | alt: PropTypes.string, 11 | href: PropTypes.string, 12 | }; 13 | 14 | class Thumbnail extends React.Component { 15 | render() { 16 | const { src, alt, className, children, ...props } = this.props; 17 | const [bsProps, elementProps] = splitBsProps(props); 18 | 19 | const Component = elementProps.href ? SafeAnchor : 'div'; 20 | const classes = getClassSet(bsProps); 21 | 22 | return ( 23 | 27 | {alt} 28 | 29 | {children && ( 30 |
        31 | {children} 32 |
        33 | )} 34 |
        35 | ); 36 | } 37 | } 38 | 39 | Thumbnail.propTypes = propTypes; 40 | 41 | export default bsClass('thumbnail', Thumbnail); 42 | -------------------------------------------------------------------------------- /docs/examples/FormBasic.js: -------------------------------------------------------------------------------- 1 | const FormExample = React.createClass({ 2 | getInitialState() { 3 | return { 4 | value: '' 5 | }; 6 | }, 7 | 8 | getValidationState() { 9 | const length = this.state.value.length; 10 | if (length > 10) return 'success'; 11 | else if (length > 5) return 'warning'; 12 | else if (length > 0) return 'error'; 13 | }, 14 | 15 | handleChange(e) { 16 | this.setState({ value: e.target.value }); 17 | }, 18 | 19 | render() { 20 | return ( 21 |
        22 | 26 | Working example with validation 27 | 33 | 34 | Validation is based on string length. 35 | 36 |
        37 | ); 38 | } 39 | }); 40 | 41 | ReactDOM.render(, mountNode); 42 | -------------------------------------------------------------------------------- /docs/src/sections/ResponsiveEmbedSection.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Anchor from '../Anchor'; 4 | import PropTable from '../PropTable'; 5 | import ReactPlayground from '../ReactPlayground'; 6 | import Samples from '../Samples'; 7 | 8 | export default function ResponsiveEmbedSection() { 9 | return ( 10 |
        11 |

        12 | Responsive embed ResponsiveEmbed 13 |

        14 | 15 |

        Allow browsers to determine video or slideshow dimensions based on the width of their containing block by creating an intrinsic ratio that will properly scale on any device.

        16 |

        You don't need to include frameborder="0" in your iframes.

        17 |

        Either 16by9 or 4by3 aspect ratio via a16by9 or a4by3 attribute must be set.

        18 | 19 | 20 |

        Props

        21 | 22 |
        23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /docs/examples/AlertDismissable.js: -------------------------------------------------------------------------------- 1 | const AlertDismissable = React.createClass({ 2 | getInitialState() { 3 | return { 4 | alertVisible: true 5 | }; 6 | }, 7 | 8 | render() { 9 | if (this.state.alertVisible) { 10 | return ( 11 | 12 |

        Oh snap! You got an error!

        13 |

        Change this and that and try again. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Cras mattis consectetur purus sit amet fermentum.

        14 |

        15 | 16 | or 17 | 18 |

        19 |
        20 | ); 21 | } 22 | 23 | return ( 24 | 25 | ); 26 | }, 27 | 28 | handleAlertDismiss() { 29 | this.setState({alertVisible: false}); 30 | }, 31 | 32 | handleAlertShow() { 33 | this.setState({alertVisible: true}); 34 | } 35 | }); 36 | 37 | ReactDOM.render(, mountNode); 38 | -------------------------------------------------------------------------------- /docs/src/sections/FormValidationSection.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Anchor from '../Anchor'; 4 | import PropTable from '../PropTable'; 5 | import ReactPlayground from '../ReactPlayground'; 6 | import Samples from '../Samples'; 7 | 8 | export default function FormValidationSection() { 9 | return ( 10 |
        11 |

        12 | Validation states FormControl.Feedback 13 |

        14 | 15 |

        Set validationState to one of 'success', 'warning' or 'error' to show validation state. Set validationState to null (or undefined) to hide validation state. Add {''} for a feedback icon when validation state is set.

        16 | 17 | 18 |

        Props

        19 | 20 |

        FormControl.Feedback

        21 | 22 |
        23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /docs/src/sections/ThumbnailSection.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Anchor from '../Anchor'; 4 | import PropTable from '../PropTable'; 5 | import ReactPlayground from '../ReactPlayground'; 6 | import Samples from '../Samples'; 7 | 8 | export default function ThumbnailSection() { 9 | return ( 10 |
        11 |

        12 | Thumbnails Thumbnail 13 |

        14 | 15 |

        Thumbnails are designed to showcase linked images with minimal required markup. You can extend the grid component with thumbnails.

        16 | 17 |

        Anchor Thumbnail

        18 |

        Creates an anchor wrapping an image.

        19 | 20 | 21 |

        Divider Thumbnail

        22 |

        Creates a divider wrapping an image and other children elements.

        23 | 24 | 25 |

        Props

        26 | 27 |
        28 | ); 29 | } 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-present Stephen J. Collings, Matthew Honnibal, Pieter Vanderwerff 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /docs/src/sections/PaginationSection.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Anchor from '../Anchor'; 4 | import PropTable from '../PropTable'; 5 | import ReactPlayground from '../ReactPlayground'; 6 | import Samples from '../Samples'; 7 | 8 | export default function PaginationSection() { 9 | return ( 10 |
        11 |

        12 | Pagination Pagination 13 |

        14 | 15 |

        Provide pagination links for your site or app with the multi-page pagination component. Set items to the number of pages. activePage prop dictates which page is active

        16 | 17 | 18 |

        More options

        19 |

        such as first, last, previous, next, boundaryLinks and ellipsis.

        20 | 21 | 22 |

        Props

        23 | 24 |
        25 | ); 26 | } 27 | -------------------------------------------------------------------------------- /test/JumbotronSpec.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactTestUtils from 'react-addons-test-utils'; 3 | import ReactDOM from 'react-dom'; 4 | 5 | import Jumbotron from '../src/Jumbotron'; 6 | 7 | describe('', () => { 8 | it('Should output a div with content', () => { 9 | let instance = ReactTestUtils.renderIntoDocument( 10 | 11 | Content 12 | 13 | ); 14 | 15 | assert.equal(ReactDOM.findDOMNode(instance).nodeName, 'DIV'); 16 | assert.ok(ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'strong')); 17 | }); 18 | 19 | it('Should have a jumbotron class', () => { 20 | let instance = ReactTestUtils.renderIntoDocument( 21 | 22 | Content 23 | 24 | ); 25 | assert.ok(ReactDOM.findDOMNode(instance).className.match(/\bjumbotron\b/)); 26 | }); 27 | 28 | it('Should override node class', () => { 29 | let instance = ReactTestUtils.renderIntoDocument( 30 | 31 | Content 32 | 33 | ); 34 | assert.equal(ReactDOM.findDOMNode(instance).nodeName, 'SECTION'); 35 | }); 36 | }); 37 | -------------------------------------------------------------------------------- /test/helpers.js: -------------------------------------------------------------------------------- 1 | import { cloneElement } from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | 4 | export function shouldWarn(about) { 5 | console.error.expected.push(about); // eslint-disable-line no-console 6 | } 7 | 8 | /** 9 | * Helper for rendering and updating props for plain class Components 10 | * since `setProps` is deprecated. 11 | * @param {ReactElement} element Root element to render 12 | * @param {HTMLElement?} mountPoint Optional mount node, when empty it uses an unattached div like `renderIntoDocument()` 13 | * @return {ComponentInstance} The instance, with a new method `renderWithProps` which will return a new instance with updated props 14 | */ 15 | export function render(element, mountPoint) { 16 | let mount = mountPoint || document.createElement('div'); 17 | let instance = ReactDOM.render(element, mount); 18 | 19 | if (instance && !instance.renderWithProps) { 20 | instance.renderWithProps = newProps => { 21 | 22 | return render( 23 | cloneElement(element, newProps), mount); 24 | }; 25 | } 26 | 27 | return instance; 28 | } 29 | 30 | export function getOne(collection) { 31 | expect(collection.length).to.equal(1); 32 | return collection[0]; 33 | } 34 | -------------------------------------------------------------------------------- /docs/examples/TableResponsive.js: -------------------------------------------------------------------------------- 1 | const tableInstance = ( 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 |
        #Table headingTable headingTable headingTable headingTable headingTable heading
        1Table cellTable cellTable cellTable cellTable cellTable cell
        2Table cellTable cellTable cellTable cellTable cellTable cell
        3Table cellTable cellTable cellTable cellTable cellTable cell
        44 | ); 45 | 46 | ReactDOM.render(tableInstance, mountNode); 47 | -------------------------------------------------------------------------------- /docs/examples/ThumbnailDiv.js: -------------------------------------------------------------------------------- 1 | const thumbnailInstance = ( 2 | 3 | 4 | 5 | 6 |

        Thumbnail label

        7 |

        Description

        8 |

        9 |   10 | 11 |

        12 |
        13 | 14 | 15 | 16 |

        Thumbnail label

        17 |

        Description

        18 |

        19 |   20 | 21 |

        22 |
        23 | 24 | 25 | 26 |

        Thumbnail label

        27 |

        Description

        28 |

        29 |   30 | 31 |

        32 |
        33 | 34 |
        35 |
        36 | ); 37 | 38 | ReactDOM.render(thumbnailInstance, mountNode); 39 | -------------------------------------------------------------------------------- /src/Pager.js: -------------------------------------------------------------------------------- 1 | import classNames from 'classnames'; 2 | import React, { cloneElement } from 'react'; 3 | import PropTypes from 'prop-types'; 4 | 5 | import PagerItem from './PagerItem'; 6 | import { bsClass, getClassSet, splitBsProps } from './utils/bootstrapUtils'; 7 | import createChainedFunction from './utils/createChainedFunction'; 8 | import ValidComponentChildren from './utils/ValidComponentChildren'; 9 | 10 | const propTypes = { 11 | onSelect: PropTypes.func, 12 | }; 13 | 14 | class Pager extends React.Component { 15 | render() { 16 | const { onSelect, className, children, ...props } = this.props; 17 | const [bsProps, elementProps] = splitBsProps(props); 18 | 19 | const classes = getClassSet(bsProps); 20 | 21 | return ( 22 |
          26 | {ValidComponentChildren.map(children, child => ( 27 | cloneElement(child, { 28 | onSelect: createChainedFunction(child.props.onSelect, onSelect), 29 | }) 30 | ))} 31 |
        32 | ); 33 | } 34 | } 35 | 36 | Pager.propTypes = propTypes; 37 | 38 | Pager.Item = PagerItem; 39 | 40 | export default bsClass('pager', Pager); 41 | -------------------------------------------------------------------------------- /docs/examples/GridWithClearfix.js: -------------------------------------------------------------------------------- 1 | const dummySentences = ['Lorem ipsum dolor sit amet, consectetuer adipiscing elit.', 'Donec hendrerit tempor tellus.', 'Donec pretium posuere tellus.', 'Proin quam nisl, tincidunt et, mattis eget, convallis nec, purus.', 'Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.', 'Nulla posuere.', 'Donec vitae dolor.', 'Nullam tristique diam non turpis.', 'Cras placerat accumsan nulla.', 'Nullam rutrum.', 'Nam vestibulum accumsan nisl.']; 2 | 3 | const gridInstance = ( 4 | 5 | 6 | <{'Col sm={6} md={3}'} />
        {dummySentences.slice(0, 6).join(' ')} 7 | <{'Col sm={6} md={3}'} />
        {dummySentences.slice(0, 4).join(' ')} 8 | <{'Clearfix visibleSmBlock'} /> 9 | <{'Col sm={6} md={3}'} />
        {dummySentences.slice(0, 6).join(' ')} 10 | <{'Col sm={6} md={3}'} />
        {dummySentences.slice(0, 2).join(' ')} 11 |
        12 |
        13 | ); 14 | 15 | ReactDOM.render(gridInstance, mountNode); 16 | -------------------------------------------------------------------------------- /test/RowSpec.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactTestUtils from 'react-addons-test-utils'; 3 | import ReactDOM from 'react-dom'; 4 | 5 | import Row from '../src/Row'; 6 | 7 | describe('Row', () => { 8 | it('uses "div" by default', () => { 9 | let instance = ReactTestUtils.renderIntoDocument( 10 | 11 | ); 12 | 13 | assert.equal(ReactDOM.findDOMNode(instance).nodeName, 'DIV'); 14 | }); 15 | 16 | it('has "row" class', () => { 17 | let instance = ReactTestUtils.renderIntoDocument( 18 | Row content 19 | ); 20 | assert.equal(ReactDOM.findDOMNode(instance).className, 'row'); 21 | }); 22 | 23 | it('Should merge additional classes passed in', () => { 24 | let instance = ReactTestUtils.renderIntoDocument( 25 | 26 | ); 27 | assert.ok(ReactDOM.findDOMNode(instance).className.match(/\bbob\b/)); 28 | assert.ok(ReactDOM.findDOMNode(instance).className.match(/\brow\b/)); 29 | }); 30 | 31 | it('allows custom elements instead of "div"', () => { 32 | let instance = ReactTestUtils.renderIntoDocument( 33 | 34 | ); 35 | 36 | assert.equal(ReactDOM.findDOMNode(instance).nodeName, 'SECTION'); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /docs/examples/DropdownButtonCustom.js: -------------------------------------------------------------------------------- 1 | 2 | const dropdownInstance = ( 3 | 4 | 5 | 6 | 7 | Pow! Zoom! 8 | 9 | 10 | Action 11 | Another action 12 | Active Item 13 | 14 | Separated link 15 | 16 | 17 | 18 | 19 | 22 | 23 | 24 | Action 25 | Another action 26 | Active Item 27 | 28 | Separated link 29 | 30 | 31 | 32 | 33 | ); 34 | 35 | ReactDOM.render(dropdownInstance, mountNode); 36 | -------------------------------------------------------------------------------- /tools/amd/build.js: -------------------------------------------------------------------------------- 1 | import fsp from 'fs-promise'; 2 | import template from 'lodash/template'; 3 | import path from 'path'; 4 | 5 | import { repoRoot, bowerRoot } from '../constants'; 6 | import { exec } from '../exec'; 7 | import { copy } from '../fs-utils'; 8 | 9 | const packagePath = path.join(repoRoot, 'package.json'); 10 | const bowerTemplatePath = path.join(__dirname, 'bower.json'); 11 | const bowerJson = path.join(bowerRoot, 'bower.json'); 12 | 13 | const readme = path.join(__dirname, 'README.md'); 14 | 15 | function bowerConfig() { 16 | return Promise.all([ 17 | fsp.readFile(packagePath) 18 | .then(json => JSON.parse(json)), 19 | fsp.readFile(bowerTemplatePath) 20 | .then(templateString => template(templateString)) 21 | ]) 22 | .then(([pkg, compiledTemplate]) => compiledTemplate({ pkg })) 23 | .then(config => fsp.writeFile(bowerJson, config)); 24 | } 25 | 26 | export default function BuildBower() { 27 | console.log('Building: '.cyan + 'bower module'.green); 28 | 29 | return exec(`rimraf ${bowerRoot}`) 30 | .then(() => fsp.mkdirs(bowerRoot)) 31 | .then(() => Promise.all([ 32 | bowerConfig(), 33 | copy(readme, bowerRoot) 34 | ])) 35 | .then(() => console.log('Built: '.cyan + 'bower module'.green)); 36 | } 37 | -------------------------------------------------------------------------------- /src/Grid.js: -------------------------------------------------------------------------------- 1 | import classNames from 'classnames'; 2 | import React from 'react'; 3 | import PropTypes from 'prop-types'; 4 | import elementType from 'prop-types-extra/lib/elementType'; 5 | 6 | import { bsClass, prefix, splitBsProps } from './utils/bootstrapUtils'; 7 | 8 | const propTypes = { 9 | /** 10 | * Turn any fixed-width grid layout into a full-width layout by this property. 11 | * 12 | * Adds `container-fluid` class. 13 | */ 14 | fluid: PropTypes.bool, 15 | /** 16 | * You can use a custom element for this component 17 | */ 18 | componentClass: elementType, 19 | }; 20 | 21 | const defaultProps = { 22 | componentClass: 'div', 23 | fluid: false, 24 | }; 25 | 26 | class Grid extends React.Component { 27 | render() { 28 | const { fluid, componentClass: Component, className, ...props } = 29 | this.props; 30 | const [bsProps, elementProps] = splitBsProps(props); 31 | 32 | const classes = prefix(bsProps, fluid && 'fluid'); 33 | 34 | return ( 35 | 39 | ); 40 | } 41 | } 42 | 43 | Grid.propTypes = propTypes; 44 | Grid.defaultProps = defaultProps; 45 | 46 | export default bsClass('container', Grid); 47 | -------------------------------------------------------------------------------- /test/InputGroupSpec.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import $ from 'teaspoon'; 3 | 4 | import Button from '../src/Button'; 5 | import FormControl from '../src/FormControl'; 6 | import InputGroup from '../src/InputGroup'; 7 | 8 | describe('', () => { 9 | it('should render properly', () => { 10 | $( 11 | 12 | 13 | Foo 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | ) 23 | .render() 24 | .single('.input-group.my-input-group') 25 | .end() 26 | .single('.input-group-addon.my-addon') 27 | .tap($addon => expect($addon.text()).to.equal('Foo')) 28 | .end() 29 | .single('input.form-control[type="text"]') 30 | .end() 31 | .single('.input-group-btn.my-button') 32 | .single($.s`${Button}`); 33 | }); 34 | 35 | it('should support bsSize', () => { 36 | $( 37 | 38 | ) 39 | .shallowRender() 40 | .single('.input-group.input-group-sm'); 41 | }); 42 | }); 43 | -------------------------------------------------------------------------------- /src/Label.js: -------------------------------------------------------------------------------- 1 | import classNames from 'classnames'; 2 | import React from 'react'; 3 | 4 | import { bsClass, bsStyles, getClassSet, splitBsProps } 5 | from './utils/bootstrapUtils'; 6 | import { State, Style } from './utils/StyleConfig'; 7 | 8 | class Label extends React.Component { 9 | hasContent(children) { 10 | let result = false; 11 | 12 | React.Children.forEach(children, child => { 13 | if (result) { 14 | return; 15 | } 16 | 17 | if (child || child === 0) { 18 | result = true; 19 | } 20 | }); 21 | 22 | return result; 23 | } 24 | 25 | render() { 26 | const { className, children, ...props } = this.props; 27 | const [bsProps, elementProps] = splitBsProps(props); 28 | 29 | const classes = { 30 | ...getClassSet(bsProps), 31 | 32 | // Hack for collapsing on IE8. 33 | hidden: !this.hasContent(children), 34 | }; 35 | 36 | return ( 37 | 41 | {children} 42 | 43 | ); 44 | } 45 | } 46 | 47 | export default bsClass('label', 48 | bsStyles( 49 | [...Object.values(State), Style.DEFAULT, Style.PRIMARY], 50 | Style.DEFAULT, 51 | Label 52 | ) 53 | ); 54 | -------------------------------------------------------------------------------- /docs/examples/Overlay.js: -------------------------------------------------------------------------------- 1 | const Example = React.createClass({ 2 | getInitialState() { 3 | return { show: true }; 4 | }, 5 | 6 | toggle() { 7 | this.setState({ show: !this.state.show }); 8 | }, 9 | 10 | render() { 11 | const sharedProps = { 12 | show: this.state.show, 13 | container: this, 14 | target: () => ReactDOM.findDOMNode(this.refs.target) 15 | }; 16 | 17 | return ( 18 |
        19 | 22 | 23 | 24 | Tooltip overload! 25 | 26 | 27 | Tooltip overload! 28 | 29 | 30 | Tooltip overload! 31 | 32 | 33 | Tooltip overload! 34 | 35 |
        36 | ); 37 | } 38 | }); 39 | 40 | ReactDOM.render(, mountNode); 41 | -------------------------------------------------------------------------------- /src/Form.js: -------------------------------------------------------------------------------- 1 | import classNames from 'classnames'; 2 | import React from 'react'; 3 | import PropTypes from 'prop-types'; 4 | import elementType from 'prop-types-extra/lib/elementType'; 5 | 6 | import { bsClass, prefix, splitBsProps } from './utils/bootstrapUtils'; 7 | 8 | const propTypes = { 9 | horizontal: PropTypes.bool, 10 | inline: PropTypes.bool, 11 | componentClass: elementType, 12 | }; 13 | 14 | const defaultProps = { 15 | horizontal: false, 16 | inline: false, 17 | componentClass: 'form', 18 | }; 19 | 20 | class Form extends React.Component { 21 | render() { 22 | const { 23 | horizontal, 24 | inline, 25 | componentClass: Component, 26 | className, 27 | ...props 28 | } = this.props; 29 | 30 | const [bsProps, elementProps] = splitBsProps(props); 31 | 32 | const classes = []; 33 | if (horizontal) { 34 | classes.push(prefix(bsProps, 'horizontal')); 35 | } 36 | if (inline) { 37 | classes.push(prefix(bsProps, 'inline')); 38 | } 39 | 40 | return ( 41 | 45 | ); 46 | } 47 | } 48 | 49 | Form.propTypes = propTypes; 50 | Form.defaultProps = defaultProps; 51 | 52 | export default bsClass('form', Form); 53 | -------------------------------------------------------------------------------- /test/LabelSpec.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactTestUtils from 'react-addons-test-utils'; 3 | import ReactDOM from 'react-dom'; 4 | 5 | import Label from '../src/Label'; 6 | 7 | describe('Label', () => { 8 | 9 | it('Should output a label with message', () => { 10 | let instance = ReactTestUtils.renderIntoDocument( 11 | 14 | ); 15 | assert.ok(ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'strong')); 16 | }); 17 | 18 | it('Should have bsClass by default', () => { 19 | let instance = ReactTestUtils.renderIntoDocument( 20 | 23 | ); 24 | assert.ok(ReactDOM.findDOMNode(instance).className.match(/\blabel\b/)); 25 | }); 26 | 27 | it('Should have bsStyle by default', () => { 28 | let instance = ReactTestUtils.renderIntoDocument( 29 | 32 | ); 33 | assert.ok(ReactDOM.findDOMNode(instance).className.match(/\blabel-default\b/)); 34 | }); 35 | 36 | it('Hides when empty', () => { 37 | let instance = ReactTestUtils.renderIntoDocument( 38 |