swup 4.0.0-rc.14 → 4.0.0-rc.21
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/README.md +100 -0
- package/dist/Swup.cjs +1 -1
- package/dist/Swup.cjs.map +1 -1
- package/dist/Swup.modern.js +1 -1
- package/dist/Swup.modern.js.map +1 -1
- package/dist/Swup.module.js +1 -1
- package/dist/Swup.module.js.map +1 -1
- package/dist/Swup.umd.js +1 -1
- package/dist/Swup.umd.js.map +1 -1
- package/dist/types/Swup.d.ts +62 -54
- package/dist/types/helpers/Location.d.ts +10 -7
- package/dist/types/helpers/delegateEvent.d.ts +3 -5
- package/dist/types/helpers/matchPath.d.ts +3 -0
- package/dist/types/helpers.d.ts +7 -10
- package/dist/types/index.d.ts +9 -6
- package/dist/types/modules/Cache.d.ts +15 -15
- package/dist/types/modules/Classes.d.ts +13 -0
- package/dist/types/modules/Context.d.ts +73 -0
- package/dist/types/modules/Hooks.d.ts +241 -0
- package/dist/types/modules/__test__/hooks.test.d.ts +1 -0
- package/dist/types/modules/__test__/replaceContent.test.d.ts +1 -0
- package/dist/types/modules/awaitAnimations.d.ts +21 -0
- package/dist/types/modules/enterPage.d.ts +6 -3
- package/dist/types/modules/fetchPage.d.ts +24 -4
- package/dist/types/modules/getAnchorElement.d.ts +8 -0
- package/dist/types/modules/leavePage.d.ts +6 -3
- package/dist/types/modules/plugins.d.ts +12 -5
- package/dist/types/modules/renderPage.d.ts +7 -7
- package/dist/types/modules/replaceContent.d.ts +8 -11
- package/dist/types/modules/visit.d.ts +33 -0
- package/dist/types/utils/index.d.ts +3 -1
- package/dist/types/utils.d.ts +1 -1
- package/package.json +7 -6
- package/src/Swup.ts +83 -65
- package/src/__test__/index.test.ts +3 -3
- package/src/helpers/Location.ts +2 -2
- package/src/helpers/delegateEvent.ts +2 -2
- package/src/helpers.ts +0 -1
- package/src/index.ts +34 -4
- package/src/modules/Cache.ts +2 -2
- package/src/modules/Classes.ts +48 -0
- package/src/modules/Context.ts +49 -19
- package/src/modules/Hooks.ts +103 -83
- package/src/modules/__test__/cache.test.ts +6 -6
- package/src/modules/__test__/hooks.test.ts +111 -40
- package/src/modules/__test__/replaceContent.test.ts +92 -0
- package/src/modules/{getAnimationPromises.ts → awaitAnimations.ts} +13 -18
- package/src/modules/enterPage.ts +21 -17
- package/src/modules/fetchPage.ts +12 -12
- package/src/modules/getAnchorElement.ts +2 -1
- package/src/modules/leavePage.ts +16 -12
- package/src/modules/plugins.ts +11 -8
- package/src/modules/renderPage.ts +28 -18
- package/src/modules/replaceContent.ts +24 -16
- package/src/modules/visit.ts +143 -0
- package/src/utils/index.ts +1 -2
- package/dist/types/helpers/cleanupAnimationClasses.d.ts +0 -2
- package/dist/types/helpers/fetch.d.ts +0 -5
- package/dist/types/helpers/getDataFromHtml.d.ts +0 -7
- package/dist/types/helpers/markSwupElements.d.ts +0 -1
- package/dist/types/modules/destroy.d.ts +0 -2
- package/dist/types/modules/enable.d.ts +0 -2
- package/dist/types/modules/events.d.ts +0 -33
- package/dist/types/modules/getAnimationPromises.d.ts +0 -7
- package/dist/types/modules/getPageData.d.ts +0 -6
- package/dist/types/modules/handleLinkToSamePage.d.ts +0 -2
- package/dist/types/modules/isSameResolvedUrl.d.ts +0 -8
- package/dist/types/modules/linkClickHandler.d.ts +0 -3
- package/dist/types/modules/loadPage.d.ts +0 -12
- package/dist/types/modules/off.d.ts +0 -3
- package/dist/types/modules/on.d.ts +0 -5
- package/dist/types/modules/popStateHandler.d.ts +0 -2
- package/dist/types/modules/resolveUrl.d.ts +0 -7
- package/dist/types/modules/shouldIgnoreVisit.d.ts +0 -4
- package/dist/types/modules/transitions.d.ts +0 -6
- package/dist/types/modules/triggerEvent.d.ts +0 -3
- package/dist/types/modules/triggerWillOpenNewWindow.d.ts +0 -2
- package/dist/types/modules/updateTransition.d.ts +0 -2
- package/readme.md +0 -78
- package/src/helpers/cleanupAnimationClasses.ts +0 -8
- package/src/modules/loadPage.ts +0 -99
- /package/dist/types/{modules/__test__/events.test.d.ts → helpers/__test__/matchPath.test.d.ts} +0 -0
- /package/dist/types/modules/__test__/{fetchPage.test.d.ts → cache.test.d.ts} +0 -0
package/src/Swup.ts
CHANGED
|
@@ -2,89 +2,93 @@ import { DelegateEvent } from 'delegate-it';
|
|
|
2
2
|
|
|
3
3
|
import version from './config/version.js';
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
delegateEvent,
|
|
8
|
-
getCurrentUrl,
|
|
9
|
-
Location,
|
|
10
|
-
updateHistoryRecord
|
|
11
|
-
} from './helpers.js';
|
|
12
|
-
import { Unsubscribe } from './helpers/delegateEvent.js';
|
|
5
|
+
import { delegateEvent, getCurrentUrl, Location, updateHistoryRecord } from './helpers.js';
|
|
6
|
+
import { DelegateEventUnsubscribe } from './helpers/delegateEvent.js';
|
|
13
7
|
|
|
14
8
|
import { Cache } from './modules/Cache.js';
|
|
9
|
+
import { Classes } from './modules/Classes.js';
|
|
15
10
|
import { Context, createContext } from './modules/Context.js';
|
|
16
|
-
import {
|
|
11
|
+
import { Hooks } from './modules/Hooks.js';
|
|
17
12
|
import { getAnchorElement } from './modules/getAnchorElement.js';
|
|
18
|
-
import {
|
|
13
|
+
import { awaitAnimations } from './modules/awaitAnimations.js';
|
|
14
|
+
import { visit, performVisit, HistoryAction } from './modules/visit.js';
|
|
19
15
|
import { fetchPage } from './modules/fetchPage.js';
|
|
20
16
|
import { leavePage } from './modules/leavePage.js';
|
|
21
|
-
import { HistoryAction, loadPage, performPageLoad } from './modules/loadPage.js';
|
|
22
17
|
import { replaceContent } from './modules/replaceContent.js';
|
|
23
|
-
import {
|
|
24
|
-
import { use, unuse, findPlugin, Plugin } from './modules/plugins.js';
|
|
18
|
+
import { enterPage } from './modules/enterPage.js';
|
|
25
19
|
import { renderPage } from './modules/renderPage.js';
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
from?: string;
|
|
29
|
-
to?: string;
|
|
30
|
-
custom?: string;
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
type DelegatedListeners = {
|
|
34
|
-
click?: Unsubscribe;
|
|
35
|
-
};
|
|
20
|
+
import { use, unuse, findPlugin, Plugin } from './modules/plugins.js';
|
|
21
|
+
import { nextTick } from './utils.js';
|
|
36
22
|
|
|
37
23
|
export type Options = {
|
|
24
|
+
/** Whether history visits are animated. Default: `false` */
|
|
38
25
|
animateHistoryBrowsing: boolean;
|
|
26
|
+
/** Selector for detecting animation timing. Default: `[class*="transition-"]` */
|
|
39
27
|
animationSelector: string | false;
|
|
40
|
-
|
|
28
|
+
/** Elements on which to add animation classes. Default: `html` element */
|
|
29
|
+
animationScope: 'html' | 'containers';
|
|
30
|
+
/** Enable in-memory page cache. Default: `true` */
|
|
41
31
|
cache: boolean;
|
|
32
|
+
/** Content containers to be replaced on page visits. Default: `['#swup']` */
|
|
42
33
|
containers: string[];
|
|
43
|
-
|
|
44
|
-
plugins: Plugin[];
|
|
45
|
-
skipPopStateHandling: (event: any) => boolean;
|
|
34
|
+
/** Callback for ignoring visits. Receives the element and event that triggered the visit. */
|
|
46
35
|
ignoreVisit: (url: string, { el, event }: { el?: Element; event?: Event }) => boolean;
|
|
36
|
+
/** Selector for links that trigger visits. Default: `'a[href]'` */
|
|
37
|
+
linkSelector: string;
|
|
38
|
+
/** Plugins to register on startup. */
|
|
39
|
+
plugins: Plugin[];
|
|
40
|
+
/** Custom headers sent along with fetch requests. */
|
|
41
|
+
requestHeaders: Record<string, string>;
|
|
42
|
+
/** Rewrite URLs before loading them. */
|
|
47
43
|
resolveUrl: (url: string) => string;
|
|
44
|
+
/** Callback for telling swup to ignore certain popstate events. */
|
|
45
|
+
skipPopStateHandling: (event: any) => boolean;
|
|
48
46
|
};
|
|
49
47
|
|
|
50
48
|
export default class Swup {
|
|
49
|
+
/** Library version */
|
|
51
50
|
version: string = version;
|
|
52
|
-
|
|
51
|
+
/** Options passed into the instance */
|
|
53
52
|
options: Options;
|
|
54
|
-
|
|
53
|
+
/** Registered plugin instances */
|
|
55
54
|
plugins: Plugin[] = [];
|
|
56
|
-
|
|
55
|
+
/** Global context of the current visit */
|
|
57
56
|
context: Context;
|
|
58
|
-
|
|
57
|
+
/** Cache instance */
|
|
59
58
|
cache: Cache;
|
|
60
|
-
|
|
59
|
+
/** Hook registry */
|
|
61
60
|
hooks: Hooks;
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
61
|
+
/** Animation class manager */
|
|
62
|
+
classes: Classes;
|
|
63
|
+
/** URL of the currently visible page */
|
|
65
64
|
currentPageUrl = getCurrentUrl();
|
|
65
|
+
/** Index of the current history entry */
|
|
66
|
+
currentHistoryIndex = 1;
|
|
67
|
+
/** Delegated event subscription handle */
|
|
68
|
+
private clickDelegate?: DelegateEventUnsubscribe;
|
|
66
69
|
|
|
67
|
-
|
|
68
|
-
|
|
70
|
+
visit = visit;
|
|
71
|
+
performVisit = performVisit;
|
|
69
72
|
leavePage = leavePage;
|
|
70
73
|
renderPage = renderPage;
|
|
71
74
|
replaceContent = replaceContent;
|
|
72
75
|
enterPage = enterPage;
|
|
73
76
|
delegateEvent = delegateEvent;
|
|
74
|
-
getAnimationPromises = getAnimationPromises;
|
|
75
77
|
fetchPage = fetchPage;
|
|
78
|
+
awaitAnimations = awaitAnimations;
|
|
76
79
|
getAnchorElement = getAnchorElement;
|
|
77
|
-
log: (message: string, context?: any) => void = () => {}; // here so it can be used by plugins
|
|
78
80
|
use = use;
|
|
79
81
|
unuse = unuse;
|
|
80
82
|
findPlugin = findPlugin;
|
|
81
83
|
getCurrentUrl = getCurrentUrl;
|
|
82
|
-
cleanupAnimationClasses = cleanupAnimationClasses;
|
|
83
84
|
createContext = createContext;
|
|
85
|
+
log: (message: string, context?: any) => void = () => {}; // here so it can be used by plugins
|
|
84
86
|
|
|
87
|
+
/** Default options before merging user options */
|
|
85
88
|
defaults: Options = {
|
|
86
89
|
animateHistoryBrowsing: false,
|
|
87
90
|
animationSelector: '[class*="transition-"]',
|
|
91
|
+
animationScope: 'html',
|
|
88
92
|
cache: true,
|
|
89
93
|
containers: ['#swup'],
|
|
90
94
|
ignoreVisit: (url, { el, event } = {}) => !!el?.closest('[data-no-swup]'),
|
|
@@ -93,7 +97,7 @@ export default class Swup {
|
|
|
93
97
|
resolveUrl: (url) => url,
|
|
94
98
|
requestHeaders: {
|
|
95
99
|
'X-Requested-With': 'swup',
|
|
96
|
-
Accept: 'text/html, application/xhtml+xml'
|
|
100
|
+
'Accept': 'text/html, application/xhtml+xml'
|
|
97
101
|
},
|
|
98
102
|
skipPopStateHandling: (event) => event.state?.source !== 'swup'
|
|
99
103
|
};
|
|
@@ -106,6 +110,7 @@ export default class Swup {
|
|
|
106
110
|
this.popStateHandler = this.popStateHandler.bind(this);
|
|
107
111
|
|
|
108
112
|
this.cache = new Cache(this);
|
|
113
|
+
this.classes = new Classes(this);
|
|
109
114
|
this.hooks = new Hooks(this);
|
|
110
115
|
this.context = this.createContext({ to: undefined });
|
|
111
116
|
|
|
@@ -125,9 +130,9 @@ export default class Swup {
|
|
|
125
130
|
}
|
|
126
131
|
|
|
127
132
|
async enable() {
|
|
128
|
-
// Add event
|
|
133
|
+
// Add event listener
|
|
129
134
|
const { linkSelector } = this.options;
|
|
130
|
-
this.
|
|
135
|
+
this.clickDelegate = this.delegateEvent(linkSelector, 'click', this.linkClickHandler);
|
|
131
136
|
|
|
132
137
|
window.addEventListener('popstate', this.popStateHandler);
|
|
133
138
|
|
|
@@ -141,21 +146,23 @@ export default class Swup {
|
|
|
141
146
|
this.options.plugins.forEach((plugin) => this.use(plugin));
|
|
142
147
|
|
|
143
148
|
// Modify initial history record
|
|
144
|
-
updateHistoryRecord();
|
|
149
|
+
updateHistoryRecord(null, { index: 1 });
|
|
145
150
|
|
|
146
|
-
// Trigger
|
|
147
|
-
await this.hooks.trigger('
|
|
151
|
+
// Trigger enable hook
|
|
152
|
+
await this.hooks.trigger('enable', undefined, () => {
|
|
148
153
|
// Add swup-enabled class to html tag
|
|
149
154
|
document.documentElement.classList.add('swup-enabled');
|
|
150
155
|
});
|
|
151
156
|
|
|
152
|
-
|
|
153
|
-
|
|
157
|
+
await nextTick();
|
|
158
|
+
|
|
159
|
+
// Trigger page view hook
|
|
160
|
+
await this.hooks.trigger('page:view', { url: this.currentPageUrl, title: document.title });
|
|
154
161
|
}
|
|
155
162
|
|
|
156
163
|
async destroy() {
|
|
157
|
-
// remove delegated
|
|
158
|
-
this.
|
|
164
|
+
// remove delegated listener
|
|
165
|
+
this.clickDelegate!.destroy();
|
|
159
166
|
|
|
160
167
|
// remove popstate listener
|
|
161
168
|
window.removeEventListener('popstate', this.popStateHandler);
|
|
@@ -166,8 +173,8 @@ export default class Swup {
|
|
|
166
173
|
// unmount plugins
|
|
167
174
|
this.options.plugins.forEach((plugin) => this.unuse(plugin));
|
|
168
175
|
|
|
169
|
-
// trigger disable
|
|
170
|
-
await this.hooks.trigger('
|
|
176
|
+
// trigger disable hook
|
|
177
|
+
await this.hooks.trigger('disable', undefined, () => {
|
|
171
178
|
// remove swup-enabled class from html tag
|
|
172
179
|
document.documentElement.classList.remove('swup-enabled');
|
|
173
180
|
});
|
|
@@ -202,8 +209,8 @@ export default class Swup {
|
|
|
202
209
|
const el = event.delegateTarget as HTMLAnchorElement;
|
|
203
210
|
const { href, url, hash } = Location.fromElement(el);
|
|
204
211
|
|
|
205
|
-
// Get the
|
|
206
|
-
const
|
|
212
|
+
// Get the animation name, if specified
|
|
213
|
+
const animation = el.getAttribute('data-swup-animation') || undefined;
|
|
207
214
|
|
|
208
215
|
// Get the history action, if specified
|
|
209
216
|
let historyAction: HistoryAction | undefined;
|
|
@@ -220,7 +227,7 @@ export default class Swup {
|
|
|
220
227
|
this.context = this.createContext({
|
|
221
228
|
to: url,
|
|
222
229
|
hash,
|
|
223
|
-
|
|
230
|
+
animation,
|
|
224
231
|
el,
|
|
225
232
|
event,
|
|
226
233
|
action: historyAction
|
|
@@ -228,7 +235,7 @@ export default class Swup {
|
|
|
228
235
|
|
|
229
236
|
// Exit early if control key pressed
|
|
230
237
|
if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
|
|
231
|
-
this.hooks.trigger('
|
|
238
|
+
this.hooks.trigger('link:newtab', { href });
|
|
232
239
|
return;
|
|
233
240
|
}
|
|
234
241
|
|
|
@@ -237,8 +244,8 @@ export default class Swup {
|
|
|
237
244
|
return;
|
|
238
245
|
}
|
|
239
246
|
|
|
240
|
-
this.hooks.triggerSync('
|
|
241
|
-
const from = this.context.from
|
|
247
|
+
this.hooks.triggerSync('link:click', { el, event }, () => {
|
|
248
|
+
const from = this.context.from.url ?? '';
|
|
242
249
|
|
|
243
250
|
event.preventDefault();
|
|
244
251
|
|
|
@@ -247,7 +254,7 @@ export default class Swup {
|
|
|
247
254
|
if (hash) {
|
|
248
255
|
updateHistoryRecord(url + hash);
|
|
249
256
|
this.hooks.triggerSync(
|
|
250
|
-
'
|
|
257
|
+
'link:anchor',
|
|
251
258
|
{ hash, options: { behavior: 'auto' } },
|
|
252
259
|
(context, { hash, options }) => {
|
|
253
260
|
const target = this.getAnchorElement(hash);
|
|
@@ -257,7 +264,8 @@ export default class Swup {
|
|
|
257
264
|
}
|
|
258
265
|
);
|
|
259
266
|
} else {
|
|
260
|
-
this.hooks.triggerSync('
|
|
267
|
+
this.hooks.triggerSync('link:self', undefined, (context) => {
|
|
268
|
+
if (!context.scroll.reset) return;
|
|
261
269
|
window.scroll({ top: 0, left: 0, behavior: 'auto' });
|
|
262
270
|
});
|
|
263
271
|
}
|
|
@@ -270,7 +278,7 @@ export default class Swup {
|
|
|
270
278
|
}
|
|
271
279
|
|
|
272
280
|
// Finally, proceed with loading the page
|
|
273
|
-
this.
|
|
281
|
+
this.performVisit(url);
|
|
274
282
|
});
|
|
275
283
|
}
|
|
276
284
|
|
|
@@ -302,22 +310,32 @@ export default class Swup {
|
|
|
302
310
|
const { url, hash } = Location.fromUrl(href);
|
|
303
311
|
const animate = this.options.animateHistoryBrowsing;
|
|
304
312
|
const resetScroll = this.options.animateHistoryBrowsing;
|
|
313
|
+
|
|
305
314
|
this.context = this.createContext({
|
|
306
315
|
to: url,
|
|
307
316
|
hash,
|
|
308
317
|
event,
|
|
309
318
|
animate,
|
|
310
|
-
resetScroll
|
|
311
|
-
popstate: true
|
|
319
|
+
resetScroll
|
|
312
320
|
});
|
|
313
321
|
|
|
322
|
+
// Mark as popstate visit
|
|
323
|
+
this.context.history.popstate = true;
|
|
324
|
+
|
|
325
|
+
// Determine direction of history visit
|
|
326
|
+
const index = Number(event.state?.index);
|
|
327
|
+
if (index) {
|
|
328
|
+
const direction = index - this.currentHistoryIndex > 0 ? 'forwards' : 'backwards';
|
|
329
|
+
this.context.history.direction = direction;
|
|
330
|
+
}
|
|
331
|
+
|
|
314
332
|
// Does this even do anything?
|
|
315
333
|
// if (!hash) {
|
|
316
334
|
// event.preventDefault();
|
|
317
335
|
// }
|
|
318
336
|
|
|
319
|
-
this.hooks.triggerSync('
|
|
320
|
-
this.
|
|
337
|
+
this.hooks.triggerSync('history:popstate', { event }, () => {
|
|
338
|
+
this.performVisit(url);
|
|
321
339
|
});
|
|
322
340
|
}
|
|
323
341
|
|
|
@@ -38,7 +38,7 @@ describe('Exports', () => {
|
|
|
38
38
|
resolveUrl: (url) => url,
|
|
39
39
|
requestHeaders: {
|
|
40
40
|
'X-Requested-With': 'swup',
|
|
41
|
-
Accept: 'text/html, application/xhtml+xml'
|
|
41
|
+
'Accept': 'text/html, application/xhtml+xml'
|
|
42
42
|
},
|
|
43
43
|
skipPopStateHandling: (event) => event.state?.source !== 'swup'
|
|
44
44
|
};
|
|
@@ -84,10 +84,10 @@ describe('ignoreVisit', () => {
|
|
|
84
84
|
);
|
|
85
85
|
});
|
|
86
86
|
|
|
87
|
-
it('should be called from
|
|
87
|
+
it('should be called from visit method', () => {
|
|
88
88
|
const ignoreVisit = vi.fn(() => true);
|
|
89
89
|
const swup = new Swup({ ignoreVisit });
|
|
90
|
-
swup.
|
|
90
|
+
swup.visit('/path/');
|
|
91
91
|
|
|
92
92
|
expect(ignoreVisit.mock.calls).toHaveLength(1);
|
|
93
93
|
});
|
package/src/helpers/Location.ts
CHANGED
|
@@ -19,7 +19,7 @@ export class Location extends URL {
|
|
|
19
19
|
/**
|
|
20
20
|
* Instantiate a Location from an element's href attribute
|
|
21
21
|
* @param el
|
|
22
|
-
* @
|
|
22
|
+
* @returns new Location instance
|
|
23
23
|
*/
|
|
24
24
|
static fromElement(el: Element): Location {
|
|
25
25
|
const href = el.getAttribute('href') || el.getAttribute('xlink:href') || '';
|
|
@@ -29,7 +29,7 @@ export class Location extends URL {
|
|
|
29
29
|
/**
|
|
30
30
|
* Instantiate a Location from a URL object or string
|
|
31
31
|
* @param url
|
|
32
|
-
* @
|
|
32
|
+
* @returns new Location instance
|
|
33
33
|
*/
|
|
34
34
|
static fromUrl(url: URL | string): Location {
|
|
35
35
|
return new Location(url);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import delegate, { DelegateEventHandler, DelegateOptions, EventType } from 'delegate-it';
|
|
2
2
|
import { ParseSelector } from 'typed-query-selector/parser.js';
|
|
3
3
|
|
|
4
|
-
export type
|
|
4
|
+
export type DelegateEventUnsubscribe = {
|
|
5
5
|
destroy: () => void;
|
|
6
6
|
};
|
|
7
7
|
|
|
@@ -10,7 +10,7 @@ export const delegateEvent = <Selector extends string, TEvent extends EventType>
|
|
|
10
10
|
type: TEvent,
|
|
11
11
|
callback: DelegateEventHandler<GlobalEventHandlersEventMap[TEvent]>,
|
|
12
12
|
options?: DelegateOptions
|
|
13
|
-
):
|
|
13
|
+
): DelegateEventUnsubscribe => {
|
|
14
14
|
const controller = new AbortController();
|
|
15
15
|
options = { ...options, signal: controller.signal };
|
|
16
16
|
delegate<string, ParseSelector<Selector, HTMLElement>, TEvent>(
|
package/src/helpers.ts
CHANGED
|
@@ -7,5 +7,4 @@ export { updateHistoryRecord } from './helpers/updateHistoryRecord.js';
|
|
|
7
7
|
export { delegateEvent } from './helpers/delegateEvent.js';
|
|
8
8
|
export { getCurrentUrl } from './helpers/getCurrentUrl.js';
|
|
9
9
|
export { Location } from './helpers/Location.js';
|
|
10
|
-
export { cleanupAnimationClasses } from './helpers/cleanupAnimationClasses.js';
|
|
11
10
|
export { matchPath } from './helpers/matchPath.js';
|
package/src/index.ts
CHANGED
|
@@ -1,13 +1,43 @@
|
|
|
1
|
+
import type { Path } from 'path-to-regexp';
|
|
2
|
+
|
|
1
3
|
import Swup, { type Options } from './Swup.js';
|
|
2
4
|
import type { CacheData } from './modules/Cache.js';
|
|
3
|
-
import type {
|
|
5
|
+
import type {
|
|
6
|
+
Context,
|
|
7
|
+
FromContext,
|
|
8
|
+
ToContext,
|
|
9
|
+
AnimationContext,
|
|
10
|
+
ScrollContext,
|
|
11
|
+
HistoryContext
|
|
12
|
+
} from './modules/Context.js';
|
|
13
|
+
import type {
|
|
14
|
+
HookDefinitions,
|
|
15
|
+
HookName,
|
|
16
|
+
HookOptions,
|
|
17
|
+
HookUnregister,
|
|
18
|
+
Handler
|
|
19
|
+
} from './modules/Hooks.js';
|
|
4
20
|
import type { Plugin } from './modules/plugins.js';
|
|
5
|
-
import type { HookDefinitions, Handler } from './modules/Hooks.js';
|
|
6
|
-
import type { Path } from 'path-to-regexp';
|
|
7
21
|
|
|
8
22
|
export default Swup;
|
|
9
23
|
|
|
10
24
|
export * from './helpers.js';
|
|
11
25
|
export * from './utils.js';
|
|
12
26
|
|
|
13
|
-
export type {
|
|
27
|
+
export type {
|
|
28
|
+
Options,
|
|
29
|
+
Plugin,
|
|
30
|
+
CacheData,
|
|
31
|
+
Context,
|
|
32
|
+
FromContext,
|
|
33
|
+
ToContext,
|
|
34
|
+
AnimationContext,
|
|
35
|
+
ScrollContext,
|
|
36
|
+
HistoryContext,
|
|
37
|
+
HookDefinitions,
|
|
38
|
+
HookName,
|
|
39
|
+
HookOptions,
|
|
40
|
+
HookUnregister,
|
|
41
|
+
Handler,
|
|
42
|
+
Path
|
|
43
|
+
};
|
package/src/modules/Cache.ts
CHANGED
|
@@ -32,7 +32,7 @@ export class Cache {
|
|
|
32
32
|
url = this.resolve(url);
|
|
33
33
|
page = { ...page, url };
|
|
34
34
|
this.pages.set(url, page);
|
|
35
|
-
this.swup.hooks.triggerSync('
|
|
35
|
+
this.swup.hooks.triggerSync('cache:set', { page });
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
public update(url: string, page: CacheData) {
|
|
@@ -47,7 +47,7 @@ export class Cache {
|
|
|
47
47
|
|
|
48
48
|
public clear(): void {
|
|
49
49
|
this.pages.clear();
|
|
50
|
-
this.swup.hooks.triggerSync('
|
|
50
|
+
this.swup.hooks.triggerSync('cache:clear');
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
public prune(predicate: (url: string, page: CacheData) => boolean): void {
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import Swup from '../Swup.js';
|
|
2
|
+
import { queryAll } from '../utils.js';
|
|
3
|
+
|
|
4
|
+
export class Classes {
|
|
5
|
+
public swup: Swup;
|
|
6
|
+
|
|
7
|
+
swupClasses = ['to-', 'is-changing', 'is-rendering', 'is-popstate', 'is-animating'];
|
|
8
|
+
|
|
9
|
+
constructor(swup: Swup) {
|
|
10
|
+
this.swup = swup;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
get selectors(): string[] {
|
|
14
|
+
const { scope } = this.swup.context.animation;
|
|
15
|
+
if (scope === 'containers') return this.swup.context.containers;
|
|
16
|
+
if (scope === 'html') return ['html'];
|
|
17
|
+
if (Array.isArray(scope)) return scope;
|
|
18
|
+
return [];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
get selector(): string {
|
|
22
|
+
return this.selectors.join(',');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
get targets(): HTMLElement[] {
|
|
26
|
+
if (!this.selector.trim()) return [];
|
|
27
|
+
return queryAll(this.selector) as HTMLElement[];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public add(...classes: string[]): void {
|
|
31
|
+
this.targets.forEach((target) => target.classList.add(...classes));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public remove(...classes: string[]): void {
|
|
35
|
+
this.targets.forEach((target) => target.classList.remove(...classes));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
public clear(): void {
|
|
39
|
+
this.targets.forEach((target) => {
|
|
40
|
+
const remove = target.className.split(' ').filter((c) => this.isSwupClass(c));
|
|
41
|
+
target.classList.remove(...remove);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
private isSwupClass(className: string): boolean {
|
|
46
|
+
return this.swupClasses.some((c) => className.startsWith(c));
|
|
47
|
+
}
|
|
48
|
+
}
|
package/src/modules/Context.ts
CHANGED
|
@@ -1,51 +1,80 @@
|
|
|
1
1
|
import Swup, { Options } from '../Swup.js';
|
|
2
|
-
import { HistoryAction } from './
|
|
2
|
+
import { HistoryAction, HistoryDirection } from './visit.js';
|
|
3
3
|
|
|
4
4
|
export interface Context<TEvent = Event> {
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
/** The previous page, about to leave */
|
|
6
|
+
from: FromContext;
|
|
7
|
+
/** The next page, about to enter */
|
|
8
|
+
to: ToContext;
|
|
9
|
+
/** The content containers, about to be replaced */
|
|
7
10
|
containers: Options['containers'];
|
|
8
|
-
|
|
11
|
+
/** Information about animated page transitions */
|
|
12
|
+
animation: AnimationContext;
|
|
13
|
+
/** What triggered this visit */
|
|
9
14
|
trigger: TriggerContext<TEvent>;
|
|
15
|
+
/** Browser history behavior on this visit */
|
|
10
16
|
history: HistoryContext;
|
|
17
|
+
/** Scroll behavior on this visit */
|
|
11
18
|
scroll: ScrollContext;
|
|
12
19
|
}
|
|
13
20
|
|
|
14
|
-
export interface
|
|
21
|
+
export interface FromContext {
|
|
22
|
+
/** The URL of the previous page */
|
|
15
23
|
url: string;
|
|
16
24
|
}
|
|
17
25
|
|
|
18
|
-
export interface
|
|
26
|
+
export interface ToContext {
|
|
27
|
+
/** The URL of the next page */
|
|
28
|
+
url?: string;
|
|
29
|
+
/** The HTML content of the next page */
|
|
30
|
+
html?: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface AnimationContext {
|
|
34
|
+
/** Whether this visit is animated. Default: `true` */
|
|
19
35
|
animate: boolean;
|
|
36
|
+
/** Whether to wait for the next page to load before starting the animation. Default: `false` */
|
|
37
|
+
wait: boolean;
|
|
38
|
+
/** Name of a custom animation to run. */
|
|
20
39
|
name?: string;
|
|
40
|
+
/** Elements on which to add animation classes. Default: `html` element */
|
|
41
|
+
scope: 'html' | 'containers' | string[];
|
|
42
|
+
/** Selector for detecting animation timing. Default: `[class*="transition-"]` */
|
|
43
|
+
selector: Options['animationSelector'];
|
|
21
44
|
}
|
|
22
45
|
|
|
23
46
|
export interface ScrollContext {
|
|
47
|
+
/** Whether to reset the scroll position after the visit. Default: `true` */
|
|
24
48
|
reset: boolean;
|
|
49
|
+
/** Anchor element to scroll to on the next page. */
|
|
25
50
|
target?: string;
|
|
26
51
|
}
|
|
27
52
|
|
|
28
53
|
export interface TriggerContext<TEvent = Event> {
|
|
54
|
+
/** DOM element that triggered this visit. */
|
|
29
55
|
el?: Element;
|
|
56
|
+
/** DOM event that triggered this visit. */
|
|
30
57
|
event?: TEvent;
|
|
31
58
|
}
|
|
32
59
|
|
|
33
60
|
export interface HistoryContext {
|
|
61
|
+
/** History action to perform: `push` for creating a new history entry, `replace` for replacing the current entry. Default: `push` */
|
|
34
62
|
action: HistoryAction;
|
|
63
|
+
/** Whether this visit was triggered by a browser history navigation. */
|
|
35
64
|
popstate: boolean;
|
|
36
|
-
|
|
65
|
+
/** The direction of travel in case of a browser history navigation: backward or forward. */
|
|
66
|
+
direction: HistoryDirection | undefined;
|
|
37
67
|
}
|
|
38
68
|
|
|
39
69
|
export interface ContextInitOptions {
|
|
40
70
|
to: string | undefined;
|
|
41
71
|
from?: string;
|
|
42
72
|
hash?: string;
|
|
43
|
-
containers?: Options['containers'];
|
|
44
73
|
animate?: boolean;
|
|
45
|
-
|
|
74
|
+
animation?: string;
|
|
75
|
+
targets?: string[];
|
|
46
76
|
el?: Element;
|
|
47
77
|
event?: Event;
|
|
48
|
-
popstate?: boolean;
|
|
49
78
|
action?: HistoryAction;
|
|
50
79
|
resetScroll?: boolean;
|
|
51
80
|
}
|
|
@@ -56,23 +85,24 @@ export function createContext(
|
|
|
56
85
|
to,
|
|
57
86
|
from = this.currentPageUrl,
|
|
58
87
|
hash: target,
|
|
59
|
-
containers = this.options.containers,
|
|
60
88
|
animate = true,
|
|
61
|
-
|
|
89
|
+
animation: name,
|
|
62
90
|
el,
|
|
63
91
|
event,
|
|
64
|
-
popstate = false,
|
|
65
92
|
action = 'push',
|
|
66
93
|
resetScroll: reset = true
|
|
67
94
|
}: ContextInitOptions
|
|
68
95
|
): Context {
|
|
69
96
|
return {
|
|
70
97
|
from: { url: from },
|
|
71
|
-
to:
|
|
72
|
-
containers,
|
|
73
|
-
|
|
98
|
+
to: { url: to },
|
|
99
|
+
containers: this.options.containers,
|
|
100
|
+
animation: {
|
|
74
101
|
animate,
|
|
75
|
-
|
|
102
|
+
wait: false,
|
|
103
|
+
name,
|
|
104
|
+
scope: this.options.animationScope,
|
|
105
|
+
selector: this.options.animationSelector
|
|
76
106
|
},
|
|
77
107
|
trigger: {
|
|
78
108
|
el,
|
|
@@ -80,8 +110,8 @@ export function createContext(
|
|
|
80
110
|
},
|
|
81
111
|
history: {
|
|
82
112
|
action,
|
|
83
|
-
popstate
|
|
84
|
-
|
|
113
|
+
popstate: false,
|
|
114
|
+
direction: undefined
|
|
85
115
|
},
|
|
86
116
|
scroll: {
|
|
87
117
|
reset,
|