image embed now uses primevue for modal
This commit is contained in:
parent
477259d85c
commit
37e7fd3416
6 changed files with 34 additions and 71 deletions
8
package-lock.json
generated
8
package-lock.json
generated
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue