UI and separation fixes. (#7045)

Signed-off-by: Alexander Platov <alexander.platov@hardcoreeng.com>
This commit is contained in:
Alexander Platov 2024-10-28 08:52:17 +03:00 committed by GitHub
parent db4e6e1945
commit 84ab130470
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 222 additions and 196 deletions

View File

@ -23,9 +23,6 @@
min-width: 0; min-width: 0;
border: 1px solid var(--theme-divider-color); // var(--global-surface-02-BorderColor); border: 1px solid var(--theme-divider-color); // var(--global-surface-02-BorderColor);
border-radius: var(--small-focus-BorderRadius); border-radius: var(--small-focus-BorderRadius);
border-bottom-right-radius: 0;
border-top-right-radius: 0;
border-right: 0;
&:not(.modal) { &:not(.modal) {
background-color: var(--theme-panel-color); // var(--global-surface-02-BackgroundColor); background-color: var(--theme-panel-color); // var(--global-surface-02-BackgroundColor);

View File

@ -64,6 +64,7 @@
props = $panelstore.panel props = $panelstore.panel
}) })
} }
$panelstore.panel.refit = fitPopupInstance
} else { } else {
props = undefined props = undefined
} }
@ -132,6 +133,7 @@
if (!keepSize && props?.element === 'content') { if (!keepSize && props?.element === 'content') {
keepSize = true keepSize = true
resizeObserver(contentPanel, checkResize) resizeObserver(contentPanel, checkResize)
if (!contentPanel.hasAttribute('data-id')) contentPanel.setAttribute('data-id', 'contentPanel')
} }
} }

View File

