Skip to content

Commit 2c5c366

Browse files
committed
fix: #89 updatePosition in window resize and resizeEnd
1 parent d24002e commit 2c5c366

1 file changed

Lines changed: 119 additions & 50 deletions

File tree

src/components/VTour.vue

Lines changed: 119 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,20 @@
11
<script setup lang="ts">
22
import { createPopper, type NanoPop } from "nanopop";
3-
import { computed, type ComputedRef, onMounted, type Reactive, reactive, type Ref, ref } from "vue";
3+
import {
4+
computed,
5+
type ComputedRef,
6+
onMounted,
7+
type Reactive,
8+
reactive,
9+
type Ref,
10+
ref,
11+
onUnmounted
12+
} from "vue";
413
import type { ITourStep } from "../Types.ts";
514
import jump from "jump.js";
615
716
export interface IVTourProps {
8-
name?: string,
17+
name?: string;
918
steps: ITourStep[];
1019
backdrop?: boolean;
1120
autoStart?: boolean;
@@ -18,10 +27,11 @@ export interface IVTourProps {
1827
done: string;
1928
skip: string;
2029
};
21-
saveToLocalStorage?: 'never' | 'step' | 'end';
30+
saveToLocalStorage?: "never" | "step" | "end";
2231
hideSkip?: boolean;
2332
hideArrow?: boolean;
2433
noScroll?: boolean;
34+
resizeTimeout?: number;
2535
}
2636
export interface IVTourData {
2737
currentStep: number;
@@ -44,62 +54,81 @@ const _CurrentStep: Reactive<IVTourData> = reactive({
4454
});
4555
const props = defineProps<IVTourProps>();
4656
const emit = defineEmits<{
47-
onTourStart: [],
48-
onTourEnd: [],
49-
onTourStep: []
50-
}>()
57+
onTourStart: [];
58+
onTourEnd: [];
59+
onTourStep: [];
60+
}>();
5161
defineExpose({
5262
startTour,
5363
nextStep,
5464
lastStep,
5565
endTour,
5666
stopTour,
5767
goToStep,
58-
resetTour
68+
resetTour,
69+
70+
updatePosition,
71+
updateHighlight,
72+
updateBackdrop,
5973
});
6074
const getNextLabel: ComputedRef<String> = computed(() => {
61-
if (_CurrentStep.currentStep === props.steps.length - 1) return props.buttonLabels?.done || 'Done';
62-
return props.buttonLabels?.next || 'Next';
75+
if (_CurrentStep.currentStep === props.steps.length - 1)
76+
return props.buttonLabels?.done || "Done";
77+
return props.buttonLabels?.next || "Next";
6378
});
6479
65-
const getClipPath = ref(getClipPathValues('.vjt-highlight') ? getClipPathValues('.vjt-highlight') : '');
80+
const getClipPath = ref(
81+
getClipPathValues(".vjt-highlight") ? getClipPathValues(".vjt-highlight") : ""
82+
);
6683
6784
function startTour(): void {
68-
if (localStorage.getItem('vjt-' + (props.name || 'default')) === 'true') return;
69-
if (props.saveToLocalStorage === 'step') {
70-
_CurrentStep.currentStep = parseInt(localStorage.getItem('vjt-' + (props.name || 'default')) || '0');
85+
if (localStorage.getItem("vjt-" + (props.name || "default")) === "true")
86+
return;
87+
if (props.saveToLocalStorage === "step") {
88+
_CurrentStep.currentStep = parseInt(
89+
localStorage.getItem("vjt-" + (props.name || "default")) || "0"
90+
);
7191
if (_CurrentStep.currentStep > 0) {
7292
_CurrentStep.lastStep = Math.max(_CurrentStep.currentStep - 1, 0);
7393
_CurrentStep.nextStep = _CurrentStep.currentStep + 1;
7494
}
75-
}
76-
else _CurrentStep.currentStep = 0;
95+
} else _CurrentStep.currentStep = 0;
7796
7897
setTimeout(async () => {
7998
await beforeStep(_CurrentStep.currentStep);
8099
if (!_VTour.value) {
81-
_VTour.value = createPopper(document.querySelector(`${_CurrentStep.getCurrentStep.target}`) as HTMLElement, _Tooltip.value!, {
82-
position: _CurrentStep.getCurrentStep.placement || 'right',
83-
margin: props.margin || ((props.highlight || _CurrentStep.getCurrentStep.highlight) ? 14 : 8),
84-
});
100+
_VTour.value = createPopper(
101+
document.querySelector(
102+
`${_CurrentStep.getCurrentStep.target}`
103+
) as HTMLElement,
104+
_Tooltip.value!,
105+
{
106+
position: _CurrentStep.getCurrentStep.placement || "right",
107+
margin:
108+
props.margin ||
109+
(props.highlight || _CurrentStep.getCurrentStep.highlight ? 14 : 8),
110+
}
111+
);
85112
}
86113
updatePosition();
87114
emit("onTourStart");
88115
}, props.startDelay);
89116
}
90117
91118
function stopTour(): void {
92-
document.querySelector('#vjt-backdrop')!.setAttribute('data-hidden', '');
93-
document.querySelectorAll('.vjt-highlight')!.forEach((element) => element.classList.remove('vjt-highlight'));
94-
_Tooltip.value!.setAttribute('data-hidden', '');
119+
document.querySelector("#vjt-backdrop")!.setAttribute("data-hidden", "");
120+
document
121+
.querySelectorAll(".vjt-highlight")!
122+
.forEach((element) => element.classList.remove("vjt-highlight"));
123+
_Tooltip.value!.setAttribute("data-hidden", "");
95124
}
96125
97126
function resetTour(restart: boolean): void {
98127
stopTour();
99128
_CurrentStep.currentStep = 0;
100129
_CurrentStep.lastStep = 0;
101130
_CurrentStep.nextStep = 1;
102-
localStorage.removeItem('vjt-' + (props.name || 'default'));
131+
localStorage.removeItem("vjt-" + (props.name || "default"));
103132
if (restart) startTour();
104133
}
105134
@@ -132,7 +161,8 @@ async function lastStep() {
132161
133162
function endTour(): void {
134163
stopTour();
135-
if (props.saveToLocalStorage !== 'never') localStorage.setItem('vjt-' + (props.name || 'default'), 'true');
164+
if (props.saveToLocalStorage !== "never")
165+
localStorage.setItem("vjt-" + (props.name || "default"), "true");
136166
emit("onTourEnd");
137167
}
138168
@@ -152,45 +182,87 @@ async function updatePosition(): Promise<void> {
152182
await new Promise<void>((resolve) => {
153183
updateHighlight();
154184
updateBackdrop();
155-
_Tooltip.value!.setAttribute('data-hidden', '');
185+
_Tooltip.value!.setAttribute("data-hidden", "");
156186
if (!props.noScroll && !_CurrentStep.getCurrentStep.noScroll) {
157-
jump(document.querySelector(`${_CurrentStep.getCurrentStep.target}`) as HTMLElement, {
158-
duration: 500,
159-
offset: -100,
160-
callback: () => { resolve() },
161-
});
187+
jump(
188+
document.querySelector(
189+
`${_CurrentStep.getCurrentStep.target}`
190+
) as HTMLElement,
191+
{
192+
duration: 500,
193+
offset: -100,
194+
callback: () => {
195+
resolve();
196+
},
197+
}
198+
);
162199
} else resolve();
163200
});
164-
_Tooltip.value!.removeAttribute('data-hidden');
165-
_Tooltip.value!.setAttribute('data-arrow', _VTour.value!.update({
166-
reference: document.querySelector(`${_CurrentStep.getCurrentStep.target}`) as HTMLElement,
167-
position: _CurrentStep.getCurrentStep.placement || 'right',
168-
}) || 'right');
169-
if (props.saveToLocalStorage === 'step') localStorage.setItem('vjt-' + (props.name || 'default'), _CurrentStep.currentStep.toString());
201+
_Tooltip.value!.removeAttribute("data-hidden");
202+
_Tooltip.value!.setAttribute(
203+
"data-arrow",
204+
_VTour.value!.update({
205+
reference: document.querySelector(
206+
`${_CurrentStep.getCurrentStep.target}`
207+
) as HTMLElement,
208+
position: _CurrentStep.getCurrentStep.placement || "right",
209+
}) || "right"
210+
);
211+
if (props.saveToLocalStorage === "step")
212+
localStorage.setItem(
213+
"vjt-" + (props.name || "default"),
214+
_CurrentStep.currentStep.toString()
215+
);
170216
await _CurrentStep.getCurrentStep.onAfter?.();
171217
emit("onTourStep");
172218
}
173219
174220
function updateHighlight(): void {
175-
document.querySelectorAll('.vjt-highlight').forEach((element) => element.classList.remove('vjt-highlight'));
221+
document
222+
.querySelectorAll(".vjt-highlight")
223+
.forEach((element) => element.classList.remove("vjt-highlight"));
176224
if (!props.highlight && !_CurrentStep.getCurrentStep.highlight) return;
177-
(document.querySelector(`${_CurrentStep.getCurrentStep.target}`) as HTMLElement).classList.add('vjt-highlight');
178-
getClipPath.value = getClipPathValues('.vjt-highlight');
225+
(
226+
document.querySelector(
227+
`${_CurrentStep.getCurrentStep.target}`
228+
) as HTMLElement
229+
).classList.add("vjt-highlight");
230+
getClipPath.value = getClipPathValues(".vjt-highlight");
179231
}
180232
181233
function updateBackdrop(): void {
182-
if (props.backdrop || _CurrentStep.getCurrentStep.backdrop) document.querySelector('#vjt-backdrop')!.removeAttribute('data-hidden');
183-
else document.querySelector('#vjt-backdrop')!.setAttribute('data-hidden', '');
234+
if (props.backdrop || _CurrentStep.getCurrentStep.backdrop)
235+
document.querySelector("#vjt-backdrop")!.removeAttribute("data-hidden");
236+
else document.querySelector("#vjt-backdrop")!.setAttribute("data-hidden", "");
237+
}
238+
239+
let resizeTimer: NodeJS.Timeout;
240+
const debounceTime = computed(() => props.resizeTimeout || 250);
241+
242+
const onResizeEnd = () => {
243+
updatePosition();
244+
245+
clearTimeout(resizeTimer);
246+
247+
resizeTimer = setTimeout(() => {
248+
updatePosition();
249+
}, debounceTime.value);
184250
}
185251
186252
onMounted(() => {
187-
_Tooltip.value = document.querySelector('#vjt-tooltip') as HTMLElement;
253+
_Tooltip.value = document.querySelector("#vjt-tooltip") as HTMLElement;
188254
if (props.autoStart) startTour();
255+
256+
window.addEventListener("resize", onResizeEnd);
257+
});
258+
259+
onUnmounted(() => {
260+
window.removeEventListener("resize", onResizeEnd);
189261
});
190262
191263
function getClipPathValues(targetSelector: string): string {
192264
const targetElement = document.querySelector(targetSelector) as HTMLElement;
193-
if (!targetElement) return '';
265+
if (!targetElement) return "";
194266
195267
const rect = targetElement.getBoundingClientRect();
196268
return `polygon(
@@ -206,7 +278,6 @@ function getClipPathValues(targetSelector: string): string {
206278
100% 0%
207279
)`;
208280
}
209-
210281
</script>
211282

212283
<template>
@@ -217,13 +288,11 @@ function getClipPathValues(targetSelector: string): string {
217288
</slot>
218289
<slot name="actions" v-bind="{ lastStep, nextStep, endTour, _CurrentStep, getNextLabel, props }">
219290
<div class="vjt-actions">
220-
<button v-if="_CurrentStep.lastStep < _CurrentStep.currentStep" type="button" @click.prevent="lastStep()"
221-
v-text="props.buttonLabels?.back || 'Back'"></button>
222-
<button v-if="!props.hideSkip" type="button" @click.prevent="endTour()"
223-
v-text="props.buttonLabels?.skip || 'Skip'"></button>
291+
<button v-if="_CurrentStep.lastStep < _CurrentStep.currentStep" type="button" @click.prevent="lastStep()" v-text="props.buttonLabels?.back || 'Back'"></button>
292+
<button v-if="!props.hideSkip" type="button" @click.prevent="endTour()" v-text="props.buttonLabels?.skip || 'Skip'"></button>
224293
<button type="button" @click.prevent="nextStep()" v-text="getNextLabel"></button>
225294
</div>
226295
</slot>
227296
<div id="vjt-arrow" v-if="!props.hideArrow"></div>
228297
</div>
229-
</template>
298+
</template>

0 commit comments

Comments
 (0)