Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | 3x 3x 32x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 23x 3x 3x 1x 3x 23x 23x 23x 36x 3x | import _ from 'lodash'; import React from 'react'; import PropTypes from 'prop-types'; import Button, { IButtonProps } from '../Button/Button'; import { lucidClassNames } from '../../util/style-helpers'; import { findTypes, StandardProps } from '../../util/component-types'; import reducers from './ButtonGroup.reducers'; import { buildModernHybridComponent } from '../../util/state-management'; const cx = lucidClassNames.bind('&-ButtonGroup'); const { any, func, arrayOf, number } = PropTypes; const ButtonGroupButton = (_props: Partial<IButtonProps>): null => null; ButtonGroupButton.displayName = 'ButtonGroup.Button'; ButtonGroupButton.peek = { description: `Renders a \`<Button\`> inside the \`ButtonGroup\`.`, }; const defaultProps = { onSelect: _.noop, selectedIndices: [], }; const nonPassThroughs = [ 'onSelect', 'className', 'children', 'selectedIndices', ]; export interface IButtonGroupState { selectedIndices: number[]; } export interface IButtonGroupProps extends StandardProps { /** A function that is called with the index of the child button clicked. */ onSelect: ( selectedIndex: number, { event, props }: { event: React.MouseEvent; props: IButtonProps } ) => void; /** An array of currently selected \`ButtonGroup.Button\`s indices. You can also pass the prop \`isActive\` to individual \`ButtonGroup.Button\` components. */ selectedIndices: number[]; } class ButtonGroup extends React.Component< IButtonGroupProps, IButtonGroupState > { static displayName = 'ButtonGroup'; static peek = { description: `\`Button Group\` allows you to pair \`Buttons\` together to form a seamless cluster. Any props not explicitly called out are spread on to the root component.`, categories: ['controls', 'buttons'], madeFrom: ['Button'], }; static Button = ButtonGroupButton; static reducers = reducers; static defaultProps = defaultProps; static propTypes = { /** A function that is called with the index of the child button clicked. \`props\` refers to the child button props. Signature: \`(selectedIndex, { event, props }) => {}\` */ onSelect: func, /** Appended to the component-specific class names set on the root element. Value is run through the \`classnames\` library. */ className: any, /** All children should be \`ButtonGroup.Button\`s and they support the same props as \`Button\`s. */ children: any, /** An array of currently selected \`ButtonGroup.Button\`s indices. You can also pass the prop \`isActive\` to individual \`ButtonGroup.Button\` components. */ selectedIndices: arrayOf(number), }; handleSelect = (event, childProps, index) => { const clickedButtonProps = _.get( findTypes(this.props, ButtonGroup.Button)[index], 'props', {} ); // If the consumer passed in an `onClick` to the child `ButtonGroup.Button` // component, we should make sure to call that in addition to the // `ButtonGroup`'s `onSelect`. if (_.isFunction(clickedButtonProps.onClick)) { clickedButtonProps.onClick({ event, props: childProps }); } this.props.onSelect(index, { event, props: childProps }); }; render() { const { selectedIndices, className, children, ...passThroughs } = this.props; const buttonChildProps = _.map( findTypes(this.props, ButtonGroup.Button), 'props' ); return ( <span {...(_.omit(passThroughs, nonPassThroughs) as any)} className={cx('&', className)} > {_.map(buttonChildProps, (buttonChildProp, index) => { return ( // The order of the spread operator below is important. If the // consumer puts `isActive` directly on a `ButtonGroup.Button`, we // want that to take precedence over the `selectedIndices` prop on // the parent `ButtonGroup`. However, we want our `onClick` at the // bottom because we manually handle passing the event to the // `ButtonGroup.Button`'s `onClick` if it exists. <Button isActive={_.includes(selectedIndices, index)} {...buttonChildProp} key={index} onClick={({ event, props }) => this.handleSelect(event, props, index) } /> ); })} {children} </span> ); } } export default buildModernHybridComponent< IButtonGroupProps, IButtonGroupState, typeof ButtonGroup >(ButtonGroup as any, { reducers }); export { ButtonGroup as ButtonGroupDumb }; |