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==",
|
"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
|
||||||
"license": "MIT"
|
"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": {
|
"node_modules/mrmime": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz",
|
||||||
|
@ -21080,6 +21087,7 @@
|
||||||
"js-yaml": "4.1.0",
|
"js-yaml": "4.1.0",
|
||||||
"marked": "15.0.8",
|
"marked": "15.0.8",
|
||||||
"marked-highlight": "2.2.1",
|
"marked-highlight": "2.2.1",
|
||||||
|
"mount-vue-component": "0.10.2",
|
||||||
"normalize.css": "8.0.1",
|
"normalize.css": "8.0.1",
|
||||||
"pinia": "3.0.2",
|
"pinia": "3.0.2",
|
||||||
"primevue": "4.3.3",
|
"primevue": "4.3.3",
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
"js-yaml": "4.1.0",
|
"js-yaml": "4.1.0",
|
||||||
"marked": "15.0.8",
|
"marked": "15.0.8",
|
||||||
"marked-highlight": "2.2.1",
|
"marked-highlight": "2.2.1",
|
||||||
|
"mount-vue-component": "0.10.2",
|
||||||
"normalize.css": "8.0.1",
|
"normalize.css": "8.0.1",
|
||||||
"pinia": "3.0.2",
|
"pinia": "3.0.2",
|
||||||
"primevue": "4.3.3",
|
"primevue": "4.3.3",
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { inflateDetailsElements } from './details'
|
import { inflateDetailsElements } from './details'
|
||||||
import { inflateImageEmbeds } from './image'
|
|
||||||
import { inflateVideoEmbeds } from './video'
|
import { inflateVideoEmbeds } from './video'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -7,6 +6,5 @@ import { inflateVideoEmbeds } from './video'
|
||||||
*/
|
*/
|
||||||
export const inflateEmbeds = () => {
|
export const inflateEmbeds = () => {
|
||||||
inflateDetailsElements()
|
inflateDetailsElements()
|
||||||
inflateImageEmbeds()
|
|
||||||
inflateVideoEmbeds()
|
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">
|
<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'
|
import { inflateEmbeds } from 'src/components/inflators/embed'
|
||||||
|
|
||||||
|
@ -7,8 +10,28 @@ const props = defineProps<{
|
||||||
content: string
|
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(() => {
|
onMounted(() => {
|
||||||
inflateEmbeds()
|
inflateEmbeds()
|
||||||
|
inflateComponents()
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -18,6 +41,6 @@ onMounted(() => {
|
||||||
)
|
)
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scope lang="sass">
|
<style lang="sass">
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -5,25 +5,11 @@ input[type="checkbox"],
|
||||||
label:has(+ input[type="checkbox"])
|
label:has(+ input[type="checkbox"])
|
||||||
cursor: pointer
|
cursor: pointer
|
||||||
|
|
||||||
.modal-outlet
|
|
||||||
.embed
|
|
||||||
img
|
|
||||||
cursor: default
|
|
||||||
|
|
||||||
.embed
|
.embed
|
||||||
video,
|
video,
|
||||||
iframe,
|
iframe,
|
||||||
object
|
object
|
||||||
border: none
|
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
|
details
|
||||||
summary
|
summary
|
||||||
|
|
Loading…
Add table
Reference in a new issue