ToggleButtonGroup.tsx 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  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), stackedButtons: stackedButtons })}
  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. stackedButtons?: boolean;
  50. }
  51. export const ToggleButton: SFC<ToggleButtonProps> = ({
  52. children,
  53. selected,
  54. className = '',
  55. value,
  56. onChange,
  57. stackedButtons,
  58. }) => {
  59. const handleChange = event => {
  60. event.stopPropagation();
  61. if (onChange) {
  62. onChange(value);
  63. }
  64. };
  65. const btnClassName = `btn ${className} ${selected ? 'active' : ''} ${stackedButtons ? 'stacked' : ''}`;
  66. return (
  67. <button className={btnClassName} onClick={handleChange}>
  68. <span>{children}</span>
  69. </button>
  70. );
  71. };