164 lines
3.1 KiB
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>
|