UNPKG

8.67 kBJavaScriptView Raw
1import _extends from 'babel-runtime/helpers/extends';
2import _objectWithoutProperties from 'babel-runtime/helpers/objectWithoutProperties';
3import _classCallCheck from 'babel-runtime/helpers/classCallCheck';
4import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn';
5import _inherits from 'babel-runtime/helpers/inherits';
6// TODO: Remove this pragma once we upgrade eslint-config-airbnb.
7/* eslint-disable react/no-multi-comp */
8
9import classNames from 'classnames';
10import React from 'react';
11import PropTypes from 'prop-types';
12import elementType from 'prop-types-extra/lib/elementType';
13import uncontrollable from 'uncontrollable';
14
15import Grid from './Grid';
16import NavbarBrand from './NavbarBrand';
17import NavbarCollapse from './NavbarCollapse';
18import NavbarHeader from './NavbarHeader';
19import NavbarToggle from './NavbarToggle';
20import { bsClass as setBsClass, bsStyles, getClassSet, prefix, splitBsPropsAndOmit } from './utils/bootstrapUtils';
21import { Style } from './utils/StyleConfig';
22import createChainedFunction from './utils/createChainedFunction';
23
24var propTypes = {
25 /**
26 * Create a fixed navbar along the top of the screen, that scrolls with the
27 * page
28 */
29 fixedTop: PropTypes.bool,
30 /**
31 * Create a fixed navbar along the bottom of the screen, that scrolls with
32 * the page
33 */
34 fixedBottom: PropTypes.bool,
35 /**
36 * Create a full-width navbar that scrolls away with the page
37 */
38 staticTop: PropTypes.bool,
39 /**
40 * An alternative dark visual style for the Navbar
41 */
42 inverse: PropTypes.bool,
43 /**
44 * Allow the Navbar to fluidly adjust to the page or container width, instead
45 * of at the predefined screen breakpoints
46 */
47 fluid: PropTypes.bool,
48
49 /**
50 * Set a custom element for this component.
51 */
52 componentClass: elementType,
53 /**
54 * A callback fired when the `<Navbar>` body collapses or expands. Fired when
55 * a `<Navbar.Toggle>` is clicked and called with the new `expanded`
56 * boolean value.
57 *
58 * @controllable expanded
59 */
60 onToggle: PropTypes.func,
61 /**
62 * A callback fired when a descendant of a child `<Nav>` is selected. Should
63 * be used to execute complex closing or other miscellaneous actions desired
64 * after selecting a descendant of `<Nav>`. Does nothing if no `<Nav>` or `<Nav>`
65 * descendants exist. The callback is called with an eventKey, which is a
66 * prop from the selected `<Nav>` descendant, and an event.
67 *
68 * ```js
69 * function (
70 * Any eventKey,
71 * SyntheticEvent event?
72 * )
73 * ```
74 *
75 * For basic closing behavior after all `<Nav>` descendant onSelect events in
76 * mobile viewports, try using collapseOnSelect.
77 *
78 * Note: If you are manually closing the navbar using this `OnSelect` prop,
79 * ensure that you are setting `expanded` to false and not *toggling* between
80 * true and false.
81 */
82 onSelect: PropTypes.func,
83 /**
84 * Sets `expanded` to `false` after the onSelect event of a descendant of a
85 * child `<Nav>`. Does nothing if no `<Nav>` or `<Nav>` descendants exist.
86 *
87 * The onSelect callback should be used instead for more complex operations
88 * that need to be executed after the `select` event of `<Nav>` descendants.
89 */
90 collapseOnSelect: PropTypes.bool,
91 /**
92 * Explicitly set the visiblity of the navbar body
93 *
94 * @controllable onToggle
95 */
96 expanded: PropTypes.bool,
97
98 role: PropTypes.string
99};
100
101var defaultProps = {
102 componentClass: 'nav',
103 fixedTop: false,
104 fixedBottom: false,
105 staticTop: false,
106 inverse: false,
107 fluid: false,
108 collapseOnSelect: false
109};
110
111var childContextTypes = {
112 $bs_navbar: PropTypes.shape({
113 bsClass: PropTypes.string,
114 expanded: PropTypes.bool,
115 onToggle: PropTypes.func.isRequired,
116 onSelect: PropTypes.func
117 })
118};
119
120var Navbar = function (_React$Component) {
121 _inherits(Navbar, _React$Component);
122
123 function Navbar(props, context) {
124 _classCallCheck(this, Navbar);
125
126 var _this = _possibleConstructorReturn(this, _React$Component.call(this, props, context));
127
128 _this.handleToggle = _this.handleToggle.bind(_this);
129 _this.handleCollapse = _this.handleCollapse.bind(_this);
130 return _this;
131 }
132
133 Navbar.prototype.getChildContext = function getChildContext() {
134 var _props = this.props,
135 bsClass = _props.bsClass,
136 expanded = _props.expanded,
137 onSelect = _props.onSelect,
138 collapseOnSelect = _props.collapseOnSelect;
139
140
141 return {
142 $bs_navbar: {
143 bsClass: bsClass,
144 expanded: expanded,
145 onToggle: this.handleToggle,
146 onSelect: createChainedFunction(onSelect, collapseOnSelect ? this.handleCollapse : null)
147 }
148 };
149 };
150
151 Navbar.prototype.handleCollapse = function handleCollapse() {
152 var _props2 = this.props,
153 onToggle = _props2.onToggle,
154 expanded = _props2.expanded;
155
156
157 if (expanded) {
158 onToggle(false);
159 }
160 };
161
162 Navbar.prototype.handleToggle = function handleToggle() {
163 var _props3 = this.props,
164 onToggle = _props3.onToggle,
165 expanded = _props3.expanded;
166
167
168 onToggle(!expanded);
169 };
170
171 Navbar.prototype.render = function render() {
172 var _extends2;
173
174 var _props4 = this.props,
175 Component = _props4.componentClass,
176 fixedTop = _props4.fixedTop,
177 fixedBottom = _props4.fixedBottom,
178 staticTop = _props4.staticTop,
179 inverse = _props4.inverse,
180 fluid = _props4.fluid,
181 className = _props4.className,
182 children = _props4.children,
183 props = _objectWithoutProperties(_props4, ['componentClass', 'fixedTop', 'fixedBottom', 'staticTop', 'inverse', 'fluid', 'className', 'children']);
184
185 var _splitBsPropsAndOmit = splitBsPropsAndOmit(props, ['expanded', 'onToggle', 'onSelect', 'collapseOnSelect']),
186 bsProps = _splitBsPropsAndOmit[0],
187 elementProps = _splitBsPropsAndOmit[1];
188
189 // will result in some false positives but that seems better
190 // than false negatives. strict `undefined` check allows explicit
191 // "nulling" of the role if the user really doesn't want one
192
193
194 if (elementProps.role === undefined && Component !== 'nav') {
195 elementProps.role = 'navigation';
196 }
197
198 if (inverse) {
199 bsProps.bsStyle = Style.INVERSE;
200 }
201
202 var classes = _extends({}, getClassSet(bsProps), (_extends2 = {}, _extends2[prefix(bsProps, 'fixed-top')] = fixedTop, _extends2[prefix(bsProps, 'fixed-bottom')] = fixedBottom, _extends2[prefix(bsProps, 'static-top')] = staticTop, _extends2));
203
204 return React.createElement(
205 Component,
206 _extends({}, elementProps, { className: classNames(className, classes) }),
207 React.createElement(
208 Grid,
209 { fluid: fluid },
210 children
211 )
212 );
213 };
214
215 return Navbar;
216}(React.Component);
217
218Navbar.propTypes = propTypes;
219Navbar.defaultProps = defaultProps;
220Navbar.childContextTypes = childContextTypes;
221
222setBsClass('navbar', Navbar);
223
224var UncontrollableNavbar = uncontrollable(Navbar, { expanded: 'onToggle' });
225
226function createSimpleWrapper(tag, suffix, displayName) {
227 var Wrapper = function Wrapper(_ref, _ref2) {
228 var _ref2$$bs_navbar = _ref2.$bs_navbar,
229 navbarProps = _ref2$$bs_navbar === undefined ? { bsClass: 'navbar' } : _ref2$$bs_navbar;
230
231 var Component = _ref.componentClass,
232 className = _ref.className,
233 pullRight = _ref.pullRight,
234 pullLeft = _ref.pullLeft,
235 props = _objectWithoutProperties(_ref, ['componentClass', 'className', 'pullRight', 'pullLeft']);
236
237 return React.createElement(Component, _extends({}, props, {
238 className: classNames(className, prefix(navbarProps, suffix), pullRight && prefix(navbarProps, 'right'), pullLeft && prefix(navbarProps, 'left'))
239 }));
240 };
241
242 Wrapper.displayName = displayName;
243
244 Wrapper.propTypes = {
245 componentClass: elementType,
246 pullRight: PropTypes.bool,
247 pullLeft: PropTypes.bool
248 };
249
250 Wrapper.defaultProps = {
251 componentClass: tag,
252 pullRight: false,
253 pullLeft: false
254 };
255
256 Wrapper.contextTypes = {
257 $bs_navbar: PropTypes.shape({
258 bsClass: PropTypes.string
259 })
260 };
261
262 return Wrapper;
263}
264
265UncontrollableNavbar.Brand = NavbarBrand;
266UncontrollableNavbar.Header = NavbarHeader;
267UncontrollableNavbar.Toggle = NavbarToggle;
268UncontrollableNavbar.Collapse = NavbarCollapse;
269
270UncontrollableNavbar.Form = createSimpleWrapper('div', 'form', 'NavbarForm');
271UncontrollableNavbar.Text = createSimpleWrapper('p', 'text', 'NavbarText');
272UncontrollableNavbar.Link = createSimpleWrapper('a', 'link', 'NavbarLink');
273
274// Set bsStyles here so they can be overridden.
275export default bsStyles([Style.DEFAULT, Style.INVERSE], Style.DEFAULT, UncontrollableNavbar);
\No newline at end of file