swup 3.0.3 → 3.0.5

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.
@@ -0,0 +1,71 @@
1
+ import Swup from '../../Swup';
2
+ import { Handler } from '../events';
3
+
4
+ describe('events', () => {
5
+ it('should add event handlers to handlers array', () => {
6
+ const swup = new Swup();
7
+ const handler = jest.fn();
8
+
9
+ swup.on('enabled', handler);
10
+
11
+ expect(swup._handlers.enabled.indexOf(handler)).toBe(0);
12
+ });
13
+
14
+ it('should remove event handlers from handlers array', () => {
15
+ const swup = new Swup();
16
+ const handler = jest.fn();
17
+
18
+ swup.on('enabled', handler);
19
+ swup.on('animationInDone', handler);
20
+ swup.on('animationInStart', handler);
21
+
22
+ expect(swup._handlers.enabled.indexOf(handler)).toBe(0);
23
+ expect(swup._handlers.animationInDone.indexOf(handler)).toBe(0);
24
+ expect(swup._handlers.animationInStart.indexOf(handler)).toBe(0);
25
+
26
+ swup.off('enabled', handler);
27
+ expect(swup._handlers.enabled.indexOf(handler)).toBe(-1);
28
+
29
+ swup.off('animationInDone');
30
+ expect(swup._handlers.animationInDone.indexOf(handler)).toBe(-1);
31
+
32
+ swup.off();
33
+ expect(swup._handlers.animationInStart.indexOf(handler)).toBe(-1);
34
+ });
35
+
36
+ it('should trigger event handler', () => {
37
+ const swup = new Swup();
38
+ const handler = jest.fn();
39
+
40
+ swup.on('enabled', handler);
41
+
42
+ swup.triggerEvent('enabled');
43
+
44
+ expect(handler).toBeCalledTimes(1);
45
+ });
46
+
47
+ it('should trigger event handler with event', () => {
48
+ const swup = new Swup();
49
+ const handler: Handler<'popState'> = jest.fn();
50
+ const event = new PopStateEvent('');
51
+
52
+ swup.on('popState', handler);
53
+ swup.triggerEvent('popState', event);
54
+
55
+ expect(handler).toBeCalledWith(event);
56
+ });
57
+
58
+ it('types work and error when necessary', () => {
59
+ const swup = new Swup();
60
+
61
+ // @ts-expect-no-error
62
+ swup.on('popState', (event: PopStateEvent) => {});
63
+ // @ts-expect-no-error
64
+ swup.triggerEvent('popState', new PopStateEvent(''));
65
+
66
+ // @ts-expect-error
67
+ swup.on('popState', (event: MouseEvent) => {});
68
+ // @ts-expect-error
69
+ swup.triggerEvent('popState', new MouseEvent(''));
70
+ });
71
+ });
@@ -1,42 +1,61 @@
1
1
  import Swup from '../Swup';
2
+ import delegate from 'delegate-it';
2
3
 
3
- export type EventType =
4
- | 'animationInDone'
5
- | 'animationInStart'
6
- | 'animationOutDone'
7
- | 'animationOutStart'
8
- | 'animationSkipped'
9
- | 'clickLink'
10
- | 'contentReplaced'
11
- | 'disabled'
12
- | 'enabled'
13
- | 'openPageInNewTab'
14
- | 'pageLoaded'
15
- | 'pageRetrievedFromCache'
16
- | 'pageView'
17
- | 'popState'
18
- | 'samePage'
19
- | 'samePageWithHash'
20
- | 'serverError'
21
- | 'transitionStart'
22
- | 'transitionEnd'
23
- | 'willReplaceContent';
24
- export type Handler = (event?: Event) => void;
25
- export type Handlers = Record<EventType, Handler[]>;
4
+ type HandlersEventMap = {
5
+ animationInDone: undefined;
6
+ animationInStart: undefined;
7
+ animationOutDone: undefined;
8
+ animationOutStart: undefined;
9
+ animationSkipped: undefined;
10
+ clickLink: delegate.Event<MouseEvent>;
11
+ contentReplaced: PopStateEvent | undefined;
12
+ disabled: undefined;
13
+ enabled: undefined;
14
+ openPageInNewTab: delegate.Event<MouseEvent>;
15
+ pageLoaded: undefined;
16
+ pageRetrievedFromCache: undefined;
17
+ pageView: PopStateEvent | undefined;
18
+ popState: PopStateEvent;
19
+ samePage: delegate.Event<MouseEvent>;
20
+ samePageWithHash: delegate.Event<MouseEvent>;
21
+ serverError: undefined;
22
+ transitionStart: PopStateEvent | undefined;
23
+ transitionEnd: PopStateEvent | undefined;
24
+ willReplaceContent: PopStateEvent | undefined;
25
+ };
26
+ type AvailableEventNames = keyof HandlersEventMap;
26
27
 
