wip
This commit is contained in:
parent
8631b3ae75
commit
09485d6540
|
@ -17,7 +17,8 @@
|
||||||
TooltipType,
|
TooltipType,
|
||||||
} from "../../Tooltip/AbsTooltip.svelte"
|
} from "../../Tooltip/AbsTooltip.svelte"
|
||||||
import ContextTooltip from "../../Tooltip/Context.svelte"
|
import ContextTooltip from "../../Tooltip/Context.svelte"
|
||||||
import { fade } from 'svelte/transition';
|
import { Heading } from "@budibase/bbui"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export let id = null
|
export let id = null
|
||||||
|
@ -119,7 +120,7 @@
|
||||||
component?.removeEventListener("scroll", null)
|
component?.removeEventListener("scroll", null)
|
||||||
})
|
})
|
||||||
|
|
||||||
const handleMouseenter = (e, option) => {
|
const handleMouseenter = (e, option, idx) => {
|
||||||
contextTooltipId += 1;
|
contextTooltipId += 1;
|
||||||
const invokedContextTooltipId = contextTooltipId
|
const invokedContextTooltipId = contextTooltipId
|
||||||
|
|
||||||
|
@ -230,8 +231,8 @@
|
||||||
{#if filteredOptions.length}
|
{#if filteredOptions.length}
|
||||||
{#each filteredOptions as option, idx}
|
{#each filteredOptions as option, idx}
|
||||||
<li
|
<li
|
||||||
on:mouseenter={(e) => handleMouseenter(e, option)}
|
on:mouseenter={(e) => handleMouseenter(e, option, idx)}
|
||||||
on:mouseleave={(e) => handleMouseleave(e, option)}
|
on:mouseleave={(e) => handleMouseleave(e, option, idx)}
|
||||||
class="spectrum-Menu-item"
|
class="spectrum-Menu-item"
|
||||||
class:is-selected={isOptionSelected(getOptionValue(option, idx))}
|
class:is-selected={isOptionSelected(getOptionValue(option, idx))}
|
||||||
role="option"
|
role="option"
|
||||||
|
@ -303,27 +304,42 @@
|
||||||
visible={contextTooltipVisible}
|
visible={contextTooltipVisible}
|
||||||
anchor={contextTooltipAnchor}
|
anchor={contextTooltipAnchor}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="tooltipContents"
|
class="tooltipContents"
|
||||||
>
|
>
|
||||||
{contextTooltipOption}
|
{#if contextTooltipOption}
|
||||||
</div>
|
<Icon name={getOptionIcon(contextTooltipOption)} />
|
||||||
<div slot="previous"
|
<Heading>{contextTooltipOption}</Heading>
|
||||||
class="tooltipContents"
|
{/if}
|
||||||
>
|
</div>
|
||||||
{previousContextTooltipOption}
|
<div slot="previous"
|
||||||
</div>
|
class="tooltipContents"
|
||||||
|
>
|
||||||
|
{#if previousContextTooltipOption}
|
||||||
|
<Icon name={getOptionIcon(previousContextTooltipOption)} />
|
||||||
|
<Heading>{previousContextTooltipOption}</Heading>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
</ContextTooltip>
|
</ContextTooltip>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.tooltipContents {
|
.tooltipContents {
|
||||||
background-color: red;
|
|
||||||
max-width: 200px;
|
max-width: 200px;
|
||||||
text-wrap: wrap;
|
background-color: var(--spectrum-global-color-gray-200);
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltipContents :global(h1) {
|
||||||
|
font-size: 15px;
|
||||||
|
text-wrap: wrap;
|
||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tooltipContents :global(svg) {
|
||||||
|
color: var(--background);
|
||||||
|
fill: var(--background);
|
||||||
|
}
|
||||||
|
|
||||||
.spectrum-Menu {
|
.spectrum-Menu {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,14 @@
|
||||||
import Portal from "svelte-portal"
|
import Portal from "svelte-portal"
|
||||||
import { fade } from 'svelte/transition';
|
import { fade } from 'svelte/transition';
|
||||||
|
|
||||||
|
export let wrapper
|
||||||
|
export let resetWrapper
|
||||||
export let currentTooltip
|
export let currentTooltip
|
||||||
export let anchor
|
export let anchor
|
||||||
export let visible = false
|
export let visible = false
|
||||||
export let hovering = false
|
export let hovering = false
|
||||||
|
|
||||||
|
let initialShow = true;
|
||||||
let previousX = 0
|
let previousX = 0
|
||||||
let previousY = 0
|
let previousY = 0
|
||||||
let currentX = 0
|
let currentX = 0
|
||||||
|
@ -15,15 +18,15 @@
|
||||||
let currentTooltipWidth = 0
|
let currentTooltipWidth = 0
|
||||||
let currentTooltipHeight = 0
|
let currentTooltipHeight = 0
|
||||||
|
|
||||||
const updatePositionOnVisibilityChange = (visible, hovering) => {
|
const handleVisibilityChange = (visible, hovering) => {
|
||||||
if (!visible && !hovering) {
|
if (!visible && !hovering) {
|
||||||
previousX = 0;
|
initialShow = true;
|
||||||
previousY = 0;
|
}
|
||||||
} }
|
}
|
||||||
|
|
||||||
const updatePosition = (anchor, currentTooltip) => {
|
const updatePosition = (anchor, currentTooltip, wrapper, resetWrapper) => {
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
if (anchor == null || currentTooltip == null) {
|
if (anchor == null || currentTooltip == null || wrapper == null || resetWrapper == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,77 +42,30 @@
|
||||||
currentX = rect.x - currentTooltipWidth
|
currentX = rect.x - currentTooltipWidth
|
||||||
currentY = rect.y
|
currentY = rect.y
|
||||||
|
|
||||||
if (previousX === 0) {
|
// Bypass animations if the tooltip has only just been opened
|
||||||
previousX = currentX
|
if (initialShow) {
|
||||||
}
|
initialShow = false;
|
||||||
|
|
||||||
if (previousY === 0) {
|
wrapper.style.transition = "none";
|
||||||
previousY = currentY
|
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");
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
$: updatePosition(anchor, currentTooltip, wrapper, resetWrapper)
|
||||||
const getNormalizedTime = (startTime, endTime, currentTime) => {
|
$: handleVisibilityChange(visible, hovering)
|
||||||
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))*/
|
|
||||||
|
|
||||||
const handleMouseenter = (e) => {
|
const handleMouseenter = (e) => {
|
||||||
hovering = true;
|
hovering = true;
|
||||||
|
@ -118,10 +74,19 @@
|
||||||
const handleMouseleave = (e) => {
|
const handleMouseleave = (e) => {
|
||||||
hovering = false;
|
hovering = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$: {
|
||||||
|
console.log(currentX)
|
||||||
|
console.log(currentY)
|
||||||
|
console.log(currentTooltipWidth)
|
||||||
|
console.log(currentTooltipHeight)
|
||||||
|
console.log();
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Portal target=".spectrum">
|
<Portal target=".spectrum">
|
||||||
<div
|
<div
|
||||||
|
bind:this={wrapper}
|
||||||
on:mouseenter={handleMouseenter}
|
on:mouseenter={handleMouseenter}
|
||||||
on:mouseleave={handleMouseleave}
|
on:mouseleave={handleMouseleave}
|
||||||
style:width={`${currentTooltipWidth}px`}
|
style:width={`${currentTooltipWidth}px`}
|
||||||
|
@ -131,7 +96,11 @@
|
||||||
class="tooltip"
|
class="tooltip"
|
||||||
class:visible={visible || hovering}
|
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:left={`${-currentX}px`}
|
||||||
style:top={`${-currentY}px`}
|
style:top={`${-currentY}px`}
|
||||||
>
|
>
|
||||||
|
@ -155,25 +124,24 @@
|
||||||
</Portal>
|
</Portal>
|
||||||
|
|
||||||
<style>
|
<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 {
|
.tooltip {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 9999;
|
z-index: 9999;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
background-color: red;
|
background-color: var(--spectrum-global-color-gray-200);
|
||||||
|
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
transition: width 300ms ease-in, height 300ms ease-in, top 300ms ease-in, left 300ms ease-in;
|
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 {
|
.visible {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
|
|
|
@ -10,10 +10,6 @@
|
||||||
export let placeholder
|
export let placeholder
|
||||||
export let fieldValidator
|
export let fieldValidator
|
||||||
|
|
||||||
$: {
|
|
||||||
console.log(fieldValidator);
|
|
||||||
}
|
|
||||||
|
|
||||||
const getFieldSupport = (schema, fieldValidator) => {
|
const getFieldSupport = (schema, fieldValidator) => {
|
||||||
if (fieldValidator == null) {
|
if (fieldValidator == null) {
|
||||||
return {}
|
return {}
|
||||||
|
|
Loading…
Reference in New Issue