Fix dropdowns
This commit is contained in:
parent
232f0ff465
commit
a7f4df68ea
|
@ -14,6 +14,7 @@ import { computed, ref, watch, watchEffect, onMounted } from 'vue'
|
||||||
import { useGettext } from 'vue3-gettext'
|
import { useGettext } from 'vue3-gettext'
|
||||||
import { useStore } from '~/store'
|
import { useStore } from '~/store'
|
||||||
import { setupDropdown } from '~/utils/fomantic'
|
import { setupDropdown } from '~/utils/fomantic'
|
||||||
|
import { useCurrentElement } from '@vueuse/core'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
width: number
|
width: number
|
||||||
|
@ -104,19 +105,14 @@ watch(languageSelection, (v) => {
|
||||||
store.dispatch('ui/currentLanguage', v)
|
store.dispatch('ui/currentLanguage', v)
|
||||||
})
|
})
|
||||||
|
|
||||||
watch(() => store.state.auth.authenticated, (authenticated) => {
|
const el = useCurrentElement()
|
||||||
if (authenticated) {
|
watchEffect(() => {
|
||||||
setupDropdown('.admin-dropdown')
|
|
||||||
}
|
|
||||||
|
|
||||||
setupDropdown('.user-dropdown')
|
|
||||||
}, { immediate: true })
|
|
||||||
|
|
||||||
watch(() => store.state.auth.availablePermissions, () => {
|
|
||||||
if (store.state.auth.authenticated) {
|
if (store.state.auth.authenticated) {
|
||||||
setupDropdown('.admin-dropdown')
|
setupDropdown('.admin-dropdown', el.value)
|
||||||
}
|
}
|
||||||
}, { immediate: true })
|
|
||||||
|
setupDropdown('.user-dropdown', el.value)
|
||||||
|
})
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
document.getElementById('fake-sidebar')?.classList.add('loaded')
|
document.getElementById('fake-sidebar')?.classList.add('loaded')
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
import type { Track, Artist, Album, Playlist, Library, Channel, Actor } from '~/types'
|
import type { Track, Artist, Album, Playlist, Library, Channel, Actor } from '~/types'
|
||||||
import type { PlayOptionsProps } from '~/composables/audio/usePlayOptions'
|
import type { PlayOptionsProps } from '~/composables/audio/usePlayOptions'
|
||||||
|
|
||||||
import { ref, computed, watch, nextTick } from 'vue'
|
import { ref, computed, onMounted } from 'vue'
|
||||||
import { useGettext } from 'vue3-gettext'
|
import { useGettext } from 'vue3-gettext'
|
||||||
import usePlayOptions from '~/composables/audio/usePlayOptions'
|
import usePlayOptions from '~/composables/audio/usePlayOptions'
|
||||||
import useReport from '~/composables/moderation/useReport'
|
import useReport from '~/composables/moderation/useReport'
|
||||||
import { useCurrentElement } from '@vueuse/core'
|
import { useCurrentElement } from '@vueuse/core'
|
||||||
import { setupDropdown, getDropdown } from '~/utils/fomantic'
|
import { setupDropdown } from '~/utils/fomantic'
|
||||||
|
|
||||||
interface Props extends PlayOptionsProps {
|
interface Props extends PlayOptionsProps {
|
||||||
dropdownIconClasses?: string[]
|
dropdownIconClasses?: string[]
|
||||||
|
@ -63,8 +63,6 @@ const {
|
||||||
|
|
||||||
const { report, getReportableObjects } = useReport()
|
const { report, getReportableObjects } = useReport()
|
||||||
|
|
||||||
const clicked = ref(false)
|
|
||||||
|
|
||||||
const { $pgettext } = useGettext()
|
const { $pgettext } = useGettext()
|
||||||
const labels = computed(() => ({
|
const labels = computed(() => ({
|
||||||
playNow: $pgettext('*/Queue/Dropdown/Button/Title', 'Play now'),
|
playNow: $pgettext('*/Queue/Dropdown/Button/Title', 'Play now'),
|
||||||
|
@ -93,29 +91,31 @@ const title = computed(() => {
|
||||||
if (props.track) {
|
if (props.track) {
|
||||||
return $pgettext('*/Queue/Button/Title', 'This track is not available in any library you have access to')
|
return $pgettext('*/Queue/Button/Title', 'This track is not available in any library you have access to')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return ''
|
||||||
})
|
})
|
||||||
|
|
||||||
watch(clicked, async () => {
|
const el = useCurrentElement()
|
||||||
await setupDropdown()
|
const dropdown = ref()
|
||||||
|
onMounted(() => {
|
||||||
getDropdown().dropdown('show', function () {
|
dropdown.value = setupDropdown('.ui.dropdown', el.value)
|
||||||
// little magic to ensure the menu is always visible in the viewport
|
|
||||||
// By default, try to diplay it on the right if there is enough room
|
|
||||||
const menu = getDropdown().find('.menu')
|
|
||||||
const viewportOffset = menu.get(0)?.getBoundingClientRect() ?? { right: 0, left: 0 }
|
|
||||||
const viewportWidth = document.documentElement.clientWidth
|
|
||||||
const rightOverflow = viewportOffset.right - viewportWidth
|
|
||||||
const leftOverflow = -viewportOffset.left
|
|
||||||
let offset = 0
|
|
||||||
if (rightOverflow > 0) {
|
|
||||||
offset = -rightOverflow - 5
|
|
||||||
menu.css({ cssText: `left: ${offset}px !important;` })
|
|
||||||
} else if (leftOverflow > 0) {
|
|
||||||
offset = leftOverflow + 5
|
|
||||||
menu.css({ cssText: `right: -${offset}px !important;` })
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const openMenu = () => {
|
||||||
|
// little magic to ensure the menu is always visible in the viewport
|
||||||
|
// By default, try to diplay it on the right if there is enough room
|
||||||
|
const menu = dropdown.value.find('.menu')
|
||||||
|
const viewportOffset = menu.get(0)?.getBoundingClientRect() ?? { right: 0, left: 0 }
|
||||||
|
const viewportWidth = document.documentElement.clientWidth
|
||||||
|
const rightOverflow = viewportOffset.right - viewportWidth
|
||||||
|
const leftOverflow = -viewportOffset.left
|
||||||
|
|
||||||
|
if (rightOverflow > 0) {
|
||||||
|
menu.css({ cssText: `left: ${-rightOverflow - 5}px !important;` })
|
||||||
|
} else if (leftOverflow > 0) {
|
||||||
|
menu.css({ cssText: `right: -${leftOverflow + 5}px !important;` })
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -143,16 +143,13 @@ watch(clicked, async () => {
|
||||||
<button
|
<button
|
||||||
v-if="!discrete && !iconOnly"
|
v-if="!discrete && !iconOnly"
|
||||||
:class="['ui', {disabled: !playable && !filterableArtist}, 'floating', 'dropdown', {'icon': !dropdownOnly}, {'button': !dropdownOnly}]"
|
:class="['ui', {disabled: !playable && !filterableArtist}, 'floating', 'dropdown', {'icon': !dropdownOnly}, {'button': !dropdownOnly}]"
|
||||||
@click.stop.prevent="clicked = true"
|
@click.stop.prevent="openMenu"
|
||||||
>
|
>
|
||||||
<i
|
<i
|
||||||
:class="dropdownIconClasses.concat(['icon'])"
|
:class="dropdownIconClasses.concat(['icon'])"
|
||||||
:title="title"
|
:title="title"
|
||||||
/>
|
/>
|
||||||
<div
|
<div class="menu">
|
||||||
v-if="clicked"
|
|
||||||
class="menu"
|
|
||||||
>
|
|
||||||
<button
|
<button
|
||||||
class="item basic"
|
class="item basic"
|
||||||
data-ref="enqueue"
|
data-ref="enqueue"
|
||||||
|
|
|
@ -7,5 +7,5 @@ export const install: InitModule = ({ app, store }) => {
|
||||||
store.commit('ui/pageTitle', binding.value)
|
store.commit('ui/pageTitle', binding.value)
|
||||||
})
|
})
|
||||||
|
|
||||||
app.directive('dropdown', setupDropdown)
|
app.directive('dropdown', (element) => setupDropdown(element))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,10 @@
|
||||||
/// <reference types="semantic-ui" />
|
/// <reference types="semantic-ui" />
|
||||||
|
|
||||||
import $ from 'jquery'
|
import $ from 'jquery'
|
||||||
import { tryOnMounted, useCurrentElement } from '@vueuse/core'
|
|
||||||
|
|
||||||
export const getDropdown = (selector = '.ui.dropdown'): JQuery => {
|
export const setupDropdown = (selector: string | HTMLElement = '.ui.dropdown', el: Element = document.body) => {
|
||||||
const el = useCurrentElement()
|
|
||||||
return $(el.value).find(selector)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const setupDropdown = (selector: string | HTMLElement = '.ui.dropdown') => tryOnMounted(() => {
|
|
||||||
const el = useCurrentElement()
|
|
||||||
const $dropdown = typeof selector === 'string'
|
const $dropdown = typeof selector === 'string'
|
||||||
? $(el.value).find(selector)
|
? $(el).find(selector)
|
||||||
: $(selector)
|
: $(selector)
|
||||||
|
|
||||||
$dropdown.dropdown({
|
$dropdown.dropdown({
|
||||||
|
@ -24,4 +17,6 @@ export const setupDropdown = (selector: string | HTMLElement = '.ui.dropdown') =
|
||||||
$dropdown.dropdown('hide')
|
$dropdown.dropdown('hide')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}, false)
|
|
||||||
|
return $dropdown
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue