soiz1's picture
Upload folder using huggingface_hub
4d70170 verified
raw
history blame
5.92 kB
<script lang="ts">
import { computed, defineComponent, ref } from 'vue'
import { SharedData } from '@vue-devtools/shared-utils'
import { useOrientation } from '@front/features/layout/orientation'
export default defineComponent({
props: {
items: {
type: Array,
required: true,
},
selectedItem: {
type: Object,
default: () => ({}),
},
optionIcon: {
type: String,
default: null,
},
},
emits: ['select'],
setup(props, { emit }) {
/* Open/Close */
const isShown = ref(false)
const isShowApplied = ref(false)
/**
* Delayed open should only happen on mouseover.
* Will be overriden when clicking
*/
const showDelayEnabled = ref(true)
let disabled = false
let toggleCloseEnabled = true
let toggleCloseTimer = null
let pendingOperation = null
let operationTimer = null
function queueOperation(type, delay) {
if (disabled) {
return
}
pendingOperation = type
clearTimeout(operationTimer)
operationTimer = setTimeout(() => applyOperation(), delay)
}
function applyOperation() {
if (pendingOperation) {
pendingOperation()
}
pendingOperation = null
clearTimeout(operationTimer)
}
function queueOpen(delay = true) {
queueOperation(() => {
isShown.value = true
toggleCloseEnabled = false
clearTimeout(toggleCloseTimer)
toggleCloseTimer = setTimeout(() => {
toggleCloseEnabled = true
}, 500)
}, delay ? 250 : 1)
}
function queueClose(delay = true) {
toggleCloseEnabled = false
clearTimeout(toggleCloseTimer)
queueOperation(() => {
isShown.value = false
}, delay ? 300 : 1)
}
function toggle() {
if (isShown.value) {
if (toggleCloseEnabled) {
queueClose(false)
}
}
else {
// We open also when it's already open and
// when the button close is disabled
// so we cancel the popper autoclose
// (the popper doesn't contain the trigger button)
queueOpen(false)
}
}
/* Select */
function select(item) {
disabled = true
emit('select', item)
// Disable menu for a short time after selecting an item
setTimeout(() => {
disabled = false
}, 500)
}
const selectedIndex = computed(() => props.items.indexOf(props.selectedItem))
function selectNext() {
const index = selectedIndex.value + 1
if (index < props.items.length) {
select(props.items[index])
}
}
function selectPrevious() {
const index = selectedIndex.value - 1
if (index >= 0) {
select(props.items[index])
}
}
let wheelEnabled = true
function onMouseWheel(e: WheelEvent) {
if (!wheelEnabled) {
return
}
if (e.deltaY > 0) {
selectNext()
}
else {
selectPrevious()
}
if (SharedData.menuStepScrolling) {
wheelEnabled = false
setTimeout(() => {
wheelEnabled = true
}, 300)
}
}
/* Layout */
const { orientation } = useOrientation()
return {
isShown,
isShowApplied,
showDelayEnabled,
queueOpen,
queueClose,
toggle,
select,
orientation,
onMouseWheel,
}
},
})
</script>
<template>
<VueDropdown
v-model="isShown"
:placement="orientation === 'landscape' ? 'right-start' : 'bottom-start'"
:triggers="[]"
:offset="[0, 0]"
:delay="0"
:auto-hide="false"
@apply-show="isShowApplied = true"
@apply-hide="isShowApplied = false"
>
<template #trigger>
<div
@mouseenter="queueOpen()"
@mouseleave="queueClose()"
@wheel="onMouseWheel"
@click.capture="toggle()"
>
<slot name="trigger">
<VueButton
class="flat"
:icon-left="selectedItem.icon"
:icon-right="orientation === 'landscape' ? 'arrow_drop_down' : null"
:class="{
'icon-button': orientation === 'portrait',
}"
>
<template v-if="orientation === 'landscape'">
{{ selectedItem.label }}
</template>
</VueButton>
</slot>
</div>
</template>
<div>
<div
class="flex flex-col"
@mouseenter="queueOpen()"
@mouseleave="queueClose()"
@wheel="onMouseWheel"
>
<slot name="before" />
<VueDropdownButton
v-for="(item, index) of items"
:key="index"
:icon-left="item.icon || optionIcon"
:class="{
selected: selectedItem === item,
}"
@click="select(item)"
>
<slot :item="item">
{{ item.label }}
</slot>
</VueDropdownButton>
<div
v-if="$shared.showMenuScrollTip"
class="text-xs flex items-center space-x-2 text-gray-500 pl-4 pr-1 py-1 border-t border-gray-200 dark:border-gray-700 group"
>
<span>Scroll to switch</span>
<VueIcon icon="mouse" />
<span class="flex-1" />
<VueButton
class="flex-none icon-button flat invisible group-hover:visible"
icon-left="close"
@click="$shared.showMenuScrollTip = false"
/>
</div>
</div>
</div>
</VueDropdown>
</template>
<style lang="postcss" scoped>
.selected {
@apply bg-green-100 text-green-700 !important;
.vue-ui-dark-mode & {
@apply bg-gray-700 text-gray-100 !important;
}
:deep(svg) {
fill: currentColor !important;
}
}
.vue-ui-dropdown-button {
min-height: 32px;
height: auto;
padding-top: 6px;
padding-bottom: 6px;
:deep(.default-slot) {
flex: 1;
}
}
</style>