From 93d5be462e31aceea0f7f436532729f3f351a3c5 Mon Sep 17 00:00:00 2001 From: Tsanie Date: Mon, 5 Jun 2023 10:09:25 +0800 Subject: [PATCH] sync --- lib/app/communications/customer.js | 1 + lib/ui/css/popup.scss | 47 ++++++++------ lib/ui/css/tooltip.scss | 5 ++ lib/ui/popup.js | 99 +++++++++++++++++------------- lib/ui/tooltip.js | 24 +++++++- 5 files changed, 111 insertions(+), 65 deletions(-) diff --git a/lib/app/communications/customer.js b/lib/app/communications/customer.js index ab388e2..233f9fd 100644 --- a/lib/app/communications/customer.js +++ b/lib/app/communications/customer.js @@ -472,6 +472,7 @@ class CustomerCommunication { title: createElement('div', div => { div.style.display = 'flex'; div.style.alignItems = 'center'; + div.style.padding = '10px 0 6px 12px'; div.append( createElement('div', div => { div.className = 'ui-popup-move'; diff --git a/lib/ui/css/popup.scss b/lib/ui/css/popup.scss index a31e1ce..31009ac 100644 --- a/lib/ui/css/popup.scss +++ b/lib/ui/css/popup.scss @@ -45,7 +45,6 @@ $buttonHeight: 28px; .ui-popup-header { flex: 0 0 auto; - padding: 10px 12px 6px; border-radius: var(--corner-radius) var(--corner-radius) 0 0; line-height: $headerLineHeight; user-select: none; @@ -63,28 +62,40 @@ $buttonHeight: 28px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; + padding: 10px 0 6px 12px; } - >svg { + >.ui-popup-header-title, + .ui-popup-move { + cursor: move; + } + + >.ui-popup-header-icons { flex: 0 0 auto; - width: $headerLineHeight; - height: $headerLineHeight; - fill: var(--title-color); - padding: 4px; - cursor: pointer; - box-sizing: border-box; - transition: opacity .12s ease; + padding: 10px 12px 6px 0; + display: flex; - &:hover { - opacity: .8; - } + >svg { + flex: 0 0 auto; + width: $headerLineHeight; + height: $headerLineHeight; + fill: var(--title-color); + padding: 4px; + cursor: pointer; + box-sizing: border-box; + transition: opacity .12s ease; - &:focus, - &:focus-visible { - outline: none; - opacity: .8; - background-color: rgb(0 0 0/10%); - border-radius: var(--corner-radius); + &:hover { + opacity: .8; + } + + &:focus, + &:focus-visible { + outline: none; + opacity: .8; + background-color: rgb(0 0 0/10%); + border-radius: var(--corner-radius); + } } } } diff --git a/lib/ui/css/tooltip.scss b/lib/ui/css/tooltip.scss index f1a8ba8..2934438 100644 --- a/lib/ui/css/tooltip.scss +++ b/lib/ui/css/tooltip.scss @@ -51,4 +51,9 @@ height: calc(100% - 16px); user-select: none; } + + &.ui-tooltip-down>.ui-tooltip-pointer { + bottom: unset; + top: -8px; + } } \ No newline at end of file diff --git a/lib/ui/popup.js b/lib/ui/popup.js index 5958127..242c32d 100644 --- a/lib/ui/popup.js +++ b/lib/ui/popup.js @@ -78,7 +78,7 @@ class Popup { if (!isNaN(r.top)) { css.push(`top: ${r.top}px`); } - const collapse = container.querySelector('.ui-popup-header>.icon-expand'); + const collapse = container.querySelector('.ui-popup-header-icons>.icon-expand'); if (r.collapsed === true) { css.push('width: 160px', 'height: 40px'); this.#bounds = r; @@ -150,6 +150,8 @@ class Popup { mask.dataset.zindex = mask.style.zIndex; mask.style.zIndex = max + 1; }); + } else { + } let tabIndex = Math.max.apply(null, [...document.querySelectorAll('[tabindex]')].map(e => e.tabIndex ?? 0)); if (tabIndex < 0) { @@ -172,11 +174,15 @@ class Popup { } header.appendChild(title); if (option.movable !== false) { - const move = title.querySelector('.ui-popup-move') ?? title; + const move = header; // title.querySelector('.ui-popup-move') ?? title; move.addEventListener('mousedown', e => { + if (['svg', 'use'].includes(e.target?.tagName)) { + return; + } if (e.buttons !== 1) { return; } + const parent = option.mask === false ? mask.parentElement : mask; const x = e.clientX - container.offsetLeft; const y = e.clientY - container.offsetTop; let moved; @@ -186,61 +192,65 @@ class Popup { container.style.top = `${e.clientY - y}px`; moved = true; } else { - mask.dispatchEvent(new MouseEvent('mouseup')); + parent.dispatchEvent(new MouseEvent('mouseup')); } }; - mask.addEventListener('mousemove', move, { passive: false }); + parent.addEventListener('mousemove', move, { passive: false }); const up = () => { - mask.removeEventListener('mousemove', move, { passive: false }); - mask.removeEventListener('mouseup', up); + parent.removeEventListener('mousemove', move, { passive: false }); + parent.removeEventListener('mouseup', up); if (moved === true && typeof option.onMoveEnded === 'function') { option.onMoveEnded.call(this); } moved = false; }; - mask.addEventListener('mouseup', up); + parent.addEventListener('mouseup', up); }); } - if (option.collapsable === true) { - const collapse = createIcon('fa-regular', 'compress-alt'); - collapse.tabIndex = tabIndex + 2; - collapse.classList.add('icon-expand'); - collapse.addEventListener('keypress', e => { - if (e.key === ' ' || e.key === 'Enter') { - collapse.dispatchEvent(new MouseEvent('click')); - } - }); - collapse.addEventListener('click', () => { - if (container.classList.contains('ui-popup-collapse')) { - const bounds = this.#bounds; - if (bounds != null) { - container.style.cssText += `width: ${bounds.width}px; height: ${bounds.height}px`; - this.#bounds = null; + const icons = createElement('div', icons => { + icons.className = 'ui-popup-header-icons'; + if (option.collapsable === true) { + const collapse = createIcon('fa-regular', 'compress-alt'); + collapse.tabIndex = tabIndex + 2; + collapse.classList.add('icon-expand'); + collapse.addEventListener('keypress', e => { + if (e.key === ' ' || e.key === 'Enter') { + collapse.dispatchEvent(new MouseEvent('click')); } - container.classList.remove('ui-popup-collapse'); - changeIcon(collapse, 'fa-regular', 'compress-alt'); - } else { - const rect = this.rect; - this.#bounds = rect; - container.style.cssText += `width: 160px; height: 40px`; - container.classList.add('ui-popup-collapse'); - changeIcon(collapse, 'fa-regular', 'expand-alt'); - } - if (typeof option.onResizeEnded === 'function') { - option.onResizeEnded.call(this); + }); + collapse.addEventListener('click', () => { + if (container.classList.contains('ui-popup-collapse')) { + const bounds = this.#bounds; + if (bounds != null) { + container.style.cssText += `width: ${bounds.width}px; height: ${bounds.height}px`; + this.#bounds = null; + } + container.classList.remove('ui-popup-collapse'); + changeIcon(collapse, 'fa-regular', 'compress-alt'); + } else { + const rect = this.rect; + this.#bounds = rect; + container.style.cssText += `width: 160px; height: 40px`; + container.classList.add('ui-popup-collapse'); + changeIcon(collapse, 'fa-regular', 'expand-alt'); + } + if (typeof option.onResizeEnded === 'function') { + option.onResizeEnded.call(this); + } + }); + icons.appendChild(collapse); + } + const cancel = createIcon('fa-regular', 'times'); + cancel.tabIndex = tabIndex + 3; + cancel.addEventListener('keypress', e => { + if (e.key === ' ' || e.key === 'Enter') { + this.close(); } }); - header.appendChild(collapse); - } - const cancel = createIcon('fa-regular', 'times'); - cancel.tabIndex = tabIndex + 3; - cancel.addEventListener('keypress', e => { - if (e.key === ' ' || e.key === 'Enter') { - this.close(); - } + cancel.addEventListener('click', () => this.close()); + icons.appendChild(cancel); }); - cancel.addEventListener('click', () => this.close()); - header.appendChild(cancel); + header.appendChild(icons); }), createElement('div', 'ui-popup-body', content, createElement('div', 'ui-popup-loading', createElement('div', null, createIcon('fa-regular', 'spinner-third')) @@ -339,7 +349,8 @@ class Popup { return; } let mask = this.#mask ?? this.create(); - const exists = [...parent.children].filter(e => e.classList.contains('ui-popup-mask')); + // const exists = [...parent.children].filter(e => e.classList.contains('ui-popup-mask')); + const exists = parent.querySelectorAll('.ui-popup-mask'); let zindex = 0; for (let ex of exists) { let z = parseInt(ex.style.zIndex); diff --git a/lib/ui/tooltip.js b/lib/ui/tooltip.js index d3d217c..80b3c7e 100644 --- a/lib/ui/tooltip.js +++ b/lib/ui/tooltip.js @@ -66,15 +66,33 @@ function setTooltip(container, content, flag = false, parent = null) { } } p = c.parentElement; - const offsetParent = c.offsetParent; - while (p != null && p !== (isParent ? parent : offsetParent)) { + const offsetParent = isParent ? parent : c.offsetParent; + while (p != null && p !== offsetParent) { left -= p.scrollLeft; top -= p.scrollTop; p = p.parentElement; } left += (c.offsetWidth - wrapper.offsetWidth) / 2; - top -= wrapper.offsetHeight + 14; wrapper.style.left = `${left}px`; + // check overflow + let t = c.offsetTop; + p = c.offsetParent; + while (p != null) { + const overflow = window.getComputedStyle(p).overflow; + if (overflow !== 'visible') { + break; + } + t += p.offsetTop; + p = p.offsetParent; + } + const offsetHeight = wrapper.offsetHeight + 14; + if (t + top - offsetHeight < 0) { + top += c.parentElement.offsetHeight + 14; + wrapper.classList.add('ui-tooltip-down'); + } else { + top -= offsetHeight; + wrapper.classList.remove('ui-tooltip-down'); + } wrapper.style.top = `${top}px`; wrapper.style.visibility = 'visible'; wrapper.style.opacity = 1;