Skip to content

Commit

Permalink
Merge pull request #12 from swup/feature/hooks
Browse files Browse the repository at this point in the history
Wrap content insertion in hooks
  • Loading branch information
daun authored Nov 22, 2023
2 parents 82ba98b + 883f36e commit f14f5b0
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 28 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

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

## [0.3.0] - 2023-11-22

- Add hooks for inserting and removing containers

## [0.2.0] - 2023-08-24

- Allow keeping the previous container indefinitely
Expand Down
45 changes: 45 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -292,3 +292,48 @@ swup.hooks.on('visit:start', (visit) => {
}
});
```

## Hooks

The plugin adds two new hooks to swup. Both hooks receive a `ContainerSet` instance as their
only argument:

```ts
type ContainerSet = {
/** Selector to match this container */
selector: string;
/** Incoming container element */
next: HTMLElement;
/** Outgoing container element */
previous: HTMLElement;
/** Container elements to keep around after the animation */
keep: HTMLElement[];
/** Container elements to remove after the animation */
remove: HTMLElement[];
};
```

### `content:insert`

Triggered when the new content containers are inserted. Hook before this to manipulate the
elements before they are inserted into the DOM.

```js
swup.hooks.before('content:insert', (visit, { containers }) => {
for (const { next } of containers) {
console.log('About to insert container', next);
}
});
```

### `content:remove`

Triggered when the previous containers are removed, after the animation has finished.

```js
swup.hooks.before('content:remove', (visit, { containers }) => {
for (const { remove } of containers) {
console.log('About to remove containers', remove);
}
});
```
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@swup/parallel-plugin",
"amdName": "SwupParallelPlugin",
"description": "A swup plugin for animating the previous and next page in parallel",
"version": "0.2.0",
"version": "0.3.0",
"type": "module",
"source": "src/index.ts",
"main": "./dist/index.cjs",
Expand Down
61 changes: 36 additions & 25 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ import { forceReflow } from 'swup';
import Plugin from '@swup/plugin';

declare module 'swup' {
export interface HookDefinitions {
'content:insert': { containers: ContainerSet[] };
'content:remove': { containers: ContainerSet[] };
}
export interface VisitAnimation {
/** Parallel visit: run in and out animation at the same time */
parallel?: boolean;
Expand All @@ -13,7 +17,7 @@ type PluginOptions = {
/** Containers to animate in parallel */
containers: string[];
/** Number of previous containers to keep around after the animation */
keep: number | { [ container: string ]: number };
keep: number | { [container: string]: number };
};

type ContainerSet = {
Expand Down Expand Up @@ -57,6 +61,10 @@ export default class SwupParallelPlugin extends Plugin {
this.options.containers = this.swup.options.containers;
}

// Create new hooks
this.swup.hooks.create('content:insert');
this.swup.hooks.create('content:remove');

// On visit: check for containers and mark as parallel visit
// Run after user hooks to allow disabling parallel animations beforehand
this.on('visit:start', this.startVisit, { priority: 1 });
Expand Down Expand Up @@ -98,25 +106,28 @@ export default class SwupParallelPlugin extends Plugin {
return;
}

// Get info about parallel containers
this.parallelContainers = this.getParallelContainersForVisit(visit, page);
// Get info about parallel containers and save for later cleanup
const containers = this.getParallelContainersForVisit(visit, page);
this.parallelContainers = containers;

// Replace parallel containers ourselves
for (const { all, next, previous, keep, remove } of this.parallelContainers) {
all.forEach((el, i) => el.style.setProperty('--swup-parallel-container', `${i}`));
previous.setAttribute('aria-hidden', 'true');
previous.before(next);

if (visit.animation.animate) {
next.classList.add('is-next-container');
forceReflow(next);
next.classList.remove('is-next-container');
this.swup.hooks.call('content:insert', { containers }, () => {
for (const { all, next, previous, keep, remove } of containers) {
all.forEach((el, i) => el.style.setProperty('--swup-parallel-container', `${i}`));
previous.setAttribute('aria-hidden', 'true');
previous.before(next);

if (visit.animation.animate) {
next.classList.add('is-next-container');
forceReflow(next);
next.classList.remove('is-next-container');
}

previous.classList.add('is-previous-container');
keep.forEach((el) => el.classList.add('is-kept-container'));
remove.forEach((el) => el.classList.add('is-removing-container'));
}

previous.classList.add('is-previous-container');
keep.forEach((el) => el.classList.add('is-kept-container'));
remove.forEach((el) => el.classList.add('is-removing-container'));
}
});

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

/** After each visit: remove previous containers */
protected cleanupContainers = () => {
for (const { remove, next } of this.parallelContainers) {
remove.forEach((el) => el.remove());
next.classList.remove('is-next-container');
}
const containers = this.parallelContainers;
this.swup.hooks.call('content:remove', { containers }, () => {
for (const { remove, next } of containers) {
remove.forEach((el) => el.remove());
next.classList.remove('is-next-container');
}
});
this.parallelContainers = [];
};

Expand Down Expand Up @@ -188,10 +202,7 @@ export default class SwupParallelPlugin extends Plugin {
protected visitHasPotentialParallelAnimation(visit: Visit) {
// Checking for visit.animation.parallel !== false here allows explicitly
// disabling parallel animations in user hooks before this plugin executes
return (
visit.animation.parallel !== false &&
this.visitHasParallelContainers(visit)
);
return visit.animation.parallel !== false && this.visitHasParallelContainers(visit);
}

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

0 comments on commit f14f5b0

Please sign in to comment.