From 096a14578bbb926b0baafc4d713b1885b3af63b6 Mon Sep 17 00:00:00 2001 From: Alexander Platov Date: Mon, 19 Sep 2022 16:57:41 +0300 Subject: [PATCH] Update Scroller: add horizontal scroll (#2271) Signed-off-by: Alexander Platov --- packages/ui/src/components/Scroller.svelte | 237 ++++++++++++++---- .../src/components/TableBrowser.svelte | 6 +- 2 files changed, 191 insertions(+), 52 deletions(-) diff --git a/packages/ui/src/components/Scroller.svelte b/packages/ui/src/components/Scroller.svelte index 107f2516ee..b8eaa059e1 100644 --- a/packages/ui/src/components/Scroller.svelte +++ b/packages/ui/src/components/Scroller.svelte @@ -21,26 +21,29 @@ export let padding: string | undefined = undefined export let autoscroll: boolean = false - // export let correctPadding: number = 0 export let bottomStart: boolean = false export let fade: FadeOptions = defaultSP - // export let verticalFade: boolean = false export let invertScroll: boolean = false + export let horizontal: boolean = false let mask: 'top' | 'bottom' | 'both' | 'none' = 'none' + let maskH: 'left' | 'right' | 'both' | 'none' = 'none' let divScroll: HTMLElement let divBox: HTMLElement let divBar: HTMLElement - let divTrack: HTMLElement - let isScrolling: boolean = false - let dY: number + let divBarH: HTMLElement + let isScrolling: 'vertical' | 'horizontal' | false = false + let dXY: number let belowContent: number | undefined = undefined let beforeContent: number | undefined = undefined + let leftContent: number | undefined = undefined + let rightContent: number | undefined = undefined let scrolling: boolean = autoscroll let firstScroll: boolean = autoscroll let timer: number + let timerH: number $: shiftTop = fade.offset?.top ? (fade.multipler?.top ?? 0) * $themeOptions.fontSize : 0 $: shiftBottom = fade.offset?.bottom ? fade.multipler?.bottom! * $themeOptions.fontSize : 0 @@ -68,21 +71,57 @@ if (divScroll.clientHeight >= divScroll.scrollHeight) divBar.style.visibility = 'hidden' } } + const checkBarH = (): void => { + if (divBarH && divScroll) { + const trackW = divScroll.clientWidth - (mask !== 'none' ? 14 : 4) + const scrollW = divScroll.scrollWidth + const proc = scrollW / trackW + divBarH.style.width = divScroll.clientWidth / proc + 'px' + divBarH.style.left = divScroll.scrollLeft / proc + 2 + 'px' + if (maskH === 'none') divBarH.style.visibility = 'hidden' + else { + divBarH.style.visibility = 'visible' + if (divBarH) { + if (timerH) { + clearTimeout(timerH) + divBarH.style.opacity = '1' + } + timerH = setTimeout(() => { + if (divBarH) divBarH.style.opacity = '0' + }, 1500) + } + } + if (divScroll.clientWidth >= divScroll.scrollWidth) divBarH.style.visibility = 'hidden' + } + } const onScroll = (event: MouseEvent): void => { scrolling = false if (isScrolling && divBar && divScroll) { const rectScroll = divScroll.getBoundingClientRect() - let Y = event.clientY - dY - if (Y < rectScroll.top + shiftTop + 2) Y = rectScroll.top + shiftTop + 2 - if (Y > rectScroll.bottom - divBar.clientHeight - shiftBottom - 2) { - Y = rectScroll.bottom - divBar.clientHeight - shiftBottom - 2 + if (isScrolling === 'vertical') { + let Y = event.clientY - dXY + if (Y < rectScroll.top + shiftTop + 2) Y = rectScroll.top + shiftTop + 2 + if (Y > rectScroll.bottom - divBar.clientHeight - shiftBottom - 2) { + Y = rectScroll.bottom - divBar.clientHeight - shiftBottom - 2 + } + divBar.style.top = Y - rectScroll.y + 'px' + const topBar = Y - rectScroll.y - shiftTop - 2 + const heightScroll = rectScroll.height - 4 - divBar.clientHeight - shiftTop - shiftBottom + const procBar = topBar / heightScroll + divScroll.scrollTop = (divScroll.scrollHeight - divScroll.clientHeight) * procBar + } else { + let X = event.clientX - dXY + if (X < rectScroll.left + 2) X = rectScroll.left + 2 + if (X > rectScroll.right - divBarH.clientWidth - (mask !== 'none' ? 12 : 2)) { + X = rectScroll.right - divBarH.clientWidth - (mask !== 'none' ? 12 : 2) + } + divBarH.style.left = X - rectScroll.x + 'px' + const topBar = X - rectScroll.x - (mask !== 'none' ? 12 : 2) + const widthScroll = rectScroll.width - 2 - divBarH.clientWidth - (mask !== 'none' ? 12 : 2) + const procBar = topBar / widthScroll + divScroll.scrollLeft = (divScroll.scrollWidth - divScroll.clientWidth) * procBar } - divBar.style.top = Y - rectScroll.y + 'px' - const topBar = Y - rectScroll.y - shiftTop - 2 - const heightScroll = rectScroll.height - 4 - divBar.clientHeight - shiftTop - shiftBottom - const procBar = topBar / heightScroll - divScroll.scrollTop = (divScroll.scrollHeight - divScroll.clientHeight) * procBar } } const onScrollEnd = (event: MouseEvent): void => { @@ -95,16 +134,19 @@ document.removeEventListener('mouseup', onScrollEnd) isScrolling = false } - const onScrollStart = (event: MouseEvent): void => { + const onScrollStart = (event: MouseEvent, direction: 'vertical' | 'horizontal'): void => { scrolling = false const el: HTMLElement = event.currentTarget as HTMLElement if (el && divScroll) { - dY = event.clientY - el.getBoundingClientRect().y + dXY = + direction === 'vertical' + ? event.clientY - el.getBoundingClientRect().y + : event.clientX - el.getBoundingClientRect().x document.addEventListener('mouseup', onScrollEnd) document.addEventListener('mousemove', onScroll) document.body.style.userSelect = 'none' document.body.style.webkitUserSelect = 'none' - isScrolling = true + isScrolling = direction } } @@ -117,6 +159,15 @@ else if (belowContent > 2) mask = 'top' else mask = 'none' + if (horizontal) { + leftContent = divScroll.scrollLeft + rightContent = divScroll.scrollWidth - divScroll.clientWidth - leftContent + if (leftContent > 2 && rightContent > 2) maskH = 'both' + else if (leftContent > 2) maskH = 'right' + else if (rightContent > 2) maskH = 'left' + else maskH = 'none' + } + if (autoscroll) { if (scrolling && divScroll.scrollHeight - divScroll.clientHeight - divScroll.scrollTop > 10 && !firstScroll) { scrolling = false @@ -125,6 +176,7 @@ } } if (!isScrolling) checkBar() + if (!isScrolling && horizontal) checkBarH() } const scrollDown = (): void => { @@ -142,6 +194,7 @@ firstScroll = false } checkBar() + if (horizontal) checkBarH() } }) onDestroy(() => { @@ -153,6 +206,8 @@ let boxHeight: number $: if (boxHeight) checkFade() + let boxWidth: number + $: if (boxWidth) checkFade() $: scrollerVars = ` --scroller-header-height: ${ @@ -163,49 +218,75 @@ }px; --scroller-header-fade: ${mask === 'none' || mask === 'top' ? '0px' : '2rem'}; --scroller-footer-fade: ${mask === 'none' || mask === 'bottom' ? '0px' : '2rem'}; + --scroller-left: ${maskH === 'none' || maskH === 'left' ? '0px' : '2rem'}; + --scroller-right: ${maskH === 'none' || maskH === 'right' ? '0px' : '2rem'}; ` -
-
{ - divHeight = element.clientHeight - }} - class="scroll relative verticalFade" - > +
+
{ - boxHeight = element.clientHeight + divHeight = element.clientHeight }} - on:dragover - on:drop + class="scroll relative verticalFade" + class:overflowXauto={horizontal} + class:overflowXhidden={!horizontal} > - +
{ + boxHeight = element.clientHeight + boxWidth = element.clientWidth + }} + on:dragover + on:drop + > + +
onScrollStart(ev, 'vertical')} on:mouseleave={checkFade} />
+ {#if horizontal} +
onScrollStart(ev, 'horizontal')} + on:mouseleave={checkFade} + /> +
+ {/if}
diff --git a/plugins/view-resources/src/components/TableBrowser.svelte b/plugins/view-resources/src/components/TableBrowser.svelte index 4bbd58351e..a3ed50f46f 100644 --- a/plugins/view-resources/src/components/TableBrowser.svelte +++ b/plugins/view-resources/src/components/TableBrowser.svelte @@ -47,8 +47,12 @@ onMount(() => { ;(document.activeElement as HTMLElement)?.blur() }) + + let docWidth: number + + (resultQuery = e.detail)} /> {/if} - +