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

137 lines
4.7 KiB
HTML

<div class="compose-autosuggest {shown ? 'shown' : ''} {realm === 'dialog' ? 'is-dialog' : ''}"
aria-hidden={!shown}
>
<ComposeAutosuggestionList
items={autosuggestSearchResults}
on:click="onClick(event)"
type={autosuggestType}
selected={autosuggestSelected}
{realm}
/>
<div class="sr-only" aria-live="assertive">
{assertiveAriaText}
</div>
</div>
<style>
.compose-autosuggest {
grid-area: autosuggest;
position: absolute;
left: 5px;
top: 0;
pointer-events: none;
opacity: 0;
transition: opacity 0.1s linear;
z-index: 7000;
}
.compose-autosuggest.is-dialog {
z-index: 11000;
}
.compose-autosuggest.shown {
pointer-events: auto;
opacity: 1;
}
@media (min-width: 480px) {
.compose-autosuggest {
min-width: 400px;
max-width: calc(100% - 20px);
}
}
@media (max-width: 479px) {
.compose-autosuggest {
/* on mobile, move it to the left and make it fill the viewport width */
transform: translateX(-58px); /* avatar size 48px + 10px padding */
width: calc(100vw - 20px);
}
.compose-autosuggest.is-dialog {
width: calc(100vw - 40px); /* extra padding when within the dialog */
}
}
</style>
<script>
import { store } from '../../_store/store'
import ComposeAutosuggestionList from './ComposeAutosuggestionList.html'
import { get } from '../../_utils/lodash-lite'
import { selectAutosuggestItem } from '../../_actions/autosuggest'
import { observe } from 'svelte-extras'
import { once } from '../../_utils/once'
import { createAutosuggestAccessibleLabel } from '../../_utils/createAutosuggestAccessibleLabel'
export default {
oncreate () {
this._promiseChain = Promise.resolve()
this.observe('shouldBeShown', (shouldBeShown) => {
// TODO: hack so that when the user clicks the button, and the textarea blurs,
// we don't immediately hide the dropdown which would cause the click to get lost
this._promiseChain = this._promiseChain.then(() => {
if (!shouldBeShown) {
return Promise.race([
new Promise(resolve => setTimeout(resolve, 200)),
new Promise(resolve => this.once('autosuggestItemSelected', resolve))
])
}
}).then(() => {
this.set({ shown: shouldBeShown })
this.store.setForCurrentAutosuggest({ autosuggestSelecting: false })
})
})
},
methods: {
observe,
once,
onClick (item) {
/* autosuggestSelecting prevents a flash of searched content */
this.store.setForCurrentAutosuggest({ autosuggestSelecting: true })
this.fire('autosuggestItemSelected')
selectAutosuggestItem(item)
}
},
computed: {
/* eslint-disable camelcase */
composeSelectionStart: ({ $autosuggestData_composeSelectionStart, $currentInstance, realm }) => (
get($autosuggestData_composeSelectionStart, [$currentInstance, realm], 0)
),
composeFocused: ({ $autosuggestData_composeFocused, $currentInstance, realm }) => (
get($autosuggestData_composeFocused, [$currentInstance, realm], false)
),
autosuggestSearchResults: ({ $autosuggestData_autosuggestSearchResults, $currentInstance, realm }) => (
get($autosuggestData_autosuggestSearchResults, [$currentInstance, realm], [])
),
autosuggestType: ({ $autosuggestData_autosuggestType, $currentInstance, realm }) => (
get($autosuggestData_autosuggestType, [$currentInstance, realm])
),
autosuggestSelected: ({ $autosuggestData_autosuggestSelected, $currentInstance, realm }) => (
get($autosuggestData_autosuggestSelected, [$currentInstance, realm], 0)
),
autosuggestSearchText: ({ $autosuggestData_autosuggestSelected, $currentInstance, realm }) => (
get($autosuggestData_autosuggestSelected, [$currentInstance, realm])
),
/* eslint-enable camelcase */
shouldBeShown: ({ realm, $autosuggestShown, composeFocused }) => (
!!($autosuggestShown && composeFocused)
),
// text that is read to screen readers. based on https://haltersweb.github.io/Accessibility/autocomplete.html
assertiveAriaText: ({ shouldBeShown,
autosuggestSearchResults,
autosuggestSelected,
autosuggestType,
$omitEmojiInDisplayNames }) => {
if (!shouldBeShown || !autosuggestSearchResults || !autosuggestSearchResults.length) {
return ''
}
return createAutosuggestAccessibleLabel(autosuggestType, $omitEmojiInDisplayNames,
autosuggestSelected, autosuggestSearchResults)
}
},
data: () => ({
shown: false
}),
store: () => store,
components: {
ComposeAutosuggestionList
}
}
</script>