Files
onboard/resources/js/Components/Tour/Tour.vue

164 lines
3.1 KiB
Vue

<script setup>
import {
watch,
nextTick,
ref
} from "vue"
import { useOnboardingStore } from "@/Stores/onboarding"
import TourOverlay from "./TourOverlay.vue"
import TourTooltip from "./TourTooltip.vue"
import { useWaitTarget } from "./composables/useWaitTarget"
import { useHighlight } from "./composables/useHighlight"
import { useFloating } from "./composables/useFloating"
const onboarding = useOnboardingStore()
const target = ref(null)
const loading = ref(false)
const {
waitTarget
} = useWaitTarget()
const {
rect,
update: updateRect
} = useHighlight(target)
/**
* Текущий шаг
*/
watch(
() => onboarding.currentStep,
async (step, oldStep) => {
if (!step) {
return
}
await leaveStep(oldStep)
await enterStep(step)
},
{
immediate: true
}
)
async function enterStep(step) {
loading.value = true
try {
if (step.beforeEnter) {
await step.beforeEnter()
}
/*
* ждём элемент
*/
if (step.target) {
target.value = await waitTarget(
step.target,
{
timeout: 10000,
visible: true
}
)
if (!target.value) {
return
}
await nextTick()
/*
* прокрутка
*/
if (step.scroll) {
target.value.scrollIntoView({
behavior: "smooth",
block: "center"
})
await delay(300)
}
console.log("TARGET:", target.value)
/*
* обновляем размеры
*/
updateRect()
console.log("RECT:", rect.value)
}
}
finally {
loading.value = false
}
}
async function leaveStep(step) {
if (!step) {
return
}
if (step.afterLeave) {
await step.afterLeave()
}
target.value = null
}
function next() {
onboarding.next()
}
function previous() {
onboarding.previous()
}
function close() {
onboarding.finish()
}
function delay(ms) {
return new Promise(resolve =>
setTimeout(resolve, ms)
)
}
</script>
<template>
<Teleport to="body">
<TourOverlay
v-if="onboarding.active &&
target &&
onboarding.currentStep?.highlight !== false &&
rect"
:allow-interaction="onboarding.currentStep?.allowInteraction ?? true"
:rect="rect"
:padding="onboarding.currentStep.padding"
/>
<TourTooltip
:step="onboarding.currentStep"
:target="target"
:visible="onboarding.active"
:is-first="onboarding.stepIndex === 0"
:is-last="onboarding.stepIndex === onboarding.tour?.steps.length - 1"
@next="onboarding.next"
@previous="onboarding.previous"
@finish="onboarding.finish"
@close="onboarding.finish"
/>
</Teleport>
</template>