Skip to content

Commit f14f5b0

Browse files
authored
Merge pull request #12 from swup/feature/hooks
Wrap content insertion in hooks
2 parents 82ba98b + 883f36e commit f14f5b0

File tree

5 files changed

+88
-28
lines changed

5 files changed

+88
-28
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
<!-- ## [Unreleased] -->
44

5+
## [0.3.0] - 2023-11-22
6+
7+
- Add hooks for inserting and removing containers
8+
59
## [0.2.0] - 2023-08-24
610

711
- Allow keeping the previous container indefinitely

README.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,3 +292,48 @@ swup.hooks.on('visit:start', (visit) => {
292292
}
293293
});
294294
```
295+
296+
## Hooks
297+
298+
The plugin adds two new hooks to swup. Both hooks receive a `ContainerSet` instance as their
299+
only argument:
300+
301+
```ts
302+
type ContainerSet = {
303+
/** Selector to match this container */
304+
selector: string;
305+
/** Incoming container element */
306+
next: HTMLElement;
307+
/** Outgoing container element */
308+
previous: HTMLElement;
309+
/** Container elements to keep around after the animation */
310+
keep: HTMLElement[];
311+
/** Container elements to remove after the animation */
312+
remove: HTMLElement[];
313+
};
314+
```
315+
316+
### `content:insert`
317+
318+
Triggered when the new content containers are inserted. Hook before this to manipulate the
319+
elements before they are inserted into the DOM.
320+
321+
```js
322+
swup.hooks.before('content:insert', (visit, { containers }) => {
323+
for (const { next } of containers) {
324+
console.log('About to insert container', next);
325+
}
326+
});
327+
```
328+
329+
### `content:remove`
330+
331+
Triggered when the previous containers are removed, after the animation has finished.
332+
333+
```js
334+
swup.hooks.before('content:remove', (visit, { containers }) => {
335+
for (const { remove } of containers) {
336+
console.log('About to remove containers', remove);
337+
}
338+
});
339+
```

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "@swup/parallel-plugin",
33
"amdName": "SwupParallelPlugin",
44
"description": "A swup plugin for animating the previous and next page in parallel",
5-
"version": "0.2.0",
5+
"version": "0.3.0",
66
"type": "module",
77
"source": "src/index.ts",
88
"main": "./dist/index.cjs",

src/index.ts

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ import { forceReflow } from 'swup';
33
import Plugin from '@swup/plugin';
44

55
declare module 'swup' {
6+
export interface HookDefinitions {
7+
'content:insert': { containers: ContainerSet[] };
8+
'content:remove': { containers: ContainerSet[] };
9+
}
610
export interface VisitAnimation {
711
/** Parallel visit: run in and out animation at the same time */
812
parallel?: boolean;
@@ -13,7 +17,7 @@ type PluginOptions = {
1317
/** Containers to animate in parallel */
1418
containers: string[];
1519
/** Number of previous containers to keep around after the animation */
16-
keep: number | { [ container: string ]: number };
20+
keep: number | { [container: string]: number };
1721
};
1822

1923
type ContainerSet = {
@@ -57,6 +61,10 @@ export default class SwupParallelPlugin extends Plugin {
5761
this.options.containers = this.swup.options.containers;
5862
}
5963

64+
// Create new hooks
65+
this.swup.hooks.create('content:insert');
66+
this.swup.hooks.create('content:remove');
67+
6068
// On visit: check for containers and mark as parallel visit
6169
// Run after user hooks to allow disabling parallel animations beforehand
6270
this.on('visit:start', this.startVisit, { priority: 1 });
@@ -98,25 +106,28 @@ export default class SwupParallelPlugin extends Plugin {
98106
return;
99107
}
100108

101-
// Get info about parallel containers
102-
this.parallelContainers = this.getParallelContainersForVisit(visit, page);
109+
// Get info about parallel containers and save for later cleanup
110+
const containers = this.getParallelContainersForVisit(visit, page);
111+
this.parallelContainers = containers;
103112

104113
// Replace parallel containers ourselves
105-
for (const { all, next, previous, keep, remove } of this.parallelContainers) {
106-
all.forEach((el, i) => el.style.setProperty('--swup-parallel-container', `${i}`));
107-
previous.setAttribute('aria-hidden', 'true');
108-
previous.before(next);
109-
110-
if (visit.animation.animate) {
111-
next.classList.add('is-next-container');
112-
forceReflow(next);
113-
next.classList.remove('is-next-container');
114+
this.swup.hooks.call('content:insert', { containers }, () => {
115+
for (const { all, next, previous, keep, remove } of containers) {
116+
all.forEach((el, i) => el.style.setProperty('--swup-parallel-container', `${i}`));
117+
previous.setAttribute('aria-hidden', 'true');
118+
previous.before(next);
119+
120+
if (visit.animation.animate) {
121+
next.classList.add('is-next-container');
122+
forceReflow(next);
123+
next.classList.remove('is-next-container');
124+
}
125+
126+
previous.classList.add('is-previous-container');
127+
keep.forEach((el) => el.classList.add('is-kept-container'));
128+
remove.forEach((el) => el.classList.add('is-removing-container'));
114129
}
115-
116-
previous.classList.add('is-previous-container');
117-
keep.forEach((el) => el.classList.add('is-kept-container'));
118-
remove.forEach((el) => el.classList.add('is-removing-container'));
119-
}
130+
});
120131

121132
// Modify visit containers so swup will only replace non-parallel containers
122133
this.originalContainers = visit.containers;
@@ -133,10 +144,13 @@ export default class SwupParallelPlugin extends Plugin {
133144

134145
/** After each visit: remove previous containers */
135146
protected cleanupContainers = () => {
136-
for (const { remove, next } of this.parallelContainers) {
137-
remove.forEach((el) => el.remove());
138-
next.classList.remove('is-next-container');
139-
}
147+
const containers = this.parallelContainers;
148+
this.swup.hooks.call('content:remove', { containers }, () => {
149+
for (const { remove, next } of containers) {
150+
remove.forEach((el) => el.remove());
151+
next.classList.remove('is-next-container');
152+
}
153+
});
140154
this.parallelContainers = [];
141155
};
142156

@@ -188,10 +202,7 @@ export default class SwupParallelPlugin extends Plugin {
188202
protected visitHasPotentialParallelAnimation(visit: Visit) {
189203
// Checking for visit.animation.parallel !== false here allows explicitly
190204
// disabling parallel animations in user hooks before this plugin executes
191-
return (
192-
visit.animation.parallel !== false &&
193-
this.visitHasParallelContainers(visit)
194-
);
205+
return visit.animation.parallel !== false && this.visitHasParallelContainers(visit);
195206
}
196207

197208
/** Check if any of a visit's containers are animated in parallel */

0 commit comments

Comments
 (0)