@elogroup-sereduc/portal-aluno-tour 1.0.6 → 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 +129 -55
- package/package.json +1 -1
- package/src/components/Tour.tsx +132 -60
|
@@ -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,50 +15,83 @@ 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
|
-
// Recalcula o rect após possíveis mudanças de scroll
|
|
20
21
|
const rect = element.getBoundingClientRect();
|
|
21
|
-
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
|
|
22
|
-
const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
|
|
23
22
|
const viewportWidth = window.innerWidth;
|
|
24
23
|
const viewportHeight = window.innerHeight;
|
|
25
24
|
// Tamanho estimado da tooltip
|
|
26
25
|
const tooltipWidth = 384; // max-w-sm = 384px
|
|
27
|
-
const tooltipHeight = 250; // altura estimada
|
|
28
|
-
const spacing = 8; // espaçamento
|
|
26
|
+
const tooltipHeight = 250; // altura estimada
|
|
27
|
+
const spacing = 8; // espaçamento próximo ao elemento
|
|
29
28
|
let top = 0;
|
|
30
29
|
let left = 0;
|
|
31
30
|
let finalPosition = position;
|
|
32
|
-
//
|
|
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
|
|
33
66
|
switch (position) {
|
|
34
67
|
case "top":
|
|
35
|
-
top = rect.top
|
|
36
|
-
left = rect.left +
|
|
68
|
+
top = rect.top - spacing;
|
|
69
|
+
left = rect.left + rect.width / 2;
|
|
37
70
|
break;
|
|
38
71
|
case "bottom":
|
|
39
|
-
top = rect.bottom +
|
|
40
|
-
left = rect.left +
|
|
72
|
+
top = rect.bottom + spacing;
|
|
73
|
+
left = rect.left + rect.width / 2;
|
|
41
74
|
break;
|
|
42
75
|
case "left":
|
|
43
|
-
top = rect.top +
|
|
44
|
-
left = rect.left
|
|
76
|
+
top = rect.top + rect.height / 2;
|
|
77
|
+
left = rect.left - spacing;
|
|
45
78
|
break;
|
|
46
79
|
case "right":
|
|
47
|
-
top = rect.top +
|
|
48
|
-
left = rect.right +
|
|
80
|
+
top = rect.top + rect.height / 2;
|
|
81
|
+
left = rect.right + spacing;
|
|
49
82
|
break;
|
|
50
83
|
default:
|
|
51
|
-
top = rect.bottom +
|
|
52
|
-
left = rect.left +
|
|
84
|
+
top = rect.bottom + spacing;
|
|
85
|
+
left = rect.left + rect.width / 2;
|
|
53
86
|
finalPosition = "bottom";
|
|
54
87
|
}
|
|
55
|
-
// Ajusta
|
|
56
|
-
// Mas mantém o mais próximo possível do elemento
|
|
88
|
+
// Ajusta horizontalmente para tooltips top/bottom - mantém próximo ao elemento
|
|
57
89
|
if (finalPosition === "bottom" || finalPosition === "top") {
|
|
58
|
-
//
|
|
59
|
-
const elementCenterX = rect.left +
|
|
60
|
-
const minLeft =
|
|
61
|
-
const maxLeft =
|
|
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
|
|
62
95
|
if (elementCenterX < minLeft) {
|
|
63
96
|
left = minLeft;
|
|
64
97
|
}
|
|
@@ -68,31 +101,43 @@ export function Tour({ enabled, steps, initialStep = 0, options = {}, onExit, on
|
|
|
68
101
|
else {
|
|
69
102
|
left = elementCenterX; // Mantém centralizado no elemento
|
|
70
103
|
}
|
|
71
|
-
// Verifica
|
|
104
|
+
// Verifica espaço vertical e ajusta posição se necessário
|
|
72
105
|
if (finalPosition === "bottom") {
|
|
73
|
-
const spaceBelow = viewportHeight -
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
+
}
|
|
79
117
|
}
|
|
80
118
|
}
|
|
81
119
|
else if (finalPosition === "top") {
|
|
82
|
-
const spaceAbove = rect.top
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
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
|
+
}
|
|
88
131
|
}
|
|
89
132
|
}
|
|
90
133
|
}
|
|
134
|
+
// Ajusta verticalmente para tooltips left/right - mantém próximo ao elemento
|
|
91
135
|
else if (finalPosition === "left" || finalPosition === "right") {
|
|
92
|
-
//
|
|
93
|
-
const elementCenterY = rect.top +
|
|
94
|
-
const minTop =
|
|
95
|
-
const maxTop =
|
|
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
|
|
96
141
|
if (elementCenterY < minTop) {
|
|
97
142
|
top = minTop;
|
|
98
143
|
}
|
|
@@ -102,21 +147,33 @@ export function Tour({ enabled, steps, initialStep = 0, options = {}, onExit, on
|
|
|
102
147
|
else {
|
|
103
148
|
top = elementCenterY; // Mantém centralizado no elemento
|
|
104
149
|
}
|
|
105
|
-
// Verifica
|
|
150
|
+
// Verifica espaço horizontal e ajusta posição se necessário
|
|
106
151
|
if (finalPosition === "left") {
|
|
107
|
-
const spaceLeft = rect.left
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
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
|
+
}
|
|
112
163
|
}
|
|
113
164
|
}
|
|
114
165
|
else if (finalPosition === "right") {
|
|
115
|
-
const spaceRight = viewportWidth -
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
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
|
+
}
|
|
120
177
|
}
|
|
121
178
|
}
|
|
122
179
|
}
|
|
@@ -155,16 +212,33 @@ export function Tour({ enabled, steps, initialStep = 0, options = {}, onExit, on
|
|
|
155
212
|
setHighlightedElement(element);
|
|
156
213
|
// Scroll para o elemento
|
|
157
214
|
element.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
158
|
-
//
|
|
159
|
-
|
|
160
|
-
setTimeout(() => {
|
|
161
|
-
// Recalcula o rect após o scroll
|
|
215
|
+
// Função para calcular e atualizar posição
|
|
216
|
+
const updatePosition = () => {
|
|
162
217
|
const updatedRect = element.getBoundingClientRect();
|
|
163
218
|
if (updatedRect.width > 0 && updatedRect.height > 0) {
|
|
164
219
|
const position = calculateTooltipPosition(element, step.position || "bottom");
|
|
165
220
|
setTooltipPosition(position);
|
|
166
221
|
}
|
|
167
|
-
}
|
|
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
|
+
};
|
|
168
242
|
}, [isVisible, currentStep, steps, calculateTooltipPosition]);
|
|
169
243
|
// Adiciona overlay e highlight ao elemento
|
|
170
244
|
useEffect(() => {
|
package/package.json
CHANGED
package/src/components/Tour.tsx
CHANGED
|
@@ -34,55 +34,88 @@ 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
|
-
// Recalcula o rect após possíveis mudanças de scroll
|
|
39
40
|
const rect = element.getBoundingClientRect();
|
|
40
|
-
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
|
|
41
|
-
const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
|
|
42
41
|
const viewportWidth = window.innerWidth;
|
|
43
42
|
const viewportHeight = window.innerHeight;
|
|
44
43
|
|
|
45
44
|
// Tamanho estimado da tooltip
|
|
46
45
|
const tooltipWidth = 384; // max-w-sm = 384px
|
|
47
|
-
const tooltipHeight = 250; // altura estimada
|
|
48
|
-
const spacing = 8; // espaçamento
|
|
46
|
+
const tooltipHeight = 250; // altura estimada
|
|
47
|
+
const spacing = 8; // espaçamento próximo ao elemento
|
|
49
48
|
|
|
50
49
|
let top = 0;
|
|
51
50
|
let left = 0;
|
|
52
51
|
let finalPosition = position;
|
|
53
52
|
|
|
54
|
-
//
|
|
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
|
|
55
88
|
switch (position) {
|
|
56
89
|
case "top":
|
|
57
|
-
top = rect.top
|
|
58
|
-
left = rect.left +
|
|
90
|
+
top = rect.top - spacing;
|
|
91
|
+
left = rect.left + rect.width / 2;
|
|
59
92
|
break;
|
|
60
93
|
case "bottom":
|
|
61
|
-
top = rect.bottom +
|
|
62
|
-
left = rect.left +
|
|
94
|
+
top = rect.bottom + spacing;
|
|
95
|
+
left = rect.left + rect.width / 2;
|
|
63
96
|
break;
|
|
64
97
|
case "left":
|
|
65
|
-
top = rect.top +
|
|
66
|
-
left = rect.left
|
|
98
|
+
top = rect.top + rect.height / 2;
|
|
99
|
+
left = rect.left - spacing;
|
|
67
100
|
break;
|
|
68
101
|
case "right":
|
|
69
|
-
top = rect.top +
|
|
70
|
-
left = rect.right +
|
|
102
|
+
top = rect.top + rect.height / 2;
|
|
103
|
+
left = rect.right + spacing;
|
|
71
104
|
break;
|
|
72
105
|
default:
|
|
73
|
-
top = rect.bottom +
|
|
74
|
-
left = rect.left +
|
|
106
|
+
top = rect.bottom + spacing;
|
|
107
|
+
left = rect.left + rect.width / 2;
|
|
75
108
|
finalPosition = "bottom";
|
|
76
109
|
}
|
|
77
110
|
|
|
78
|
-
// Ajusta
|
|
79
|
-
// Mas mantém o mais próximo possível do elemento
|
|
111
|
+
// Ajusta horizontalmente para tooltips top/bottom - mantém próximo ao elemento
|
|
80
112
|
if (finalPosition === "bottom" || finalPosition === "top") {
|
|
81
|
-
//
|
|
82
|
-
const elementCenterX = rect.left +
|
|
83
|
-
const minLeft =
|
|
84
|
-
const maxLeft =
|
|
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;
|
|
85
117
|
|
|
118
|
+
// Mantém o mais próximo possível do centro do elemento
|
|
86
119
|
if (elementCenterX < minLeft) {
|
|
87
120
|
left = minLeft;
|
|
88
121
|
} else if (elementCenterX > maxLeft) {
|
|
@@ -91,32 +124,41 @@ export function Tour({
|
|
|
91
124
|
left = elementCenterX; // Mantém centralizado no elemento
|
|
92
125
|
}
|
|
93
126
|
|
|
94
|
-
// Verifica
|
|
127
|
+
// Verifica espaço vertical e ajusta posição se necessário
|
|
95
128
|
if (finalPosition === "bottom") {
|
|
96
|
-
const spaceBelow = viewportHeight -
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
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
|
+
}
|
|
103
139
|
}
|
|
104
140
|
} else if (finalPosition === "top") {
|
|
105
|
-
const spaceAbove = rect.top
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
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
|
+
}
|
|
112
151
|
}
|
|
113
152
|
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
const
|
|
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;
|
|
119
160
|
|
|
161
|
+
// Mantém o mais próximo possível do centro do elemento
|
|
120
162
|
if (elementCenterY < minTop) {
|
|
121
163
|
top = minTop;
|
|
122
164
|
} else if (elementCenterY > maxTop) {
|
|
@@ -125,22 +167,30 @@ export function Tour({
|
|
|
125
167
|
top = elementCenterY; // Mantém centralizado no elemento
|
|
126
168
|
}
|
|
127
169
|
|
|
128
|
-
// Verifica
|
|
170
|
+
// Verifica espaço horizontal e ajusta posição se necessário
|
|
129
171
|
if (finalPosition === "left") {
|
|
130
|
-
const spaceLeft = rect.left
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
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
|
+
}
|
|
136
182
|
}
|
|
137
183
|
} else if (finalPosition === "right") {
|
|
138
|
-
const spaceRight = viewportWidth -
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
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
|
+
}
|
|
144
194
|
}
|
|
145
195
|
}
|
|
146
196
|
}
|
|
@@ -187,16 +237,38 @@ export function Tour({
|
|
|
187
237
|
// Scroll para o elemento
|
|
188
238
|
element.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
189
239
|
|
|
190
|
-
//
|
|
191
|
-
|
|
192
|
-
setTimeout(() => {
|
|
193
|
-
// Recalcula o rect após o scroll
|
|
240
|
+
// Função para calcular e atualizar posição
|
|
241
|
+
const updatePosition = () => {
|
|
194
242
|
const updatedRect = element.getBoundingClientRect();
|
|
195
243
|
if (updatedRect.width > 0 && updatedRect.height > 0) {
|
|
196
244
|
const position = calculateTooltipPosition(element, step.position || "bottom");
|
|
197
245
|
setTooltipPosition(position);
|
|
198
246
|
}
|
|
199
|
-
}
|
|
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
|
+
};
|
|
200
272
|
}, [isVisible, currentStep, steps, calculateTooltipPosition]);
|
|
201
273
|
|
|
202
274
|
// Adiciona overlay e highlight ao elemento
|