@elogroup-sereduc/portal-aluno-tour 1.0.5 → 1.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Tour.d.ts.map +1 -1
- package/dist/components/Tour.js +153 -52
- package/package.json +1 -1
- package/src/components/Tour.tsx +156 -55
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tour.d.ts","sourceRoot":"","sources":["../../src/components/Tour.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAY,MAAM,UAAU,CAAC;AAG/C;;GAEG;AACH,wBAAgB,IAAI,CAAC,EACnB,OAAO,EACP,KAAK,EACL,WAAe,EACf,OAAY,EACZ,MAAM,EACN,UAAU,GACX,EAAE,SAAS,
|
|
1
|
+
{"version":3,"file":"Tour.d.ts","sourceRoot":"","sources":["../../src/components/Tour.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAY,MAAM,UAAU,CAAC;AAG/C;;GAEG;AACH,wBAAgB,IAAI,CAAC,EACnB,OAAO,EACP,KAAK,EACL,WAAe,EACf,OAAY,EACZ,MAAM,EACN,UAAU,GACX,EAAE,SAAS,kDA0iBX"}
|
package/dist/components/Tour.js
CHANGED
|
@@ -15,86 +15,165 @@ export function Tour({ enabled, steps, initialStep = 0, options = {}, onExit, on
|
|
|
15
15
|
const isConfiguredRef = useRef(false);
|
|
16
16
|
const { nextLabel = "Próximo", prevLabel = "Anterior", skipLabel = "Pular", doneLabel = "Concluir", showProgress = true, showBullets = true, exitOnOverlayClick = false, exitOnEsc = true, } = options;
|
|
17
17
|
// Calcula a posição da tooltip baseado no elemento destacado
|
|
18
|
+
// Usa getBoundingClientRect() que retorna posições relativas à viewport
|
|
19
|
+
// Isso mantém a tooltip sempre visível mesmo durante scroll
|
|
18
20
|
const calculateTooltipPosition = useCallback((element, position = "bottom") => {
|
|
19
21
|
const rect = element.getBoundingClientRect();
|
|
20
|
-
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
|
|
21
|
-
const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
|
|
22
22
|
const viewportWidth = window.innerWidth;
|
|
23
23
|
const viewportHeight = window.innerHeight;
|
|
24
|
-
// Tamanho estimado da tooltip
|
|
24
|
+
// Tamanho estimado da tooltip
|
|
25
25
|
const tooltipWidth = 384; // max-w-sm = 384px
|
|
26
|
-
const tooltipHeight =
|
|
27
|
-
const spacing =
|
|
26
|
+
const tooltipHeight = 250; // altura estimada
|
|
27
|
+
const spacing = 8; // espaçamento próximo ao elemento
|
|
28
28
|
let top = 0;
|
|
29
29
|
let left = 0;
|
|
30
30
|
let finalPosition = position;
|
|
31
|
-
//
|
|
31
|
+
// Verifica se o elemento está visível na viewport
|
|
32
|
+
const isElementVisible = rect.top < viewportHeight &&
|
|
33
|
+
rect.bottom > 0 &&
|
|
34
|
+
rect.left < viewportWidth &&
|
|
35
|
+
rect.right > 0;
|
|
36
|
+
// Se o elemento não estiver visível, tenta posicionar próximo à borda mais próxima
|
|
37
|
+
if (!isElementVisible) {
|
|
38
|
+
// Elemento está fora da viewport - posiciona próximo à borda mais próxima
|
|
39
|
+
if (rect.bottom < 0) {
|
|
40
|
+
// Elemento está acima da viewport
|
|
41
|
+
top = 8;
|
|
42
|
+
left = Math.max(tooltipWidth / 2 + 8, Math.min(viewportWidth - tooltipWidth / 2 - 8, rect.left + rect.width / 2));
|
|
43
|
+
finalPosition = "top";
|
|
44
|
+
}
|
|
45
|
+
else if (rect.top > viewportHeight) {
|
|
46
|
+
// Elemento está abaixo da viewport
|
|
47
|
+
top = viewportHeight - tooltipHeight - 8;
|
|
48
|
+
left = Math.max(tooltipWidth / 2 + 8, Math.min(viewportWidth - tooltipWidth / 2 - 8, rect.left + rect.width / 2));
|
|
49
|
+
finalPosition = "bottom";
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
// Elemento está à esquerda ou direita
|
|
53
|
+
top = Math.max(tooltipHeight / 2 + 8, Math.min(viewportHeight - tooltipHeight / 2 - 8, rect.top + rect.height / 2));
|
|
54
|
+
if (rect.right < 0) {
|
|
55
|
+
left = 8;
|
|
56
|
+
finalPosition = "left";
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
left = viewportWidth - tooltipWidth - 8;
|
|
60
|
+
finalPosition = "right";
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return { top, left, position: finalPosition };
|
|
64
|
+
}
|
|
65
|
+
// Elemento está visível - calcula posição normal próxima ao elemento
|
|
32
66
|
switch (position) {
|
|
33
67
|
case "top":
|
|
34
|
-
top = rect.top
|
|
35
|
-
left = rect.left +
|
|
68
|
+
top = rect.top - spacing;
|
|
69
|
+
left = rect.left + rect.width / 2;
|
|
36
70
|
break;
|
|
37
71
|
case "bottom":
|
|
38
|
-
top = rect.bottom +
|
|
39
|
-
left = rect.left +
|
|
72
|
+
top = rect.bottom + spacing;
|
|
73
|
+
left = rect.left + rect.width / 2;
|
|
40
74
|
break;
|
|
41
75
|
case "left":
|
|
42
|
-
top = rect.top +
|
|
43
|
-
left = rect.left
|
|
76
|
+
top = rect.top + rect.height / 2;
|
|
77
|
+
left = rect.left - spacing;
|
|
44
78
|
break;
|
|
45
79
|
case "right":
|
|
46
|
-
top = rect.top +
|
|
47
|
-
left = rect.right +
|
|
80
|
+
top = rect.top + rect.height / 2;
|
|
81
|
+
left = rect.right + spacing;
|
|
48
82
|
break;
|
|
49
83
|
default:
|
|
50
|
-
top = rect.bottom +
|
|
51
|
-
left = rect.left +
|
|
84
|
+
top = rect.bottom + spacing;
|
|
85
|
+
left = rect.left + rect.width / 2;
|
|
52
86
|
finalPosition = "bottom";
|
|
53
87
|
}
|
|
54
|
-
// Ajusta
|
|
88
|
+
// Ajusta horizontalmente para tooltips top/bottom - mantém próximo ao elemento
|
|
55
89
|
if (finalPosition === "bottom" || finalPosition === "top") {
|
|
56
|
-
//
|
|
57
|
-
|
|
58
|
-
|
|
90
|
+
// Centraliza no elemento, mas ajusta apenas se necessário para não sair da tela
|
|
91
|
+
const elementCenterX = rect.left + rect.width / 2;
|
|
92
|
+
const minLeft = tooltipWidth / 2 + 8;
|
|
93
|
+
const maxLeft = viewportWidth - tooltipWidth / 2 - 8;
|
|
94
|
+
// Mantém o mais próximo possível do centro do elemento
|
|
95
|
+
if (elementCenterX < minLeft) {
|
|
96
|
+
left = minLeft;
|
|
97
|
+
}
|
|
98
|
+
else if (elementCenterX > maxLeft) {
|
|
99
|
+
left = maxLeft;
|
|
59
100
|
}
|
|
60
|
-
else
|
|
61
|
-
left =
|
|
101
|
+
else {
|
|
102
|
+
left = elementCenterX; // Mantém centralizado no elemento
|
|
62
103
|
}
|
|
63
|
-
//
|
|
64
|
-
if (finalPosition === "bottom"
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
104
|
+
// Verifica espaço vertical e ajusta posição se necessário
|
|
105
|
+
if (finalPosition === "bottom") {
|
|
106
|
+
const spaceBelow = viewportHeight - rect.bottom;
|
|
107
|
+
if (spaceBelow < tooltipHeight + spacing + 8) {
|
|
108
|
+
const spaceAbove = rect.top;
|
|
109
|
+
if (spaceAbove > spaceBelow && spaceAbove > tooltipHeight + spacing + 8) {
|
|
110
|
+
top = rect.top - spacing;
|
|
111
|
+
finalPosition = "top";
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
// Mantém próximo ao elemento mesmo se não couber perfeitamente
|
|
115
|
+
top = rect.bottom + spacing;
|
|
116
|
+
}
|
|
68
117
|
}
|
|
69
118
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
if (
|
|
73
|
-
|
|
74
|
-
|
|
119
|
+
else if (finalPosition === "top") {
|
|
120
|
+
const spaceAbove = rect.top;
|
|
121
|
+
if (spaceAbove < tooltipHeight + spacing + 8) {
|
|
122
|
+
const spaceBelow = viewportHeight - rect.bottom;
|
|
123
|
+
if (spaceBelow > spaceAbove && spaceBelow > tooltipHeight + spacing + 8) {
|
|
124
|
+
top = rect.bottom + spacing;
|
|
125
|
+
finalPosition = "bottom";
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
// Mantém próximo ao elemento mesmo se não couber perfeitamente
|
|
129
|
+
top = rect.top - spacing;
|
|
130
|
+
}
|
|
75
131
|
}
|
|
76
132
|
}
|
|
77
133
|
}
|
|
134
|
+
// Ajusta verticalmente para tooltips left/right - mantém próximo ao elemento
|
|
78
135
|
else if (finalPosition === "left" || finalPosition === "right") {
|
|
79
|
-
//
|
|
80
|
-
|
|
81
|
-
|
|
136
|
+
// Centraliza no elemento verticalmente
|
|
137
|
+
const elementCenterY = rect.top + rect.height / 2;
|
|
138
|
+
const minTop = tooltipHeight / 2 + 8;
|
|
139
|
+
const maxTop = viewportHeight - tooltipHeight / 2 - 8;
|
|
140
|
+
// Mantém o mais próximo possível do centro do elemento
|
|
141
|
+
if (elementCenterY < minTop) {
|
|
142
|
+
top = minTop;
|
|
82
143
|
}
|
|
83
|
-
else if (
|
|
84
|
-
top =
|
|
144
|
+
else if (elementCenterY > maxTop) {
|
|
145
|
+
top = maxTop;
|
|
85
146
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
147
|
+
else {
|
|
148
|
+
top = elementCenterY; // Mantém centralizado no elemento
|
|
149
|
+
}
|
|
150
|
+
// Verifica espaço horizontal e ajusta posição se necessário
|
|
151
|
+
if (finalPosition === "left") {
|
|
152
|
+
const spaceLeft = rect.left;
|
|
153
|
+
if (spaceLeft < tooltipWidth + spacing + 8) {
|
|
154
|
+
const spaceRight = viewportWidth - rect.right;
|
|
155
|
+
if (spaceRight > spaceLeft && spaceRight > tooltipWidth + spacing + 8) {
|
|
156
|
+
left = rect.right + spacing;
|
|
157
|
+
finalPosition = "right";
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
// Mantém próximo ao elemento mesmo se não couber perfeitamente
|
|
161
|
+
left = rect.left - spacing;
|
|
162
|
+
}
|
|
91
163
|
}
|
|
92
164
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
if (
|
|
96
|
-
|
|
97
|
-
|
|
165
|
+
else if (finalPosition === "right") {
|
|
166
|
+
const spaceRight = viewportWidth - rect.right;
|
|
167
|
+
if (spaceRight < tooltipWidth + spacing + 8) {
|
|
168
|
+
const spaceLeft = rect.left;
|
|
169
|
+
if (spaceLeft > spaceRight && spaceLeft > tooltipWidth + spacing + 8) {
|
|
170
|
+
left = rect.left - spacing;
|
|
171
|
+
finalPosition = "left";
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
// Mantém próximo ao elemento mesmo se não couber perfeitamente
|
|
175
|
+
left = rect.right + spacing;
|
|
176
|
+
}
|
|
98
177
|
}
|
|
99
178
|
}
|
|
100
179
|
}
|
|
@@ -133,11 +212,33 @@ export function Tour({ enabled, steps, initialStep = 0, options = {}, onExit, on
|
|
|
133
212
|
setHighlightedElement(element);
|
|
134
213
|
// Scroll para o elemento
|
|
135
214
|
element.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
136
|
-
//
|
|
137
|
-
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
|
|
215
|
+
// Função para calcular e atualizar posição
|
|
216
|
+
const updatePosition = () => {
|
|
217
|
+
const updatedRect = element.getBoundingClientRect();
|
|
218
|
+
if (updatedRect.width > 0 && updatedRect.height > 0) {
|
|
219
|
+
const position = calculateTooltipPosition(element, step.position || "bottom");
|
|
220
|
+
setTooltipPosition(position);
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
// Calcula posição inicial após um delay para garantir que o scroll terminou
|
|
224
|
+
setTimeout(updatePosition, 400);
|
|
225
|
+
// Adiciona listeners para recalcular posição em tempo real
|
|
226
|
+
const handleScroll = () => {
|
|
227
|
+
// Usa requestAnimationFrame para suavizar a atualização durante scroll
|
|
228
|
+
requestAnimationFrame(updatePosition);
|
|
229
|
+
};
|
|
230
|
+
const handleResize = () => {
|
|
231
|
+
updatePosition();
|
|
232
|
+
};
|
|
233
|
+
// Adiciona listeners em window e document para capturar todos os tipos de scroll
|
|
234
|
+
window.addEventListener("scroll", handleScroll, { passive: true, capture: true });
|
|
235
|
+
window.addEventListener("resize", handleResize, { passive: true });
|
|
236
|
+
document.addEventListener("scroll", handleScroll, { passive: true, capture: true });
|
|
237
|
+
return () => {
|
|
238
|
+
window.removeEventListener("scroll", handleScroll, true);
|
|
239
|
+
window.removeEventListener("resize", handleResize);
|
|
240
|
+
document.removeEventListener("scroll", handleScroll, true);
|
|
241
|
+
};
|
|
141
242
|
}, [isVisible, currentStep, steps, calculateTooltipPosition]);
|
|
142
243
|
// Adiciona overlay e highlight ao elemento
|
|
143
244
|
useEffect(() => {
|
package/package.json
CHANGED
package/src/components/Tour.tsx
CHANGED
|
@@ -34,89 +34,163 @@ export function Tour({
|
|
|
34
34
|
} = options;
|
|
35
35
|
|
|
36
36
|
// Calcula a posição da tooltip baseado no elemento destacado
|
|
37
|
+
// Usa getBoundingClientRect() que retorna posições relativas à viewport
|
|
38
|
+
// Isso mantém a tooltip sempre visível mesmo durante scroll
|
|
37
39
|
const calculateTooltipPosition = useCallback((element: HTMLElement, position: string = "bottom") => {
|
|
38
40
|
const rect = element.getBoundingClientRect();
|
|
39
|
-
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
|
|
40
|
-
const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
|
|
41
41
|
const viewportWidth = window.innerWidth;
|
|
42
42
|
const viewportHeight = window.innerHeight;
|
|
43
43
|
|
|
44
|
-
// Tamanho estimado da tooltip
|
|
44
|
+
// Tamanho estimado da tooltip
|
|
45
45
|
const tooltipWidth = 384; // max-w-sm = 384px
|
|
46
|
-
const tooltipHeight =
|
|
47
|
-
const spacing =
|
|
46
|
+
const tooltipHeight = 250; // altura estimada
|
|
47
|
+
const spacing = 8; // espaçamento próximo ao elemento
|
|
48
48
|
|
|
49
49
|
let top = 0;
|
|
50
50
|
let left = 0;
|
|
51
51
|
let finalPosition = position;
|
|
52
52
|
|
|
53
|
-
//
|
|
53
|
+
// Verifica se o elemento está visível na viewport
|
|
54
|
+
const isElementVisible =
|
|
55
|
+
rect.top < viewportHeight &&
|
|
56
|
+
rect.bottom > 0 &&
|
|
57
|
+
rect.left < viewportWidth &&
|
|
58
|
+
rect.right > 0;
|
|
59
|
+
|
|
60
|
+
// Se o elemento não estiver visível, tenta posicionar próximo à borda mais próxima
|
|
61
|
+
if (!isElementVisible) {
|
|
62
|
+
// Elemento está fora da viewport - posiciona próximo à borda mais próxima
|
|
63
|
+
if (rect.bottom < 0) {
|
|
64
|
+
// Elemento está acima da viewport
|
|
65
|
+
top = 8;
|
|
66
|
+
left = Math.max(tooltipWidth / 2 + 8, Math.min(viewportWidth - tooltipWidth / 2 - 8, rect.left + rect.width / 2));
|
|
67
|
+
finalPosition = "top";
|
|
68
|
+
} else if (rect.top > viewportHeight) {
|
|
69
|
+
// Elemento está abaixo da viewport
|
|
70
|
+
top = viewportHeight - tooltipHeight - 8;
|
|
71
|
+
left = Math.max(tooltipWidth / 2 + 8, Math.min(viewportWidth - tooltipWidth / 2 - 8, rect.left + rect.width / 2));
|
|
72
|
+
finalPosition = "bottom";
|
|
73
|
+
} else {
|
|
74
|
+
// Elemento está à esquerda ou direita
|
|
75
|
+
top = Math.max(tooltipHeight / 2 + 8, Math.min(viewportHeight - tooltipHeight / 2 - 8, rect.top + rect.height / 2));
|
|
76
|
+
if (rect.right < 0) {
|
|
77
|
+
left = 8;
|
|
78
|
+
finalPosition = "left";
|
|
79
|
+
} else {
|
|
80
|
+
left = viewportWidth - tooltipWidth - 8;
|
|
81
|
+
finalPosition = "right";
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return { top, left, position: finalPosition };
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Elemento está visível - calcula posição normal próxima ao elemento
|
|
54
88
|
switch (position) {
|
|
55
89
|
case "top":
|
|
56
|
-
top = rect.top
|
|
57
|
-
left = rect.left +
|
|
90
|
+
top = rect.top - spacing;
|
|
91
|
+
left = rect.left + rect.width / 2;
|
|
58
92
|
break;
|
|
59
93
|
case "bottom":
|
|
60
|
-
top = rect.bottom +
|
|
61
|
-
left = rect.left +
|
|
94
|
+
top = rect.bottom + spacing;
|
|
95
|
+
left = rect.left + rect.width / 2;
|
|
62
96
|
break;
|
|
63
97
|
case "left":
|
|
64
|
-
top = rect.top +
|
|
65
|
-
left = rect.left
|
|
98
|
+
top = rect.top + rect.height / 2;
|
|
99
|
+
left = rect.left - spacing;
|
|
66
100
|
break;
|
|
67
101
|
case "right":
|
|
68
|
-
top = rect.top +
|
|
69
|
-
left = rect.right +
|
|
102
|
+
top = rect.top + rect.height / 2;
|
|
103
|
+
left = rect.right + spacing;
|
|
70
104
|
break;
|
|
71
105
|
default:
|
|
72
|
-
top = rect.bottom +
|
|
73
|
-
left = rect.left +
|
|
106
|
+
top = rect.bottom + spacing;
|
|
107
|
+
left = rect.left + rect.width / 2;
|
|
74
108
|
finalPosition = "bottom";
|
|
75
109
|
}
|
|
76
110
|
|
|
77
|
-
// Ajusta
|
|
111
|
+
// Ajusta horizontalmente para tooltips top/bottom - mantém próximo ao elemento
|
|
78
112
|
if (finalPosition === "bottom" || finalPosition === "top") {
|
|
79
|
-
//
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
113
|
+
// Centraliza no elemento, mas ajusta apenas se necessário para não sair da tela
|
|
114
|
+
const elementCenterX = rect.left + rect.width / 2;
|
|
115
|
+
const minLeft = tooltipWidth / 2 + 8;
|
|
116
|
+
const maxLeft = viewportWidth - tooltipWidth / 2 - 8;
|
|
117
|
+
|
|
118
|
+
// Mantém o mais próximo possível do centro do elemento
|
|
119
|
+
if (elementCenterX < minLeft) {
|
|
120
|
+
left = minLeft;
|
|
121
|
+
} else if (elementCenterX > maxLeft) {
|
|
122
|
+
left = maxLeft;
|
|
123
|
+
} else {
|
|
124
|
+
left = elementCenterX; // Mantém centralizado no elemento
|
|
84
125
|
}
|
|
85
126
|
|
|
86
|
-
//
|
|
87
|
-
if (finalPosition === "bottom"
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
127
|
+
// Verifica espaço vertical e ajusta posição se necessário
|
|
128
|
+
if (finalPosition === "bottom") {
|
|
129
|
+
const spaceBelow = viewportHeight - rect.bottom;
|
|
130
|
+
if (spaceBelow < tooltipHeight + spacing + 8) {
|
|
131
|
+
const spaceAbove = rect.top;
|
|
132
|
+
if (spaceAbove > spaceBelow && spaceAbove > tooltipHeight + spacing + 8) {
|
|
133
|
+
top = rect.top - spacing;
|
|
134
|
+
finalPosition = "top";
|
|
135
|
+
} else {
|
|
136
|
+
// Mantém próximo ao elemento mesmo se não couber perfeitamente
|
|
137
|
+
top = rect.bottom + spacing;
|
|
138
|
+
}
|
|
91
139
|
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
140
|
+
} else if (finalPosition === "top") {
|
|
141
|
+
const spaceAbove = rect.top;
|
|
142
|
+
if (spaceAbove < tooltipHeight + spacing + 8) {
|
|
143
|
+
const spaceBelow = viewportHeight - rect.bottom;
|
|
144
|
+
if (spaceBelow > spaceAbove && spaceBelow > tooltipHeight + spacing + 8) {
|
|
145
|
+
top = rect.bottom + spacing;
|
|
146
|
+
finalPosition = "bottom";
|
|
147
|
+
} else {
|
|
148
|
+
// Mantém próximo ao elemento mesmo se não couber perfeitamente
|
|
149
|
+
top = rect.top - spacing;
|
|
150
|
+
}
|
|
98
151
|
}
|
|
99
152
|
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
153
|
+
}
|
|
154
|
+
// Ajusta verticalmente para tooltips left/right - mantém próximo ao elemento
|
|
155
|
+
else if (finalPosition === "left" || finalPosition === "right") {
|
|
156
|
+
// Centraliza no elemento verticalmente
|
|
157
|
+
const elementCenterY = rect.top + rect.height / 2;
|
|
158
|
+
const minTop = tooltipHeight / 2 + 8;
|
|
159
|
+
const maxTop = viewportHeight - tooltipHeight / 2 - 8;
|
|
160
|
+
|
|
161
|
+
// Mantém o mais próximo possível do centro do elemento
|
|
162
|
+
if (elementCenterY < minTop) {
|
|
163
|
+
top = minTop;
|
|
164
|
+
} else if (elementCenterY > maxTop) {
|
|
165
|
+
top = maxTop;
|
|
166
|
+
} else {
|
|
167
|
+
top = elementCenterY; // Mantém centralizado no elemento
|
|
106
168
|
}
|
|
107
169
|
|
|
108
|
-
//
|
|
109
|
-
if (finalPosition === "left"
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
170
|
+
// Verifica espaço horizontal e ajusta posição se necessário
|
|
171
|
+
if (finalPosition === "left") {
|
|
172
|
+
const spaceLeft = rect.left;
|
|
173
|
+
if (spaceLeft < tooltipWidth + spacing + 8) {
|
|
174
|
+
const spaceRight = viewportWidth - rect.right;
|
|
175
|
+
if (spaceRight > spaceLeft && spaceRight > tooltipWidth + spacing + 8) {
|
|
176
|
+
left = rect.right + spacing;
|
|
177
|
+
finalPosition = "right";
|
|
178
|
+
} else {
|
|
179
|
+
// Mantém próximo ao elemento mesmo se não couber perfeitamente
|
|
180
|
+
left = rect.left - spacing;
|
|
181
|
+
}
|
|
113
182
|
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
183
|
+
} else if (finalPosition === "right") {
|
|
184
|
+
const spaceRight = viewportWidth - rect.right;
|
|
185
|
+
if (spaceRight < tooltipWidth + spacing + 8) {
|
|
186
|
+
const spaceLeft = rect.left;
|
|
187
|
+
if (spaceLeft > spaceRight && spaceLeft > tooltipWidth + spacing + 8) {
|
|
188
|
+
left = rect.left - spacing;
|
|
189
|
+
finalPosition = "left";
|
|
190
|
+
} else {
|
|
191
|
+
// Mantém próximo ao elemento mesmo se não couber perfeitamente
|
|
192
|
+
left = rect.right + spacing;
|
|
193
|
+
}
|
|
120
194
|
}
|
|
121
195
|
}
|
|
122
196
|
}
|
|
@@ -163,11 +237,38 @@ export function Tour({
|
|
|
163
237
|
// Scroll para o elemento
|
|
164
238
|
element.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
165
239
|
|
|
166
|
-
//
|
|
167
|
-
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
|
|
240
|
+
// Função para calcular e atualizar posição
|
|
241
|
+
const updatePosition = () => {
|
|
242
|
+
const updatedRect = element.getBoundingClientRect();
|
|
243
|
+
if (updatedRect.width > 0 && updatedRect.height > 0) {
|
|
244
|
+
const position = calculateTooltipPosition(element, step.position || "bottom");
|
|
245
|
+
setTooltipPosition(position);
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
// Calcula posição inicial após um delay para garantir que o scroll terminou
|
|
250
|
+
setTimeout(updatePosition, 400);
|
|
251
|
+
|
|
252
|
+
// Adiciona listeners para recalcular posição em tempo real
|
|
253
|
+
const handleScroll = () => {
|
|
254
|
+
// Usa requestAnimationFrame para suavizar a atualização durante scroll
|
|
255
|
+
requestAnimationFrame(updatePosition);
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
const handleResize = () => {
|
|
259
|
+
updatePosition();
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
// Adiciona listeners em window e document para capturar todos os tipos de scroll
|
|
263
|
+
window.addEventListener("scroll", handleScroll, { passive: true, capture: true });
|
|
264
|
+
window.addEventListener("resize", handleResize, { passive: true });
|
|
265
|
+
document.addEventListener("scroll", handleScroll, { passive: true, capture: true });
|
|
266
|
+
|
|
267
|
+
return () => {
|
|
268
|
+
window.removeEventListener("scroll", handleScroll, true);
|
|
269
|
+
window.removeEventListener("resize", handleResize);
|
|
270
|
+
document.removeEventListener("scroll", handleScroll, true);
|
|
271
|
+
};
|
|
171
272
|
}, [isVisible, currentStep, steps, calculateTooltipPosition]);
|
|
172
273
|
|
|
173
274
|
// Adiciona overlay e highlight ao elemento
|