Files
speckle-server/packages/frontend-2/components/presentation/controls/Controls.vue
T
Kristaps Fabians Geikins d394e1cd9b fix: various presentations mode fixes related to resetting (#5635)
* better workspace feature flag ops

* user activity is correctly tracked

* more fixes
2025-10-03 12:39:59 +03:00

99 lines
2.7 KiB
Vue

<template>
<div
class="flex items-center rounded-xl bg-foundation border border-outline-3 shadow-md overflow-hidden h-10 p-[3px]"
:class="{ hidden: hideUi }"
>
<PresentationControlsButton
:icon="LucideChevronLeft"
:disabled="disablePrevious"
tooltip="Previous slide"
@click="onPrevious"
/>
<PresentationControlsButton
:icon="LucideRotateCcw"
:disabled="!hasViewChanged"
tooltip="Reset slide"
@click="resetView"
/>
<PresentationControlsButton
:icon="LucideChevronRight"
:disabled="disableNext"
tooltip="Next slide"
@click="onNext"
/>
</div>
</template>
<script setup lang="ts">
import { LucideChevronLeft, LucideChevronRight, LucideRotateCcw } from 'lucide-vue-next'
import { useInjectedPresentationState } from '~/lib/presentations/composables/setup'
import { clamp } from 'lodash-es'
import { useEventListener } from '@vueuse/core'
import { useResetViewUtils } from '~/lib/presentations/composables/utils'
defineProps<{
hideUi?: boolean
}>()
const {
ui: { slideIdx: currentVisibleIndex, slideCount },
viewer: { hasViewChanged }
} = useInjectedPresentationState()
const { resetView } = useResetViewUtils()
const disablePrevious = computed(() => currentVisibleIndex.value === 0)
const disableNext = computed(() =>
slideCount.value ? currentVisibleIndex.value === slideCount.value - 1 : false
)
const onPrevious = () => {
currentVisibleIndex.value = clamp(currentVisibleIndex.value - 1, 0, slideCount.value)
}
const onNext = () => {
currentVisibleIndex.value = clamp(currentVisibleIndex.value + 1, 0, slideCount.value)
}
// Prevent viewer from moving when using arrow keys
useEventListener(
'keydown',
(event) => {
// Don't handle arrow keys if an input element is focused
if (
event.target instanceof HTMLInputElement ||
event.target instanceof HTMLTextAreaElement
)
return
// Don't handle arrow keys if a dialog is open
if (document.querySelector('[role="dialog"]')) {
event.preventDefault()
event.stopPropagation()
event.stopImmediatePropagation()
return
}
const targetKeys = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown']
if (targetKeys.includes(event.key)) {
event.preventDefault()
event.stopPropagation()
event.stopImmediatePropagation()
// Remove focus from any currently focused element to prevent blue outline
if (document.activeElement instanceof HTMLElement) {
document.activeElement.blur()
}
}
if (event.key === 'ArrowLeft') {
if (disablePrevious.value) return
onPrevious()
}
if (event.key === 'ArrowRight') {
if (disableNext.value) return
onNext()
}
},
{ capture: true }
)
</script>