11<script setup>
2- import { ref , computed , watch , onMounted , onBeforeUnmount } from ' vue' ;
2+ import { ref , computed , watch , onMounted , onBeforeUnmount , nextTick , onUpdated } from ' vue' ;
33import BaseIcon from ' ./BaseIcon.vue' ;
44import { useResponsive } from ' ../useResponsive' ;
55import { throttle } from ' ../canvas-lib' ;
6- import { XMLNS , createSmoothPath , createStraightPath , createUid } from ' ../lib' ;
6+ import { XMLNS , adaptColorToBackground , createSmoothPath , createStraightPath , createUid } from ' ../lib' ;
77
88const props = defineProps ({
99 background: {
@@ -128,13 +128,28 @@ const highlightStyle = computed(() => {
128128 const range = props .max - props .min ;
129129 const startPercent = ((startValue .value - props .min ) / range) * 100 ;
130130 const endPercent = ((endValue .value - props .min ) / range) * 100 ;
131+
131132 return {
132133 left: ` ${ startPercent} %` ,
133134 width: ` ${ endPercent - startPercent} %` ,
134- background: props .selectColor
135+ background: props .selectColor ,
136+ tooltipLeft: ` calc(${ startPercent} % - ${ overflowsLeft .value ? 0 : tooltipLeftWidth .value / 2 } px)` ,
137+ tooltipRight: ` calc(${ endPercent} % - ${ overflowsRight .value ? tooltipRightWidth .value : tooltipRightWidth .value / 2 } px)` ,
138+ arrowLeft: ! overflowsLeft .value ,
139+ arrowRight: ! overflowsRight .value
135140 };
136141});
137142
143+ const overflowsLeft = computed (() => {
144+ if (! zoomWrapper .value ) return false ;
145+ return zoomWrapper .value .getBoundingClientRect ().width * ((startValue .value - props .min ) / (props .max - props .min )) - tooltipLeftWidth .value / 2 < 0
146+ });
147+
148+ const overflowsRight = computed (() => {
149+ if (! zoomWrapper .value ) return false ;
150+ return zoomWrapper .value .getBoundingClientRect ().width * ((endValue .value - props .min ) / (props .max - props .min )) + tooltipRightWidth .value / 2 > zoomWrapper .value .getBoundingClientRect ().width ;
151+ })
152+
138153const slicerColor = computed (() => props .inputColor );
139154const backgroundColor = computed (() => props .background );
140155const selectColorOpaque = computed (() => ` ${ props .selectColor } 33` );
@@ -336,6 +351,7 @@ const flooredDatapointsToWidth = computed(() => {
336351})
337352
338353const startDragging = (event ) => {
354+ showTooltip .value = true ;
339355 if (! props .enableSelectionDrag ) {
340356 return ;
341357 }
@@ -408,6 +424,39 @@ function endDragging(moveEvent, endEvent) {
408424 window .removeEventListener (endEvent, stopDragging);
409425};
410426
427+ const isMouseDown = ref (false )
428+ const tooltipLeft = ref (null );
429+ const tooltipRight = ref (null );
430+ const tooltipLeftWidth = ref (1 );
431+ const tooltipRightWidth = ref (1 );
432+ const showTooltip = ref (false );
433+
434+ function setTooltipLeft () {
435+ if (tooltipLeft .value ) {
436+ tooltipLeftWidth .value = tooltipLeft .value .getBoundingClientRect ().width ;
437+ }
438+ }
439+
440+ function setTooltipRight () {
441+ if (tooltipRight .value ) {
442+ tooltipRightWidth .value = tooltipRight .value .getBoundingClientRect ().width ;
443+ }
444+ }
445+
446+ onUpdated (() => {
447+ setTooltipLeft ();
448+ setTooltipRight ();
449+ })
450+
451+ watch (() => props .labelLeft , () => {
452+ nextTick (setTooltipLeft);
453+ }, { deep: true });
454+
455+ watch (() => props .labelRight , () => {
456+ nextTick (setTooltipRight);
457+ }, { deep: true });
458+
459+
411460defineExpose ({
412461 setStartValue,
413462 setEndValue
@@ -423,6 +472,7 @@ defineExpose({
423472 ref =" zoomWrapper"
424473 @mousedown =" startDragging"
425474 @touchstart =" startDragging"
475+ @touchend =" showTooltip = false"
426476 >
427477 <div class =" vue-data-ui-slicer-labels" style =" position : relative ; z-index : 1 ; pointer-events : none ;" >
428478 <div v-if =" valueStart !== refreshStartPoint || valueEnd !== endpoint" style =" width : 100% ; position : relative " >
@@ -442,7 +492,7 @@ defineExpose({
442492 </div >
443493 </div >
444494
445- <div class =" double-range-slider" ref =" minimapWrapper" style =" z-index : 0 " >
495+ <div class =" double-range-slider" ref =" minimapWrapper" style =" z-index : 0 " @mouseenter = " showTooltip = true " @mouseleave = " showTooltip = false " >
446496 <template v-if =" hasMinimap " >
447497 <div class =" minimap" style =" width : 100% " data-cy =" minimap" >
448498 <svg :xmlns =" XMLNS" :viewBox =" `0 0 ${svgMinimap.width < 0 ? 0 : svgMinimap.width} ${svgMinimap.height < 0 ? 0 : svgMinimap.height}`" >
@@ -563,19 +613,30 @@ defineExpose({
563613 fill =" transparent"
564614 style =" pointer-events : all !important ;"
565615 :style =" {
566- cursor: trap >= valueStart && trap < valueEnd && enableSelectionDrag ? 'move ' : 'default',
616+ cursor: trap >= valueStart && trap < valueEnd && enableSelectionDrag ? isMouseDown ? 'grabbing' : 'grab ' : 'default',
567617 }"
618+ @mousedown =" isMouseDown = true"
619+ @mouseup =" isMouseDown = false"
568620 @mouseenter =" trapMouse(trap)"
569621 @mouseleave =" selectedTrap = null; emit('trapMouse', null)"
570622 />
571623 </svg >
572624 </div >
573625 </template >
574626 <div class =" slider-track" ></div >
575- <div :class =" {
576- 'range-highlight': true,
577- 'move': enableSelectionDrag
578- }" :style =" highlightStyle" ></div >
627+ <div
628+ :class =" {
629+ 'range-highlight': true,
630+ 'move': enableSelectionDrag
631+ }"
632+ @mousedown =" isMouseDown = true"
633+ @mouseup =" isMouseDown = false"
634+ :style =" {
635+ ...highlightStyle,
636+ cursor: isMouseDown ? 'grabbing' : 'grab'
637+ }"
638+ />
639+
579640 <input
580641 v-if =" enableRangeHandles"
581642 ref =" rangeStart"
@@ -587,9 +648,9 @@ defineExpose({
587648 v-model =" startValue"
588649 @input =" onStartInput"
589650 />
590- <div class =" thumb-label thumb-label-left" :style =" leftLabelPosition" >
651+ <!-- < div class="thumb-label thumb-label-left" :style="leftLabelPosition">
591652 {{ labelLeft }}
592- </div >
653+ </div> -->
593654 <input
594655 v-if =" enableRangeHandles"
595656 ref =" rangeEnd"
@@ -600,7 +661,43 @@ defineExpose({
600661 v-model =" endValue"
601662 @input =" onEndInput"
602663 />
603- <div class =" thumb-label thumb-label-right" :style =" rightLabelPosition" >
664+ <!-- <div class="thumb-label thumb-label-right" :style="rightLabelPosition">
665+ {{ labelRight }}
666+ </div> -->
667+ <div
668+ v-if =" labelLeft"
669+ ref =" tooltipLeft"
670+ :class =" {
671+ 'range-tooltip': true,
672+ 'range-tooltip-visible': showTooltip,
673+ 'range-tooltip-arrow': highlightStyle.arrowLeft && !verticalHandles,
674+ 'range-tooltip-arrow-left': !highlightStyle.arrowLeft && !verticalHandles
675+ }"
676+ :style =" {
677+ left: highlightStyle.tooltipLeft,
678+ color: adaptColorToBackground(selectColor),
679+ backgroundColor: selectColor,
680+ border: `1px solid ${borderColor}`
681+ }"
682+ >
683+ {{ labelLeft }}
684+ </div >
685+ <div
686+ v-if =" labelRight"
687+ ref =" tooltipRight"
688+ :class =" {
689+ 'range-tooltip': true,
690+ 'range-tooltip-visible': showTooltip,
691+ 'range-tooltip-arrow': highlightStyle.arrowRight && !verticalHandles,
692+ 'range-tooltip-arrow-right': !highlightStyle.arrowRight && !verticalHandles
693+ }"
694+ :style =" {
695+ left: highlightStyle.tooltipRight,
696+ color: adaptColorToBackground(selectColor),
697+ backgroundColor: selectColor,
698+ border: `1px solid ${borderColor}`
699+ }"
700+ >
604701 {{ labelRight }}
605702 </div >
606703 </div >
@@ -787,4 +884,55 @@ input[type="range"]::-ms-thumb {
787884 width : 1px ;
788885 white-space : nowrap ;
789886}
887+
888+ .range-tooltip {
889+ z-index : 4 ;
890+ padding : 2px 4px ;
891+ font-size : 10px ;
892+ border-radius : 3px ;
893+ opacity : 0 ;
894+ transition : opacity 0.3s ease-in-out ;
895+ text-align :center ;
896+ pointer-events : none ;
897+ position : absolute ;
898+ top : -100% ;
899+ width : fit-content ;
900+ }
901+
902+ .range-tooltip-arrow ,
903+ .range-tooltip-arrow-left ,
904+ .range-tooltip-arrow-right {
905+ & ::after {
906+ content : ' ' ;
907+ position : absolute ;
908+ top : 100% ;
909+ border-width : 4px ;
910+ border-style : solid ;
911+ border-color : v-bind (selectColor ) transparent transparent transparent ;
912+ }
913+ }
914+
915+ .range-tooltip-arrow {
916+ & ::after {
917+ left : 50% ;
918+ transform : translateX (-50% );
919+ }
920+ }
921+
922+ .range-tooltip-arrow-left {
923+ & ::after {
924+ left : 3px ;
925+ }
926+ }
927+
928+ .range-tooltip-arrow-right {
929+ & ::after {
930+ right : 3px ;
931+ }
932+ }
933+
934+ .range-tooltip-visible {
935+ opacity : 1 ;
936+ transition : opacity 0.3s ease-in-out ;
937+ }
790938 </style >
0 commit comments