diff --git a/src/components/notification-group/notification-group.ts b/src/components/notification-group/notification-group.ts index 30d4019..3077e85 100644 --- a/src/components/notification-group/notification-group.ts +++ b/src/components/notification-group/notification-group.ts @@ -5,24 +5,105 @@ import { eventOptions, queryAssignedElements, } from 'lit/decorators.js' -import {StarNotification} from '../notification/notification.js' +import {StarNotification} from '@star-web-components/notification' @customElement('star-notification-group') export class StarNotificationGroup extends LitElement { + _opacity: number = 0 + _show: boolean = false @property({type: Number}) count = 0 @property({type: String}) id = '' @queryAssignedElements({flatten: true}) slotElements!: | HTMLSlotElement[] | StarNotification[] + get show() { + return this._show + } + n = 0 + set show(value) { + if (this._show !== value) { + /* 暂时未填加手指按住滑动的控制, 变更show, 即在合并和展开之间二极切换 */ + if (value) { + this.addGroupHeight(this._singleHeight * this.children.length) + } else { + this.addGroupHeight(0) + } + this.setAttribute('show', String(value)) + this._show = value + } + } + + /* 控制单条消息具体内容的透明度 */ + set contentOpacity(value: number) { + this._opacity = value + this.style.setProperty('--single-noti-opacity', String(value)) + if (value !== 1) { + this.style.setProperty('--single-noti-events', 'none') + } else { + this.style.removeProperty('--single-noti-events') + } + } + + get contentOpacity() { + return this._opacity + } + + /** + * 设置通知组的展开高度 + */ + set containerHeight(value: number) { + // 通知组DOM的最大高度, 为通知数量个数的高度之和 + const maxHeight = this._singleHeight * this.children.length + if (value < (this._singleHeight ?? 0)) { + // 小于单条通知高度时, 移除展开高度的控制, 显示为合并高度 + this.style.removeProperty('--expand-height') + return + } else if (value > maxHeight) { + value = maxHeight + } + this.style.setProperty('--expand-height', value + 'px') + } + + /* 增加控制通知组容器高度 */ + addGroupHeight(value: number) { + // 所有被隐藏的通知的展开动画的将会在滑动一个高度前完成 + let ratio = value / this._singleHeight + ratio = ratio > 1 ? 1 : ratio + ratio = ratio < 0 ? 0 : ratio + this.contentOpacity = ratio + this.containerHeight = value + } + + _singleHeight!: number connectedCallback() { super.connectedCallback() window.addEventListener('notification-delete', this) window.addEventListener('notification-touchmove', this) + window.addEventListener('resize', this.resize) + + // 用于监控自身高度变化, 用于第一时间设置自身高度 + const resizeObserver = new ResizeObserver(() => { + if ((this.children[0] as HTMLElement)?.offsetHeight) { + this.resize() + resizeObserver.unobserve(this) + } + }) + resizeObserver.observe(this) + } + + resize = () => { + if (this.children.length) { + // 获取单条通知高度, 并作为合并状态时的高度 + this._singleHeight = (this.children[0] as StarNotification).offsetHeight + this.style.setProperty('--shrink-height', this._singleHeight + 'px') + } else { + this.addEventListener('slotchange', this.resize, {once: true}) + } } firstUpdated() { - this.setAttribute('show', 'false') + this.show = false } @eventOptions({passive: false}) @@ -36,7 +117,7 @@ export class StarNotificationGroup extends LitElement { ;(this.slotElements as StarNotification[]).forEach( (el: StarNotification) => { if (!el.noclear) { - if (this.getAttribute('show') == 'false') { + if (!this.show) { if (el.id == id) { // 删除某个notification-group this.dispatchEvent( @@ -94,17 +175,17 @@ export class StarNotificationGroup extends LitElement { if (slotLen == 1) { // group中只有一条消息,应该转为'one-notification'类型,并折叠 - this.setAttribute('show', 'false') firstChild.setAttribute( 'notificationType', 'group-with-one-notification' ) + this.show = false firstChild.withArrowUp = false firstChild.removeEventListener('notification-tap', allNotificationshown) } else if (slotLen > 1) { let lastChild = slotElements[slotLen - 1] as StarNotification - if (this.getAttribute('show') == 'true') { + if (this.show) { // 展开 firstChild.setAttribute('radiusType', 'top-border-radius') firstChild.setAttribute('notificationType', 'more-notifiactions') @@ -156,6 +237,7 @@ export class StarNotificationGroup extends LitElement { } allNotificationshown(event: Event) { + console.log('allNotificationshown') let firstChild = this.slotElements[0] as StarNotification if (firstChild !== event.target || this.slotElements.length == 1) { return @@ -167,10 +249,12 @@ export class StarNotificationGroup extends LitElement { event.stopImmediatePropagation() } - let isShow = this.getAttribute('show') == 'true' + let isShow = this.show + console.log('hellowq allNotificationshown isShow: ', isShow) if (isShow) { // 当前是展开状态,点击需折叠 let self = this + this.show = false firstChild.setAttribute('radiusType', 'border-radius') firstChild.withArrowUp = false firstChild.setAttribute('notificationType', 'more-notifiactions-first') @@ -179,7 +263,7 @@ export class StarNotificationGroup extends LitElement { ;(element as StarNotification).classList.add('animation-out') element.addEventListener('animationend', function tEnd() { if (index == self.slotElements.length - 1) { - self.setAttribute('show', 'false') + self.show = false self.dispatchEventFurther() } ;(element as StarNotification).classList.remove('animation-out') @@ -188,7 +272,7 @@ export class StarNotificationGroup extends LitElement { } }) } else { - this.setAttribute('show', 'true') + this.show = true this.dispatchEventFurther() this.slotElements.forEach((element) => { if (element !== firstChild) { @@ -228,7 +312,7 @@ export class StarNotificationGroup extends LitElement { collapseNotifications() { let firstChild = this.slotElements[0] as StarNotification - let isShow = this.getAttribute('show') == 'true' + let isShow = this.show ;(this.slotElements as StarNotification[]).forEach((element) => { element.closeNotificationTools() }) @@ -243,7 +327,7 @@ export class StarNotificationGroup extends LitElement { ;(element as StarNotification).classList.add('animation-out') element.addEventListener('animationend', function tEnd() { if (index == self.slotElements.length - 1) { - self.setAttribute('show', 'false') + self.show = false self.preventDefaultBehavior(true) } ;(element as StarNotification).classList.remove('animation-out') @@ -264,15 +348,20 @@ export class StarNotificationGroup extends LitElement { :host { display: block; margin-top: var(--auto-16px); + background: var(--notification-bgc); border-radius: var(--auto-20px); + height: var(--expand-height, var(--shrink-height)); + transition: height 0.25s; + + --notification-bgc: var(--opacity-white-55); + --single-noti-opacity: 0; + --single-noti-bgc: transparent; } - :host([show='false']) ::slotted(*) { - display: none; - } - - :host([show='false']) ::slotted(:first-child) { - display: block; + @media (prefers-color-scheme: dark) { + :host { + --notification-bgc: var(--opacity-black-25); + } } :host([show='true']) ::slotted(*) { @@ -295,6 +384,10 @@ export class StarNotificationGroup extends LitElement { animation: disappearing 0.25s cubic-bezier(0.25, 0.1, 0.25, 1); } + ::slotted(*) { + background: transparent; + } + @keyframes disappearing { 0% { opacity: 1; diff --git a/src/components/notification/notification.ts b/src/components/notification/notification.ts index 36e2d3c..9a221dc 100644 --- a/src/components/notification/notification.ts +++ b/src/components/notification/notification.ts @@ -122,11 +122,13 @@ export class StarNotification extends StarBaseElement { render(): HTMLTemplateResult | typeof nothing { switch (this.notificationType) { case NotificationType.ONE: - case NotificationType.MORE: case NotificationType.GROUP_ONE: return this.getone() + case NotificationType.MORE: case NotificationType.MORE_FIRST: - return this.getmorefirst() + return html` + ${this.getmorefirst()} ${this.getone()} + ` case NotificationType.BLUETOOTH_TRANSFER: return this.getbluetoothtransfer() default: @@ -296,10 +298,10 @@ export class StarNotification extends StarBaseElement { const deleteShow = this.noclear == true ? html` -
- - ` +