Skip to content

Commit

Permalink
Dedupe middlewares
Browse files Browse the repository at this point in the history
  • Loading branch information
patrikholcak committed Oct 16, 2024
1 parent c5bf7bc commit e579d19
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 2 deletions.
14 changes: 13 additions & 1 deletion shepherd.js/src/step.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@ import {
isUndefined
} from './utils/type-check.ts';
import { bindAdvance } from './utils/bind.ts';
import { parseAttachTo, normalizePrefix, uuid } from './utils/general.ts';
import {
parseAttachTo,
normalizePrefix,
uuid,
dedupeMiddlewares
} from './utils/general.ts';
import {
setupTooltip,
destroyTooltip,
Expand Down Expand Up @@ -522,6 +527,13 @@ export class Step extends Evented {

tourOptions = deepmerge({}, tourOptions || {});

if (tourOptions.floatingUIOptions?.middleware) {
tourOptions.floatingUIOptions.middleware = dedupeMiddlewares(
[...tourOptions.floatingUIOptions.middleware],
options.floatingUIOptions?.middleware
);
}

this.options = Object.assign(
{
arrow: true
Expand Down
7 changes: 6 additions & 1 deletion shepherd.js/src/utils/floating-ui.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { deepmerge } from 'deepmerge-ts';
import { shouldCenterStep } from './general.ts';
import { dedupeMiddlewares, shouldCenterStep } from './general.ts';
import {
autoUpdate,
arrow,
Expand Down Expand Up @@ -202,6 +202,11 @@ export function getFloatingUIOptions(
options.placement = attachToOptions.on;
}

options.middleware = dedupeMiddlewares(
options.middleware,
step.options.floatingUIOptions?.middleware
);

return deepmerge(options, step.options.floatingUIOptions || {});
}

Expand Down
15 changes: 15 additions & 0 deletions shepherd.js/src/utils/general.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
type StepOptions
} from '../step.ts';
import { isFunction, isString } from './type-check.ts';
import type { ComputePositionConfig } from '@floating-ui/dom';

export class StepNoOp {
constructor(_options: StepOptions) {}
Expand Down Expand Up @@ -89,3 +90,17 @@ export function uuid() {
return (c == 'x' ? r : (r & 0x3) | 0x8).toString(16);
});
}

export function dedupeMiddlewares(
defaultMiddlewares?: ComputePositionConfig['middleware'],
stepMiddlewares?: ComputePositionConfig['middleware']
) {
return defaultMiddlewares?.filter(
(defaultMiddleware) =>
!defaultMiddleware ||
!stepMiddlewares?.some(
(stepMiddleware) =>
stepMiddleware && stepMiddleware.name === defaultMiddleware.name
)
);
}
39 changes: 39 additions & 0 deletions test/unit/tour.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,45 @@ describe('Tour | Top-Level Class', function () {

expect(stepsContainer.contains(stepElement)).toBe(true);
});

it.only('deduplicates middlewares', () => {
instance = new Shepherd.Tour({
defaultStepOptions: {
floatingUIOptions: {
middleware: [{ name: 'foo', options: 'bar', fn: (args) => args }]
}
}
});

const step = instance.addStep({
id: 'test',
title: 'This is a test step for our tour',
floatingUIOptions: {
middleware: [{ name: 'foo', options: 'bar', fn: (args) => args }]
}
});

const step2 = instance.addStep({
id: 'test',
title: 'This is a test step for our tour',
floatingUIOptions: {
middleware: [
{ name: 'foo', options: 'bar', fn: (args) => args },
{ name: 'bar', options: 'bar', fn: (args) => args }
]
}
});

instance.start();

const step1FloatingUIOptions = setupTooltip(step);
expect(step1FloatingUIOptions.middleware.length).toBe(1);

instance.next();

const step2FloatingUIOptions = setupTooltip(step2);
expect(step2FloatingUIOptions.middleware.length).toBe(2);
});
});

describe('shepherdModalOverlayContainer', function () {
Expand Down

0 comments on commit e579d19

Please sign in to comment.