ToggleButtonGroup.tsx 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. import React, { SFC, ReactNode, PureComponent, ReactElement } from 'react';
  2. interface ToggleButtonGroupProps {
  3. onChange: (value) => void;
  4. value?: any;
  5. label?: string;
  6. render: (props) => void;
  7. stackedButtons?: boolean;
  8. }
  9. export default class ToggleButtonGroup extends PureComponent<ToggleButtonGroupProps> {
  10. static defaultProps = {
  11. stackedButtons: false,
  12. };
  13. getValues() {
  14. const { children } = this.props;
  15. return React.Children.toArray(children).map((c: ReactElement<any>) => c.props.value);
  16. }
  17. smallChildren() {
  18. const { children } = this.props;
  19. return React.Children.toArray(children).every((c: ReactElement<any>) => c.props.className.includes('small'));
  20. }
  21. handleToggle(toggleValue) {
  22. const { value, onChange } = this.props;
  23. if (value && value === toggleValue) {
  24. return;
  25. }
  26. onChange(toggleValue);
  27. }
  28. render() {
  29. const { value, label, stackedButtons } = this.props;
  30. const values = this.getValues();
  31. const selectedValue = value || values[0];
  32. const labelClassName = `gf-form-label ${this.smallChildren() ? 'small' : ''}`;
  33. return (
  34. <div className="gf-form">
  35. <div className={`toggle-button-group ${stackedButtons ? 'stacked' : ''}`}>
  36. {label && <label className={labelClassName}>{label}</label>}
  37. {this.props.render({ selectedValue, onChange: this.handleToggle.bind(this) })}
  38. </div>
  39. </div>
  40. );
  41. }
  42. }
  43. interface ToggleButtonProps {
  44. onChange?: (value) => void;
  45. selected?: boolean;
  46. value: any;
  47. className?: string;
  48. children: ReactNode;
  49. }
  50. export const ToggleButton: SFC<ToggleButtonProps> = ({ children, selected, className = '', value, onChange }) => {
  51. const handleChange = event => {
  52. event.stopPropagation();
  53. if (onChange) {
  54. onChange(value);
  55. }
  56. };
  57. const btnClassName = `btn ${className} ${selected ? 'active' : ''}`;
  58. return (
  59. <button className={btnClassName} onClick={handleChange}>
  60. <span>{children}</span>
  61. </button>
  62. );
  63. };