<commit_before>import { document } from 'global';
import PropTypes from 'prop-types';
import React from 'react';
import { SketchPicker } from 'react-color';

import { styled } from '@storybook/theming';

import { Form } from '@storybook/components';

const { Button } = Form;

const Swatch = styled.div(({ theme }) => ({
  position: 'absolute',
  top: '50%',
  transform: 'translateY(-50%)',
  left: 6,
  width: 16,
  height: 16,
  boxShadow: `${theme.appBorderColor} 0 0 0 1px inset`,
  borderRadius: '1rem',
}));

const Popover = styled.div({
  position: 'absolute',
  zIndex: '2',
});

class ColorType extends React.Component {
  state = {
    displayColorPicker: false,
  };

  componentDidMount() {
    document.addEventListener('mousedown', this.handleWindowMouseDown);
  }

  shouldComponentUpdate(nextProps, nextState) {
    const { knob } = this.props;
    const { displayColorPicker } = this.state;

    return (
      nextProps.knob.value !== knob.value || nextState.displayColorPicker !== displayColorPicker
    );
  }

  componentWillUnmount() {
    document.removeEventListener('mousedown', this.handleWindowMouseDown);
  }

  handleWindowMouseDown = e => {
    const { displayColorPicker } = this.state;
    if (!displayColorPicker || this.popover.contains(e.target)) {
      return;
    }

    this.setState({
      displayColorPicker: false,
    });
  };

  handleClick = () => {
    const { displayColorPicker } = this.state;

    this.setState({
      displayColorPicker: !displayColorPicker,
    });
  };

  handleChange = color => {
    const { onChange } = this.props;

    onChange(`rgba(${color.rgb.r},${color.rgb.g},${color.rgb.b},${color.rgb.a})`);
  };

  render() {
    const { knob } = this.props;
    const { displayColorPicker } = this.state;
    const colorStyle = {
      background: knob.value,
    };

    return (
      <Button type="button" name={knob.name} onClick={this.handleClick} size="flex">
        {knob.value.toUpperCase()}
        <Swatch style={colorStyle} />
        {displayColorPicker ? (
          <Popover
            ref={e => {
              this.popover = e;
            }}
          >
            <SketchPicker color={knob.value} onChange={this.handleChange} />
          </Popover>
        ) : null}
      </Button>
    );
  }
}

ColorType.propTypes = {
  knob: PropTypes.shape({
    name: PropTypes.string,
    value: PropTypes.string,
  }),
  onChange: PropTypes.func,
};
ColorType.defaultProps = {
  knob: {},
  onChange: value => value,
};

ColorType.serialize = value => value;
ColorType.deserialize = value => value;

export default ColorType;
<commit_msg>fix(knobs): color type button z-index<commit_after>import { document } from 'global';
import PropTypes from 'prop-types';
import React from 'react';
import { SketchPicker } from 'react-color';

import { styled } from '@storybook/theming';

import { Form } from '@storybook/components';

const { Button } = Form;

const Swatch = styled.div(({ theme }) => ({
  position: 'absolute',
  top: '50%',
  transform: 'translateY(-50%)',
  left: 6,
  width: 16,
  height: 16,
  boxShadow: `${theme.appBorderColor} 0 0 0 1px inset`,
  borderRadius: '1rem',
}));

const ColorButton = styled(Button)(({ active }) => ({
  zIndex: active ? 3 : 'unset',
}));

const Popover = styled.div({
  position: 'absolute',
  zIndex: '2',
});

class ColorType extends React.Component {
  state = {
    displayColorPicker: false,
  };

  componentDidMount() {
    document.addEventListener('mousedown', this.handleWindowMouseDown);
  }

  shouldComponentUpdate(nextProps, nextState) {
    const { knob } = this.props;
    const { displayColorPicker } = this.state;

    return (
      nextProps.knob.value !== knob.value || nextState.displayColorPicker !== displayColorPicker
    );
  }

  componentWillUnmount() {
    document.removeEventListener('mousedown', this.handleWindowMouseDown);
  }

  handleWindowMouseDown = e => {
    const { displayColorPicker } = this.state;
    if (!displayColorPicker || this.popover.contains(e.target)) {
      return;
    }

    this.setState({
      displayColorPicker: false,
    });
  };

  handleClick = () => {
    const { displayColorPicker } = this.state;

    this.setState({
      displayColorPicker: !displayColorPicker,
    });
  };

  handleChange = color => {
    const { onChange } = this.props;

    onChange(`rgba(${color.rgb.r},${color.rgb.g},${color.rgb.b},${color.rgb.a})`);
  };

  render() {
    const { knob } = this.props;
    const { displayColorPicker } = this.state;
    const colorStyle = {
      background: knob.value,
    };

    return (
      <ColorButton
        active={displayColorPicker}
        type="button"
        name={knob.name}
        onClick={this.handleClick}
        size="flex"
      >
        {knob.value.toUpperCase()}
        <Swatch style={colorStyle} />
        {displayColorPicker ? (
          <Popover
            ref={e => {
              this.popover = e;
            }}
          >
            <SketchPicker color={knob.value} onChange={this.handleChange} />
          </Popover>
        ) : null}
      </ColorButton>
    );
  }
}

ColorType.propTypes = {
  knob: PropTypes.shape({
    name: PropTypes.string,
    value: PropTypes.string,
  }),
  onChange: PropTypes.func,
};
ColorType.defaultProps = {
  knob: {},
  onChange: value => value,
};

ColorType.serialize = value => value;
ColorType.deserialize = value => value;

export default ColorType;

{'fraction_non_alphanumeric': 0.15015622128285241, 'fraction_numerical': 0.005697482080499908, 'mean_word_length': 2.8982808022922635, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 32, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1776781', 'n_tokens_mistral': 1732, 'n_tokens_neox': 1703, 'n_words': 341}