🆙 Add cms i using 🆙

This commit is contained in:
Remco
2025-11-25 22:42:56 +01:00
parent 94704e0925
commit d44196149e
35591 changed files with 3601123 additions and 0 deletions
@@ -0,0 +1,352 @@
import { v4 as uuid } from 'uuid-browser'
class Notification {
constructor() {
this.id(uuid())
return this
}
id(id) {
this.id = id
return this
}
title(title) {
this.title = title
return this
}
body(body) {
this.body = body
return this
}
actions(actions) {
this.actions = actions
return this
}
status(status) {
this.status = status
return this
}
color(color) {
this.color = color
return this
}
icon(icon) {
this.icon = icon
return this
}
iconColor(color) {
this.iconColor = color
return this
}
duration(duration) {
this.duration = duration
return this
}
seconds(seconds) {
this.duration(seconds * 1000)
return this
}
persistent() {
this.duration('persistent')
return this
}
danger() {
this.status('danger')
return this
}
info() {
this.status('info')
return this
}
success() {
this.status('success')
return this
}
warning() {
this.status('warning')
return this
}
view(view) {
this.view = view
return this
}
viewData(viewData) {
this.viewData = viewData
return this
}
send() {
window.dispatchEvent(
new CustomEvent('notificationSent', {
detail: {
notification: this,
},
}),
)
return this
}
}
class Action {
constructor(name) {
this.name(name)
return this
}
name(name) {
this.name = name
return this
}
color(color) {
this.color = color
return this
}
dispatch(event, data) {
this.event(event)
this.eventData(data)
return this
}
dispatchSelf(event, data) {
this.dispatch(event, data)
this.dispatchDirection = 'self'
return this
}
dispatchTo(component, event, data) {
this.dispatch(event, data)
this.dispatchDirection = 'to'
this.dispatchToComponent = component
return this
}
/**
* @deprecated Use `dispatch()` instead.
*/
emit(event, data) {
this.dispatch(event, data)
return this
}
/**
* @deprecated Use `dispatchSelf()` instead.
*/
emitSelf(event, data) {
this.dispatchSelf(event, data)
return this
}
/**
* @deprecated Use `dispatchTo()` instead.
*/
emitTo(component, event, data) {
this.dispatchTo(component, event, data)
return this
}
dispatchDirection(dispatchDirection) {
this.dispatchDirection = dispatchDirection
return this
}
dispatchToComponent(component) {
this.dispatchToComponent = component
return this
}
event(event) {
this.event = event
return this
}
eventData(data) {
this.eventData = data
return this
}
extraAttributes(attributes) {
this.extraAttributes = attributes
return this
}
icon(icon) {
this.icon = icon
return this
}
iconPosition(position) {
this.iconPosition = position
return this
}
outlined(condition = true) {
this.isOutlined = condition
return this
}
disabled(condition = true) {
this.isDisabled = condition
return this
}
label(label) {
this.label = label
return this
}
close(condition = true) {
this.shouldClose = condition
return this
}
openUrlInNewTab(condition = true) {
this.shouldOpenUrlInNewTab = condition
return this
}
size(size) {
this.size = size
return this
}
url(url) {
this.url = url
return this
}
view(view) {
this.view = view
return this
}
button() {
this.view('filament::components.button.index')
return this
}
grouped() {
this.view('filament::components.dropdown.list.item')
return this
}
iconButton() {
this.view('filament::components.icon-button')
return this
}
link() {
this.view('filament::components.link')
return this
}
}
class ActionGroup {
constructor(actions) {
this.actions(actions)
return this
}
actions(actions) {
this.actions = actions.map((action) => action.grouped())
return this
}
color(color) {
this.color = color
return this
}
icon(icon) {
this.icon = icon
return this
}
iconPosition(position) {
this.iconPosition = position
return this
}
label(label) {
this.label = label
return this
}
tooltip(tooltip) {
this.tooltip = tooltip
return this
}
}
export { Action, ActionGroup, Notification }
@@ -0,0 +1,167 @@
import { once } from 'alpinejs/src/utils/once'
export default (Alpine) => {
Alpine.data('notificationComponent', ({ notification }) => ({
isShown: false,
computedStyle: null,
transitionDuration: null,
transitionEasing: null,
init() {
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() {
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() {
let animation
Livewire.hook(
'commit',
({ component, commit, succeed, fail, respond }) => {
if (
!component.snapshot.data
.isFilamentNotificationsComponent
) {
return
}
// Calling `el.getBoundingClientRect()` from outside `requestAnimationFrame()` can
// occasionally cause the page to scroll to the top.
requestAnimationFrame(() => {
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() {
this.isShown = false
setTimeout(
() =>
window.dispatchEvent(
new CustomEvent('notificationClosed', {
detail: {
id: notification.id,
},
}),
),
this.transitionDuration,
)
},
markAsRead() {
window.dispatchEvent(
new CustomEvent('markedNotificationAsRead', {
detail: {
id: notification.id,
},
}),
)
},
markAsUnread() {
window.dispatchEvent(
new CustomEvent('markedNotificationAsUnread', {
detail: {
id: notification.id,
},
}),
)
},
}))
}
@@ -0,0 +1,14 @@
import NotificationComponentAlpinePlugin from './components/notification'
import {
Action as NotificationAction,
ActionGroup as NotificationActionGroup,
Notification,
} from './Notification'
window.FilamentNotificationAction = NotificationAction
window.FilamentNotificationActionGroup = NotificationActionGroup
window.FilamentNotification = Notification
document.addEventListener('alpine:init', () => {
window.Alpine.plugin(NotificationComponentAlpinePlugin)
})