@ -174,7 +174,7 @@
} }
} }
const handleScroll = (event: MouseEvent): void => { const handleScroll = (event: PointerEvent): void => {
scrolling = false scrolling = false
if ( if (
(divBar == null && isScrolling === 'vertical') || (divBar == null && isScrolling === 'vertical') ||
@ -185,7 +185,7 @@
} }
const rectScroll = divScroll.getBoundingClientRect() const rectScroll = divScroll.getBoundingClientRect()
if (isScrolling === 'vertical') { if (isScrolling === 'vertical') {
let Y = event.clientY - dXY let Y = Math.round(event.clientY) - dXY
if (Y < rectScroll.top + shiftTop + 2) Y = rectScroll.top + shiftTop + 2 if (Y < rectScroll.top + shiftTop + 2) Y = rectScroll.top + shiftTop + 2
if (Y > rectScroll.bottom - divBar.clientHeight - shiftBottom - 2) { if (Y > rectScroll.bottom - divBar.clientHeight - shiftBottom - 2) {
Y = rectScroll.bottom - divBar.clientHeight - shiftBottom - 2 Y = rectScroll.bottom - divBar.clientHeight - shiftBottom - 2
@ -201,7 +201,7 @@
divScroll.scrollTop = (divScroll.scrollHeight - divScroll.clientHeight) * procBar divScroll.scrollTop = (divScroll.scrollHeight - divScroll.clientHeight) * procBar
} }
} else if (isScrolling === 'horizontal') { } else if (isScrolling === 'horizontal') {
let X = event.clientX - dXY let X = Math.round(event.clientX) - dXY
if (X < rectScroll.left + 2 + shiftLeft) X = rectScroll.left + 2 + shiftLeft if (X < rectScroll.left + 2 + shiftLeft) X = rectScroll.left + 2 + shiftLeft
if (X > rectScroll.right - divBarH.clientWidth - (mask !== 'none' ? 12 : 2) - shiftRight) { if (X > rectScroll.right - divBarH.clientWidth - (mask !== 'none' ? 12 : 2) - shiftRight) {
X = rectScroll.right - divBarH.clientWidth - (mask !== 'none' ? 12 : 2) - shiftRight X = rectScroll.right - divBarH.clientWidth - (mask !== 'none' ? 12 : 2) - shiftRight
@ -215,18 +215,18 @@
} }
} }
const onScrollEnd = (): void => { const onScrollEnd = (): void => {
document.removeEventListener('mousemove', handleScroll) document.removeEventListener('pointermove', handleScroll)
document.body.style.userSelect = 'auto' document.body.style.userSelect = 'auto'
document.body.style.webkitUserSelect = 'auto' document.body.style.webkitUserSelect = 'auto'
document.removeEventListener('mouseup', onScrollEnd) document.removeEventListener('pointerup', onScrollEnd)
isScrolling = false isScrolling = false
} }
const onScrollStart = (event: MouseEvent, direction: 'vertical' | 'horizontal'): void => { const onScrollStart = (event: PointerEvent, direction: 'vertical' | 'horizontal'): void => {
if (divScroll == null) return if (divScroll == null) return
scrolling = false scrolling = false
dXY = direction === 'vertical' ? event.offsetY : event.offsetX dXY = Math.round(direction === 'vertical' ? event.offsetY : event.offsetX)
document.addEventListener('mouseup', onScrollEnd) document.addEventListener('pointerup', onScrollEnd)
document.addEventListener('mousemove', handleScroll) document.addEventListener('pointermove', handleScroll)
document.body.style.userSelect = 'none' document.body.style.userSelect = 'none'
document.body.style.webkitUserSelect = 'none' document.body.style.webkitUserSelect = 'none'
isScrolling = direction isScrolling = direction
@ -666,10 +666,10 @@
class:hovered={isScrolling === 'vertical'} class:hovered={isScrolling === 'vertical'}
class:reverse={scrollDirection === 'vertical-reverse'} class:reverse={scrollDirection === 'vertical-reverse'}
bind:this={divBar} bind:this={divBar}
on:mousedown|stopPropagation={(ev) => { on:pointerdown|stopPropagation={(ev) => {
onScrollStart(ev, 'vertical') onScrollStart(ev, 'vertical')
}} }}
on:mouseleave={checkFade} on:pointerleave={checkFade}
/> />
{/if} {/if}
{#if horizontal && maskH !== 'none'} {#if horizontal && maskH !== 'none'}
@ -687,10 +687,10 @@
class="bar-horizontal" class="bar-horizontal"
class:hovered={isScrolling === 'horizontal'} class:hovered={isScrolling === 'horizontal'}
bind:this={divBarH} bind:this={divBarH}
on:mousedown|stopPropagation={(ev) => { on:pointerdown|stopPropagation={(ev) => {
onScrollStart(ev, 'horizontal') onScrollStart(ev, 'horizontal')
}} }}
on:mouseleave={checkFade} on:pointerleave={checkFade}
/> />
{/if} {/if}
</div> </div>
@ -864,9 +864,11 @@
overscroll-behavior: none; overscroll-behavior: none;
} }
&::-webkit-scrollbar:vertical { &::-webkit-scrollbar:vertical {
display: none;
width: 0; width: 0;
} }
&::-webkit-scrollbar:horizontal { &::-webkit-scrollbar:horizontal {
display: none;
height: 0; height: 0;
} }

View File

@ -24,6 +24,7 @@
separatorsStore, separatorsStore,
SeparatorState SeparatorState
} from '..' } from '..'
import { panelstore } from '../panelup'
export let prevElementSize: SeparatedItem | undefined = undefined export let prevElementSize: SeparatedItem | undefined = undefined
export let nextElementSize: SeparatedItem | undefined = undefined export let nextElementSize: SeparatedItem | undefined = undefined
@ -52,6 +53,7 @@
let isSeparate: boolean = false let isSeparate: boolean = false
let excludedIndexes: number[] = [] let excludedIndexes: number[] = []
let correctedIndex: number = index let correctedIndex: number = index
let realIndex: number = index
let offset: number = 0 let offset: number = 0
let separatorsSizes: number[] | null = null let separatorsSizes: number[] | null = null
const separatorsWide: { before: number, after: number, total: number } = { before: 0, after: 0, total: 0 } const separatorsWide: { before: number, after: number, total: number } = { before: 0, after: 0, total: 0 }
@ -80,7 +82,7 @@
if (prevElementSize !== undefined) prevElSize = prevElementSize if (prevElementSize !== undefined) prevElSize = prevElementSize
if (nextElementSize !== undefined) nextElSize = nextElementSize if (nextElementSize !== undefined) nextElSize = nextElementSize
setTimeout(() => { setTimeout(() => {
if (!parentElement && separator) parentElement = separator.parentElement if (parentElement === null && separator != null) parentElement = separator.parentElement
checkSibling(true) checkSibling(true)
calculateSeparators() calculateSeparators()
}) })
@ -109,21 +111,34 @@
const sizePx = direction === 'horizontal' ? rect.width : rect.height const sizePx = direction === 'horizontal' ? rect.width : rect.height
element.setAttribute('data-size', `${sizePx}`) element.setAttribute('data-size', `${sizePx}`)
if (sState === SeparatorState.NORMAL) { if (sState === SeparatorState.NORMAL) {
if (separators) separators[index + (next ? 1 : 0)].size = pxToRem(sizePx) if (separators != null) separators[index + (next ? 1 : 0)].size = pxToRem(sizePx)
if (next) nextElSize.size = typeof size === 'number' ? pxToRem(sizePx) : size if (next) nextElSize.size = typeof size === 'number' ? pxToRem(sizePx) : size
else prevElSize.size = typeof size === 'number' ? pxToRem(sizePx) : size else prevElSize.size = typeof size === 'number' ? pxToRem(sizePx) : size
} }
} }
const getStyles = (
element: Element | null,
dropStyles: string[] = ['min-width', 'max-width', 'width']
): Map<string, string> => {
const result = new Map<string, string>()
const style = element != null ? element.getAttribute('style') : null
if (style !== null) {
style
.replace(/ /g, '')
.split(';')
.filter((f) => f !== '')
.forEach((st) => result.set(st.split(':')[0], st.split(':')[1]))
dropStyles.forEach((key) => result.delete(key))
}
return result
}
const generateMap = (): void => { const generateMap = (): void => {
if (parentElement === null) return if (parentElement == null || separators === null || separatorsSizes === null) return
const children: Element[] = Array.from(parentElement.children) const children: Element[] = Array.from(parentElement.children)
if (children.length > 1 && separators !== null && separatorsSizes !== null) { if (children.length > 1) {
const elements = children.filter( const hasSep = children.filter((el) => el.hasAttribute('data-float')).map((el) => el.getAttribute('data-float'))
(el) =>
!el.classList.contains('antiSeparator') && (el.hasAttribute('data-size') || el.hasAttribute('data-auto'))
)
const hasSep = elements.filter((el) => el.hasAttribute('data-float')).map((el) => el.getAttribute('data-float'))
const excluded = separators const excluded = separators
.filter((separ) => separ.float !== undefined && !hasSep.includes(separ.float)) .filter((separ) => separ.float !== undefined && !hasSep.includes(separ.float))
.map((separ) => separ.float) .map((separ) => separ.float)
@ -132,43 +147,49 @@
if (excluded.includes(separ.float)) excludedIndexes.push(i) if (excluded.includes(separ.float)) excludedIndexes.push(i)
}) })
correctedIndex = index - excludedIndexes.filter((i) => i < index).length correctedIndex = index - excludedIndexes.filter((i) => i < index).length
realIndex = correctedIndex
const sm: SeparatedElement[] = [] const sm: SeparatedElement[] = []
let ind: number = 0 let ind: number = 0
elements.forEach((element, i) => { let drop: number = 0
if (separators && excluded.includes(separators[i].float)) ind++ children.forEach((element, i) => {
const styles = new Map<string, string>() if (separators != null) {
const dropStyles = ['min-width', 'max-width', 'width'] if (separators[ind]?.float !== undefined && excluded.includes(separators[ind].float)) {
const style = elements[i] ? elements[i].getAttribute('style') : null ind++
if (style !== null) { drop++
style }
.replace(/ /g, '') const styles: Map<string, string> = getStyles(element)
.split(';') const rect = element.getBoundingClientRect()
.filter((f) => f !== '') const size = direction === 'horizontal' ? rect.width : rect.height
.forEach((st) => styles.set(st.split(':')[0], st.split(':')[1])) const sep = element.classList.contains('antiSeparator')
dropStyles.forEach((key) => styles.delete(key)) const extra = !(sep || element.hasAttribute('data-size') || element.hasAttribute('data-auto'))
if (extra) realIndex++
if (!sep) {
sm.push({
id: extra ? -1 : ind,
element,
styles,
minSize: extra
? size
: typeof separators[ind].minSize === 'number'
? remToPx(separators[ind].minSize as number)
: remToPx(20),
maxSize: extra
? size
: typeof separators[ind].maxSize === 'number'
? remToPx(separators[ind].maxSize as number)
: -1,
size,
begin: ind - drop <= correctedIndex,
resize: false,
float: extra ? undefined : separators[ind].float
})
if (!extra) ind++
}
} }
const rect = element.getBoundingClientRect()
const size = direction === 'horizontal' ? rect.width : rect.height
if (separators) {
sm.push({
id: ind,
element,
styles,
minSize:
typeof separators[ind].minSize === 'number' ? remToPx(separators[ind].minSize as number) : remToPx(20),
maxSize: typeof separators[ind].maxSize === 'number' ? remToPx(separators[ind].maxSize as number) : -1,
size,
begin: i <= correctedIndex,
resize: false,
float: separators[ind].float
})
}
ind++
}) })
separatorMap = sm separatorMap = sm
const cropIndex = correctedIndex - excludedIndexes.filter((ex) => ex < correctedIndex).length const startBoxes = separatorMap.filter((sm) => sm.begin)
const startBoxes = separatorMap.filter((_, i) => i < cropIndex + 1) const endBoxes = separatorMap.filter((sm) => !sm.begin)
const endBoxes = separatorMap.slice(cropIndex + 1, sm.length)
containers.minStart = startBoxes.map((box) => box.minSize).reduce((prev, a) => prev + a, 0) containers.minStart = startBoxes.map((box) => box.minSize).reduce((prev, a) => prev + a, 0)
containers.minEnd = endBoxes.map((box) => box.minSize).reduce((prev, a) => prev + a, 0) containers.minEnd = endBoxes.map((box) => box.minSize).reduce((prev, a) => prev + a, 0)
containers.maxStart = containers.maxStart =
@ -232,7 +253,7 @@
} }
if (isSeparate) style += 'pointer-events:none;' if (isSeparate) style += 'pointer-events:none;'
item.element.setAttribute('style', style) item.element.setAttribute('style', style)
if (final) { if (final && item.id !== -1) {
const rect = item.element.getBoundingClientRect() const rect = item.element.getBoundingClientRect()
item.element.setAttribute( item.element.setAttribute(
item.maxSize === -1 ? 'data-auto' : 'data-size', item.maxSize === -1 ? 'data-auto' : 'data-size',
@ -246,7 +267,7 @@
const resizeContainer = (id: number, min: number, max: number, count: number, stretch: boolean = false): number => { const resizeContainer = (id: number, min: number, max: number, count: number, stretch: boolean = false): number => {
const diff = max - min const diff = max - min
if (diff) { if (diff !== 0) {
const size = min + (count >= diff ? (stretch ? diff : 0) : stretch ? count : diff - count) const size = min + (count >= diff ? (stretch ? diff : 0) : stretch ? count : diff - count)
separatorMap[id].size = size separatorMap[id].size = size
separatorMap[id].resize = true separatorMap[id].resize = true
@ -260,13 +281,13 @@
return 0 return 0
} }
function mouseMove (event: MouseEvent) { function pointerMove (event: PointerEvent): void {
if (sState === SeparatorState.NORMAL) normalMouseMove(event) if (sState === SeparatorState.NORMAL) normalMouseMove(event)
else if (sState === SeparatorState.FLOAT) floatMouseMove(event) else if (sState === SeparatorState.FLOAT) floatMouseMove(event)
} }
const preparePanel = (): void => { const preparePanel = (): void => {
if (!parentElement || parentSize === null) return if (parentElement === null || parentSize === null) return
setSize(parentElement, panel.size === 'auto' ? 'auto' : remToPx(panel.size)) setSize(parentElement, panel.size === 'auto' ? 'auto' : remToPx(panel.size))
const s = separator.getBoundingClientRect() const s = separator.getBoundingClientRect()
if (s) { if (s) {
@ -282,9 +303,9 @@
parentElement.style.pointerEvents = 'none' parentElement.style.pointerEvents = 'none'
} }
function floatMouseMove (event: MouseEvent) { function floatMouseMove (event: PointerEvent): void {
if (!isSeparate || parentSize === null || parentElement === null) return if (!isSeparate || parentSize === null || parentElement === null) return
const coord: number = direction === 'horizontal' ? event.x - offset : event.y - offset const coord: number = Math.round(direction === 'horizontal' ? event.x - offset : event.y - offset)
const parentCoord: number = coord - parentSize.start const parentCoord: number = coord - parentSize.start
const min = remToPx(panel.minSize === 'auto' ? 10 : panel.minSize) const min = remToPx(panel.minSize === 'auto' ? 10 : panel.minSize)
const max = remToPx(panel.maxSize === 'auto' ? 30 : panel.maxSize) const max = remToPx(panel.maxSize === 'auto' ? 30 : panel.maxSize)
@ -304,9 +325,9 @@
setSize(parentElement, newCoord) setSize(parentElement, newCoord)
} }
function normalMouseMove (event: MouseEvent) { function normalMouseMove (event: PointerEvent): void {
if (!isSeparate || separatorMap === null || parentSize === null || separatorsSizes === null) return if (!isSeparate || separatorMap === undefined || parentSize === null || separatorsSizes === null) return
const coord: number = direction === 'horizontal' ? event.x - offset : event.y - offset const coord: number = Math.round(direction === 'horizontal' ? event.x - offset : event.y - offset)
let parentCoord: number = coord - parentSize.start let parentCoord: number = coord - parentSize.start
let prevCoord: number = separatorMap let prevCoord: number = separatorMap
.filter((f) => f.begin) .filter((f) => f.begin)
@ -330,22 +351,22 @@
if (remains !== 0) { if (remains !== 0) {
const reverse = remains < 0 const reverse = remains < 0
if (reverse) remains = Math.abs(remains) if (reverse) remains = Math.abs(remains)
const minusId = correctedIndex + (reverse ? 1 : 0) const minusId = realIndex + (reverse ? 1 : 0)
const plusId = correctedIndex + (reverse ? 0 : 1) const plusId = realIndex + (reverse ? 0 : 1)
const minusAutoBoxes = separatorMap.filter( const minusAutoBoxes = separatorMap.filter(
(s, i) => s.maxSize === -1 && ((!reverse && i < correctedIndex) || (reverse && i > correctedIndex + 1)) (s, i) => s.maxSize === -1 && ((!reverse && i < realIndex) || (reverse && i > realIndex + 1))
) )
const minusBoxes = separatorMap.filter( const minusBoxes = separatorMap.filter(
(s, i) => s.maxSize !== -1 && ((!reverse && i < correctedIndex) || (reverse && i > correctedIndex + 1)) (s, i) => s.maxSize !== -1 && ((!reverse && i < realIndex) || (reverse && i > realIndex + 1))
) )
const minusBox = separatorMap[minusId] const minusBox = separatorMap[minusId]
const startMinus = separatorMap[minusId].maxSize === -1 const startMinus = separatorMap[minusId].maxSize === -1
const plusAutoBoxes = separatorMap.filter( const plusAutoBoxes = separatorMap.filter(
(s, i) => s.maxSize === -1 && ((!reverse && i > correctedIndex + 1) || (reverse && i < correctedIndex)) (s, i) => s.maxSize === -1 && ((!reverse && i > realIndex + 1) || (reverse && i < realIndex))
) )
const plusBoxes = separatorMap.filter( const plusBoxes = separatorMap.filter(
(s, i) => s.maxSize !== -1 && ((!reverse && i > correctedIndex + 1) || (reverse && i < correctedIndex)) (s, i) => s.maxSize !== -1 && ((!reverse && i > realIndex + 1) || (reverse && i < realIndex))
) )
const plusBox = separatorMap[plusId] const plusBox = separatorMap[plusId]
const startPlus = separatorMap[plusId].maxSize === -1 const startPlus = separatorMap[plusId].maxSize === -1
@ -354,46 +375,53 @@
if (startMinus && minusBox.size - minusBox.minSize > 0) { if (startMinus && minusBox.size - minusBox.minSize > 0) {
remains = resizeContainer(minusId, minusBox.minSize, minusBox.size, remains) remains = resizeContainer(minusId, minusBox.minSize, minusBox.size, remains)
} }
if (remains && minusAutoBoxes.length > 0) { if (remains > 0 && minusAutoBoxes.length > 0) {
minusAutoBoxes.forEach((box) => { minusAutoBoxes.forEach((box) => {
if (remains) remains = resizeContainer(box.id, box.minSize, box.size, remains) if (remains > 0) remains = resizeContainer(box.id, box.minSize, box.size, remains)
}) })
} }
if (remains && !startMinus && minusBox.size - minusBox.minSize > 0) { if (remains > 0 && !startMinus && minusBox.size - minusBox.minSize > 0) {
remains = resizeContainer(minusId, minusBox.minSize, minusBox.size, remains) remains = resizeContainer(minusId, minusBox.minSize, minusBox.size, remains)
} }
if (remains && minusBoxes.length > 0) { if (remains > 0 && minusBoxes.length > 0) {
minusBoxes.forEach((box) => { minusBoxes.forEach((box) => {
if (remains) remains = resizeContainer(box.id, box.minSize, box.size, remains) if (remains > 0) remains = resizeContainer(box.id, box.minSize, box.size, remains)
}) })
} }
let needAdd: number = Math.abs(diff) - remains let needAdd: number = Math.abs(diff) - remains
// Find for stretch // Find for stretch
if (needAdd && startPlus) needAdd = stretchContainer(plusId, plusBox.size + needAdd) if (needAdd > 0 && startPlus) needAdd = stretchContainer(plusId, plusBox.size + needAdd)
if (needAdd && plusAutoBoxes.length > 0) { if (needAdd > 0 && plusAutoBoxes.length > 0) {
const div = needAdd / plusAutoBoxes.length const div = needAdd / plusAutoBoxes.length
plusAutoBoxes.forEach((box) => (needAdd = stretchContainer(box.id, box.size + div))) plusAutoBoxes.forEach((box) => (needAdd = stretchContainer(box.id, box.size + div)))
} }
if (needAdd && plusBox.maxSize - plusBox.size > 0) { if (needAdd > 0 && plusBox.maxSize - plusBox.size > 0) {
needAdd = resizeContainer(plusId, plusBox.size, plusBox.maxSize, needAdd, true) needAdd = resizeContainer(plusId, plusBox.size, plusBox.maxSize, needAdd, true)
} }
if (needAdd && plusBoxes.length > 0) { if (needAdd > 0 && plusBoxes.length > 0) {
plusBoxes.forEach((box) => { plusBoxes.forEach((box) => {
if (needAdd) needAdd = resizeContainer(box.id, box.size, box.maxSize, needAdd, true) if (needAdd > 0) needAdd = resizeContainer(box.id, box.size, box.maxSize, needAdd, true)
}) })
} }
separatorMap = separatorMap separatorMap = separatorMap
} }
applyStyles() applyStyles()
if ($panelstore.panel?.refit !== undefined) $panelstore.panel.refit()
} }
function mouseUp () { function pointerUp (): void {
finalSeparation()
document.removeEventListener('pointermove', pointerMove)
document.removeEventListener('pointerup', pointerUp)
}
function finalSeparation (): void {
isSeparate = false isSeparate = false
if (sState === SeparatorState.NORMAL) { if (sState === SeparatorState.NORMAL) {
applyStyles(true) applyStyles(true)
if (index !== -1 && separators && separatorMap) { if (index !== -1 && separators != null && separatorMap != null) {
let ind: number = 0 let ind: number = 0
const sep: SeparatedItem[] = [] const sep: SeparatedItem[] = []
separatorMap = separatorMap.filter((sm) => sm.id !== -1)
separators.forEach((sm, i) => { separators.forEach((sm, i) => {
let save = false let save = false
if (excludedIndexes.includes(i)) { if (excludedIndexes.includes(i)) {
@ -412,17 +440,20 @@
}) })
saveSeparator(name, false, sep) saveSeparator(name, false, sep)
} }
} else if (sState === SeparatorState.FLOAT && parentElement) { } else if (sState === SeparatorState.FLOAT && parentElement != null) {
parentElement.style.pointerEvents = 'all' parentElement.style.pointerEvents = 'all'
saveSeparator(name, float, panel) saveSeparator(name, float, panel)
} }
document.body.style.cursor = '' document.body.style.cursor = ''
document.removeEventListener('mousemove', mouseMove)
document.removeEventListener('mouseup', mouseUp)
} }
function mouseDown (event: MouseEvent) { function pointerDown (event: PointerEvent): void {
if (!parentElement) return prepareSeparation(event)
document.addEventListener('pointermove', pointerMove)
document.addEventListener('pointerup', pointerUp)
}
function prepareSeparation (event: PointerEvent): void {
if (parentElement == null) return
if (sState === SeparatorState.FLOAT && parentElement === null) { if (sState === SeparatorState.FLOAT && parentElement === null) {
checkParent() checkParent()
return return
@ -430,7 +461,7 @@
checkSibling() checkSibling()
return return
} }
offset = direction === 'horizontal' ? event.offsetX : event.offsetY offset = Math.round(direction === 'horizontal' ? event.offsetX : event.offsetY)
const p = parentElement.getBoundingClientRect() const p = parentElement.getBoundingClientRect()
parentSize = parentSize =
direction === 'horizontal' direction === 'horizontal'
@ -441,33 +472,31 @@
generateMap() generateMap()
applyStyles(true) applyStyles(true)
} else if (sState === SeparatorState.FLOAT) preparePanel() } else if (sState === SeparatorState.FLOAT) preparePanel()
document.addEventListener('mousemove', mouseMove)
document.addEventListener('mouseup', mouseUp)
document.body.style.cursor = direction === 'horizontal' ? 'col-resize' : 'row-resize' document.body.style.cursor = direction === 'horizontal' ? 'col-resize' : 'row-resize'
} }
const checkSibling = (start: boolean = false): void => { const checkSibling = (start: boolean = false): void => {
if (separator === null) return if (separator === null) return
if ((prevElement === null || start) && separator) { if ((prevElement === null || start) && separator != null) {
prevElement = separator.previousElementSibling as HTMLElement prevElement = separator.previousElementSibling as HTMLElement
} }
if ((nextElement === null || start) && separator) { if ((nextElement === null || start) && separator != null) {
nextElement = separator.nextElementSibling as HTMLElement nextElement = separator.nextElementSibling as HTMLElement
} }
if (separators && prevElement && separators[index].float !== undefined) { if (separators != null && prevElement != null && separators[index].float !== undefined) {
prevElement.setAttribute('data-float', separators[index].float ?? '') prevElement.setAttribute('data-float', separators[index].float ?? '')
} }
if (separators && nextElement && separators[index + 1].float !== undefined) { if (separators != null && nextElement != null && separators[index + 1].float !== undefined) {
nextElement.setAttribute('data-float', separators[index + 1].float ?? '') nextElement.setAttribute('data-float', separators[index + 1].float ?? '')
} }
} }
const checkParent = (): void => { const checkParent = (): void => {
if (parentElement === null && separator) parentElement = separator.parentElement as HTMLElement if (parentElement === null && separator != null) parentElement = separator.parentElement as HTMLElement
if (parentElement && typeof float === 'string') parentElement.setAttribute('data-float', float) if (parentElement != null && typeof float === 'string') parentElement.setAttribute('data-float', float)
} }
const calculateSeparators = (): void => { const calculateSeparators = (): void => {
if (parentElement) { if (parentElement != null) {
const elements: Element[] = Array.from(parentElement.children) const elements: Element[] = Array.from(parentElement.children)
separatorsSizes = elements separatorsSizes = elements
.filter((el) => el.classList.contains('antiSeparator')) .filter((el) => el.classList.contains('antiSeparator'))
@ -483,7 +512,7 @@
if (parentElement == null || checkElements || sState !== SeparatorState.NORMAL) return if (parentElement == null || checkElements || sState !== SeparatorState.NORMAL) return
checkElements = true checkElements = true
setTimeout(() => { setTimeout(() => {
if (parentElement != null && separators) { if (parentElement != null && separators != null) {
const children: Element[] = Array.from(parentElement.children) const children: Element[] = Array.from(parentElement.children)
let totalSize: number = 0 let totalSize: number = 0
let ind: number = 0 let ind: number = 0
@ -513,9 +542,9 @@
let ind: number = 0 let ind: number = 0
reverseSep.forEach((separ, i) => { reverseSep.forEach((separ, i) => {
const pass = excluded.includes(separ.float) const pass = excluded.includes(separ.float)
if (diff > 0 && !pass && separators) { if (diff > 0 && !pass && separators != null) {
const box = rects.get(reverseSep.length - ind - 1) const box = rects.get(reverseSep.length - ind - 1)
if (box) { if (box != null) {
const minSize: number = remToPx(separ.minSize === 'auto' ? 20 : separ.minSize) const minSize: number = remToPx(separ.minSize === 'auto' ? 20 : separ.minSize)
const forCrop = box.size - minSize const forCrop = box.size - minSize
if (forCrop > 0) { if (forCrop > 0) {
@ -545,7 +574,7 @@
} }
onMount(() => { onMount(() => {
if (separator) { if (separator != null) {
parentElement = separator.parentElement as HTMLElement parentElement = separator.parentElement as HTMLElement
if (sState === SeparatorState.FLOAT) checkParent() if (sState === SeparatorState.FLOAT) checkParent()
else if (sState === SeparatorState.NORMAL) { else if (sState === SeparatorState.NORMAL) {
@ -586,7 +615,7 @@
class:short class:short
class:hovered={isSeparate} class:hovered={isSeparate}
data-size={separatorSize} data-size={separatorSize}
on:mousedown|stopPropagation={mouseDown} on:pointerdown|stopPropagation={pointerDown}
/> />
{/if} {/if}

View File

@ -8,6 +8,7 @@ export interface PanelProps {
_class: string _class: string
element?: PopupAlignment element?: PopupAlignment
rightSection?: AnyComponent rightSection?: AnyComponent
refit?: () => void
} }
export const panelstore = writable<{ panel?: PanelProps | undefined }>({ panel: undefined }) export const panelstore = writable<{ panel?: PanelProps | undefined }>({ panel: undefined })

View File

@ -152,9 +152,9 @@
}} }}
> >
{#if personInfo} {#if personInfo}
<Avatar name={person?.name ?? personInfo.name} {person} size={'full'} /> <Avatar name={person?.name ?? personInfo.name} {person} size={'full'} showStatus={false} />
{:else if hoveredRoomX === x && hoveredRoomY === y} {:else if hoveredRoomX === x && hoveredRoomY === y}
<Avatar name={meName} person={meAvatar} size={'full'} /> <Avatar name={meName} person={meAvatar} size={'full'} showStatus={false} />
{/if} {/if}
</div> </div>
{/each} {/each}

View File

@ -90,7 +90,7 @@
<style lang="scss"> <style lang="scss">
.container { .container {
padding: var(--spacing-2) var(--spacing-2) var(--spacing-2_5); padding: var(--spacing-2) var(--spacing-2) var(--spacing-2_5);
min-height: calc(4.75rem + 0.5px); min-height: calc(4.875rem - 0.5px);
border-bottom: 1px solid var(--theme-divider-color); border-bottom: 1px solid var(--theme-divider-color);
} }
</style> </style>

View File

@ -2,6 +2,4 @@
import PlanView from './PlanView.svelte' import PlanView from './PlanView.svelte'
</script> </script>
<div class="hulyPanels-container"> <PlanView on:change />
<PlanView on:change />
</div>

View File

@ -86,20 +86,18 @@
{#if $deviceInfo.navigator.visible} {#if $deviceInfo.navigator.visible}
<ToDosNavigator bind:mode bind:tag bind:currentDate /> <ToDosNavigator bind:mode bind:tag bind:currentDate />
<Separator <Separator name={'time'} float={$deviceInfo.navigator.float} index={0} color={'var(--theme-divider-color)'} />
name={'time'}
float={$deviceInfo.navigator.float}
index={0}
disabledWhen={['panel-aside']}
color={'var(--theme-divider-color)'}
/>
{/if} {/if}
<div class="flex-col w-full clear-mins" class:left-divider={!$deviceInfo.navigator.visible} bind:this={mainPanel}> <div class="flex-col w-full clear-mins" class:left-divider={!$deviceInfo.navigator.visible} bind:this={mainPanel}>
<ToDos {mode} {tag} bind:currentDate /> <ToDos {mode} {tag} bind:currentDate />
</div> </div>
{#if visibleCalendar} {#if visibleCalendar}
<Separator name={'time'} index={1} color={'transparent'} separatorSize={0} short /> <Separator name={'time'} index={1} color={'transparent'} separatorSize={0} short />
<div class="flex-col clear-mins" bind:this={replacedPanel}> <PlanningCalendar
<PlanningCalendar {dragItem} bind:currentDate displayedDaysCount={5} on:dragDrop={drop} /> {dragItem}
</div> bind:element={replacedPanel}
bind:currentDate
displayedDaysCount={5}
on:dragDrop={drop}
/>
{/if} {/if}

View File

@ -27,6 +27,7 @@
export let dragItem: ToDo | null = null export let dragItem: ToDo | null = null
export let currentDate: Date = new Date() export let currentDate: Date = new Date()
export let displayedDaysCount = 1 export let displayedDaysCount = 1
export let element: HTMLElement | undefined = undefined
export let createComponent: AnyComponent | undefined = calendar.component.CreateEvent export let createComponent: AnyComponent | undefined = calendar.component.CreateEvent
const q = createQuery() const q = createQuery()
@ -175,6 +176,7 @@
<div <div
class="hulyComponent modal" class="hulyComponent modal"
bind:this={element}
use:resizeObserver={(element) => { use:resizeObserver={(element) => {
showLabel = showLabel ? element.clientWidth > rem(3.5) + 399 : element.clientWidth > rem(3.5) + 400 showLabel = showLabel ? element.clientWidth > rem(3.5) + 399 : element.clientWidth > rem(3.5) + 400
}} }}

View File

@ -28,7 +28,7 @@ export function getNearest (events: WorkSlot[]): WorkSlot | undefined {
export const timeSeparators: DefSeparators = [ export const timeSeparators: DefSeparators = [
{ minSize: 18, size: 18, maxSize: 22.5, float: 'navigator' }, { minSize: 18, size: 18, maxSize: 22.5, float: 'navigator' },
null, null,
{ minSize: 20, size: 41.25, maxSize: 90 } { minSize: 25, size: 41.25, maxSize: 90 }
] ]
/** /**

View File

@ -872,7 +872,7 @@
application: currentApplication?._id application: currentApplication?._id
}} }}
/> />
<div class="workbench-container inner"> <div class="workbench-container inner" class:rounded={$sidebarStore.variant === SidebarVariant.EXPANDED}>
{#if mainNavigator} {#if mainNavigator}
<!-- svelte-ignore a11y-click-events-have-key-events --> <!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-no-static-element-interactions --> <!-- svelte-ignore a11y-no-static-element-interactions -->
@ -932,6 +932,7 @@
<div <div
bind:this={contentPanel} bind:this={contentPanel}
class={navigatorModel === undefined ? 'hulyPanels-container' : 'hulyComponent overflow-hidden'} class={navigatorModel === undefined ? 'hulyPanels-container' : 'hulyComponent overflow-hidden'}
data-id={'contentPanel'}
> >
{#if currentApplication && currentApplication.component} {#if currentApplication && currentApplication.component}
<Component <Component
@ -972,11 +973,11 @@
</div> </div>
{/if} {/if}
</div> </div>
{#if $sidebarStore.variant === SidebarVariant.EXPANDED}
<Separator name={'main'} index={0} color={'transparent'} separatorSize={0} short />
{/if}
<WidgetsBar />
</div> </div>
{#if $sidebarStore.variant === SidebarVariant.EXPANDED}
<Separator name={'main'} index={0} color={'transparent'} separatorSize={0} short />
{/if}
<WidgetsBar />
<Dock /> <Dock />
<div bind:this={cover} class="cover" /> <div bind:this={cover} class="cover" />
<TooltipInstance /> <TooltipInstance />
@ -1002,12 +1003,15 @@
min-height: 0; min-height: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
background-color: var(--theme-statusbar-color); background-color: var(--theme-panel-color);
touch-action: none; touch-action: none;
&.inner { &.inner {
background-color: var(--theme-navpanel-color); background-color: var(--theme-navpanel-color);
border-radius: 0 var(--medium-BorderRadius) var(--medium-BorderRadius) 0;
&.rounded {
border-radius: 0 var(--medium-BorderRadius) var(--medium-BorderRadius) 0;
}
} }
&:not(.inner)::after { &:not(.inner)::after {
position: absolute; position: absolute;
@ -1015,8 +1019,6 @@
inset: 0; inset: 0;
border: 1px solid var(--theme-divider-color); border: 1px solid var(--theme-divider-color);
border-radius: var(--medium-BorderRadius); border-radius: var(--medium-BorderRadius);
border-bottom-right-radius: 0;
border-top-right-radius: 0;
pointer-events: none; pointer-events: none;
} }
.antiPanel-application { .antiPanel-application {

View File

@ -17,6 +17,7 @@
import { WidgetPreference, SidebarEvent, TxSidebarEvent, OpenSidebarWidgetParams } from '@hcengineering/workbench' import { WidgetPreference, SidebarEvent, TxSidebarEvent, OpenSidebarWidgetParams } from '@hcengineering/workbench'
import { Tx } from '@hcengineering/core' import { Tx } from '@hcengineering/core'
import { onMount } from 'svelte' import { onMount } from 'svelte'
import { panelstore } from '@hcengineering/ui'
import workbench from '../../plugin' import workbench from '../../plugin'
import { createWidgetTab, openWidget, sidebarStore, SidebarVariant } from '../../sidebar' import { createWidgetTab, openWidget, sidebarStore, SidebarVariant } from '../../sidebar'
@ -33,7 +34,8 @@
preferences = res preferences = res
}) })
$: size = $sidebarStore.variant === SidebarVariant.MINI ? 'mini' : undefined $: mini = $sidebarStore.variant === SidebarVariant.MINI
$: if ((!mini || mini) && $panelstore.panel?.refit !== undefined) $panelstore.panel.refit()
function txListener (tx: Tx): void { function txListener (tx: Tx): void {
if (tx._class === workbench.class.TxSidebarEvent) { if (tx._class === workbench.class.TxSidebarEvent) {
@ -59,8 +61,8 @@
}) })
</script> </script>
<div class="antiPanel-component antiComponent root size-{size}" id="sidebar"> <div class="antiPanel-application vertical root" class:mini id="sidebar">
{#if $sidebarStore.variant === SidebarVariant.MINI} {#if mini}
<SidebarMini {widgets} {preferences} /> <SidebarMini {widgets} {preferences} />
{:else if $sidebarStore.variant === SidebarVariant.EXPANDED} {:else if $sidebarStore.variant === SidebarVariant.EXPANDED}
<SidebarExpanded {widgets} {preferences} /> <SidebarExpanded {widgets} {preferences} />
@ -69,10 +71,11 @@
<style lang="scss"> <style lang="scss">
.root { .root {
position: relative; flex-direction: row;
background-color: var(--theme-panel-color); min-width: 25rem;
border-radius: 0 var(--medium-BorderRadius) var(--medium-BorderRadius) 0;
&.size-mini { &.mini {
width: 3.5rem !important; width: 3.5rem !important;
min-width: 3.5rem !important; min-width: 3.5rem !important;
max-width: 3.5rem !important; max-width: 3.5rem !important;

View File

@ -96,84 +96,78 @@
} }
</script> </script>
<div class="root"> <div class="content">
<div class="content"> {#if widget?.component}
{#if widget?.component} <div class="component" use:resizeObserver={resize}>
<div class="component" use:resizeObserver={resize}> {#if widget.headerLabel}
{#if widget.headerLabel} <Header
<Header allowFullsize={false}
allowFullsize={false} type="type-aside"
type="type-aside" hideBefore={true}
hideBefore={true} hideActions={false}
hideActions={false} hideDescription={true}
hideDescription={true} adaptive="disabled"
adaptive="disabled" closeOnEscape={false}
closeOnEscape={false}
on:close={() => {
if (widget !== undefined) {
closeWidget(widget._id)
}
}}
>
<Breadcrumbs items={[{ label: widget.headerLabel }]} currentOnly />
</Header>
{/if}
<Component
is={widget?.component}
props={{ tab, widgetState, height: componentHeight, width: componentWidth, widget }}
on:close={() => { on:close={() => {
if (widget !== undefined) { if (widget !== undefined) {
closeWidget(widget._id) closeWidget(widget._id)
} }
}} }}
/> >
</div> <Breadcrumbs items={[{ label: widget.headerLabel }]} currentOnly />
{/if} </Header>
</div> {/if}
{#if widget !== undefined && tabs.length > 0} <Component
<SidebarTabs is={widget?.component}
{tabs} props={{ tab, widgetState, height: componentHeight, width: componentWidth, widget }}
selected={tab?.id} on:close={() => {
{widget} if (widget !== undefined) {
on:close={(e) => { closeWidget(widget._id)
void handleTabClose(e.detail, widget) }
}} }}
on:open={(e) => { />
handleTabOpen(e.detail, widget) </div>
}}
/>
{/if} {/if}
<WidgetsBar {widgets} {preferences} selected={widgetId} />
</div> </div>
{#if widget !== undefined && tabs.length > 0}
<SidebarTabs
{tabs}
selected={tab?.id}
{widget}
on:close={(e) => {
void handleTabClose(e.detail, widget)
}}
on:open={(e) => {
handleTabOpen(e.detail, widget)
}}
/>
{/if}
<WidgetsBar {widgets} {preferences} selected={widgetId} />
<style lang="scss"> <style lang="scss">
.root {
display: flex;
flex: 1;
height: 100%;
overflow: hidden;
}
.content { .content {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
border-top: 1px solid var(--theme-divider-color); border-top: 1px solid transparent; // var(--theme-divider-color);
border-right: 1px solid var(--theme-divider-color);
overflow: auto; overflow: auto;
flex: 1;
width: calc(100% - 3.5rem); width: calc(100% - 3.5rem);
height: 100%; height: 100%;
background: var(--theme-panel-color); min-width: 0;
border-right: 1px solid var(--global-ui-BorderColor); min-height: 0;
background-color: var(--theme-panel-color);
border-left: none;
} }
.component { .component {
position: relative; position: relative;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
flex: 1; flex-grow: 1;
overflow: hidden; overflow: hidden;
border-bottom: 1px solid transparent; background-color: var(--theme-panel-color);
} }
</style> </style>

View File

@ -89,9 +89,8 @@
width: 30px; width: 30px;
min-width: 30px; min-width: 30px;
max-width: 30px; max-width: 30px;
flex: 1; height: 100%;
border-right: 1px solid var(--theme-divider-color); border-right: 1px solid var(--theme-divider-color);
border-top: 1px solid var(--theme-divider-color);
gap: 0.25rem; gap: 0.25rem;
align-items: center; align-items: center;
padding: 0.25rem 0; padding: 0.25rem 0;

View File

@ -95,13 +95,12 @@
.root { .root {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: space-between; padding-block: var(--spacing-2);
height: 100%; height: 100%;
padding: 0.5rem 0;
width: 3.5rem; width: 3.5rem;
min-width: 3.5rem; min-width: 3.5rem;
max-width: 3.5rem; max-width: 3.5rem;
border-top: 1px solid var(--theme-divider-color); border-radius: 0 var(--medium-BorderRadius) var(--medium-BorderRadius) 0;
overflow-y: auto; overflow-y: auto;
} }