@@ -3,11 +3,13 @@ import property from "@ui5/webcomponents-base/dist/decorators/property.js";
33import i18n from "@ui5/webcomponents-base/dist/decorators/i18n.js" ;
44import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js" ;
55import type { IFormInputElement } from "@ui5/webcomponents-base/dist/features/InputElementsFormSupport.js" ;
6+ import ValueState from "@ui5/webcomponents-base/dist/types/ValueState.js" ;
67import {
78 isEscape ,
89 isEnter ,
910 isHome ,
1011 isEnd ,
12+ isF2 ,
1113} from "@ui5/webcomponents-base/dist/Keys.js" ;
1214import SliderBase from "./SliderBase.js" ;
1315import RangeSliderTemplate from "./RangeSliderTemplate.js" ;
@@ -102,7 +104,14 @@ class RangeSlider extends SliderBase implements IFormInputElement {
102104 * @public
103105 */
104106 @property ( { type : Number } )
105- startValue = 0 ;
107+ set startValue ( value : number ) {
108+ this . _startValue = value ;
109+ this . tooltipStartValue = value . toString ( ) ;
110+ }
111+
112+ get startValue ( ) {
113+ return this . _startValue ;
114+ }
106115
107116 /**
108117 * Defines end point of a selection - position of a second handle on the slider.
@@ -112,7 +121,26 @@ class RangeSlider extends SliderBase implements IFormInputElement {
112121 * @public
113122 */
114123 @property ( { type : Number } )
115- endValue = 100 ;
124+ set endValue ( value : number ) {
125+ this . _endValue = value ;
126+ this . tooltipEndValue = value . toString ( ) ;
127+ }
128+
129+ get endValue ( ) {
130+ return this . _endValue ;
131+ }
132+
133+ @property ( )
134+ tooltipStartValue = "" ;
135+
136+ @property ( )
137+ tooltipEndValue = "" ;
138+
139+ @property ( )
140+ tooltipStartValueState : `${ValueState } ` = "None" ;
141+
142+ @property ( )
143+ tooltipEndValueState : `${ValueState } ` = "None" ;
116144
117145 @property ( { type : Boolean } )
118146 rangePressed = false ;
@@ -123,6 +151,8 @@ class RangeSlider extends SliderBase implements IFormInputElement {
123151 @property ( { type : Boolean } )
124152 _isEndValueValid = false ;
125153
154+ _startValue : number = 0 ;
155+ _endValue : number = 100 ;
126156 _startValueInitial ?: number ;
127157 _endValueInitial ?: number ;
128158 _valueAffected ?: AffectedValue ;
@@ -164,18 +194,6 @@ class RangeSlider extends SliderBase implements IFormInputElement {
164194 this . _lastValidEndValue = this . max . toString ( ) ;
165195 }
166196
167- get tooltipStartValue ( ) {
168- const ctor = this . constructor as typeof RangeSlider ;
169- const stepPrecision = ctor . _getDecimalPrecisionOfNumber ( this . _effectiveStep ) ;
170- return this . startValue . toFixed ( stepPrecision ) ;
171- }
172-
173- get tooltipEndValue ( ) {
174- const ctor = this . constructor as typeof RangeSlider ;
175- const stepPrecision = ctor . _getDecimalPrecisionOfNumber ( this . _effectiveStep ) ;
176- return this . endValue . toFixed ( stepPrecision ) ;
177- }
178-
179197 get _ariaDisabled ( ) {
180198 return this . disabled || undefined ;
181199 }
@@ -233,6 +251,14 @@ class RangeSlider extends SliderBase implements IFormInputElement {
233251 this . update ( this . _valueAffected , this . startValue , this . endValue ) ;
234252 }
235253
254+ onAfterRendering ( ) : void {
255+ super . onAfterRendering ( ) ;
256+
257+ [ ...this . getDomRef ( ) ! . querySelectorAll ( "[ui5-slider-tooltip]" ) ] . forEach ( tooltip => {
258+ ( tooltip as SliderTooltip ) . repositionTooltip ( ) ;
259+ } ) ;
260+ }
261+
236262 syncUIAndState ( ) {
237263 // Validate step and update the stored state for the step property.
238264 if ( this . isPropertyUpdated ( "step" ) ) {
@@ -370,6 +396,9 @@ class RangeSlider extends SliderBase implements IFormInputElement {
370396 const newEndValue = ctor . clipValue ( newValueOffset + this . endValue , min , max ) ;
371397 this . update ( affectedValue , newStartValue , newEndValue ) ;
372398 }
399+
400+ this . tooltipStartValue = this . startValue . toString ( ) ;
401+ this . tooltipEndValue = this . endValue . toString ( ) ;
373402 }
374403
375404 /**
@@ -515,6 +544,9 @@ class RangeSlider extends SliderBase implements IFormInputElement {
515544
516545 // Updates UI and state when dragging of the whole selected range
517546 this . _updateValueOnRangeDrag ( e ) ;
547+
548+ this . tooltipStartValue = this . startValue . toString ( ) ;
549+ this . tooltipEndValue = this . endValue . toString ( ) ;
518550 }
519551
520552 /**
@@ -779,7 +811,12 @@ class RangeSlider extends SliderBase implements IFormInputElement {
779811 const tooltip = this . shadowRoot ! . querySelector ( tooltipSelector ) as SliderTooltip ;
780812
781813 if ( tooltip ?. hidePopover && tooltip ?. showPopover ) {
782- requestAnimationFrame ( ( ) => {
814+ const frame = requestAnimationFrame ( ( ) => {
815+ if ( tooltip . getDomRef ( ) ?. offsetParent === null ) {
816+ cancelAnimationFrame ( frame ) ;
817+ return ;
818+ }
819+
783820 tooltip . hidePopover ( ) ;
784821 tooltip . showPopover ( ) ;
785822 } ) ;
@@ -796,6 +833,18 @@ class RangeSlider extends SliderBase implements IFormInputElement {
796833 const tooltip = e . target as SliderTooltip ;
797834 const isStart = tooltip . hasAttribute ( "data-sap-ui-start-value" ) ;
798835 const inputValue = parseFloat ( e . detail . value as string ) ;
836+ const isInvalid = inputValue > this . _effectiveMax || inputValue < this . _effectiveMin ;
837+
838+ if ( isInvalid ) {
839+ if ( isStart ) {
840+ this . tooltipStartValueState = ValueState . Negative ;
841+ this . tooltipStartValue = e . detail . value ;
842+ } else {
843+ this . tooltipEndValueState = ValueState . Negative ;
844+ this . tooltipEndValue = e . detail . value ;
845+ }
846+ return ;
847+ }
799848
800849 const clampedValue = Math . min ( this . max , Math . max ( this . min , inputValue ) ) ;
801850
@@ -831,6 +880,48 @@ class RangeSlider extends SliderBase implements IFormInputElement {
831880 this . fireDecoratorEvent ( "change" ) ;
832881 }
833882
883+ _onTooltipFocusChange ( e : CustomEvent ) {
884+ const tooltip = e . target as SliderTooltip ;
885+ const isStart = tooltip . hasAttribute ( "data-sap-ui-start-value" ) ;
886+ const value = isStart ? this . tooltipStartValue : this . tooltipEndValue ;
887+ const isInvalid = parseFloat ( value ) > this . _effectiveMax || parseFloat ( value ) < this . _effectiveMin ;
888+
889+ if ( isInvalid ) {
890+ if ( isStart ) {
891+ this . tooltipStartValueState = ValueState . None ;
892+ this . tooltipStartValue = this . startValue . toString ( ) ;
893+ } else {
894+ this . tooltipEndValueState = ValueState . None ;
895+ this . tooltipEndValue = this . endValue . toString ( ) ;
896+ }
897+ }
898+ }
899+
900+ _onTooltipOpen ( ) {
901+ const ctor = this . constructor as typeof RangeSlider ;
902+ const stepPrecision = ctor . _getDecimalPrecisionOfNumber ( this . _effectiveStep ) ;
903+ this . tooltipStartValue = this . startValue . toFixed ( stepPrecision ) ;
904+ this . tooltipEndValue = this . endValue . toFixed ( stepPrecision ) ;
905+ }
906+
907+ _onTooltipInput ( e : CustomEvent ) {
908+ const tooltip = e . target as SliderTooltip ;
909+ const isStart = tooltip . hasAttribute ( "data-sap-ui-start-value" ) ;
910+
911+ if ( isStart ) {
912+ this . tooltipStartValue = e . detail . value ;
913+ } else {
914+ this . tooltipEndValue = e . detail . value ;
915+ }
916+ }
917+
918+ _onTooltipKeydown ( e : KeyboardEvent ) {
919+ if ( isF2 ( e ) ) {
920+ e . preventDefault ( ) ;
921+ ( e . target as SliderTooltip ) . followRef ?. focus ( ) ;
922+ }
923+ }
924+
834925 _getFormattedValue ( value : string ) {
835926 const valueNumber = parseFloat ( value ) ;
836927 const ctor = this . constructor as typeof RangeSlider ;
0 commit comments