From 49f0197d1db411b0623b0a85652d31c296b6d7cd Mon Sep 17 00:00:00 2001 From: Mister-Hope Date: Fri, 28 Mar 2025 22:28:56 +0800 Subject: [PATCH 1/7] feat(helper): add Message class to handle message --- eslint.config.js | 4 ++ tools/helper/src/client/styles/message.scss | 58 +++++++++++++++++++ tools/helper/src/client/utils/index.ts | 1 + tools/helper/src/client/utils/message.ts | 63 +++++++++++++++++++++ 4 files changed, 126 insertions(+) create mode 100644 tools/helper/src/client/styles/message.scss create mode 100644 tools/helper/src/client/utils/message.ts diff --git a/eslint.config.js b/eslint.config.js index 16e834e950..a50bd2bad5 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -99,6 +99,10 @@ export default vuepress( ], '@typescript-eslint/no-dynamic-delete': 'off', '@typescript-eslint/no-non-null-assertion': 'off', + '@typescript-eslint/no-empty-function': [ + 'error', + { allow: ['private-constructors'] }, + ], '@typescript-eslint/no-floating-promises': [ 'error', { diff --git a/tools/helper/src/client/styles/message.scss b/tools/helper/src/client/styles/message.scss new file mode 100644 index 0000000000..22ce46498e --- /dev/null +++ b/tools/helper/src/client/styles/message.scss @@ -0,0 +1,58 @@ +@keyframes message-move-in { + 0% { + opacity: 0; + transform: translateY(-100%); + } + + 100% { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes message-move-out { + 0% { + opacity: 1; + transform: translateY(0); + } + + 100% { + opacity: 0; + transform: translateY(-100%); + } +} + +#message-container { + position: fixed; + inset: calc(var(--message-offset, 3.6rem) + 1rem) 0 auto; + z-index: 75; + text-align: center; +} + +.message-item { + display: inline-block; + + padding: 8px 10px; + border-radius: 3px; + + background: var(--vp-c-bg); + color: var(--vp-c-text); + box-shadow: 0 0 10px 0 var(--vp-c-shadow); + + font-size: 14px; + + &.move-in { + animation: message-move-in 0.3s ease-in-out; + } + + &.move-out { + animation: message-move-out 0.3s ease-in-out; + animation-fill-mode: forwards; + } + + svg { + position: relative; + bottom: -0.125em; + margin-inline-end: 5px; + } +} diff --git a/tools/helper/src/client/utils/index.ts b/tools/helper/src/client/utils/index.ts index 452cc47b3f..8babf00fb9 100644 --- a/tools/helper/src/client/utils/index.ts +++ b/tools/helper/src/client/utils/index.ts @@ -5,4 +5,5 @@ export * from './getHeaders.js' export * from './isFocusingTextControl.js' export * from './isKeyMatched.js' export * from './hasGlobalComponent.js' +export * from './message.js' export * from './wait.js' diff --git a/tools/helper/src/client/utils/message.ts b/tools/helper/src/client/utils/message.ts new file mode 100644 index 0000000000..7eb3daf3d0 --- /dev/null +++ b/tools/helper/src/client/utils/message.ts @@ -0,0 +1,63 @@ +import { keys } from '../../shared/index.js' + +const containerId = 'message-container' + +export class Message { + private elements: Record = {} + + private constructor() {} + + public static get containerElement(): HTMLElement { + let containerElement = document.getElementById(containerId) + + if (containerElement) return containerElement + + containerElement = document.createElement('div') + + containerElement.id = containerId + document.body.appendChild(containerElement) + + return containerElement + } + + public pop(html: string, duration = 2000): number { + const messageElement = document.createElement('div') + const messageId = Date.now() + + messageElement.className = 'message-item move-in' + messageElement.innerHTML = html + Message.containerElement.appendChild(messageElement) + this.elements[messageId] = messageElement + + if (duration > 0) + setTimeout(() => { + this.close(messageId) + }, duration) + + return messageId + } + + public close(messageId?: number): void { + if (messageId) { + const messageElement = this.elements[messageId] + + messageElement.classList.remove('move-in') + messageElement.classList.add('move-out') + messageElement.addEventListener('animationend', () => { + messageElement.remove() + delete this.elements[messageId] + }) + } else { + keys(this.elements).forEach((id) => { + this.close(Number(id)) + }) + } + } + + public destroy(): void { + const containerElement = document.getElementById(containerId) + + if (containerElement) document.body.removeChild(containerElement) + this.elements = {} + } +} From b0d0c5400ade213b5cee9fa93a569cd5c46ad27d Mon Sep 17 00:00:00 2001 From: Mister-Hope Date: Fri, 28 Mar 2025 22:33:57 +0800 Subject: [PATCH 2/7] feat: add clickToClose --- tools/helper/src/client/utils/message.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tools/helper/src/client/utils/message.ts b/tools/helper/src/client/utils/message.ts index 7eb3daf3d0..7ccc9f36bf 100644 --- a/tools/helper/src/client/utils/message.ts +++ b/tools/helper/src/client/utils/message.ts @@ -20,7 +20,11 @@ export class Message { return containerElement } - public pop(html: string, duration = 2000): number { + public getElement(messageId: number): HTMLDivElement { + return this.elements[messageId] + } + + public pop(html: string, duration = 2000, clickToClose = true): number { const messageElement = document.createElement('div') const messageId = Date.now() @@ -29,6 +33,11 @@ export class Message { Message.containerElement.appendChild(messageElement) this.elements[messageId] = messageElement + if (clickToClose) + messageElement.addEventListener('click', () => { + this.close(messageId) + }) + if (duration > 0) setTimeout(() => { this.close(messageId) From 1cf9d9c7963da22482e1b1663649f14c6cd5fc13 Mon Sep 17 00:00:00 2001 From: Mister-Hope Date: Fri, 28 Mar 2025 22:40:48 +0800 Subject: [PATCH 3/7] chore: tweaks --- eslint.config.js | 2 +- tools/helper/package.json | 1 + tools/helper/src/client/utils/message.ts | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/eslint.config.js b/eslint.config.js index a50bd2bad5..46effc413e 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -101,7 +101,7 @@ export default vuepress( '@typescript-eslint/no-non-null-assertion': 'off', '@typescript-eslint/no-empty-function': [ 'error', - { allow: ['private-constructors'] }, + { allow: ['protected-constructors'] }, ], '@typescript-eslint/no-floating-promises': [ 'error', diff --git a/tools/helper/package.json b/tools/helper/package.json index 8240e7f589..02a76f1d84 100644 --- a/tools/helper/package.json +++ b/tools/helper/package.json @@ -31,6 +31,7 @@ "./noopComponent": "./lib/client/noopComponent.js", "./noopModule": "./lib/client/noopModule.js", "./colors.css": "./lib/client/styles/colors.css", + "./message.css": "./lib/client/styles/message.css", "./normalize.css": "./lib/client/styles/normalize.css", "./sr-only.css": "./lib/client/styles/sr-only.css", "./transition/*.css": "./lib/client/styles/transition/*.css", diff --git a/tools/helper/src/client/utils/message.ts b/tools/helper/src/client/utils/message.ts index 7ccc9f36bf..6f2d17d47c 100644 --- a/tools/helper/src/client/utils/message.ts +++ b/tools/helper/src/client/utils/message.ts @@ -5,7 +5,7 @@ const containerId = 'message-container' export class Message { private elements: Record = {} - private constructor() {} + protected constructor() {} public static get containerElement(): HTMLElement { let containerElement = document.getElementById(containerId) From 8dea7cfde84e75369c390a9b4048bcf513dc573d Mon Sep 17 00:00:00 2001 From: Mister-Hope Date: Fri, 28 Mar 2025 22:43:30 +0800 Subject: [PATCH 4/7] chore: tweaks --- tools/helper/src/client/utils/message.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/helper/src/client/utils/message.ts b/tools/helper/src/client/utils/message.ts index 6f2d17d47c..3601c0e4ed 100644 --- a/tools/helper/src/client/utils/message.ts +++ b/tools/helper/src/client/utils/message.ts @@ -3,9 +3,11 @@ import { keys } from '../../shared/index.js' const containerId = 'message-container' export class Message { - private elements: Record = {} + private elements: Record - protected constructor() {} + public constructor() { + this.elements = {} + } public static get containerElement(): HTMLElement { let containerElement = document.getElementById(containerId) From c5979a3702afb3cdf78dd7b0ad7a31463adcbe1a Mon Sep 17 00:00:00 2001 From: Mister-Hope Date: Fri, 28 Mar 2025 23:19:56 +0800 Subject: [PATCH 5/7] feat: update style --- tools/helper/src/client/styles/message.scss | 22 +++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/tools/helper/src/client/styles/message.scss b/tools/helper/src/client/styles/message.scss index 22ce46498e..88e0094fa3 100644 --- a/tools/helper/src/client/styles/message.scss +++ b/tools/helper/src/client/styles/message.scss @@ -1,7 +1,13 @@ +:root { + --message-offset: calc(var(--vp-header-offset, 3.6rem) + 1rem); + --message-timing-duration: 0.3s; + --message-timing-function: ease-in-out; +} + @keyframes message-move-in { 0% { opacity: 0; - transform: translateY(-100%); + transform: translateY(-10px); } 100% { @@ -24,8 +30,14 @@ #message-container { position: fixed; - inset: calc(var(--message-offset, 3.6rem) + 1rem) 0 auto; + inset: var(--message-offset) 0 auto; z-index: 75; + + display: flex; + flex-flow: column; + gap: 0.5rem; + align-items: center; + text-align: center; } @@ -42,11 +54,13 @@ font-size: 14px; &.move-in { - animation: message-move-in 0.3s ease-in-out; + animation: message-move-in var(--message-timing-duration) + var(--message-timing-function); } &.move-out { - animation: message-move-out 0.3s ease-in-out; + animation: message-move-out var(--message-timing-duration) + var(--message-timing-function); animation-fill-mode: forwards; } From 005d83fdd0015729ebebc42b45f6fb6d4df9ea25 Mon Sep 17 00:00:00 2001 From: Mister-Hope Date: Fri, 28 Mar 2025 23:20:24 +0800 Subject: [PATCH 6/7] feat: update style --- tools/helper/src/client/styles/message.scss | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/helper/src/client/styles/message.scss b/tools/helper/src/client/styles/message.scss index 88e0094fa3..7e44a34c5f 100644 --- a/tools/helper/src/client/styles/message.scss +++ b/tools/helper/src/client/styles/message.scss @@ -2,6 +2,7 @@ --message-offset: calc(var(--vp-header-offset, 3.6rem) + 1rem); --message-timing-duration: 0.3s; --message-timing-function: ease-in-out; + --message-gap: 0.5rem; } @keyframes message-move-in { @@ -35,7 +36,7 @@ display: flex; flex-flow: column; - gap: 0.5rem; + gap: var(--message-gap); align-items: center; text-align: center; From 13f85fd403fdbd3d87860c0581af038a0d7e5ddc Mon Sep 17 00:00:00 2001 From: Mister-Hope Date: Fri, 28 Mar 2025 23:23:28 +0800 Subject: [PATCH 7/7] chore: tweaks --- tools/helper/src/client/utils/message.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tools/helper/src/client/utils/message.ts b/tools/helper/src/client/utils/message.ts index 3601c0e4ed..5abbdef690 100644 --- a/tools/helper/src/client/utils/message.ts +++ b/tools/helper/src/client/utils/message.ts @@ -15,7 +15,6 @@ export class Message { if (containerElement) return containerElement containerElement = document.createElement('div') - containerElement.id = containerId document.body.appendChild(containerElement) @@ -27,9 +26,8 @@ export class Message { } public pop(html: string, duration = 2000, clickToClose = true): number { - const messageElement = document.createElement('div') const messageId = Date.now() - + const messageElement = document.createElement('div') messageElement.className = 'message-item move-in' messageElement.innerHTML = html Message.containerElement.appendChild(messageElement) @@ -67,7 +65,6 @@ export class Message { public destroy(): void { const containerElement = document.getElementById(containerId) - if (containerElement) document.body.removeChild(containerElement) this.elements = {} }