This commit is contained in:
2025-05-24 01:49:48 +09:00
commit 62abbcf4eb
2376 changed files with 325522 additions and 0 deletions

View File

@@ -0,0 +1,32 @@
import type { Directive, DirectiveHook } from 'vue'
const onUpdate: DirectiveHook = (el: HTMLElement, bindings) => {
const src = bindings.value.src
const placeholder = bindings.value.placeholder
if (src) {
const image = new Image()
if (placeholder) {
image.onerror = () => {
image.onerror = null
el.style.backgroundImage = `url(${placeholder})`
}
}
image.onload = () => {
image.onload = null
el.style.backgroundImage = `url(${src})`
}
image.src = src
}
}
export const vBackground: Directive = {
getSSRProps() {
return {}
},
updated: onUpdate,
mounted: onUpdate,
}

View File

@@ -0,0 +1,48 @@
import type { Directive } from 'vue'
const handlers = new WeakMap()
const preloaded = new Set<string>()
/**
* This directive is used to prefetch a link when the user hovers over it.
* This allow to reduce the time it takes to load the page, and thus improve the user experience.
* @exemple <RouterLink to="/" v-preload-link>Home</RouterLink>
*/
export const vPreloadLink: Directive = {
getSSRProps() {
return {}
},
created: (el: HTMLAnchorElement) => {
const handler = function () {
const href = (el.href ?? '').split('#')[0]
if (!href || preloaded.has(href)) {
el.removeEventListener('mouseenter', handler)
return
}
const newPreLoadLink = document.createElement('link')
newPreLoadLink.rel = 'prefetch'
newPreLoadLink.href = href
document.head.appendChild(newPreLoadLink)
preloaded.add(href)
el.removeEventListener('mouseenter', handler)
}
handlers.set(el, handler)
},
beforeMount() {
const currentHref = window.location.toString().split('#')[0]
if (!currentHref || preloaded.has(currentHref)) {
return
}
preloaded.add(currentHref)
},
mounted: (el: HTMLAnchorElement) => {
el.addEventListener('mouseenter', handlers.get(el), { passive: true })
},
unmounted: (el: HTMLAnchorElement) => {
el.removeEventListener('mouseenter', handlers.get(el))
},
}

94
src/directives/tooltip.ts Normal file
View File

@@ -0,0 +1,94 @@
import type { Directive, DirectiveHook } from 'vue'
const updateVTooltip: DirectiveHook = (el: HTMLElement, bindings) => {
const value = bindings.value
let placement = 'top'
let color = ''
let shape = ''
if (bindings.modifiers.bottom) {
placement = 'bottom'
}
if (bindings.modifiers.left) {
placement += '-left'
}
else if (bindings.modifiers.right) {
placement += '-right'
}
if (bindings.modifiers.light) {
color = 'hint--light'
}
else if (bindings.modifiers.primary) {
color = 'hint--primary'
}
else if (bindings.modifiers.info) {
color = 'hint--info'
}
else if (bindings.modifiers.success) {
color = 'hint--success'
}
else if (bindings.modifiers.warning) {
color = 'hint--warning'
}
else if (bindings.modifiers.error) {
color = 'hint--error'
}
if (bindings.modifiers.rounded) {
shape = 'hint--rounded'
}
else if (bindings.modifiers.bubble) {
shape = 'hint--bubble'
}
const previousClasses: string[] = []
const nextClasses: string[] = []
el.classList.forEach((className) => {
if (className.startsWith('hint--')) {
previousClasses.push(className)
}
})
if (typeof value === 'string') {
el.dataset.hint = value
el.ariaLabel = value
el.tabIndex ??= 0
nextClasses.push(`hint--${placement}`)
if (color) {
nextClasses.push(color)
}
if (shape) {
nextClasses.push(shape)
}
}
else {
el.dataset.hint = undefined
}
// add new classes
nextClasses.forEach((className) => {
if (!previousClasses.includes(className)) {
el.classList.add(className)
}
})
// remove old classes
previousClasses.forEach((className) => {
if (!nextClasses.includes(className)) {
el.classList.remove(className)
}
})
}
export const vTooltip = {
getSSRProps() {
return {}
},
updated: updateVTooltip,
mounted: updateVTooltip,
} satisfies Directive