163 lines
4.9 KiB
JavaScript
163 lines
4.9 KiB
JavaScript
import { once } from 'alpinejs/src/utils/once'
|
|
|
|
export default (Alpine) => {
|
|
Alpine.data('notificationComponent', ({ notification }) => ({
|
|
isShown: false,
|
|
|
|
computedStyle: null,
|
|
|
|
transitionDuration: null,
|
|
|
|
transitionEasing: null,
|
|
|
|
init: function () {
|
|
this.computedStyle = window.getComputedStyle(this.$el)
|
|
|
|
this.transitionDuration =
|
|
parseFloat(this.computedStyle.transitionDuration) * 1000
|
|
|
|
this.transitionEasing = this.computedStyle.transitionTimingFunction
|
|
|
|
this.configureTransitions()
|
|
this.configureAnimations()
|
|
|
|
if (
|
|
notification.duration &&
|
|
notification.duration !== 'persistent'
|
|
) {
|
|
setTimeout(() => {
|
|
if (!this.$el.matches(':hover')) {
|
|
this.close()
|
|
|
|
return
|
|
}
|
|
|
|
this.$el.addEventListener('mouseleave', () => this.close())
|
|
}, notification.duration)
|
|
}
|
|
|
|
this.isShown = true
|
|
},
|
|
|
|
configureTransitions: function () {
|
|
const display = this.computedStyle.display
|
|
|
|
const show = () => {
|
|
Alpine.mutateDom(() => {
|
|
this.$el.style.setProperty('display', display)
|
|
this.$el.style.setProperty('visibility', 'visible')
|
|
})
|
|
this.$el._x_isShown = true
|
|
}
|
|
|
|
const hide = () => {
|
|
Alpine.mutateDom(() => {
|
|
this.$el._x_isShown
|
|
? this.$el.style.setProperty('visibility', 'hidden')
|
|
: this.$el.style.setProperty('display', 'none')
|
|
})
|
|
}
|
|
|
|
const toggle = once(
|
|
(value) => (value ? show() : hide()),
|
|
(value) => {
|
|
this.$el._x_toggleAndCascadeWithTransitions(
|
|
this.$el,
|
|
value,
|
|
show,
|
|
hide,
|
|
)
|
|
},
|
|
)
|
|
|
|
Alpine.effect(() => toggle(this.isShown))
|
|
},
|
|
|
|
configureAnimations: function () {
|
|
let animation
|
|
|
|
Livewire.hook(
|
|
'commit',
|
|
({ component, commit, succeed, fail, respond }) => {
|
|
if (
|
|
!component.snapshot.data
|
|
.isFilamentNotificationsComponent
|
|
) {
|
|
return
|
|
}
|
|
|
|
const getTop = () => this.$el.getBoundingClientRect().top
|
|
const oldTop = getTop()
|
|
|
|
respond(() => {
|
|
animation = () => {
|
|
if (!this.isShown) {
|
|
return
|
|
}
|
|
|
|
this.$el.animate(
|
|
[
|
|
{
|
|
transform: `translateY(${
|
|
oldTop - getTop()
|
|
}px)`,
|
|
},
|
|
{ transform: 'translateY(0px)' },
|
|
],
|
|
{
|
|
duration: this.transitionDuration,
|
|
easing: this.transitionEasing,
|
|
},
|
|
)
|
|
}
|
|
|
|
this.$el
|
|
.getAnimations()
|
|
.forEach((animation) => animation.finish())
|
|
})
|
|
|
|
succeed(({ snapshot, effect }) => {
|
|
animation()
|
|
})
|
|
},
|
|
)
|
|
},
|
|
|
|
close: function () {
|
|
this.isShown = false
|
|
|
|
setTimeout(
|
|
() =>
|
|
window.dispatchEvent(
|
|
new CustomEvent('notificationClosed', {
|
|
detail: {
|
|
id: notification.id,
|
|
},
|
|
}),
|
|
),
|
|
this.transitionDuration,
|
|
)
|
|
},
|
|
|
|
markAsRead: function () {
|
|
window.dispatchEvent(
|
|
new CustomEvent('markedNotificationAsRead', {
|
|
detail: {
|
|
id: notification.id,
|
|
},
|
|
}),
|
|
)
|
|
},
|
|
|
|
markAsUnread: function () {
|
|
window.dispatchEvent(
|
|
new CustomEvent('markedNotificationAsUnread', {
|
|
detail: {
|
|
id: notification.id,
|
|
},
|
|
}),
|
|
)
|
|
},
|
|
}))
|
|
}
|