import React, { ReactNode } from 'react'; import { observer } from 'mobx-react'; import { toJS } from 'mobx'; import classNames from 'classnames'; import noop from 'lodash/noop'; import { pxToRem } from 'choerodon-ui/lib/_util/UnitConvertor'; import C7NRate, { RateProps as C7NRateProps } from 'choerodon-ui/lib/rate'; import { FIELD_SUFFIX } from '../form/utils'; import { FormField, FormFieldProps } from '../field/FormField'; import { renderValidationMessage } from '../field/utils'; import Icon from '../icon'; import { LabelLayout, ShowValidation } from '../form/enum'; import autobind from '../_util/autobind'; import { hide, show } from '../tooltip/singleton'; import ValidationResult from '../validator/ValidationResult'; import { ShowHelp } from '../field/enum'; export interface RateProps extends C7NRateProps, FormFieldProps { defaultValue?: number; onChange?: (value: number) => any; value?: number; } @observer export default class Rate<T extends RateProps> extends FormField<T> { static displayName = 'Rate'; static defaultProps = { ...C7NRate.defaultProps, ...FormField.defaultProps, suffixCls: 'rate', }; // eslint-disable-next-line camelcase static __PRO_RATE = true; // eslint-disable-next-line camelcase static __IS_IN_CELL_EDITOR = true; get hasFloatLabel(): boolean { const { labelLayout } = this; if (labelLayout) { return [LabelLayout.float, LabelLayout.placeholder].includes(labelLayout); } return false; } @autobind renderValidationResult(validationResult?: ValidationResult): ReactNode { const validationMessage = this.getValidationMessage(validationResult); const { labelLayout, showValidation, getProPrefixCls } = this.context; if (validationMessage) { const showIcon = !((labelLayout && [LabelLayout.float, LabelLayout.placeholder].includes(labelLayout)) || showValidation === ShowValidation.newLine); return renderValidationMessage(validationMessage, showIcon, getProPrefixCls); } } onChange = (value: number) => { this.setValue(value); }; @autobind handleHelpMouseEnter(e) { const { getTooltipTheme, getTooltipPlacement } = this.context; const { helpTooltipProps } = this; let helpTooltipCls = `${this.getContextConfig('proPrefixCls')}-tooltip-popup-help`; if (helpTooltipProps && helpTooltipProps.popupClassName) { helpTooltipCls = helpTooltipCls.concat(' ', helpTooltipProps.popupClassName) } show(e.currentTarget, { title: this.getDisplayProp('help'), theme: getTooltipTheme('help'), placement: getTooltipPlacement('help'), ...helpTooltipProps, popupClassName: helpTooltipCls, }); } handleHelpMouseLeave() { hide(); } renderTooltipHelp(): ReactNode { const help = this.getDisplayProp('help'); if (help) { return ( <Icon type="help" onMouseEnter={this.handleHelpMouseEnter} onMouseLeave={this.handleHelpMouseLeave} /> ); } } renderFloatLabel(): ReactNode { if (this.hasFloatLabel) { const label = this.getLabel(); if (label) { const { floatLabelOffsetX } = this; const prefixCls = this.getContextProPrefixCls(FIELD_SUFFIX); const required = this.getProp('required'); const classString = classNames(`${prefixCls}-label`, { [`${prefixCls}-required`]: required, [`${prefixCls}-readonly`]: this.readOnly, }); const style = floatLabelOffsetX ? { marginLeft: pxToRem(floatLabelOffsetX, true), } : undefined; return ( <div className={`${prefixCls}-label-wrapper`} style={style}> <div className={classString} onMouseEnter={this.handleFloatLabelMouseEnter} onMouseLeave={this.handleFloatLabelMouseLeave} > {label} </div> {this.renderTooltipHelp()} </div> ); } } } getOtherProps() { const otherProps = super.getOtherProps(); otherProps.onFocus = noop; otherProps.onBlur = noop; return otherProps; } renderWrapper(): ReactNode { const value = this.getValue(); return ( <label key="wrapper" {...this.getWrapperProps()}> {this.renderFloatLabel()} <div onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}> <C7NRate {...this.getOtherProps()} onChange={this.onChange} value={value} /> </div> </label> ); } renderHelpMessage(): ReactNode { const { showHelp } = this; const label = this.getLabel(); if ([ShowHelp.none, ShowHelp.label].includes(showHelp)) return; if (!this.hasFloatLabel || !label) { const help = this.getDisplayProp('help'); if (help) { return ( <div key="help" className={`${this.getContextProPrefixCls(FIELD_SUFFIX)}-help`}> {toJS(help)} </div> ); } } } }