// Copyright (c) 2022 Uber Technologies, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. import React, {Component, createRef, CSSProperties, RefObject} from 'react'; import classnames from 'classnames'; import styled from 'styled-components'; import MouseEventHandler from './mouse-event'; import {StyleRangeSliderType} from './slider'; interface StyledSliderHandleProps { vertical?: boolean; sliderHandleWidth: number; active?: boolean; } const StyledSliderHandle = styled.span.attrs(props => ({ className: classnames('kg-range-slider__handle', props.className) }))` position: absolute; z-index: 10; ${props => (props.vertical ? 'margin-left' : 'margin-top')}: -${props => (props.sliderHandleWidth - props.theme.sliderBarHeight) / 2}px; height: ${props => Number.isFinite(props.sliderHandleWidth) ? props.sliderHandleWidth : props.theme.sliderHandleHeight}px; width: ${props => Number.isFinite(props.sliderHandleWidth) ? props.sliderHandleWidth : props.theme.sliderHandleHeight}px; box-shadow: ${props => props.theme.sliderHandleShadow}; background-color: ${props => props.theme.sliderHandleColor}; color: ${props => props.theme.sliderHandleTextColor}; border-width: 1px; border-radius: ${props => props.theme.sliderBorderRadius}; border-style: solid; border-color: ${props => props.active ? props.theme.selectBorderColor : props.theme.sliderInactiveBorderColor}; :hover { background-color: ${props => props.theme.sliderHandleHoverColor}; cursor: pointer; } line-height: 10px; font-size: 6px; padding: 0 3px; letter-spacing: 1px; :after { content: '${props => props.theme.sliderHandleAfterContent}'; } `; interface StyledSliderTooltipProps { vertical?: boolean; sliderHandleWidth: number; active?: boolean; } const StyledSliderTooltip = styled.div` position: absolute; border-radius: 3px; display: inline-block; pointer-events: none; transition: opacity 0.3s ease-out; z-index: 999; margin-left: ${props => props.sliderHandleWidth + 12}px; font-size: 9.5px; font-weight: 500; padding: 7px 10px; background-color: ${props => props.theme.tooltipBg}; color: ${props => props.theme.tooltipColor}; margin-bottom: -6px; width: 50px; :before, :after { content: ''; width: 0; height: 0; position: absolute; } :before { border-top: 6px solid transparent; border-bottom: 6px solid transparent; left: -8px; top: 50%; } :after { border-top: 5px solid transparent; border-bottom: 5px solid transparent; left: -6px; top: 50%; margin-top: -4px; border-right-color: ${props => props.theme.tooltipBg}; border-right-style: solid; border-right-width: 6px; } `; type SliderTooltipProps = { value?: number | null; format?: (value: number | null | undefined) => number | null | undefined; style: CSSProperties; sliderHandleWidth: number; }; const SliderTooltip = ({ value, format = val => val, style, sliderHandleWidth }: SliderTooltipProps) => { return ( {format(value)} ); }; type SliderHandleProps = { sliderHandleWidth: number; left: string; display: boolean; valueListener: (distance: number) => void; vertical: boolean; track: RefObject; showTooltip: boolean; value?: number; }; export default class SliderHandle extends Component { static defaultProps = { sliderHandleWidth: 12, left: '50%', display: true, vertical: false, valueListener: function valueListenerFn() {}, showTooltip: false }; public mouseEvent: MouseEventHandler; constructor(public props: SliderHandleProps) { super(props); this.mouseEvent = new MouseEventHandler({ vertical: props.vertical, valueListener: props.valueListener, toggleMouseOver: this.toggleMouseOver, track: props.track }); } state = {mouseOver: false}; ref = createRef(); toggleMouseOver = () => { this.setState({mouseOver: !this.state.mouseOver}); }; render() { const style = {[this.props.vertical ? 'bottom' : 'left']: this.props.left}; return (
{this.props.showTooltip && this.state.mouseOver ? ( ) : null}
); } }