This commit is contained in:
Gerard Burns 2024-04-02 16:46:31 +01:00
parent 8631b3ae75
commit 09485d6540
3 changed files with 83 additions and 103 deletions

View File

@ -17,7 +17,8 @@
TooltipType,
} from "../../Tooltip/AbsTooltip.svelte"
import ContextTooltip from "../../Tooltip/Context.svelte"
import { fade } from 'svelte/transition';
import { Heading } from "@budibase/bbui"
export let id = null
@ -119,7 +120,7 @@
component?.removeEventListener("scroll", null)
})
const handleMouseenter = (e, option) => {
const handleMouseenter = (e, option, idx) => {
contextTooltipId += 1;
const invokedContextTooltipId = contextTooltipId
@ -230,8 +231,8 @@
{#if filteredOptions.length}
{#each filteredOptions as option, idx}
<li
on:mouseenter={(e) => handleMouseenter(e, option)}
on:mouseleave={(e) => handleMouseleave(e, option)}
on:mouseenter={(e) => handleMouseenter(e, option, idx)}
on:mouseleave={(e) => handleMouseleave(e, option, idx)}
class="spectrum-Menu-item"
class:is-selected={isOptionSelected(getOptionValue(option, idx))}
role="option"
@ -303,27 +304,42 @@
visible={contextTooltipVisible}
anchor={contextTooltipAnchor}
>
<div
class="tooltipContents"
>
{contextTooltipOption}
</div>
<div slot="previous"
class="tooltipContents"
>
{previousContextTooltipOption}
</div>
<div
class="tooltipContents"
>
{#if contextTooltipOption}
<Icon name={getOptionIcon(contextTooltipOption)} />
<Heading>{contextTooltipOption}</Heading>
{/if}
</div>
<div slot="previous"
class="tooltipContents"
>
{#if previousContextTooltipOption}
<Icon name={getOptionIcon(previousContextTooltipOption)} />
<Heading>{previousContextTooltipOption}</Heading>
{/if}
</div>
</ContextTooltip>
<style>
.tooltipContents {
background-color: red;
max-width: 200px;
text-wrap: wrap;
background-color: var(--spectrum-global-color-gray-200);
display: inline-block;
}
.tooltipContents :global(h1) {
font-size: 15px;
text-wrap: wrap;
word-break: break-all;
}
.tooltipContents :global(svg) {
color: var(--background);
fill: var(--background);
}
.spectrum-Menu {
display: block;
}

View File

@ -2,11 +2,14 @@
import Portal from "svelte-portal"
import { fade } from 'svelte/transition';
export let wrapper
export let resetWrapper
export let currentTooltip
export let anchor
export let visible = false
export let hovering = false
let initialShow = true;
let previousX = 0
let previousY = 0
let currentX = 0
@ -15,15 +18,15 @@
let currentTooltipWidth = 0
let currentTooltipHeight = 0
const updatePositionOnVisibilityChange = (visible, hovering) => {
const handleVisibilityChange = (visible, hovering) => {
if (!visible && !hovering) {
previousX = 0;
previousY = 0;
} }
initialShow = true;
}
}
const updatePosition = (anchor, currentTooltip) => {
const updatePosition = (anchor, currentTooltip, wrapper, resetWrapper) => {
requestAnimationFrame(() => {
if (anchor == null || currentTooltip == null) {
if (anchor == null || currentTooltip == null || wrapper == null || resetWrapper == null) {
return;
}
@ -39,77 +42,30 @@
currentX = rect.x - currentTooltipWidth
currentY = rect.y
if (previousX === 0) {
previousX = currentX
}
// Bypass animations if the tooltip has only just been opened
if (initialShow) {
initialShow = false;
if (previousY === 0) {
previousY = currentY
wrapper.style.transition = "none";
wrapper.style.width = `${currentTooltipWidth}px`
wrapper.style.height = `${currentTooltipHeight}px`
wrapper.style.top = `${currentY}px`
wrapper.style.left = `${currentX}px`
resetWrapper.style.transition = "none";
resetWrapper.style.top = `${-currentY}px`
resetWrapper.style.left = `${-currentX}px`
requestAnimationFrame(() => {
wrapper.style.removeProperty("transition");
resetWrapper.style.removeProperty("transition");
})
}
})
}
/*
const getNormalizedTime = (startTime, endTime, currentTime) => {
const distanceFromStart = currentTime - startTime;
const timeDiff = endTime - startTime;
return distanceFromStart / timeDiff;
}
const cubicBezierInterpolation = (p1, p2, p3, p4, currentTime) => {
return (
(Math.pow(1 - currentTime, 3) * p1) +
(3 * Math.pow(1 - currentTime, 2) * currentTime * p2) +
(3 * (1 - currentTime) * Math.pow(currentTime, 2) * p3) +
(Math.pow(currentTime, 3) * p4)
)
}
// Made to match the interface of the css bezier curve function
const cubicBezierEasing = (a, b, c, d, t) => {
// CSS bezier curve function implicitly provides p1 and p4
const p1 = { x: 0, y: 0 }
const p2 = { x: a, y: b }
const p3 = { x: c, y: d }
const p4 = { x: 1, y: 1 }
return {
x: cubicBezierInterpolation(p1.x, p2.x, p3.x, p4.x, t),
y: cubicBezierInterpolation(p1.y, p2.y, p3.y, p4.y, t)
}
}
const linearInterpolation = (p1, p2, t) => {
return p1 + t * (p2 - p1);
}
const animate = (invokedAnimationStartTime, frameTime) => {
if (invokedAnimationStartTime !== animationStartTime) {
console.log("CANCEL ANIMATION ", invokedAnimationStartTime, " ", animationStartTime);
return;
}
const animationDuration = 300
const normalizedTime = getNormalizedTime(invokedAnimationStartTime, invokedAnimationStartTime + animationDuration, frameTime)
if (normalizedTime >= 1) {
console.log("exiting");
return;
}
const easing = cubicBezierEasing(0.25, 0.1, 0.25, 1, normalizedTime)
x = linearInterpolation(startX, endX, easing.x)
y = linearInterpolation(startY, endY, easing.y)
w = linearInterpolation(previousTooltipWidth, currentTooltipWidth, easing.x)
requestAnimationFrame((newFrameTime) => animate(invokedAnimationStartTime, newFrameTime))
}*/
$: updatePosition(anchor, currentTooltip)
$: updatePositionOnVisibilityChange(visible, hovering)
/*$: requestAnimationFrame((frameTime) => animate(animationStartTime, frameTime))*/
$: updatePosition(anchor, currentTooltip, wrapper, resetWrapper)
$: handleVisibilityChange(visible, hovering)
const handleMouseenter = (e) => {
hovering = true;
@ -118,10 +74,19 @@
const handleMouseleave = (e) => {
hovering = false;
}
$: {
console.log(currentX)
console.log(currentY)
console.log(currentTooltipWidth)
console.log(currentTooltipHeight)
console.log();
}
</script>
<Portal target=".spectrum">
<div
bind:this={wrapper}
on:mouseenter={handleMouseenter}
on:mouseleave={handleMouseleave}
style:width={`${currentTooltipWidth}px`}
@ -131,7 +96,11 @@
class="tooltip"
class:visible={visible || hovering}
>
<div class="screenSize"
<!-- absolutely position element with the opposite positioning, so that the tooltip elements can be positioned
using the same values as the root wrapper, while still being occluded by it.
-->
<div class="screenSizeAbsoluteWrapper"
bind:this={resetWrapper}
style:left={`${-currentX}px`}
style:top={`${-currentY}px`}
>
@ -155,25 +124,24 @@
</Portal>
<style>
/* Screen width absolute parent for tooltip content so that'd the applied width and height
to the root doesn't affect their size */
.screenSize {
position: absolute;
width: 100vw;
height: 100vh;
transition: top 300ms ease-in, left 300ms ease-in;
}
.tooltip {
position: absolute;
z-index: 9999;
pointer-events: none;
background-color: red;
background-color: var(--spectrum-global-color-gray-200);
opacity: 0;
overflow: hidden;
transition: width 300ms ease-in, height 300ms ease-in, top 300ms ease-in, left 300ms ease-in;
}
.screenSizeAbsoluteWrapper {
position: absolute;
width: 100vw;
height: 100vh;
transition: top 300ms ease-in, left 300ms ease-in;
}
.visible {
opacity: 1;
pointer-events: auto;

View File

@ -10,10 +10,6 @@
export let placeholder
export let fieldValidator
$: {
console.log(fieldValidator);
}
const getFieldSupport = (schema, fieldValidator) => {
if (fieldValidator == null) {
return {}