27
- export function on(this: Swup, event: EventType, handler: Handler) {
28
- if (this._handlers[event]) {
29
- this._handlers[event].push(handler);
28
+ export type Handler<T extends keyof HandlersEventMap> = (event: HandlersEventMap[T]) => void;
29
+ export type Handlers = {
30
+ [Key in keyof HandlersEventMap]: Handler<Key>[];
31
+ };
32
+
33
+ export function on<TEventType extends AvailableEventNames>(
34
+ this: Swup,
35
+ event: TEventType,
36
+ handler: Handler<TEventType>
37
+ ): void {
38
+ const eventHandlers = this._handlers[event] as Handler<TEventType>[];
39
+
40
+ if (eventHandlers) {
41
+ eventHandlers.push(handler);
30
42
  } else {
31
43
  console.warn(`Unsupported event ${event}.`);
32
44
  }
33
45
  }
34
46
 
35
- export function off(this: Swup, event?: EventType, handler?: Handler) {
47
+ export function off<TEventType extends AvailableEventNames>(
48
+ this: Swup,
49
+ event?: TEventType,
50
+ handler?: Handler<TEventType>
51
+ ) {
36
52
  if (event && handler) {
53
+ const eventHandlers = this._handlers[event] as Handler<TEventType>[];
37
54
  // Remove specific handler
38
- if (this._handlers[event].includes(handler)) {
39
- this._handlers[event] = this._handlers[event].filter((h) => h !== handler);
55
+ if (eventHandlers.includes(handler)) {
56
+ (this._handlers[event] as Handler<TEventType>[]) = eventHandlers.filter(
57
+ (h) => h !== handler
58
+ );
40
59
  } else {
41
60
  console.warn(`Handler for event '${event}' not found.`);
42
61
  }
@@ -46,16 +65,22 @@ export function off(this: Swup, event?: EventType, handler?: Handler) {
46
65
  } else {
47
66
  // Remove all handlers for all events
48
67
  Object.keys(this._handlers).forEach((event) => {
49
- this._handlers[event as EventType] = [];
68
+ this._handlers[event as keyof HandlersEventMap] = [];
50
69
  });
51
70
  }
52
71
  }
53
72
 
54
- export function triggerEvent(this: Swup, eventName: EventType, originalEvent?: Event): void {
73
+ export function triggerEvent<TEventType extends AvailableEventNames>(
74
+ this: Swup,
75
+ eventName: TEventType,
76
+ originalEvent?: HandlersEventMap[TEventType]
77
+ ): void {
78
+ const eventHandlers = this._handlers[eventName] as Handler<TEventType>[];
79
+
55
80
  // call saved handlers with "on" method and pass originalEvent object if available
56
- this._handlers[eventName].forEach((handler) => {
81
+ eventHandlers.forEach((handler) => {
57
82
  try {
58
- handler(originalEvent);
83
+ handler(originalEvent as HandlersEventMap[TEventType]);
59
84
  } catch (error) {
60
85
  console.error(error);
61
86
  }
@@ -9,7 +9,7 @@ export type TransitionOptions = {
9
9
 
10
10
  export type PageLoadOptions = {
11
11
  url: string;
12
- event?: Event;
12
+ event?: PopStateEvent;
13
13
  customTransition?: string;
14
14
  };
15
15
 
@@ -41,6 +41,9 @@ export function performPageLoad(this: Swup, data: PageLoadOptions) {
41
41
  // start/skip animation
42
42
  const animationPromises = this.leavePage({ event, skipTransition });
43
43
 
44
+ // Load page data
45
+ const fetchPromise = this.fetchPage(data);
46
+
44
47
  // create history record if this is not a popstate call (with or without anchor)
45
48
  if (!isHistoryVisit) {
46
49
  createHistoryRecord(url + (this.scrollToElement || ''));
@@ -48,9 +51,6 @@ export function performPageLoad(this: Swup, data: PageLoadOptions) {
48
51
 
49
52
  this.currentPageUrl = getCurrentUrl();
50
53
 
51
- // Load page data
52
- const fetchPromise = this.fetchPage(data);
53
-
54
54
  // when everything is ready, render the page
55
55
  Promise.all<PageRecord | void>([fetchPromise, ...animationPromises])
56
56
  .then(([pageData]) => {
@@ -3,7 +3,7 @@ import Swup from '../Swup';
3
3
  import { PageRecord } from './Cache';
4
4
 
5
5
  export type PageRenderOptions = {
6
- event?: Event;
6
+ event?: PopStateEvent;
7
7
  skipTransition?: boolean;
8
8
  };
9
9