image embed now uses primevue for modal

This commit is contained in:
lightling 2025-04-18 00:44:41 -04:00
parent 477259d85c
commit 37e7fd3416
Signed by: lightling
GPG key ID: F1F29650D537C773
6 changed files with 34 additions and 71 deletions

8
package-lock.json generated
View file

@ -14016,6 +14016,13 @@
"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
"license": "MIT"
},
"node_modules/mount-vue-component": {
"version": "0.10.2",
"resolved": "https://registry.npmjs.org/mount-vue-component/-/mount-vue-component-0.10.2.tgz",
"integrity": "sha512-oighx0My03ArLOoTV/kLTJnrBwKdQMvn8uRP+u02rGkgkLiX1LycaHzFGib7mUwkyjp3q3uzVgwHjLZqM6rxyA==",
"dev": true,
"license": "MIT"
},
"node_modules/mrmime": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz",
@ -21080,6 +21087,7 @@
"js-yaml": "4.1.0",
"marked": "15.0.8",
"marked-highlight": "2.2.1",
"mount-vue-component": "0.10.2",
"normalize.css": "8.0.1",
"pinia": "3.0.2",
"primevue": "4.3.3",

View file

@ -24,6 +24,7 @@
"js-yaml": "4.1.0",
"marked": "15.0.8",
"marked-highlight": "2.2.1",
"mount-vue-component": "0.10.2",
"normalize.css": "8.0.1",
"pinia": "3.0.2",
"primevue": "4.3.3",

View file

@ -1,5 +1,4 @@
import { inflateDetailsElements } from './details'
import { inflateImageEmbeds } from './image'
import { inflateVideoEmbeds } from './video'
/**
@ -7,6 +6,5 @@ import { inflateVideoEmbeds } from './video'
*/
export const inflateEmbeds = () => {
inflateDetailsElements()
inflateImageEmbeds()
inflateVideoEmbeds()
}

View file

@ -1,53 +0,0 @@
import { useModalStore } from 'src/modal'
/**
* Queries for HTMLImageElement nodes and inflates them with extra functionality
* @param _window the reference to the window
*/
export const inflateImageEmbeds = () => {
document.querySelectorAll('.content img:not(.no-inflate)').forEach((_element) => {
new ImageElement(_element as HTMLImageElement)
})
}
/**
* Inflates HTMLImageElement with extra functionality,
* namely previewing images in the modal service and displaying captions from titles
*/
export class ImageElement {
element: HTMLImageElement
caption: HTMLParagraphElement | null = null
wrapper: HTMLDivElement
constructor(_element: HTMLImageElement) {
this.element = _element
const parent = this.element.parentElement!
this.wrapper = document.createElement('div')
this.wrapper.classList.add('embed', 'image')
const subWrapper = document.createElement('div')
subWrapper.classList.add('image-wrapper')
parent.appendChild(this.wrapper)
this.wrapper.appendChild(subWrapper)
subWrapper.appendChild(this.element)
if (!!this.element.title) {
this.caption = document.createElement('p')
this.wrapper.appendChild(this.caption)
this.caption.innerHTML = this.element.title
}
this.element.addEventListener('click', this.onClick)
}
/**
* Handler for when the image is clicked
* @param event the click event
*/
onClick = (event: Event) => {
event.preventDefault()
let cloned = this.wrapper.cloneNode(true) as HTMLElement
let image = cloned.firstChild as HTMLElement
image.removeEventListener('click', this.onClick)
const store = useModalStore()
store.content = cloned.outerHTML
store.isOpen = true
}
}

View file

@ -1,5 +1,8 @@
<script setup lang="ts">
import { onMounted } from 'vue'
import { onMounted, createApp, getCurrentInstance } from 'vue'
import { mount } from 'mount-vue-component'
import PrimeVueImage from 'primevue/image'
import { inflateEmbeds } from 'src/components/inflators/embed'
@ -7,8 +10,28 @@ const props = defineProps<{
content: string
}>()
const instance = getCurrentInstance()
const inflateComponents = () => {
// replace images with primevue/image
document.querySelectorAll('.content img:not(.no-inflate)').forEach((_element) => {
const inflated = mount(PrimeVueImage, {
props: {
alt: _element.getAttribute('alt'),
title: _element.getAttribute('title'),
src: _element.getAttribute('src'),
preview: true,
},
app: instance!.appContext.app,
})
_element.parentElement!.appendChild(inflated.el)
inflated.el.classList.add('embed', 'image')
_element.remove()
})
}
onMounted(() => {
inflateEmbeds()
inflateComponents()
})
</script>
@ -18,6 +41,6 @@ onMounted(() => {
)
</template>
<style scope lang="sass">
<style lang="sass">
</style>

View file

@ -5,25 +5,11 @@ input[type="checkbox"],
label:has(+ input[type="checkbox"])
cursor: pointer
.modal-outlet
.embed
img
cursor: default
.embed
video,
iframe,
object
border: none
.image-wrapper
display: grid
grid-template-columns: 1fr
grid-template-rows: 1fr
img
cursor: pointer
max-width: 100%
max-height: 100%
margin: auto
details
summary