-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
/
ViewTransitions.astro
118 lines (108 loc) · 3.22 KB
/
ViewTransitions.astro
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
---
type Fallback = 'none' | 'animate' | 'swap';
export interface Props {
fallback?: Fallback;
handleForms?: boolean;
}
const { fallback = 'animate', handleForms } = Astro.props;
---
<style is:global>
/* Route announcer */
.astro-route-announcer {
position: absolute;
left: 0;
top: 0;
clip: rect(0 0 0 0);
clip-path: inset(50%);
overflow: hidden;
white-space: nowrap;
width: 1px;
height: 1px;
}
</style>
<meta name="astro-view-transitions-enabled" content="true" />
<meta name="astro-view-transitions-fallback" content={fallback} />
{ handleForms ?
<meta name="astro-view-transitions-forms" content="true" /> :
''
}
<script>
import type { Options } from 'astro:transitions/client';
import { supportsViewTransitions, navigate } from 'astro:transitions/client';
// NOTE: import from `astro/prefetch` as `astro:prefetch` requires the `prefetch` config to be enabled
import { init } from 'astro/prefetch';
export type Fallback = 'none' | 'animate' | 'swap';
function getFallback(): Fallback {
const el = document.querySelector('[name="astro-view-transitions-fallback"]');
if (el) {
return el.getAttribute('content') as Fallback;
}
return 'animate';
}
function isReloadEl(el: HTMLElement): boolean {
return el.dataset.astroReload !== undefined;
}
if (supportsViewTransitions || getFallback() !== 'none') {
document.addEventListener('click', (ev) => {
let link = ev.target;
if (link instanceof Element && link.tagName !== 'A') {
link = link.closest('a');
}
// This check verifies that the click is happening on an anchor
// that is going to another page within the same origin. Basically it determines
// same-origin navigation, but omits special key combos for new tabs, etc.
if (
!link ||
!(link instanceof HTMLAnchorElement) ||
isReloadEl(link) ||
link.hasAttribute('download') ||
!link.href ||
(link.target && link.target !== '_self') ||
link.origin !== location.origin ||
ev.button !== 0 || // left clicks only
ev.metaKey || // new tab (mac)
ev.ctrlKey || // new tab (windows)
ev.altKey || // download
ev.shiftKey || // new window
ev.defaultPrevented
) {
// No page transitions in these cases,
// Let the browser standard action handle this
return;
}
ev.preventDefault();
navigate(link.href, {
history: link.dataset.astroHistory === 'replace' ? 'replace' : 'auto',
});
});
if(document.querySelector('[name="astro-view-transitions-forms"]')) {
document.addEventListener('submit', (ev) => {
let el = ev.target as HTMLElement;
if (
el.tagName !== 'FORM' ||
isReloadEl(el)
) {
return;
}
const form = el as HTMLFormElement;
const formData = new FormData(form);
let action = form.action;
const options: Options = {};
if(form.method === 'get') {
const params = new URLSearchParams(formData as any);
const url = new URL(action);
url.search = params.toString();
action = url.toString();
} else {
options.formData = formData;
}
ev.preventDefault();
navigate(action, options);
});
}
// @ts-expect-error injected by vite-plugin-transitions for treeshaking
if (!__PREFETCH_DISABLED__) {
init({ prefetchAll: true });
}
}
</script>