woocommerce/plugins/woocommerce-admin/client/guided-tours/wc-addons-tour/get-config.ts

126 lines
3.2 KiB
TypeScript

/**
* External dependencies
*/
import { TourKitTypes } from '@woocommerce/components';
/**
* Internal dependencies
*/
import { scrollPopperToVisibleAreaIfNeeded } from './utils';
export const getTourConfig = ( {
closeHandler,
onNextStepHandler,
autoScrollBlock,
steps,
}: {
closeHandler: TourKitTypes.CloseHandler;
onNextStepHandler: ( currentStepIndex: number ) => void;
autoScrollBlock: ScrollLogicalPosition;
steps: TourKitTypes.WooStep[];
} ): TourKitTypes.WooConfig => {
let previousPopperTopPosition: number | null = null;
let perviousPopperRef: unknown = null;
const defaultPlacement = 'top-start';
return {
placement: defaultPlacement,
options: {
effects: {
spotlight: {
interactivity: {
enabled: true,
rootElementSelector: '.woocommerce.wc-addons-wrap',
},
},
autoScroll: {
behavior: 'auto',
block: autoScrollBlock,
},
},
popperModifiers: [
{
name: 'arrow',
options: {
padding: ( {
popper,
}: {
popper: { width: number };
} ) => {
return {
// Align the arrow to the left of the popper.
right: popper.width - 34,
};
},
},
},
{
name: 'offset',
options: {
offset: [ 20, 20 ],
},
},
{
name: 'flip',
options: {
allowedAutoPlacements: [ 'right', 'bottom', 'top' ],
fallbackPlacements: [ 'bottom-start', 'right' ],
flipVariations: false,
boundry: 'clippingParents',
},
},
{
name: 'inAppTourPopperModifications',
enabled: true,
phase: 'read',
fn( { state, instance } ) {
// 1. First modification - force `right` placement for items in admin menu.
if ( perviousPopperRef !== state.elements.reference ) {
const isAdminMenuItem = (
state.elements.reference as HTMLElement
).closest( '#adminmenu' );
const desiredPlacement = isAdminMenuItem
? 'right'
: defaultPlacement;
if ( state.placement !== desiredPlacement ) {
instance.setOptions( {
placement: desiredPlacement,
} );
}
}
// 2. Second modification - Try to make sure that the popper is visible once when
// the next step is displayed.
const popperBoundingRect =
state.elements.popper.getBoundingClientRect();
const arrowBoundingRect =
state.elements.arrow?.getBoundingClientRect();
const arrowHeight = arrowBoundingRect?.height || 0;
// Try to make sure that the popper is visible if poppers' reference (step) changed and
// if arrowHeight is not 0 (it means that popper's position hasn't been updated yet).
// Also, change if popper's top position changed - the modifier can be called
// multiple times for the same position.
if (
perviousPopperRef !== state.elements.reference &&
arrowHeight !== 0 &&
previousPopperTopPosition !== popperBoundingRect.top
) {
scrollPopperToVisibleAreaIfNeeded(
popperBoundingRect
);
previousPopperTopPosition = popperBoundingRect.top;
perviousPopperRef = state.elements.reference;
}
},
},
],
callbacks: {
onNextStep: onNextStepHandler,
},
},
steps,
closeHandler,
};
};