120 lines
4.1 KiB
HTML
120 lines
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>
|