Skip to content

Commit 3aaab8f

Browse files
fix: queues and events propagation
1 parent 40521de commit 3aaab8f

File tree

7 files changed

+54
-31
lines changed

7 files changed

+54
-31
lines changed

src/runtime/components/NinjaToaster.ts

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ import {
1111
withDirectives
1212
} from 'vue'
1313

14+
import type { NinjaToastEventBus } from '../events'
1415
import type { NinjaToasterProps } from '../../props'
1516
import { usePausableTimeout } from '../composables/usePausableTimeout'
1617
import { useNinjaToasterContainer } from '../composables/useNinjaToasterContainer'
1718
import { createNinjaToasterState } from '../composables/useNinjaToasterState'
1819
import { type NinjaToasterRenderQueue, createRenderQueue } from '../queue'
19-
import { useNuxtApp } from '#app'
2020

2121
export default defineComponent({
2222
name: 'NinjaToaster',
@@ -28,7 +28,7 @@ export default defineComponent({
2828
required: true
2929
},
3030
duration: {
31-
type: Number as PropType<NinjaToasterProps['duration']>,
31+
type: Number,
3232
default: 5000
3333
},
3434
transition: {
@@ -40,16 +40,24 @@ export default defineComponent({
4040
default: () => ({} as NinjaToasterProps['theme'])
4141
},
4242
dismissible: {
43-
type: Boolean as PropType<NinjaToasterProps['dismissible']>,
43+
type: Boolean,
4444
default: true
4545
},
4646
pauseOnHover: {
47-
type: Boolean as PropType<NinjaToasterProps['pauseOnHover']>,
47+
type: Boolean,
4848
default: true
4949
},
5050
maxToasts: {
51-
type: Number as PropType<NinjaToasterProps['maxToasts']>,
51+
type: Number,
5252
default: Infinity
53+
},
54+
queues: {
55+
type: Map as PropType<Map<string, NinjaToasterRenderQueue>>,
56+
default: () => new Map()
57+
},
58+
events: {
59+
type: Object as PropType<NinjaToastEventBus>,
60+
default: () => ({})
5361
}
5462
},
5563
emits: ['close', 'click', 'show'],
@@ -63,15 +71,13 @@ export default defineComponent({
6371
const isActive = ref(false)
6472
const unqueue = ref<() => void>()
6573
const rootElement = ref<HTMLElement>()
66-
const nuxt = useNuxtApp()
67-
const events = nuxt.$nt.events
6874
let queue: NinjaToasterRenderQueue
6975

70-
if (nuxt.$nt.queues.has(containerId)) {
71-
queue = nuxt.$nt.queues.get(containerId)
76+
if (props.queues.has(containerId)) {
77+
queue = props.queues.get(containerId)!
7278
} else {
7379
queue = createRenderQueue()
74-
nuxt.$nt.queues.set(containerId, queue)
80+
props.queues.set(containerId, queue)
7581
}
7682

7783
const content = computed(() => {
@@ -81,6 +87,10 @@ export default defineComponent({
8187
})
8288

8389
const shouldQueue = () => {
90+
if (!container.value) {
91+
return false
92+
}
93+
8494
if (props.maxToasts <= 0 || props.maxToasts === Infinity) {
8595
return false
8696
}
@@ -116,6 +126,10 @@ export default defineComponent({
116126
return
117127
}
118128

129+
if (!container.value || !rootElement.value) {
130+
return
131+
}
132+
119133
container.value.insertAdjacentElement('afterbegin', rootElement.value)
120134
isActive.value = true
121135

@@ -175,19 +189,19 @@ export default defineComponent({
175189
if (typeof rootElement.value?.remove !== 'undefined') {
176190
rootElement.value?.remove()
177191
} else {
178-
rootElement.value?.parentNode.removeChild(rootElement.value)
192+
rootElement.value?.parentNode?.removeChild(rootElement.value)
179193
}
180194
}
181195

182196
onMounted(() => {
183197
show()
184198

185-
events.on('clear', close)
186-
events.on(`clear-${containerId}`, close)
199+
props.events.on('clear', close)
200+
props.events.on(`clear-${containerId}`, close)
187201
})
188202
onBeforeUnmount(() => {
189-
events.off('clear', close)
190-
events.off(`clear-${containerId}`, close)
203+
props.events.off('clear', close)
204+
props.events.off(`clear-${containerId}`, close)
191205
})
192206

193207
createNinjaToasterState({
@@ -206,7 +220,7 @@ export default defineComponent({
206220
{
207221
role: 'alert',
208222
tabindex: 0,
209-
class: props.theme.wrapperClass,
223+
class: props.theme?.wrapperClass,
210224
onMouseover,
211225
onMouseleave,
212226
onFocus,

src/runtime/composables/usePausableTimeout.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { ref } from 'vue'
22
import { tryOnBeforeUnmount } from '@vueuse/core'
33

4-
export function usePausableTimeout(callback: Function, timeout: number) {
4+
export function usePausableTimeout(callback: Function, timeout?: number) {
55
const pausedAt = ref(0)
66
const startedAt = ref(0)
77
const remaining = ref(0)
88

9-
let timer
9+
let timer: number | undefined
1010

1111
function stop() {
1212
if (!timer) {
@@ -20,7 +20,7 @@ export function usePausableTimeout(callback: Function, timeout: number) {
2020
function start() {
2121
pausedAt.value = 0
2222
startedAt.value = Date.now()
23-
remaining.value = timeout
23+
remaining.value = timeout ?? 0
2424

2525
stop()
2626
timer = setTimeout(callback, remaining.value)

src/runtime/create.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,29 @@ import { defu } from 'defu'
44
import type { NinjaToasterTheme } from '../theme'
55
import type { NinjaToasterProps } from '../props'
66
import type { NinjaToasterRenderQueue } from './queue'
7-
import { createEventBus } from './events'
7+
import { type NinjaToastEventBus, createEventBus } from './events'
88
import NinjaToaster from './components/NinjaToaster'
9+
10+
// @ts-expect-error - Nuxt 3 auto-imports
911
import { useNuxtApp, useRuntimeConfig } from '#app'
1012

1113
function createElement() {
14+
// @ts-expect-error - Nuxt 3 context
1215
if (process.server) {
1316
return null
1417
}
1518

1619
return document.createElement('div')
1720
}
1821

19-
function mountWithContext(app: App, component: any, props: NinjaToasterProps) {
22+
function mountWithContext(
23+
app: App,
24+
component: any,
25+
props: NinjaToasterProps & {
26+
events: NinjaToastEventBus
27+
queues: Map<string, NinjaToasterRenderQueue>
28+
}
29+
) {
2030
const el = createElement()
2131

2232
if (el) {
@@ -58,6 +68,8 @@ export function createNinjaToaster(
5868
return new Promise<NinjaToasterShow>((resolve) => {
5969
mountWithContext(app, NinjaToaster, {
6070
...props,
71+
events,
72+
queues,
6173
onShow: (toast: NinjaToasterShow) => {
6274
resolve(toast)
6375

@@ -67,6 +79,7 @@ export function createNinjaToaster(
6779
}
6880
})
6981

82+
// @ts-expect-error - Nuxt 3 context
7083
if (process.server) {
7184
resolve({
7285
el: null,
@@ -77,8 +90,6 @@ export function createNinjaToaster(
7790
}
7891

7992
function clearAll() {
80-
console.log('clear all')
81-
8293
events.emit('clear')
8394
queues.forEach((queue) => {
8495
queue.clear()
@@ -89,17 +100,13 @@ export function createNinjaToaster(
89100
function clear(theme: NinjaToasterTheme | string) {
90101
const containerId = typeof theme === 'string' ? theme : theme.containerId
91102

92-
console.log('clear', containerId)
93-
94103
events.emit(`clear-${containerId}`)
95104
if (queues.has(containerId)) {
96105
queues.get(containerId)?.clear()
97106
}
98107
}
99108

100109
return {
101-
events,
102-
queues,
103110
show,
104111
clearAll,
105112
clear

src/runtime/events.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export function createEventBus() {
88
queue[name].push(callback)
99
}
1010

11-
function off(name: string, callback) {
11+
function off(name: string, callback: NinjaToasterEventCallback) {
1212
if (queue[name]) {
1313
for (let i = 0; i < queue[name].length; i++) {
1414
if (queue[name][i] === callback) {

src/runtime/plugin.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import { createNinjaToaster } from './create'
2+
3+
// @ts-expect-error - Nuxt 3 auto-imports
24
import { defineNuxtPlugin } from '#app'
35

46
export default defineNuxtPlugin(() => {

src/runtime/queue.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export interface NinjaToasterQueue {
66
export function createRenderQueue() {
77
// last in last out queue
88
const queue: NinjaToasterQueue[] = []
9-
let timer: ReturnType<typeof setTimeout> | null = null
9+
let timer: ReturnType<typeof setTimeout> | undefined
1010

1111
function add(item: NinjaToasterQueue) {
1212
queue.push(item)
@@ -32,7 +32,7 @@ export function createRenderQueue() {
3232
queue.length = 0
3333
if (timer) {
3434
clearTimeout(timer)
35-
timer = null
35+
timer = undefined
3636
}
3737
}
3838

src/theme.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
export interface NinjaToasterTheme {
2-
containerId?: string;
2+
containerId: string;
33
containerClass?: string;
44
wrapperClass?: string;
55
}

0 commit comments

Comments
 (0)