in packages/eui/src/components/form/range/dual_range.tsx [401:783]
render() {
const { defaultFullWidth } = this.context as FormContextValue;
const {
className,
css: customCss,
compressed,
disabled,
fullWidth = defaultFullWidth,
isLoading,
readOnly,
id: propsId,
max: maxProps,
min: minProps,
name,
step,
showLabels,
showInput,
showTicks,
tickInterval,
ticks,
levels,
onBlur,
onChange,
onFocus,
showRange,
value,
isInvalid,
append,
prepend,
minInputProps,
maxInputProps,
inputPopoverProps,
isDraggable,
theme,
...rest
} = this.props;
const min = minProps!;
const max = maxProps!;
const { id } = this.state;
const showInputOnly = this.isInPopover;
const canShowDropdown = showInputOnly && !readOnly && !disabled;
const rangeStyles = euiRangeStyles(theme);
const minInput = !!showInput ? (
<EuiRangeInput
// Overridable props
aria-describedby={this.props['aria-describedby']}
aria-label={this.props['aria-label']}
disabled={disabled}
isInvalid={isInvalid}
name={`${name}-minValue`}
value={this.lowerValue}
readOnly={readOnly}
{...minInputProps}
// Non-overridable props
side="min"
min={min}
max={this.upperValue === '' ? max : Number(this.upperValue)}
step={step}
compressed={compressed}
autoSize={!showInputOnly}
fullWidth={!!showInputOnly && fullWidth}
controlOnly={showInputOnly}
onChange={(event) => {
this.handleLowerInputChange(event);
minInputProps?.onChange?.(event);
}}
onKeyDown={(event) => {
this.handleInputKeyDown(event);
minInputProps?.onKeyDown?.(event);
}}
onFocus={(event) => {
if (canShowDropdown) {
this.onInputFocus(event);
} else {
onFocus?.(event);
}
minInputProps?.onFocus?.(event);
}}
onBlur={(event) => {
if (canShowDropdown) {
this.onInputBlur(event);
} else {
onBlur?.(event);
}
minInputProps?.onBlur?.(event);
}}
onMouseDown={(event) => {
if (showInputOnly) {
this.preventPopoverClose = true;
}
minInputProps?.onMouseDown?.(event);
}}
/>
) : undefined;
const maxInput = !!showInput ? (
<EuiRangeInput
// Overridable props
aria-describedby={this.props['aria-describedby']}
aria-label={this.props['aria-label']}
disabled={disabled}
isInvalid={isInvalid}
name={`${name}-maxValue`}
value={this.upperValue}
readOnly={readOnly}
{...maxInputProps}
// Non-overridable props
side="max"
min={this.lowerValue === '' ? min : Number(this.lowerValue)}
max={max}
step={step}
compressed={compressed}
autoSize={!showInputOnly}
fullWidth={!!showInputOnly && fullWidth}
controlOnly={showInputOnly}
onChange={(event) => {
this.handleUpperInputChange(event);
maxInputProps?.onChange?.(event);
}}
onKeyDown={(event) => {
this.handleInputKeyDown(event);
maxInputProps?.onKeyDown?.(event);
}}
onFocus={(event) => {
if (canShowDropdown) {
this.onInputFocus(event);
} else {
onFocus?.(event);
}
maxInputProps?.onFocus?.(event);
}}
onBlur={(event) => {
if (canShowDropdown) {
this.onInputBlur(event);
} else {
onBlur?.(event);
}
maxInputProps?.onBlur?.(event);
}}
onMouseDown={(event) => {
if (showInputOnly) {
this.preventPopoverClose = true;
}
maxInputProps?.onMouseDown?.(event);
}}
/>
) : undefined;
const classes = classNames('euiDualRange', className);
const dualRangeStyles = euiDualRangeStyles();
const cssStyles = [dualRangeStyles.euiDualRange, customCss];
const leftThumbPosition = this.state.rangeWidth
? this.calculateThumbPositionStyle(
Number(this.lowerValue) || min,
this.state.rangeWidth
)
: { left: '0' };
const rightThumbPosition = this.state.rangeWidth
? this.calculateThumbPositionStyle(
Number(this.upperValue) || max,
this.state.rangeWidth
)
: { left: '0' };
const leftThumbColor =
levels && getLevelColor(levels, Number(this.lowerValue));
const rightThumbColor =
levels && getLevelColor(levels, Number(this.upperValue));
const leftThumbStyles = leftThumbColor
? {
...leftThumbPosition,
'--euiRangeThumbColor': euiRangeLevelColor(leftThumbColor, theme),
}
: leftThumbPosition;
const rightThumbStyles = rightThumbColor
? {
...rightThumbPosition,
'--euiRangeThumbColor': euiRangeLevelColor(rightThumbColor, theme),
}
: rightThumbPosition;
const dualSliderScreenReaderInstructions = (
<EuiI18n
token="euiDualRange.sliderScreenReaderInstructions"
default="You are in a custom range slider. Use the Up and Down arrow keys to change the minimum value. Press Tab to interact with the maximum value."
/>
);
const theRange = (
<EuiRangeWrapper
css={cssStyles}
className={classes}
fullWidth={fullWidth}
compressed={compressed}
>
{showInput && !showInputOnly && (
<>
{minInput}
<div
className={
showTicks || ticks
? 'euiRange__slimHorizontalSpacer'
: 'euiRange__horizontalSpacer'
}
css={
showTicks || ticks
? rangeStyles.euiRange__slimHorizontalSpacer
: rangeStyles.euiRange__horizontalSpacer
}
/>
</>
)}
{showLabels && (
<EuiRangeLabel side="min" disabled={disabled}>
{min}
</EuiRangeLabel>
)}
<EuiRangeTrack
trackWidth={this.state.rangeWidth}
compressed={compressed}
disabled={disabled}
max={max}
min={min}
step={step}
showTicks={showTicks}
tickInterval={tickInterval}
ticks={ticks}
levels={levels}
onChange={this.handleSliderChange}
value={value}
aria-hidden={showInput === true}
showRange={showRange}
>
<EuiRangeSlider
className="euiDualRange__slider"
css={dualRangeStyles.euiDualRange__slider}
id={id}
name={name}
min={min}
max={max}
step={step}
disabled={disabled}
onChange={this.handleSliderChange}
showTicks={showTicks}
aria-hidden={true}
tabIndex={-1}
showRange={showRange}
onFocus={onFocus}
onBlur={onBlur}
{...rest}
onResize={this.setRangeWidth}
/>
{isDraggable && this.isValid && (
<EuiRangeDraggable
min={min}
max={max}
value={[this.lowerValue, this.upperValue]}
disabled={disabled}
lowerPosition={leftThumbPosition.left}
upperPosition={rightThumbPosition.left}
showTicks={showTicks}
onChange={this.handleDrag}
onFocus={this.onThumbFocus}
onBlur={this.onThumbBlur}
onKeyDown={this.handleDraggableKeyDown}
aria-describedby={
showInputOnly ? undefined : this.props['aria-describedby']
}
aria-label={showInputOnly ? undefined : this.props['aria-label']}
/>
)}
<EuiRangeThumb
min={min}
max={Number(this.upperValue)}
value={this.lowerValue}
disabled={disabled}
showTicks={showTicks}
showInput={!!showInput}
onKeyDown={this.handleLowerKeyDown}
onFocus={this.onThumbFocus}
onBlur={this.onThumbBlur}
style={logicalStyles(leftThumbStyles)}
aria-describedby={
showInputOnly ? undefined : this.props['aria-describedby']
}
aria-label={showInputOnly ? undefined : this.props['aria-label']}
/>
<EuiRangeThumb
min={Number(this.lowerValue)}
max={max}
value={this.upperValue}
disabled={disabled}
showTicks={showTicks}
showInput={!!showInput}
onKeyDown={this.handleUpperKeyDown}
onFocus={this.onThumbFocus}
onBlur={this.onThumbBlur}
style={logicalStyles(rightThumbStyles)}
aria-describedby={
showInputOnly ? undefined : this.props['aria-describedby']
}
aria-label={showInputOnly ? undefined : this.props['aria-label']}
/>
{showRange && this.isValid && (
<EuiRangeHighlight
showTicks={showTicks}
min={Number(min)}
max={Number(max)}
lowerValue={Number(this.lowerValue)}
upperValue={Number(this.upperValue)}
levels={levels}
trackWidth={this.state.rangeWidth}
/>
)}
</EuiRangeTrack>
{showLabels && <EuiRangeLabel disabled={disabled}>{max}</EuiRangeLabel>}
{showInput && !showInputOnly && (
<>
<div
className={
showTicks || ticks
? 'euiRange__slimHorizontalSpacer'
: 'euiRange__horizontalSpacer'
}
css={
showTicks || ticks
? rangeStyles.euiRange__slimHorizontalSpacer
: rangeStyles.euiRange__horizontalSpacer
}
/>
{maxInput}
</>
)}
</EuiRangeWrapper>
);
const thePopover = showInputOnly ? (
<EuiInputPopover
{...inputPopoverProps}
className={classNames(
'euiDualRange__popover',
inputPopoverProps?.className
)}
input={
<EuiFormControlLayoutDelimited
startControl={minInput!}
endControl={maxInput!}
isDisabled={disabled}
fullWidth={fullWidth}
compressed={compressed}
readOnly={readOnly}
append={append}
prepend={prepend}
isLoading={isLoading}
isInvalid={isInvalid}
/>
}
fullWidth={fullWidth}
isOpen={this.state.isPopoverOpen}
closePopover={this.closePopover}
disableFocusTrap={true}
popoverScreenReaderText={dualSliderScreenReaderInstructions}
>
{theRange}
</EuiInputPopover>
) : undefined;
return thePopover || theRange;
}