pinafore/src/routes/_components/compose/ComposeAutosuggest.html

121 wiersze
4.1 KiB
HTML

<div class="compose-autosuggest-anchor-point" ref:anchor></div>
<style>
.compose-autosuggest-anchor-point {
grid-area: autosuggest;
width: 100%;
height: 0;
}
</style>
<script>
import ComposeAutosuggestContainer from './ComposeAutosuggestContainer.html'
import { requestPostAnimationFrame } from '../../_utils/requestPostAnimationFrame'
import { observe } from 'svelte-extras'
import { throttleTimer } from '../../_utils/throttleTimer'
import { on } from '../../_utils/eventBus'
import { store } from '../../_store/store'
import { addScrollListener, getScrollContainer, removeScrollListener } from '../../_utils/scrollContainer'
import { get } from '../../_utils/lodash-lite'
import { registerResizeListener, unregisterResizeListener } from '../../_utils/resize'
const updatePosition = process.browser && throttleTimer(requestAnimationFrame)
export default {
oncreate () {
const { dialogId } = this.get()
this.onResize = () => updatePosition(() => this.doResize())
let setupDone = false
if (this.get().realm === 'dialog') {
// wait for dialog to render first
on('dialogDidRender', this, id => {
if (id === dialogId && !setupDone) {
setupDone = true
this.setup()
}
})
} else {
setupDone = true
this.setup()
}
},
ondestroy () {
if (this._autosuggest) {
this._autosuggest.destroy()
this._autosuggest = null
}
if (this._element) {
this._element.remove()
}
unregisterResizeListener(this.onResize)
removeScrollListener(this.onResize)
},
methods: {
observe,
setup () {
const { realm, text, dialogId } = this.get()
requestAnimationFrame(() => {
const id = `the-autosuggest-container-${realm}`
this._element = document.getElementById(id)
if (!this._element) {
this._element = document.createElement('div')
this._element.id = id
const parent = realm === 'dialog' ? document.querySelector('.modal-dialog-contents') : document.body
parent.appendChild(this._element) // write
}
requestPostAnimationFrame(() => {
const { left, top } = this.calculateLeftAndTop()
this._autosuggest = new ComposeAutosuggestContainer({
target: this._element,
data: {
realm,
text,
dialogId,
left,
top
}
})
this.observe('text', text => {
this._autosuggest.set({ text })
}, { init: false })
this.observe('shouldBeShown', shouldBeShown => {
if (shouldBeShown) {
this.onResize() // just in case the window size changed while we weren't focused
}
})
registerResizeListener(this.onResize)
addScrollListener(this.onResize)
})
})
},
doResize () {
const { shouldBeShown } = this.get()
if (this._autosuggest && shouldBeShown) {
const { left, top } = this.calculateLeftAndTop()
console.log('updating autosuggest position', { left, top })
this._autosuggest.set({ left, top })
}
},
calculateLeftAndTop () {
const { anchor } = this.refs
const { realm } = this.get()
const { left, bottom } = anchor.getBoundingClientRect()
const yOffset = realm === 'dialog' ? 0 : getScrollContainer().scrollTop
return {
left,
top: bottom + yOffset
}
}
},
store: () => store,
computed: {
/* eslint-disable camelcase */
composeFocused: ({ $autosuggestData_composeFocused, $currentInstance, realm }) => (
get($autosuggestData_composeFocused, [$currentInstance, realm], false)
),
/* eslint-enable camelcase */
shouldBeShown: ({ $autosuggestShown, composeFocused }) => (
!!($autosuggestShown && composeFocused)
)
}
}
</script>