lampuotomatis/public/build/libs/shepherd.js/js/shepherd.esm.js

4596 lines
140 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*! shepherd.js 11.2.0 */
var isMergeableObject = function isMergeableObject(value) {
return isNonNullObject(value) && !isSpecial(value);
};
function isNonNullObject(value) {
return !!value && typeof value === 'object';
}
function isSpecial(value) {
var stringValue = Object.prototype.toString.call(value);
return stringValue === '[object RegExp]' || stringValue === '[object Date]' || isReactElement(value);
}
// see https://github.com/facebook/react/blob/b5ac963fb791d1298e7f396236383bc955f916c1/src/isomorphic/classic/element/ReactElement.js#L21-L25
var canUseSymbol = typeof Symbol === 'function' && Symbol.for;
var REACT_ELEMENT_TYPE = canUseSymbol ? Symbol.for('react.element') : 0xeac7;
function isReactElement(value) {
return value.$$typeof === REACT_ELEMENT_TYPE;
}
function emptyTarget(val) {
return Array.isArray(val) ? [] : {};
}
function cloneUnlessOtherwiseSpecified(value, options) {
return options.clone !== false && options.isMergeableObject(value) ? deepmerge(emptyTarget(value), value, options) : value;
}
function defaultArrayMerge(target, source, options) {
return target.concat(source).map(function (element) {
return cloneUnlessOtherwiseSpecified(element, options);
});
}
function getMergeFunction(key, options) {
if (!options.customMerge) {
return deepmerge;
}
var customMerge = options.customMerge(key);
return typeof customMerge === 'function' ? customMerge : deepmerge;
}
function getEnumerableOwnPropertySymbols(target) {
return Object.getOwnPropertySymbols ? Object.getOwnPropertySymbols(target).filter(function (symbol) {
return Object.propertyIsEnumerable.call(target, symbol);
}) : [];
}
function getKeys(target) {
return Object.keys(target).concat(getEnumerableOwnPropertySymbols(target));
}
function propertyIsOnObject(object, property) {
try {
return property in object;
} catch (_) {
return false;
}
}
// Protects from prototype poisoning and unexpected merging up the prototype chain.
function propertyIsUnsafe(target, key) {
return propertyIsOnObject(target, key) // Properties are safe to merge if they don't exist in the target yet,
&& !(Object.hasOwnProperty.call(target, key) // unsafe if they exist up the prototype chain,
&& Object.propertyIsEnumerable.call(target, key)); // and also unsafe if they're nonenumerable.
}
function mergeObject(target, source, options) {
var destination = {};
if (options.isMergeableObject(target)) {
getKeys(target).forEach(function (key) {
destination[key] = cloneUnlessOtherwiseSpecified(target[key], options);
});
}
getKeys(source).forEach(function (key) {
if (propertyIsUnsafe(target, key)) {
return;
}
if (propertyIsOnObject(target, key) && options.isMergeableObject(source[key])) {
destination[key] = getMergeFunction(key, options)(target[key], source[key], options);
} else {
destination[key] = cloneUnlessOtherwiseSpecified(source[key], options);
}
});
return destination;
}
function deepmerge(target, source, options) {
options = options || {};
options.arrayMerge = options.arrayMerge || defaultArrayMerge;
options.isMergeableObject = options.isMergeableObject || isMergeableObject;
// cloneUnlessOtherwiseSpecified is added to `options` so that custom arrayMerge()
// implementations can use it. The caller may not replace it.
options.cloneUnlessOtherwiseSpecified = cloneUnlessOtherwiseSpecified;
var sourceIsArray = Array.isArray(source);
var targetIsArray = Array.isArray(target);
var sourceAndTargetTypesMatch = sourceIsArray === targetIsArray;
if (!sourceAndTargetTypesMatch) {
return cloneUnlessOtherwiseSpecified(source, options);
} else if (sourceIsArray) {
return options.arrayMerge(target, source, options);
} else {
return mergeObject(target, source, options);
}
}
deepmerge.all = function deepmergeAll(array, options) {
if (!Array.isArray(array)) {
throw new Error('first argument should be an array');
}
return array.reduce(function (prev, next) {
return deepmerge(prev, next, options);
}, {});
};
var deepmerge_1 = deepmerge;
var cjs = deepmerge_1;
/**
* Checks if `value` is classified as an `Element`.
* @param {*} value The param to check if it is an Element
*/
function isElement$1(value) {
return value instanceof Element;
}
/**
* Checks if `value` is classified as an `HTMLElement`.
* @param {*} value The param to check if it is an HTMLElement
*/
function isHTMLElement$1(value) {
return value instanceof HTMLElement;
}
/**
* Checks if `value` is classified as a `Function` object.
* @param {*} value The param to check if it is a function
*/
function isFunction(value) {
return typeof value === 'function';
}
/**
* Checks if `value` is classified as a `String` object.
* @param {*} value The param to check if it is a string
*/
function isString(value) {
return typeof value === 'string';
}
/**
* Checks if `value` is undefined.
* @param {*} value The param to check if it is undefined
*/
function isUndefined(value) {
return value === undefined;
}
class Evented {
on(event, handler, ctx, once = false) {
if (isUndefined(this.bindings)) {
this.bindings = {};
}
if (isUndefined(this.bindings[event])) {
this.bindings[event] = [];
}
this.bindings[event].push({
handler,
ctx,
once
});
return this;
}
once(event, handler, ctx) {
return this.on(event, handler, ctx, true);
}
off(event, handler) {
if (isUndefined(this.bindings) || isUndefined(this.bindings[event])) {
return this;
}
if (isUndefined(handler)) {
delete this.bindings[event];
} else {
this.bindings[event].forEach((binding, index) => {
if (binding.handler === handler) {
this.bindings[event].splice(index, 1);
}
});
}
return this;
}
trigger(event, ...args) {
if (!isUndefined(this.bindings) && this.bindings[event]) {
this.bindings[event].forEach((binding, index) => {
const {
ctx,
handler,
once
} = binding;
const context = ctx || this;
handler.apply(context, args);
if (once) {
this.bindings[event].splice(index, 1);
}
});
}
return this;
}
}
/**
* Binds all the methods on a JS Class to the `this` context of the class.
* Adapted from https://github.com/sindresorhus/auto-bind
* @param {object} self The `this` context of the class
* @return {object} The `this` context of the class
*/
function autoBind(self) {
const keys = Object.getOwnPropertyNames(self.constructor.prototype);
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
const val = self[key];
if (key !== 'constructor' && typeof val === 'function') {
self[key] = val.bind(self);
}
}
return self;
}
/**
* Sets up the handler to determine if we should advance the tour
* @param {string} selector
* @param {Step} step The step instance
* @return {Function}
* @private
*/
function _setupAdvanceOnHandler(selector, step) {
return event => {
if (step.isOpen()) {
const targetIsEl = step.el && event.currentTarget === step.el;
const targetIsSelector = !isUndefined(selector) && event.currentTarget.matches(selector);
if (targetIsSelector || targetIsEl) {
step.tour.next();
}
}
};
}
/**
* Bind the event handler for advanceOn
* @param {Step} step The step instance
*/
function bindAdvance(step) {
// An empty selector matches the step element
const {
event,
selector
} = step.options.advanceOn || {};
if (event) {
const handler = _setupAdvanceOnHandler(selector, step);
// TODO: this should also bind/unbind on show/hide
let el;
try {
el = document.querySelector(selector);
} catch (e) {
// TODO
}
if (!isUndefined(selector) && !el) {
return console.error(`No element was found for the selector supplied to advanceOn: ${selector}`);
} else if (el) {
el.addEventListener(event, handler);
step.on('destroy', () => {
return el.removeEventListener(event, handler);
});
} else {
document.body.addEventListener(event, handler, true);
step.on('destroy', () => {
return document.body.removeEventListener(event, handler, true);
});
}
} else {
return console.error('advanceOn was defined, but no event name was passed.');
}
}
/**
* Ensure class prefix ends in `-`
* @param {string} prefix The prefix to prepend to the class names generated by nano-css
* @return {string} The prefix ending in `-`
*/
function normalizePrefix(prefix) {
if (!isString(prefix) || prefix === '') {
return '';
}
return prefix.charAt(prefix.length - 1) !== '-' ? `${prefix}-` : prefix;
}
/**
* Resolves attachTo options, converting element option value to a qualified HTMLElement.
* @param {Step} step The step instance
* @returns {{}|{element, on}}
* `element` is a qualified HTML Element
* `on` is a string position value
*/
function parseAttachTo(step) {
const options = step.options.attachTo || {};
const returnOpts = Object.assign({}, options);
if (isFunction(returnOpts.element)) {
// Bind the callback to step so that it has access to the object, to enable running additional logic
returnOpts.element = returnOpts.element.call(step);
}
if (isString(returnOpts.element)) {
// Can't override the element in user opts reference because we can't
// guarantee that the element will exist in the future.
try {
returnOpts.element = document.querySelector(returnOpts.element);
} catch (e) {
// TODO
}
if (!returnOpts.element) {
console.error(`The element for this Shepherd step was not found ${options.element}`);
}
}
return returnOpts;
}
/**
* Checks if the step should be centered or not. Does not trigger attachTo.element evaluation, making it a pure
* alternative for the deprecated step.isCentered() method.
* @param resolvedAttachToOptions
* @returns {boolean}
*/
function shouldCenterStep(resolvedAttachToOptions) {
if (resolvedAttachToOptions === undefined || resolvedAttachToOptions === null) {
return true;
}
return !resolvedAttachToOptions.element || !resolvedAttachToOptions.on;
}
/**
* Create a unique id for steps, tours, modals, etc
* @return {string}
*/
function uuid() {
let d = Date.now();
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
const r = (d + Math.random() * 16) % 16 | 0;
d = Math.floor(d / 16);
return (c == 'x' ? r : r & 0x3 | 0x8).toString(16);
});
}
function _extends() {
_extends = Object.assign ? Object.assign.bind() : function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
return _extends.apply(this, arguments);
}
function _objectWithoutPropertiesLoose(source, excluded) {
if (source == null) return {};
var target = {};
var sourceKeys = Object.keys(source);
var key, i;
for (i = 0; i < sourceKeys.length; i++) {
key = sourceKeys[i];
if (excluded.indexOf(key) >= 0) continue;
target[key] = source[key];
}
return target;
}
const min = Math.min;
const max = Math.max;
const round = Math.round;
const floor = Math.floor;
const createCoords = v => ({
x: v,
y: v
});
const oppositeSideMap = {
left: 'right',
right: 'left',
bottom: 'top',
top: 'bottom'
};
const oppositeAlignmentMap = {
start: 'end',
end: 'start'
};
function clamp(start, value, end) {
return max(start, min(value, end));
}
function evaluate(value, param) {
return typeof value === 'function' ? value(param) : value;
}
function getSide(placement) {
return placement.split('-')[0];
}
function getAlignment(placement) {
return placement.split('-')[1];
}
function getOppositeAxis(axis) {
return axis === 'x' ? 'y' : 'x';
}
function getAxisLength(axis) {
return axis === 'y' ? 'height' : 'width';
}
function getSideAxis(placement) {
return ['top', 'bottom'].includes(getSide(placement)) ? 'y' : 'x';
}
function getAlignmentAxis(placement) {
return getOppositeAxis(getSideAxis(placement));
}
function getAlignmentSides(placement, rects, rtl) {
if (rtl === void 0) {
rtl = false;
}
const alignment = getAlignment(placement);
const alignmentAxis = getAlignmentAxis(placement);
const length = getAxisLength(alignmentAxis);
let mainAlignmentSide = alignmentAxis === 'x' ? alignment === (rtl ? 'end' : 'start') ? 'right' : 'left' : alignment === 'start' ? 'bottom' : 'top';
if (rects.reference[length] > rects.floating[length]) {
mainAlignmentSide = getOppositePlacement(mainAlignmentSide);
}
return [mainAlignmentSide, getOppositePlacement(mainAlignmentSide)];
}
function getExpandedPlacements(placement) {
const oppositePlacement = getOppositePlacement(placement);
return [getOppositeAlignmentPlacement(placement), oppositePlacement, getOppositeAlignmentPlacement(oppositePlacement)];
}
function getOppositeAlignmentPlacement(placement) {
return placement.replace(/start|end/g, alignment => oppositeAlignmentMap[alignment]);
}
function getSideList(side, isStart, rtl) {
const lr = ['left', 'right'];
const rl = ['right', 'left'];
const tb = ['top', 'bottom'];
const bt = ['bottom', 'top'];
switch (side) {
case 'top':
case 'bottom':
if (rtl) return isStart ? rl : lr;
return isStart ? lr : rl;
case 'left':
case 'right':
return isStart ? tb : bt;
default:
return [];
}
}
function getOppositeAxisPlacements(placement, flipAlignment, direction, rtl) {
const alignment = getAlignment(placement);
let list = getSideList(getSide(placement), direction === 'start', rtl);
if (alignment) {
list = list.map(side => side + "-" + alignment);
if (flipAlignment) {
list = list.concat(list.map(getOppositeAlignmentPlacement));
}
}
return list;
}
function getOppositePlacement(placement) {
return placement.replace(/left|right|bottom|top/g, side => oppositeSideMap[side]);
}
function expandPaddingObject(padding) {
return _extends({
top: 0,
right: 0,
bottom: 0,
left: 0
}, padding);
}
function getPaddingObject(padding) {
return typeof padding !== 'number' ? expandPaddingObject(padding) : {
top: padding,
right: padding,
bottom: padding,
left: padding
};
}
function rectToClientRect(rect) {
return _extends({}, rect, {
top: rect.y,
left: rect.x,
right: rect.x + rect.width,
bottom: rect.y + rect.height
});
}
const _excluded2 = ["mainAxis", "crossAxis", "fallbackPlacements", "fallbackStrategy", "fallbackAxisSideDirection", "flipAlignment"],
_excluded4 = ["mainAxis", "crossAxis", "limiter"];
function computeCoordsFromPlacement(_ref, placement, rtl) {
let {
reference,
floating
} = _ref;
const sideAxis = getSideAxis(placement);
const alignmentAxis = getAlignmentAxis(placement);
const alignLength = getAxisLength(alignmentAxis);
const side = getSide(placement);
const isVertical = sideAxis === 'y';
const commonX = reference.x + reference.width / 2 - floating.width / 2;
const commonY = reference.y + reference.height / 2 - floating.height / 2;
const commonAlign = reference[alignLength] / 2 - floating[alignLength] / 2;
let coords;
switch (side) {
case 'top':
coords = {
x: commonX,
y: reference.y - floating.height
};
break;
case 'bottom':
coords = {
x: commonX,
y: reference.y + reference.height
};
break;
case 'right':
coords = {
x: reference.x + reference.width,
y: commonY
};
break;
case 'left':
coords = {
x: reference.x - floating.width,
y: commonY
};
break;
default:
coords = {
x: reference.x,
y: reference.y
};
}
switch (getAlignment(placement)) {
case 'start':
coords[alignmentAxis] -= commonAlign * (rtl && isVertical ? -1 : 1);
break;
case 'end':
coords[alignmentAxis] += commonAlign * (rtl && isVertical ? -1 : 1);
break;
}
return coords;
}
/**
* Computes the `x` and `y` coordinates that will place the floating element
* next to a reference element when it is given a certain positioning strategy.
*
* This export does not have any `platform` interface logic. You will need to
* write one for the platform you are using Floating UI with.
*/
const computePosition$1 = async (reference, floating, config) => {
const {
placement = 'bottom',
strategy = 'absolute',
middleware = [],
platform
} = config;
const validMiddleware = middleware.filter(Boolean);
const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(floating));
let rects = await platform.getElementRects({
reference,
floating,
strategy
});
let {
x,
y
} = computeCoordsFromPlacement(rects, placement, rtl);
let statefulPlacement = placement;
let middlewareData = {};
let resetCount = 0;
for (let i = 0; i < validMiddleware.length; i++) {
const {
name,
fn
} = validMiddleware[i];
const {
x: nextX,
y: nextY,
data,
reset
} = await fn({
x,
y,
initialPlacement: placement,
placement: statefulPlacement,
strategy,
middlewareData,
rects,
platform,
elements: {
reference,
floating
}
});
x = nextX != null ? nextX : x;
y = nextY != null ? nextY : y;
middlewareData = _extends({}, middlewareData, {
[name]: _extends({}, middlewareData[name], data)
});
if (reset && resetCount <= 50) {
resetCount++;
if (typeof reset === 'object') {
if (reset.placement) {
statefulPlacement = reset.placement;
}
if (reset.rects) {
rects = reset.rects === true ? await platform.getElementRects({
reference,
floating,
strategy
}) : reset.rects;
}
({
x,
y
} = computeCoordsFromPlacement(rects, statefulPlacement, rtl));
}
i = -1;
continue;
}
}
return {
x,
y,
placement: statefulPlacement,
strategy,
middlewareData
};
};
/**
* Resolves with an object of overflow side offsets that determine how much the
* element is overflowing a given clipping boundary on each side.
* - positive = overflowing the boundary by that number of pixels
* - negative = how many pixels left before it will overflow
* - 0 = lies flush with the boundary
* @see https://floating-ui.com/docs/detectOverflow
*/
async function detectOverflow(state, options) {
var _await$platform$isEle;
if (options === void 0) {
options = {};
}
const {
x,
y,
platform,
rects,
elements,
strategy
} = state;
const {
boundary = 'clippingAncestors',
rootBoundary = 'viewport',
elementContext = 'floating',
altBoundary = false,
padding = 0
} = evaluate(options, state);
const paddingObject = getPaddingObject(padding);
const altContext = elementContext === 'floating' ? 'reference' : 'floating';
const element = elements[altBoundary ? altContext : elementContext];
const clippingClientRect = rectToClientRect(await platform.getClippingRect({
element: ((_await$platform$isEle = await (platform.isElement == null ? void 0 : platform.isElement(element))) != null ? _await$platform$isEle : true) ? element : element.contextElement || (await (platform.getDocumentElement == null ? void 0 : platform.getDocumentElement(elements.floating))),
boundary,
rootBoundary,
strategy
}));
const rect = elementContext === 'floating' ? _extends({}, rects.floating, {
x,
y
}) : rects.reference;
const offsetParent = await (platform.getOffsetParent == null ? void 0 : platform.getOffsetParent(elements.floating));
const offsetScale = (await (platform.isElement == null ? void 0 : platform.isElement(offsetParent))) ? (await (platform.getScale == null ? void 0 : platform.getScale(offsetParent))) || {
x: 1,
y: 1
} : {
x: 1,
y: 1
};
const elementClientRect = rectToClientRect(platform.convertOffsetParentRelativeRectToViewportRelativeRect ? await platform.convertOffsetParentRelativeRectToViewportRelativeRect({
rect,
offsetParent,
strategy
}) : rect);
return {
top: (clippingClientRect.top - elementClientRect.top + paddingObject.top) / offsetScale.y,
bottom: (elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom) / offsetScale.y,
left: (clippingClientRect.left - elementClientRect.left + paddingObject.left) / offsetScale.x,
right: (elementClientRect.right - clippingClientRect.right + paddingObject.right) / offsetScale.x
};
}
/**
* Provides data to position an inner element of the floating element so that it
* appears centered to the reference element.
* @see https://floating-ui.com/docs/arrow
*/
const arrow = options => ({
name: 'arrow',
options,
async fn(state) {
const {
x,
y,
placement,
rects,
platform,
elements
} = state;
// Since `element` is required, we don't Partial<> the type.
const {
element,
padding = 0
} = evaluate(options, state) || {};
if (element == null) {
return {};
}
const paddingObject = getPaddingObject(padding);
const coords = {
x,
y
};
const axis = getAlignmentAxis(placement);
const length = getAxisLength(axis);
const arrowDimensions = await platform.getDimensions(element);
const isYAxis = axis === 'y';
const minProp = isYAxis ? 'top' : 'left';
const maxProp = isYAxis ? 'bottom' : 'right';
const clientProp = isYAxis ? 'clientHeight' : 'clientWidth';
const endDiff = rects.reference[length] + rects.reference[axis] - coords[axis] - rects.floating[length];
const startDiff = coords[axis] - rects.reference[axis];
const arrowOffsetParent = await (platform.getOffsetParent == null ? void 0 : platform.getOffsetParent(element));
let clientSize = arrowOffsetParent ? arrowOffsetParent[clientProp] : 0;
// DOM platform can return `window` as the `offsetParent`.
if (!clientSize || !(await (platform.isElement == null ? void 0 : platform.isElement(arrowOffsetParent)))) {
clientSize = elements.floating[clientProp] || rects.floating[length];
}
const centerToReference = endDiff / 2 - startDiff / 2;
// If the padding is large enough that it causes the arrow to no longer be
// centered, modify the padding so that it is centered.
const largestPossiblePadding = clientSize / 2 - arrowDimensions[length] / 2 - 1;
const minPadding = min(paddingObject[minProp], largestPossiblePadding);
const maxPadding = min(paddingObject[maxProp], largestPossiblePadding);
// Make sure the arrow doesn't overflow the floating element if the center
// point is outside the floating element's bounds.
const min$1 = minPadding;
const max = clientSize - arrowDimensions[length] - maxPadding;
const center = clientSize / 2 - arrowDimensions[length] / 2 + centerToReference;
const offset = clamp(min$1, center, max);
// If the reference is small enough that the arrow's padding causes it to
// to point to nothing for an aligned placement, adjust the offset of the
// floating element itself. This stops `shift()` from taking action, but can
// be worked around by calling it again after the `arrow()` if desired.
const shouldAddOffset = getAlignment(placement) != null && center != offset && rects.reference[length] / 2 - (center < min$1 ? minPadding : maxPadding) - arrowDimensions[length] / 2 < 0;
const alignmentOffset = shouldAddOffset ? center < min$1 ? min$1 - center : max - center : 0;
return {
[axis]: coords[axis] - alignmentOffset,
data: {
[axis]: offset,
centerOffset: center - offset + alignmentOffset
}
};
}
});
/**
* Optimizes the visibility of the floating element by flipping the `placement`
* in order to keep it in view when the preferred placement(s) will overflow the
* clipping boundary. Alternative to `autoPlacement`.
* @see https://floating-ui.com/docs/flip
*/
const flip = function flip(options) {
if (options === void 0) {
options = {};
}
return {
name: 'flip',
options,
async fn(state) {
var _middlewareData$flip;
const {
placement,
middlewareData,
rects,
initialPlacement,
platform,
elements
} = state;
const _evaluate2 = evaluate(options, state),
{
mainAxis: checkMainAxis = true,
crossAxis: checkCrossAxis = true,
fallbackPlacements: specifiedFallbackPlacements,
fallbackStrategy = 'bestFit',
fallbackAxisSideDirection = 'none',
flipAlignment = true
} = _evaluate2,
detectOverflowOptions = _objectWithoutPropertiesLoose(_evaluate2, _excluded2);
const side = getSide(placement);
const isBasePlacement = getSide(initialPlacement) === initialPlacement;
const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating));
const fallbackPlacements = specifiedFallbackPlacements || (isBasePlacement || !flipAlignment ? [getOppositePlacement(initialPlacement)] : getExpandedPlacements(initialPlacement));
if (!specifiedFallbackPlacements && fallbackAxisSideDirection !== 'none') {
fallbackPlacements.push(...getOppositeAxisPlacements(initialPlacement, flipAlignment, fallbackAxisSideDirection, rtl));
}
const placements = [initialPlacement, ...fallbackPlacements];
const overflow = await detectOverflow(state, detectOverflowOptions);
const overflows = [];
let overflowsData = ((_middlewareData$flip = middlewareData.flip) == null ? void 0 : _middlewareData$flip.overflows) || [];
if (checkMainAxis) {
overflows.push(overflow[side]);
}
if (checkCrossAxis) {
const sides = getAlignmentSides(placement, rects, rtl);
overflows.push(overflow[sides[0]], overflow[sides[1]]);
}
overflowsData = [...overflowsData, {
placement,
overflows
}];
// One or more sides is overflowing.
if (!overflows.every(side => side <= 0)) {
var _middlewareData$flip2, _overflowsData$filter;
const nextIndex = (((_middlewareData$flip2 = middlewareData.flip) == null ? void 0 : _middlewareData$flip2.index) || 0) + 1;
const nextPlacement = placements[nextIndex];
if (nextPlacement) {
// Try next placement and re-run the lifecycle.
return {
data: {
index: nextIndex,
overflows: overflowsData
},
reset: {
placement: nextPlacement
}
};
}
// First, find the candidates that fit on the mainAxis side of overflow,
// then find the placement that fits the best on the main crossAxis side.
let resetPlacement = (_overflowsData$filter = overflowsData.filter(d => d.overflows[0] <= 0).sort((a, b) => a.overflows[1] - b.overflows[1])[0]) == null ? void 0 : _overflowsData$filter.placement;
// Otherwise fallback.
if (!resetPlacement) {
switch (fallbackStrategy) {
case 'bestFit':
{
var _overflowsData$map$so;
const placement = (_overflowsData$map$so = overflowsData.map(d => [d.placement, d.overflows.filter(overflow => overflow > 0).reduce((acc, overflow) => acc + overflow, 0)]).sort((a, b) => a[1] - b[1])[0]) == null ? void 0 : _overflowsData$map$so[0];
if (placement) {
resetPlacement = placement;
}
break;
}
case 'initialPlacement':
resetPlacement = initialPlacement;
break;
}
}
if (placement !== resetPlacement) {
return {
reset: {
placement: resetPlacement
}
};
}
}
return {};
}
};
};
/**
* Optimizes the visibility of the floating element by shifting it in order to
* keep it in view when it will overflow the clipping boundary.
* @see https://floating-ui.com/docs/shift
*/
const shift = function shift(options) {
if (options === void 0) {
options = {};
}
return {
name: 'shift',
options,
async fn(state) {
const {
x,
y,
placement
} = state;
const _evaluate4 = evaluate(options, state),
{
mainAxis: checkMainAxis = true,
crossAxis: checkCrossAxis = false,
limiter = {
fn: _ref => {
let {
x,
y
} = _ref;
return {
x,
y
};
}
}
} = _evaluate4,
detectOverflowOptions = _objectWithoutPropertiesLoose(_evaluate4, _excluded4);
const coords = {
x,
y
};
const overflow = await detectOverflow(state, detectOverflowOptions);
const crossAxis = getSideAxis(getSide(placement));
const mainAxis = getOppositeAxis(crossAxis);
let mainAxisCoord = coords[mainAxis];
let crossAxisCoord = coords[crossAxis];
if (checkMainAxis) {
const minSide = mainAxis === 'y' ? 'top' : 'left';
const maxSide = mainAxis === 'y' ? 'bottom' : 'right';
const min = mainAxisCoord + overflow[minSide];
const max = mainAxisCoord - overflow[maxSide];
mainAxisCoord = clamp(min, mainAxisCoord, max);
}
if (checkCrossAxis) {
const minSide = crossAxis === 'y' ? 'top' : 'left';
const maxSide = crossAxis === 'y' ? 'bottom' : 'right';
const min = crossAxisCoord + overflow[minSide];
const max = crossAxisCoord - overflow[maxSide];
crossAxisCoord = clamp(min, crossAxisCoord, max);
}
const limitedCoords = limiter.fn(_extends({}, state, {
[mainAxis]: mainAxisCoord,
[crossAxis]: crossAxisCoord
}));
return _extends({}, limitedCoords, {
data: {
x: limitedCoords.x - x,
y: limitedCoords.y - y
}
});
}
};
};
/**
* Built-in `limiter` that will stop `shift()` at a certain point.
*/
const limitShift = function limitShift(options) {
if (options === void 0) {
options = {};
}
return {
options,
fn(state) {
const {
x,
y,
placement,
rects,
middlewareData
} = state;
const {
offset = 0,
mainAxis: checkMainAxis = true,
crossAxis: checkCrossAxis = true
} = evaluate(options, state);
const coords = {
x,
y
};
const crossAxis = getSideAxis(placement);
const mainAxis = getOppositeAxis(crossAxis);
let mainAxisCoord = coords[mainAxis];
let crossAxisCoord = coords[crossAxis];
const rawOffset = evaluate(offset, state);
const computedOffset = typeof rawOffset === 'number' ? {
mainAxis: rawOffset,
crossAxis: 0
} : _extends({
mainAxis: 0,
crossAxis: 0
}, rawOffset);
if (checkMainAxis) {
const len = mainAxis === 'y' ? 'height' : 'width';
const limitMin = rects.reference[mainAxis] - rects.floating[len] + computedOffset.mainAxis;
const limitMax = rects.reference[mainAxis] + rects.reference[len] - computedOffset.mainAxis;
if (mainAxisCoord < limitMin) {
mainAxisCoord = limitMin;
} else if (mainAxisCoord > limitMax) {
mainAxisCoord = limitMax;
}
}
if (checkCrossAxis) {
var _middlewareData$offse, _middlewareData$offse2;
const len = mainAxis === 'y' ? 'width' : 'height';
const isOriginSide = ['top', 'left'].includes(getSide(placement));
const limitMin = rects.reference[crossAxis] - rects.floating[len] + (isOriginSide ? ((_middlewareData$offse = middlewareData.offset) == null ? void 0 : _middlewareData$offse[crossAxis]) || 0 : 0) + (isOriginSide ? 0 : computedOffset.crossAxis);
const limitMax = rects.reference[crossAxis] + rects.reference[len] + (isOriginSide ? 0 : ((_middlewareData$offse2 = middlewareData.offset) == null ? void 0 : _middlewareData$offse2[crossAxis]) || 0) - (isOriginSide ? computedOffset.crossAxis : 0);
if (crossAxisCoord < limitMin) {
crossAxisCoord = limitMin;
} else if (crossAxisCoord > limitMax) {
crossAxisCoord = limitMax;
}
}
return {
[mainAxis]: mainAxisCoord,
[crossAxis]: crossAxisCoord
};
}
};
};
function getNodeName(node) {
if (isNode(node)) {
return (node.nodeName || '').toLowerCase();
}
// Mocked nodes in testing environments may not be instances of Node. By
// returning `#document` an infinite loop won't occur.
// https://github.com/floating-ui/floating-ui/issues/2317
return '#document';
}
function getWindow(node) {
var _node$ownerDocument;
return (node == null ? void 0 : (_node$ownerDocument = node.ownerDocument) == null ? void 0 : _node$ownerDocument.defaultView) || window;
}
function getDocumentElement(node) {
var _ref;
return (_ref = (isNode(node) ? node.ownerDocument : node.document) || window.document) == null ? void 0 : _ref.documentElement;
}
function isNode(value) {
return value instanceof Node || value instanceof getWindow(value).Node;
}
function isElement(value) {
return value instanceof Element || value instanceof getWindow(value).Element;
}
function isHTMLElement(value) {
return value instanceof HTMLElement || value instanceof getWindow(value).HTMLElement;
}
function isShadowRoot(value) {
// Browsers without `ShadowRoot` support.
if (typeof ShadowRoot === 'undefined') {
return false;
}
return value instanceof ShadowRoot || value instanceof getWindow(value).ShadowRoot;
}
function isOverflowElement(element) {
const {
overflow,
overflowX,
overflowY,
display
} = getComputedStyle(element);
return /auto|scroll|overlay|hidden|clip/.test(overflow + overflowY + overflowX) && !['inline', 'contents'].includes(display);
}
function isTableElement(element) {
return ['table', 'td', 'th'].includes(getNodeName(element));
}
function isContainingBlock(element) {
const webkit = isWebKit();
const css = getComputedStyle(element);
// https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block
return css.transform !== 'none' || css.perspective !== 'none' || (css.containerType ? css.containerType !== 'normal' : false) || !webkit && (css.backdropFilter ? css.backdropFilter !== 'none' : false) || !webkit && (css.filter ? css.filter !== 'none' : false) || ['transform', 'perspective', 'filter'].some(value => (css.willChange || '').includes(value)) || ['paint', 'layout', 'strict', 'content'].some(value => (css.contain || '').includes(value));
}
function getContainingBlock(element) {
let currentNode = getParentNode(element);
while (isHTMLElement(currentNode) && !isLastTraversableNode(currentNode)) {
if (isContainingBlock(currentNode)) {
return currentNode;
} else {
currentNode = getParentNode(currentNode);
}
}
return null;
}
function isWebKit() {
if (typeof CSS === 'undefined' || !CSS.supports) return false;
return CSS.supports('-webkit-backdrop-filter', 'none');
}
function isLastTraversableNode(node) {
return ['html', 'body', '#document'].includes(getNodeName(node));
}
function getComputedStyle(element) {
return getWindow(element).getComputedStyle(element);
}
function getNodeScroll(element) {
if (isElement(element)) {
return {
scrollLeft: element.scrollLeft,
scrollTop: element.scrollTop
};
}
return {
scrollLeft: element.pageXOffset,
scrollTop: element.pageYOffset
};
}
function getParentNode(node) {
if (getNodeName(node) === 'html') {
return node;
}
const result =
// Step into the shadow DOM of the parent of a slotted node.
node.assignedSlot ||
// DOM Element detected.
node.parentNode ||
// ShadowRoot detected.
isShadowRoot(node) && node.host ||
// Fallback.
getDocumentElement(node);
return isShadowRoot(result) ? result.host : result;
}
function getNearestOverflowAncestor(node) {
const parentNode = getParentNode(node);
if (isLastTraversableNode(parentNode)) {
return node.ownerDocument ? node.ownerDocument.body : node.body;
}
if (isHTMLElement(parentNode) && isOverflowElement(parentNode)) {
return parentNode;
}
return getNearestOverflowAncestor(parentNode);
}
function getOverflowAncestors(node, list) {
var _node$ownerDocument2;
if (list === void 0) {
list = [];
}
const scrollableAncestor = getNearestOverflowAncestor(node);
const isBody = scrollableAncestor === ((_node$ownerDocument2 = node.ownerDocument) == null ? void 0 : _node$ownerDocument2.body);
const win = getWindow(scrollableAncestor);
if (isBody) {
return list.concat(win, win.visualViewport || [], isOverflowElement(scrollableAncestor) ? scrollableAncestor : []);
}
return list.concat(scrollableAncestor, getOverflowAncestors(scrollableAncestor));
}
function getCssDimensions(element) {
const css = getComputedStyle(element);
// In testing environments, the `width` and `height` properties are empty
// strings for SVG elements, returning NaN. Fallback to `0` in this case.
let width = parseFloat(css.width) || 0;
let height = parseFloat(css.height) || 0;
const hasOffset = isHTMLElement(element);
const offsetWidth = hasOffset ? element.offsetWidth : width;
const offsetHeight = hasOffset ? element.offsetHeight : height;
const shouldFallback = round(width) !== offsetWidth || round(height) !== offsetHeight;
if (shouldFallback) {
width = offsetWidth;
height = offsetHeight;
}
return {
width,
height,
$: shouldFallback
};
}
function unwrapElement(element) {
return !isElement(element) ? element.contextElement : element;
}
function getScale(element) {
const domElement = unwrapElement(element);
if (!isHTMLElement(domElement)) {
return createCoords(1);
}
const rect = domElement.getBoundingClientRect();
const {
width,
height,
$
} = getCssDimensions(domElement);
let x = ($ ? round(rect.width) : rect.width) / width;
let y = ($ ? round(rect.height) : rect.height) / height;
// 0, NaN, or Infinity should always fallback to 1.
if (!x || !Number.isFinite(x)) {
x = 1;
}
if (!y || !Number.isFinite(y)) {
y = 1;
}
return {
x,
y
};
}
const noOffsets = /*#__PURE__*/createCoords(0);
function getVisualOffsets(element) {
const win = getWindow(element);
if (!isWebKit() || !win.visualViewport) {
return noOffsets;
}
return {
x: win.visualViewport.offsetLeft,
y: win.visualViewport.offsetTop
};
}
function shouldAddVisualOffsets(element, isFixed, floatingOffsetParent) {
if (isFixed === void 0) {
isFixed = false;
}
if (!floatingOffsetParent || isFixed && floatingOffsetParent !== getWindow(element)) {
return false;
}
return isFixed;
}
function getBoundingClientRect(element, includeScale, isFixedStrategy, offsetParent) {
if (includeScale === void 0) {
includeScale = false;
}
if (isFixedStrategy === void 0) {
isFixedStrategy = false;
}
const clientRect = element.getBoundingClientRect();
const domElement = unwrapElement(element);
let scale = createCoords(1);
if (includeScale) {
if (offsetParent) {
if (isElement(offsetParent)) {
scale = getScale(offsetParent);
}
} else {
scale = getScale(element);
}
}
const visualOffsets = shouldAddVisualOffsets(domElement, isFixedStrategy, offsetParent) ? getVisualOffsets(domElement) : createCoords(0);
let x = (clientRect.left + visualOffsets.x) / scale.x;
let y = (clientRect.top + visualOffsets.y) / scale.y;
let width = clientRect.width / scale.x;
let height = clientRect.height / scale.y;
if (domElement) {
const win = getWindow(domElement);
const offsetWin = offsetParent && isElement(offsetParent) ? getWindow(offsetParent) : offsetParent;
let currentIFrame = win.frameElement;
while (currentIFrame && offsetParent && offsetWin !== win) {
const iframeScale = getScale(currentIFrame);
const iframeRect = currentIFrame.getBoundingClientRect();
const css = getComputedStyle(currentIFrame);
const left = iframeRect.left + (currentIFrame.clientLeft + parseFloat(css.paddingLeft)) * iframeScale.x;
const top = iframeRect.top + (currentIFrame.clientTop + parseFloat(css.paddingTop)) * iframeScale.y;
x *= iframeScale.x;
y *= iframeScale.y;
width *= iframeScale.x;
height *= iframeScale.y;
x += left;
y += top;
currentIFrame = getWindow(currentIFrame).frameElement;
}
}
return rectToClientRect({
width,
height,
x,
y
});
}
function convertOffsetParentRelativeRectToViewportRelativeRect(_ref) {
let {
rect,
offsetParent,
strategy
} = _ref;
const isOffsetParentAnElement = isHTMLElement(offsetParent);
const documentElement = getDocumentElement(offsetParent);
if (offsetParent === documentElement) {
return rect;
}
let scroll = {
scrollLeft: 0,
scrollTop: 0
};
let scale = createCoords(1);
const offsets = createCoords(0);
if (isOffsetParentAnElement || !isOffsetParentAnElement && strategy !== 'fixed') {
if (getNodeName(offsetParent) !== 'body' || isOverflowElement(documentElement)) {
scroll = getNodeScroll(offsetParent);
}
if (isHTMLElement(offsetParent)) {
const offsetRect = getBoundingClientRect(offsetParent);
scale = getScale(offsetParent);
offsets.x = offsetRect.x + offsetParent.clientLeft;
offsets.y = offsetRect.y + offsetParent.clientTop;
}
}
return {
width: rect.width * scale.x,
height: rect.height * scale.y,
x: rect.x * scale.x - scroll.scrollLeft * scale.x + offsets.x,
y: rect.y * scale.y - scroll.scrollTop * scale.y + offsets.y
};
}
function getClientRects(element) {
return Array.from(element.getClientRects());
}
function getWindowScrollBarX(element) {
// If <html> has a CSS width greater than the viewport, then this will be
// incorrect for RTL.
return getBoundingClientRect(getDocumentElement(element)).left + getNodeScroll(element).scrollLeft;
}
// Gets the entire size of the scrollable document area, even extending outside
// of the `<html>` and `<body>` rect bounds if horizontally scrollable.
function getDocumentRect(element) {
const html = getDocumentElement(element);
const scroll = getNodeScroll(element);
const body = element.ownerDocument.body;
const width = max(html.scrollWidth, html.clientWidth, body.scrollWidth, body.clientWidth);
const height = max(html.scrollHeight, html.clientHeight, body.scrollHeight, body.clientHeight);
let x = -scroll.scrollLeft + getWindowScrollBarX(element);
const y = -scroll.scrollTop;
if (getComputedStyle(body).direction === 'rtl') {
x += max(html.clientWidth, body.clientWidth) - width;
}
return {
width,
height,
x,
y
};
}
function getViewportRect(element, strategy) {
const win = getWindow(element);
const html = getDocumentElement(element);
const visualViewport = win.visualViewport;
let width = html.clientWidth;
let height = html.clientHeight;
let x = 0;
let y = 0;
if (visualViewport) {
width = visualViewport.width;
height = visualViewport.height;
const visualViewportBased = isWebKit();
if (!visualViewportBased || visualViewportBased && strategy === 'fixed') {
x = visualViewport.offsetLeft;
y = visualViewport.offsetTop;
}
}
return {
width,
height,
x,
y
};
}
// Returns the inner client rect, subtracting scrollbars if present.
function getInnerBoundingClientRect(element, strategy) {
const clientRect = getBoundingClientRect(element, true, strategy === 'fixed');
const top = clientRect.top + element.clientTop;
const left = clientRect.left + element.clientLeft;
const scale = isHTMLElement(element) ? getScale(element) : createCoords(1);
const width = element.clientWidth * scale.x;
const height = element.clientHeight * scale.y;
const x = left * scale.x;
const y = top * scale.y;
return {
width,
height,
x,
y
};
}
function getClientRectFromClippingAncestor(element, clippingAncestor, strategy) {
let rect;
if (clippingAncestor === 'viewport') {
rect = getViewportRect(element, strategy);
} else if (clippingAncestor === 'document') {
rect = getDocumentRect(getDocumentElement(element));
} else if (isElement(clippingAncestor)) {
rect = getInnerBoundingClientRect(clippingAncestor, strategy);
} else {
const visualOffsets = getVisualOffsets(element);
rect = _extends({}, clippingAncestor, {
x: clippingAncestor.x - visualOffsets.x,
y: clippingAncestor.y - visualOffsets.y
});
}
return rectToClientRect(rect);
}
function hasFixedPositionAncestor(element, stopNode) {
const parentNode = getParentNode(element);
if (parentNode === stopNode || !isElement(parentNode) || isLastTraversableNode(parentNode)) {
return false;
}
return getComputedStyle(parentNode).position === 'fixed' || hasFixedPositionAncestor(parentNode, stopNode);
}
// A "clipping ancestor" is an `overflow` element with the characteristic of
// clipping (or hiding) child elements. This returns all clipping ancestors
// of the given element up the tree.
function getClippingElementAncestors(element, cache) {
const cachedResult = cache.get(element);
if (cachedResult) {
return cachedResult;
}
let result = getOverflowAncestors(element).filter(el => isElement(el) && getNodeName(el) !== 'body');
let currentContainingBlockComputedStyle = null;
const elementIsFixed = getComputedStyle(element).position === 'fixed';
let currentNode = elementIsFixed ? getParentNode(element) : element;
// https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block
while (isElement(currentNode) && !isLastTraversableNode(currentNode)) {
const computedStyle = getComputedStyle(currentNode);
const currentNodeIsContaining = isContainingBlock(currentNode);
if (!currentNodeIsContaining && computedStyle.position === 'fixed') {
currentContainingBlockComputedStyle = null;
}
const shouldDropCurrentNode = elementIsFixed ? !currentNodeIsContaining && !currentContainingBlockComputedStyle : !currentNodeIsContaining && computedStyle.position === 'static' && !!currentContainingBlockComputedStyle && ['absolute', 'fixed'].includes(currentContainingBlockComputedStyle.position) || isOverflowElement(currentNode) && !currentNodeIsContaining && hasFixedPositionAncestor(element, currentNode);
if (shouldDropCurrentNode) {
// Drop non-containing blocks.
result = result.filter(ancestor => ancestor !== currentNode);
} else {
// Record last containing block for next iteration.
currentContainingBlockComputedStyle = computedStyle;
}
currentNode = getParentNode(currentNode);
}
cache.set(element, result);
return result;
}
// Gets the maximum area that the element is visible in due to any number of
// clipping ancestors.
function getClippingRect(_ref) {
let {
element,
boundary,
rootBoundary,
strategy
} = _ref;
const elementClippingAncestors = boundary === 'clippingAncestors' ? getClippingElementAncestors(element, this._c) : [].concat(boundary);
const clippingAncestors = [...elementClippingAncestors, rootBoundary];
const firstClippingAncestor = clippingAncestors[0];
const clippingRect = clippingAncestors.reduce((accRect, clippingAncestor) => {
const rect = getClientRectFromClippingAncestor(element, clippingAncestor, strategy);
accRect.top = max(rect.top, accRect.top);
accRect.right = min(rect.right, accRect.right);
accRect.bottom = min(rect.bottom, accRect.bottom);
accRect.left = max(rect.left, accRect.left);
return accRect;
}, getClientRectFromClippingAncestor(element, firstClippingAncestor, strategy));
return {
width: clippingRect.right - clippingRect.left,
height: clippingRect.bottom - clippingRect.top,
x: clippingRect.left,
y: clippingRect.top
};
}
function getDimensions(element) {
return getCssDimensions(element);
}
function getRectRelativeToOffsetParent(element, offsetParent, strategy) {
const isOffsetParentAnElement = isHTMLElement(offsetParent);
const documentElement = getDocumentElement(offsetParent);
const isFixed = strategy === 'fixed';
const rect = getBoundingClientRect(element, true, isFixed, offsetParent);
let scroll = {
scrollLeft: 0,
scrollTop: 0
};
const offsets = createCoords(0);
if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {
if (getNodeName(offsetParent) !== 'body' || isOverflowElement(documentElement)) {
scroll = getNodeScroll(offsetParent);
}
if (isOffsetParentAnElement) {
const offsetRect = getBoundingClientRect(offsetParent, true, isFixed, offsetParent);
offsets.x = offsetRect.x + offsetParent.clientLeft;
offsets.y = offsetRect.y + offsetParent.clientTop;
} else if (documentElement) {
offsets.x = getWindowScrollBarX(documentElement);
}
}
return {
x: rect.left + scroll.scrollLeft - offsets.x,
y: rect.top + scroll.scrollTop - offsets.y,
width: rect.width,
height: rect.height
};
}
function getTrueOffsetParent(element, polyfill) {
if (!isHTMLElement(element) || getComputedStyle(element).position === 'fixed') {
return null;
}
if (polyfill) {
return polyfill(element);
}
return element.offsetParent;
}
// Gets the closest ancestor positioned element. Handles some edge cases,
// such as table ancestors and cross browser bugs.
function getOffsetParent(element, polyfill) {
const window = getWindow(element);
if (!isHTMLElement(element)) {
return window;
}
let offsetParent = getTrueOffsetParent(element, polyfill);
while (offsetParent && isTableElement(offsetParent) && getComputedStyle(offsetParent).position === 'static') {
offsetParent = getTrueOffsetParent(offsetParent, polyfill);
}
if (offsetParent && (getNodeName(offsetParent) === 'html' || getNodeName(offsetParent) === 'body' && getComputedStyle(offsetParent).position === 'static' && !isContainingBlock(offsetParent))) {
return window;
}
return offsetParent || getContainingBlock(element) || window;
}
const getElementRects = async function getElementRects(_ref) {
let {
reference,
floating,
strategy
} = _ref;
const getOffsetParentFn = this.getOffsetParent || getOffsetParent;
const getDimensionsFn = this.getDimensions;
return {
reference: getRectRelativeToOffsetParent(reference, await getOffsetParentFn(floating), strategy),
floating: _extends({
x: 0,
y: 0
}, await getDimensionsFn(floating))
};
};
function isRTL(element) {
return getComputedStyle(element).direction === 'rtl';
}
const platform = {
convertOffsetParentRelativeRectToViewportRelativeRect,
getDocumentElement,
getClippingRect,
getOffsetParent,
getElementRects,
getClientRects,
getDimensions,
getScale,
isElement,
isRTL
};
// https://samthor.au/2021/observing-dom/
function observeMove(element, onMove) {
let io = null;
let timeoutId;
const root = getDocumentElement(element);
function cleanup() {
clearTimeout(timeoutId);
io && io.disconnect();
io = null;
}
function refresh(skip, threshold) {
if (skip === void 0) {
skip = false;
}
if (threshold === void 0) {
threshold = 1;
}
cleanup();
const {
left,
top,
width,
height
} = element.getBoundingClientRect();
if (!skip) {
onMove();
}
if (!width || !height) {
return;
}
const insetTop = floor(top);
const insetRight = floor(root.clientWidth - (left + width));
const insetBottom = floor(root.clientHeight - (top + height));
const insetLeft = floor(left);
const rootMargin = -insetTop + "px " + -insetRight + "px " + -insetBottom + "px " + -insetLeft + "px";
const options = {
rootMargin,
threshold: max(0, min(1, threshold)) || 1
};
let isFirstUpdate = true;
function handleObserve(entries) {
const ratio = entries[0].intersectionRatio;
if (ratio !== threshold) {
if (!isFirstUpdate) {
return refresh();
}
if (!ratio) {
timeoutId = setTimeout(() => {
refresh(false, 1e-7);
}, 100);
} else {
refresh(false, ratio);
}
}
isFirstUpdate = false;
}
// Older browsers don't support a `document` as the root and will throw an
// error.
try {
io = new IntersectionObserver(handleObserve, _extends({}, options, {
// Handle <iframe>s
root: root.ownerDocument
}));
} catch (e) {
io = new IntersectionObserver(handleObserve, options);
}
io.observe(element);
}
refresh(true);
return cleanup;
}
/**
* Automatically updates the position of the floating element when necessary.
* Should only be called when the floating element is mounted on the DOM or
* visible on the screen.
* @returns cleanup function that should be invoked when the floating element is
* removed from the DOM or hidden from the screen.
* @see https://floating-ui.com/docs/autoUpdate
*/
function autoUpdate(reference, floating, update, options) {
if (options === void 0) {
options = {};
}
const {
ancestorScroll = true,
ancestorResize = true,
elementResize = typeof ResizeObserver === 'function',
layoutShift = typeof IntersectionObserver === 'function',
animationFrame = false
} = options;
const referenceEl = unwrapElement(reference);
const ancestors = ancestorScroll || ancestorResize ? [...(referenceEl ? getOverflowAncestors(referenceEl) : []), ...getOverflowAncestors(floating)] : [];
ancestors.forEach(ancestor => {
ancestorScroll && ancestor.addEventListener('scroll', update, {
passive: true
});
ancestorResize && ancestor.addEventListener('resize', update);
});
const cleanupIo = referenceEl && layoutShift ? observeMove(referenceEl, update) : null;
let reobserveFrame = -1;
let resizeObserver = null;
if (elementResize) {
resizeObserver = new ResizeObserver(_ref => {
let [firstEntry] = _ref;
if (firstEntry && firstEntry.target === referenceEl && resizeObserver) {
// Prevent update loops when using the `size` middleware.
// https://github.com/floating-ui/floating-ui/issues/1740
resizeObserver.unobserve(floating);
cancelAnimationFrame(reobserveFrame);
reobserveFrame = requestAnimationFrame(() => {
resizeObserver && resizeObserver.observe(floating);
});
}
update();
});
if (referenceEl && !animationFrame) {
resizeObserver.observe(referenceEl);
}
resizeObserver.observe(floating);
}
let frameId;
let prevRefRect = animationFrame ? getBoundingClientRect(reference) : null;
if (animationFrame) {
frameLoop();
}
function frameLoop() {
const nextRefRect = getBoundingClientRect(reference);
if (prevRefRect && (nextRefRect.x !== prevRefRect.x || nextRefRect.y !== prevRefRect.y || nextRefRect.width !== prevRefRect.width || nextRefRect.height !== prevRefRect.height)) {
update();
}
prevRefRect = nextRefRect;
frameId = requestAnimationFrame(frameLoop);
}
update();
return () => {
ancestors.forEach(ancestor => {
ancestorScroll && ancestor.removeEventListener('scroll', update);
ancestorResize && ancestor.removeEventListener('resize', update);
});
cleanupIo && cleanupIo();
resizeObserver && resizeObserver.disconnect();
resizeObserver = null;
if (animationFrame) {
cancelAnimationFrame(frameId);
}
};
}
/**
* Computes the `x` and `y` coordinates that will place the floating element
* next to a reference element when it is given a certain CSS positioning
* strategy.
*/
const computePosition = (reference, floating, options) => {
// This caches the expensive `getClippingElementAncestors` function so that
// multiple lifecycle resets re-use the same result. It only lives for a
// single call. If other functions become expensive, we can add them as well.
const cache = new Map();
const mergedOptions = _extends({
platform
}, options);
const platformWithCache = _extends({}, mergedOptions.platform, {
_c: cache
});
return computePosition$1(reference, floating, _extends({}, mergedOptions, {
platform: platformWithCache
}));
};
/**
* Floating UI Options
*
* @typedef {object} FloatingUIOptions
*/
/**
* Determines options for the tooltip and initializes event listeners.
*
* @param {Step} step The step instance
*
* @return {FloatingUIOptions}
*/
function setupTooltip(step) {
if (step.cleanup) {
step.cleanup();
}
const attachToOptions = step._getResolvedAttachToOptions();
let target = attachToOptions.element;
const floatingUIOptions = getFloatingUIOptions(attachToOptions, step);
const shouldCenter = shouldCenterStep(attachToOptions);
if (shouldCenter) {
target = document.body;
const content = step.shepherdElementComponent.getElement();
content.classList.add('shepherd-centered');
}
step.cleanup = autoUpdate(target, step.el, () => {
// The element might have already been removed by the end of the tour.
if (!step.el) {
step.cleanup();
return;
}
setPosition(target, step, floatingUIOptions, shouldCenter);
});
step.target = attachToOptions.element;
return floatingUIOptions;
}
/**
* Merge tooltip options handling nested keys.
*
* @param tourOptions - The default tour options.
* @param options - Step specific options.
*
* @return {floatingUIOptions: FloatingUIOptions}
*/
function mergeTooltipConfig(tourOptions, options) {
return {
floatingUIOptions: cjs(tourOptions.floatingUIOptions || {}, options.floatingUIOptions || {})
};
}
/**
* Cleanup function called when the step is closed/destroyed.
*
* @param {Step} step
*/
function destroyTooltip(step) {
if (step.cleanup) {
step.cleanup();
}
step.cleanup = null;
}
/**
*
* @return {Promise<*>}
*/
function setPosition(target, step, floatingUIOptions, shouldCenter) {
return computePosition(target, step.el, floatingUIOptions).then(floatingUIposition(step, shouldCenter))
// Wait before forcing focus.
.then(step => new Promise(resolve => {
setTimeout(() => resolve(step), 300);
}))
// Replaces focusAfterRender modifier.
.then(step => {
if (step && step.el) {
step.el.focus({
preventScroll: true
});
}
});
}
/**
*
* @param step
* @param shouldCenter
* @return {function({x: *, y: *, placement: *, middlewareData: *}): Promise<unknown>}
*/
function floatingUIposition(step, shouldCenter) {
return ({
x,
y,
placement,
middlewareData
}) => {
if (!step.el) {
return step;
}
if (shouldCenter) {
Object.assign(step.el.style, {
position: 'fixed',
left: '50%',
top: '50%',
transform: 'translate(-50%, -50%)'
});
} else {
Object.assign(step.el.style, {
position: 'absolute',
left: `${x}px`,
top: `${y}px`
});
}
step.el.dataset.popperPlacement = placement;
placeArrow(step.el, middlewareData);
return step;
};
}
/**
*
* @param el
* @param middlewareData
*/
function placeArrow(el, middlewareData) {
const arrowEl = el.querySelector('.shepherd-arrow');
if (arrowEl && middlewareData.arrow) {
const {
x: arrowX,
y: arrowY
} = middlewareData.arrow;
Object.assign(arrowEl.style, {
left: arrowX != null ? `${arrowX}px` : '',
top: arrowY != null ? `${arrowY}px` : ''
});
}
}
/**
* Gets the `Floating UI` options from a set of base `attachTo` options
* @param attachToOptions
* @param {Step} step The step instance
* @return {Object}
* @private
*/
function getFloatingUIOptions(attachToOptions, step) {
const options = {
strategy: 'absolute',
middleware: []
};
const arrowEl = addArrow(step);
const shouldCenter = shouldCenterStep(attachToOptions);
if (!shouldCenter) {
options.middleware.push(flip(),
// Replicate PopperJS default behavior.
shift({
limiter: limitShift(),
crossAxis: true
}));
if (arrowEl) {
options.middleware.push(arrow({
element: arrowEl
}));
}
options.placement = attachToOptions.on;
}
return cjs(step.options.floatingUIOptions || {}, options);
}
/**
* @param {Step} step
* @return {HTMLElement|false|null}
*/
function addArrow(step) {
if (step.options.arrow && step.el) {
return step.el.querySelector('.shepherd-arrow');
}
return false;
}
function noop() {}
function assign(tar, src) {
// @ts-ignore
for (const k in src) tar[k] = src[k];
return tar;
}
function run(fn) {
return fn();
}
function blank_object() {
return Object.create(null);
}
function run_all(fns) {
fns.forEach(run);
}
function is_function(thing) {
return typeof thing === 'function';
}
function safe_not_equal(a, b) {
return a != a ? b == b : a !== b || a && typeof a === 'object' || typeof a === 'function';
}
function is_empty(obj) {
return Object.keys(obj).length === 0;
}
function append(target, node) {
target.appendChild(node);
}
function insert(target, node, anchor) {
target.insertBefore(node, anchor || null);
}
function detach(node) {
if (node.parentNode) {
node.parentNode.removeChild(node);
}
}
function destroy_each(iterations, detaching) {
for (let i = 0; i < iterations.length; i += 1) {
if (iterations[i]) iterations[i].d(detaching);
}
}
function element(name) {
return document.createElement(name);
}
function svg_element(name) {
return document.createElementNS('http://www.w3.org/2000/svg', name);
}
function text(data) {
return document.createTextNode(data);
}
function space() {
return text(' ');
}
function empty() {
return text('');
}
function listen(node, event, handler, options) {
node.addEventListener(event, handler, options);
return () => node.removeEventListener(event, handler, options);
}
function attr(node, attribute, value) {
if (value == null) node.removeAttribute(attribute);else if (node.getAttribute(attribute) !== value) node.setAttribute(attribute, value);
}
/**
* List of attributes that should always be set through the attr method,
* because updating them through the property setter doesn't work reliably.
* In the example of `width`/`height`, the problem is that the setter only
* accepts numeric values, but the attribute can also be set to a string like `50%`.
* If this list becomes too big, rethink this approach.
*/
const always_set_through_set_attribute = ['width', 'height'];
function set_attributes(node, attributes) {
// @ts-ignore
const descriptors = Object.getOwnPropertyDescriptors(node.__proto__);
for (const key in attributes) {
if (attributes[key] == null) {
node.removeAttribute(key);
} else if (key === 'style') {
node.style.cssText = attributes[key];
} else if (key === '__value') {
node.value = node[key] = attributes[key];
} else if (descriptors[key] && descriptors[key].set && always_set_through_set_attribute.indexOf(key) === -1) {
node[key] = attributes[key];
} else {
attr(node, key, attributes[key]);
}
}
}
function children(element) {
return Array.from(element.childNodes);
}
function toggle_class(element, name, toggle) {
element.classList[toggle ? 'add' : 'remove'](name);
}
let current_component;
function set_current_component(component) {
current_component = component;
}
function get_current_component() {
if (!current_component) throw new Error('Function called outside component initialization');
return current_component;
}
/**
* The `onMount` function schedules a callback to run as soon as the component has been mounted to the DOM.
* It must be called during the component's initialisation (but doesn't need to live *inside* the component;
* it can be called from an external module).
*
* `onMount` does not run inside a [server-side component](/docs#run-time-server-side-component-api).
*
* https://svelte.dev/docs#run-time-svelte-onmount
*/
function onMount(fn) {
get_current_component().$$.on_mount.push(fn);
}
/**
* Schedules a callback to run immediately after the component has been updated.
*
* The first time the callback runs will be after the initial `onMount`
*/
function afterUpdate(fn) {
get_current_component().$$.after_update.push(fn);
}
const dirty_components = [];
const binding_callbacks = [];
let render_callbacks = [];
const flush_callbacks = [];
const resolved_promise = /* @__PURE__ */Promise.resolve();
let update_scheduled = false;
function schedule_update() {
if (!update_scheduled) {
update_scheduled = true;
resolved_promise.then(flush);
}
}
function add_render_callback(fn) {
render_callbacks.push(fn);
}
// flush() calls callbacks in this order:
// 1. All beforeUpdate callbacks, in order: parents before children
// 2. All bind:this callbacks, in reverse order: children before parents.
// 3. All afterUpdate callbacks, in order: parents before children. EXCEPT
// for afterUpdates called during the initial onMount, which are called in
// reverse order: children before parents.
// Since callbacks might update component values, which could trigger another
// call to flush(), the following steps guard against this:
// 1. During beforeUpdate, any updated components will be added to the
// dirty_components array and will cause a reentrant call to flush(). Because
// the flush index is kept outside the function, the reentrant call will pick
// up where the earlier call left off and go through all dirty components. The
// current_component value is saved and restored so that the reentrant call will
// not interfere with the "parent" flush() call.
// 2. bind:this callbacks cannot trigger new flush() calls.
// 3. During afterUpdate, any updated components will NOT have their afterUpdate
// callback called a second time; the seen_callbacks set, outside the flush()
// function, guarantees this behavior.
const seen_callbacks = new Set();
let flushidx = 0; // Do *not* move this inside the flush() function
function flush() {
// Do not reenter flush while dirty components are updated, as this can
// result in an infinite loop. Instead, let the inner flush handle it.
// Reentrancy is ok afterwards for bindings etc.
if (flushidx !== 0) {
return;
}
const saved_component = current_component;
do {
// first, call beforeUpdate functions
// and update components
try {
while (flushidx < dirty_components.length) {
const component = dirty_components[flushidx];
flushidx++;
set_current_component(component);
update(component.$$);
}
} catch (e) {
// reset dirty state to not end up in a deadlocked state and then rethrow
dirty_components.length = 0;
flushidx = 0;
throw e;
}
set_current_component(null);
dirty_components.length = 0;
flushidx = 0;
while (binding_callbacks.length) binding_callbacks.pop()();
// then, once components are updated, call
// afterUpdate functions. This may cause
// subsequent updates...
for (let i = 0; i < render_callbacks.length; i += 1) {
const callback = render_callbacks[i];
if (!seen_callbacks.has(callback)) {
// ...so guard against infinite loops
seen_callbacks.add(callback);
callback();
}
}
render_callbacks.length = 0;
} while (dirty_components.length);
while (flush_callbacks.length) {
flush_callbacks.pop()();
}
update_scheduled = false;
seen_callbacks.clear();
set_current_component(saved_component);
}
function update($$) {
if ($$.fragment !== null) {
$$.update();
run_all($$.before_update);
const dirty = $$.dirty;
$$.dirty = [-1];
$$.fragment && $$.fragment.p($$.ctx, dirty);
$$.after_update.forEach(add_render_callback);
}
}
/**
* Useful for example to execute remaining `afterUpdate` callbacks before executing `destroy`.
*/
function flush_render_callbacks(fns) {
const filtered = [];
const targets = [];
render_callbacks.forEach(c => fns.indexOf(c) === -1 ? filtered.push(c) : targets.push(c));
targets.forEach(c => c());
render_callbacks = filtered;
}
const outroing = new Set();
let outros;
function group_outros() {
outros = {
r: 0,
c: [],
p: outros // parent group
};
}
function check_outros() {
if (!outros.r) {
run_all(outros.c);
}
outros = outros.p;
}
function transition_in(block, local) {
if (block && block.i) {
outroing.delete(block);
block.i(local);
}
}
function transition_out(block, local, detach, callback) {
if (block && block.o) {
if (outroing.has(block)) return;
outroing.add(block);
outros.c.push(() => {
outroing.delete(block);
if (callback) {
if (detach) block.d(1);
callback();
}
});
block.o(local);
} else if (callback) {
callback();
}
}
function get_spread_update(levels, updates) {
const update = {};
const to_null_out = {};
const accounted_for = {
$$scope: 1
};
let i = levels.length;
while (i--) {
const o = levels[i];
const n = updates[i];
if (n) {
for (const key in o) {
if (!(key in n)) to_null_out[key] = 1;
}
for (const key in n) {
if (!accounted_for[key]) {
update[key] = n[key];
accounted_for[key] = 1;
}
}
levels[i] = n;
} else {
for (const key in o) {
accounted_for[key] = 1;
}
}
}
for (const key in to_null_out) {
if (!(key in update)) update[key] = undefined;
}
return update;
}
function create_component(block) {
block && block.c();
}
function mount_component(component, target, anchor, customElement) {
const {
fragment,
after_update
} = component.$$;
fragment && fragment.m(target, anchor);
if (!customElement) {
// onMount happens before the initial afterUpdate
add_render_callback(() => {
const new_on_destroy = component.$$.on_mount.map(run).filter(is_function);
// if the component was destroyed immediately
// it will update the `$$.on_destroy` reference to `null`.
// the destructured on_destroy may still reference to the old array
if (component.$$.on_destroy) {
component.$$.on_destroy.push(...new_on_destroy);
} else {
// Edge case - component was destroyed immediately,
// most likely as a result of a binding initialising
run_all(new_on_destroy);
}
component.$$.on_mount = [];
});
}
after_update.forEach(add_render_callback);
}
function destroy_component(component, detaching) {
const $$ = component.$$;
if ($$.fragment !== null) {
flush_render_callbacks($$.after_update);
run_all($$.on_destroy);
$$.fragment && $$.fragment.d(detaching);
// TODO null out other refs, including component.$$ (but need to
// preserve final state?)
$$.on_destroy = $$.fragment = null;
$$.ctx = [];
}
}
function make_dirty(component, i) {
if (component.$$.dirty[0] === -1) {
dirty_components.push(component);
schedule_update();
component.$$.dirty.fill(0);
}
component.$$.dirty[i / 31 | 0] |= 1 << i % 31;
}
function init(component, options, instance, create_fragment, not_equal, props, append_styles, dirty = [-1]) {
const parent_component = current_component;
set_current_component(component);
const $$ = component.$$ = {
fragment: null,
ctx: [],
// state
props,
update: noop,
not_equal,
bound: blank_object(),
// lifecycle
on_mount: [],
on_destroy: [],
on_disconnect: [],
before_update: [],
after_update: [],
context: new Map(options.context || (parent_component ? parent_component.$$.context : [])),
// everything else
callbacks: blank_object(),
dirty,
skip_bound: false,
root: options.target || parent_component.$$.root
};
append_styles && append_styles($$.root);
let ready = false;
$$.ctx = instance ? instance(component, options.props || {}, (i, ret, ...rest) => {
const value = rest.length ? rest[0] : ret;
if ($$.ctx && not_equal($$.ctx[i], $$.ctx[i] = value)) {
if (!$$.skip_bound && $$.bound[i]) $$.bound[i](value);
if (ready) make_dirty(component, i);
}
return ret;
}) : [];
$$.update();
ready = true;
run_all($$.before_update);
// `false` as a special case of no DOM component
$$.fragment = create_fragment ? create_fragment($$.ctx) : false;
if (options.target) {
if (options.hydrate) {
const nodes = children(options.target);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
$$.fragment && $$.fragment.l(nodes);
nodes.forEach(detach);
} else {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
$$.fragment && $$.fragment.c();
}
if (options.intro) transition_in(component.$$.fragment);
mount_component(component, options.target, options.anchor, options.customElement);
flush();
}
set_current_component(parent_component);
}
/**
* Base class for Svelte components. Used when dev=false.
*/
class SvelteComponent {
$destroy() {
destroy_component(this, 1);
this.$destroy = noop;
}
$on(type, callback) {
if (!is_function(callback)) {
return noop;
}
const callbacks = this.$$.callbacks[type] || (this.$$.callbacks[type] = []);
callbacks.push(callback);
return () => {
const index = callbacks.indexOf(callback);
if (index !== -1) callbacks.splice(index, 1);
};
}
$set($$props) {
if (this.$$set && !is_empty($$props)) {
this.$$.skip_bound = true;
this.$$set($$props);
this.$$.skip_bound = false;
}
}
}
/* src/js/components/shepherd-button.svelte generated by Svelte v3.59.2 */
function create_fragment$8(ctx) {
let button;
let button_aria_label_value;
let button_class_value;
let mounted;
let dispose;
return {
c() {
button = element("button");
attr(button, "aria-label", button_aria_label_value = /*label*/ctx[3] ? /*label*/ctx[3] : null);
attr(button, "class", button_class_value = `${/*classes*/ctx[1] || ''} shepherd-button ${/*secondary*/ctx[4] ? 'shepherd-button-secondary' : ''}`);
button.disabled = /*disabled*/ctx[2];
attr(button, "tabindex", "0");
},
m(target, anchor) {
insert(target, button, anchor);
button.innerHTML = /*text*/ctx[5];
if (!mounted) {
dispose = listen(button, "click", function () {
if (is_function( /*action*/ctx[0])) /*action*/ctx[0].apply(this, arguments);
});
mounted = true;
}
},
p(new_ctx, [dirty]) {
ctx = new_ctx;
if (dirty & /*text*/32) button.innerHTML = /*text*/ctx[5];
if (dirty & /*label*/8 && button_aria_label_value !== (button_aria_label_value = /*label*/ctx[3] ? /*label*/ctx[3] : null)) {
attr(button, "aria-label", button_aria_label_value);
}
if (dirty & /*classes, secondary*/18 && button_class_value !== (button_class_value = `${/*classes*/ctx[1] || ''} shepherd-button ${/*secondary*/ctx[4] ? 'shepherd-button-secondary' : ''}`)) {
attr(button, "class", button_class_value);
}
if (dirty & /*disabled*/4) {
button.disabled = /*disabled*/ctx[2];
}
},
i: noop,
o: noop,
d(detaching) {
if (detaching) detach(button);
mounted = false;
dispose();
}
};
}
function instance$8($$self, $$props, $$invalidate) {
let {
config,
step
} = $$props;
let action, classes, disabled, label, secondary, text;
function getConfigOption(option) {
if (isFunction(option)) {
return option = option.call(step);
}
return option;
}
$$self.$$set = $$props => {
if ('config' in $$props) $$invalidate(6, config = $$props.config);
if ('step' in $$props) $$invalidate(7, step = $$props.step);
};
$$self.$$.update = () => {
if ($$self.$$.dirty & /*config, step*/192) {
{
$$invalidate(0, action = config.action ? config.action.bind(step.tour) : null);
$$invalidate(1, classes = config.classes);
$$invalidate(2, disabled = config.disabled ? getConfigOption(config.disabled) : false);
$$invalidate(3, label = config.label ? getConfigOption(config.label) : null);
$$invalidate(4, secondary = config.secondary);
$$invalidate(5, text = config.text ? getConfigOption(config.text) : null);
}
}
};
return [action, classes, disabled, label, secondary, text, config, step];
}
class Shepherd_button extends SvelteComponent {
constructor(options) {
super();
init(this, options, instance$8, create_fragment$8, safe_not_equal, {
config: 6,
step: 7
});
}
}
/* src/js/components/shepherd-footer.svelte generated by Svelte v3.59.2 */
function get_each_context(ctx, list, i) {
const child_ctx = ctx.slice();
child_ctx[2] = list[i];
return child_ctx;
}
// (24:4) {#if buttons}
function create_if_block$3(ctx) {
let each_1_anchor;
let current;
let each_value = /*buttons*/ctx[1];
let each_blocks = [];
for (let i = 0; i < each_value.length; i += 1) {
each_blocks[i] = create_each_block(get_each_context(ctx, each_value, i));
}
const out = i => transition_out(each_blocks[i], 1, 1, () => {
each_blocks[i] = null;
});
return {
c() {
for (let i = 0; i < each_blocks.length; i += 1) {
each_blocks[i].c();
}
each_1_anchor = empty();
},
m(target, anchor) {
for (let i = 0; i < each_blocks.length; i += 1) {
if (each_blocks[i]) {
each_blocks[i].m(target, anchor);
}
}
insert(target, each_1_anchor, anchor);
current = true;
},
p(ctx, dirty) {
if (dirty & /*buttons, step*/3) {
each_value = /*buttons*/ctx[1];
let i;
for (i = 0; i < each_value.length; i += 1) {
const child_ctx = get_each_context(ctx, each_value, i);
if (each_blocks[i]) {
each_blocks[i].p(child_ctx, dirty);
transition_in(each_blocks[i], 1);
} else {
each_blocks[i] = create_each_block(child_ctx);
each_blocks[i].c();
transition_in(each_blocks[i], 1);
each_blocks[i].m(each_1_anchor.parentNode, each_1_anchor);
}
}
group_outros();
for (i = each_value.length; i < each_blocks.length; i += 1) {
out(i);
}
check_outros();
}
},
i(local) {
if (current) return;
for (let i = 0; i < each_value.length; i += 1) {
transition_in(each_blocks[i]);
}
current = true;
},
o(local) {
each_blocks = each_blocks.filter(Boolean);
for (let i = 0; i < each_blocks.length; i += 1) {
transition_out(each_blocks[i]);
}
current = false;
},
d(detaching) {
destroy_each(each_blocks, detaching);
if (detaching) detach(each_1_anchor);
}
};
}
// (25:8) {#each buttons as config}
function create_each_block(ctx) {
let shepherdbutton;
let current;
shepherdbutton = new Shepherd_button({
props: {
config: /*config*/ctx[2],
step: /*step*/ctx[0]
}
});
return {
c() {
create_component(shepherdbutton.$$.fragment);
},
m(target, anchor) {
mount_component(shepherdbutton, target, anchor);
current = true;
},
p(ctx, dirty) {
const shepherdbutton_changes = {};
if (dirty & /*buttons*/2) shepherdbutton_changes.config = /*config*/ctx[2];
if (dirty & /*step*/1) shepherdbutton_changes.step = /*step*/ctx[0];
shepherdbutton.$set(shepherdbutton_changes);
},
i(local) {
if (current) return;
transition_in(shepherdbutton.$$.fragment, local);
current = true;
},
o(local) {
transition_out(shepherdbutton.$$.fragment, local);
current = false;
},
d(detaching) {
destroy_component(shepherdbutton, detaching);
}
};
}
function create_fragment$7(ctx) {
let footer;
let current;
let if_block = /*buttons*/ctx[1] && create_if_block$3(ctx);
return {
c() {
footer = element("footer");
if (if_block) if_block.c();
attr(footer, "class", "shepherd-footer");
},
m(target, anchor) {
insert(target, footer, anchor);
if (if_block) if_block.m(footer, null);
current = true;
},
p(ctx, [dirty]) {
if ( /*buttons*/ctx[1]) {
if (if_block) {
if_block.p(ctx, dirty);
if (dirty & /*buttons*/2) {
transition_in(if_block, 1);
}
} else {
if_block = create_if_block$3(ctx);
if_block.c();
transition_in(if_block, 1);
if_block.m(footer, null);
}
} else if (if_block) {
group_outros();
transition_out(if_block, 1, 1, () => {
if_block = null;
});
check_outros();
}
},
i(local) {
if (current) return;
transition_in(if_block);
current = true;
},
o(local) {
transition_out(if_block);
current = false;
},
d(detaching) {
if (detaching) detach(footer);
if (if_block) if_block.d();
}
};
}
function instance$7($$self, $$props, $$invalidate) {
let buttons;
let {
step
} = $$props;
$$self.$$set = $$props => {
if ('step' in $$props) $$invalidate(0, step = $$props.step);
};
$$self.$$.update = () => {
if ($$self.$$.dirty & /*step*/1) {
$$invalidate(1, buttons = step.options.buttons);
}
};
return [step, buttons];
}
class Shepherd_footer extends SvelteComponent {
constructor(options) {
super();
init(this, options, instance$7, create_fragment$7, safe_not_equal, {
step: 0
});
}
}
/* src/js/components/shepherd-cancel-icon.svelte generated by Svelte v3.59.2 */
function create_fragment$6(ctx) {
let button;
let span;
let button_aria_label_value;
let mounted;
let dispose;
return {
c() {
button = element("button");
span = element("span");
span.textContent = "×";
attr(span, "aria-hidden", "true");
attr(button, "aria-label", button_aria_label_value = /*cancelIcon*/ctx[0].label ? /*cancelIcon*/ctx[0].label : 'Close Tour');
attr(button, "class", "shepherd-cancel-icon");
attr(button, "type", "button");
},
m(target, anchor) {
insert(target, button, anchor);
append(button, span);
if (!mounted) {
dispose = listen(button, "click", /*handleCancelClick*/ctx[1]);
mounted = true;
}
},
p(ctx, [dirty]) {
if (dirty & /*cancelIcon*/1 && button_aria_label_value !== (button_aria_label_value = /*cancelIcon*/ctx[0].label ? /*cancelIcon*/ctx[0].label : 'Close Tour')) {
attr(button, "aria-label", button_aria_label_value);
}
},
i: noop,
o: noop,
d(detaching) {
if (detaching) detach(button);
mounted = false;
dispose();
}
};
}
function instance$6($$self, $$props, $$invalidate) {
let {
cancelIcon,
step
} = $$props;
/**
* Add a click listener to the cancel link that cancels the tour
*/
const handleCancelClick = e => {
e.preventDefault();
step.cancel();
};
$$self.$$set = $$props => {
if ('cancelIcon' in $$props) $$invalidate(0, cancelIcon = $$props.cancelIcon);
if ('step' in $$props) $$invalidate(2, step = $$props.step);
};
return [cancelIcon, handleCancelClick, step];
}
class Shepherd_cancel_icon extends SvelteComponent {
constructor(options) {
super();
init(this, options, instance$6, create_fragment$6, safe_not_equal, {
cancelIcon: 0,
step: 2
});
}
}
/* src/js/components/shepherd-title.svelte generated by Svelte v3.59.2 */
function create_fragment$5(ctx) {
let h3;
return {
c() {
h3 = element("h3");
attr(h3, "id", /*labelId*/ctx[1]);
attr(h3, "class", "shepherd-title");
},
m(target, anchor) {
insert(target, h3, anchor);
/*h3_binding*/
ctx[3](h3);
},
p(ctx, [dirty]) {
if (dirty & /*labelId*/2) {
attr(h3, "id", /*labelId*/ctx[1]);
}
},
i: noop,
o: noop,
d(detaching) {
if (detaching) detach(h3);
/*h3_binding*/
ctx[3](null);
}
};
}
function instance$5($$self, $$props, $$invalidate) {
let {
labelId,
element,
title
} = $$props;
afterUpdate(() => {
if (isFunction(title)) {
$$invalidate(2, title = title());
}
$$invalidate(0, element.innerHTML = title, element);
});
function h3_binding($$value) {
binding_callbacks[$$value ? 'unshift' : 'push'](() => {
element = $$value;
$$invalidate(0, element);
});
}
$$self.$$set = $$props => {
if ('labelId' in $$props) $$invalidate(1, labelId = $$props.labelId);
if ('element' in $$props) $$invalidate(0, element = $$props.element);
if ('title' in $$props) $$invalidate(2, title = $$props.title);
};
return [element, labelId, title, h3_binding];
}
class Shepherd_title extends SvelteComponent {
constructor(options) {
super();
init(this, options, instance$5, create_fragment$5, safe_not_equal, {
labelId: 1,
element: 0,
title: 2
});
}
}
/* src/js/components/shepherd-header.svelte generated by Svelte v3.59.2 */
function create_if_block_1$1(ctx) {
let shepherdtitle;
let current;
shepherdtitle = new Shepherd_title({
props: {
labelId: /*labelId*/ctx[0],
title: /*title*/ctx[2]
}
});
return {
c() {
create_component(shepherdtitle.$$.fragment);
},
m(target, anchor) {
mount_component(shepherdtitle, target, anchor);
current = true;
},
p(ctx, dirty) {
const shepherdtitle_changes = {};
if (dirty & /*labelId*/1) shepherdtitle_changes.labelId = /*labelId*/ctx[0];
if (dirty & /*title*/4) shepherdtitle_changes.title = /*title*/ctx[2];
shepherdtitle.$set(shepherdtitle_changes);
},
i(local) {
if (current) return;
transition_in(shepherdtitle.$$.fragment, local);
current = true;
},
o(local) {
transition_out(shepherdtitle.$$.fragment, local);
current = false;
},
d(detaching) {
destroy_component(shepherdtitle, detaching);
}
};
}
// (39:4) {#if cancelIcon && cancelIcon.enabled}
function create_if_block$2(ctx) {
let shepherdcancelicon;
let current;
shepherdcancelicon = new Shepherd_cancel_icon({
props: {
cancelIcon: /*cancelIcon*/ctx[3],
step: /*step*/ctx[1]
}
});
return {
c() {
create_component(shepherdcancelicon.$$.fragment);
},
m(target, anchor) {
mount_component(shepherdcancelicon, target, anchor);
current = true;
},
p(ctx, dirty) {
const shepherdcancelicon_changes = {};
if (dirty & /*cancelIcon*/8) shepherdcancelicon_changes.cancelIcon = /*cancelIcon*/ctx[3];
if (dirty & /*step*/2) shepherdcancelicon_changes.step = /*step*/ctx[1];
shepherdcancelicon.$set(shepherdcancelicon_changes);
},
i(local) {
if (current) return;
transition_in(shepherdcancelicon.$$.fragment, local);
current = true;
},
o(local) {
transition_out(shepherdcancelicon.$$.fragment, local);
current = false;
},
d(detaching) {
destroy_component(shepherdcancelicon, detaching);
}
};
}
function create_fragment$4(ctx) {
let header;
let t;
let current;
let if_block0 = /*title*/ctx[2] && create_if_block_1$1(ctx);
let if_block1 = /*cancelIcon*/ctx[3] && /*cancelIcon*/ctx[3].enabled && create_if_block$2(ctx);
return {
c() {
header = element("header");
if (if_block0) if_block0.c();
t = space();
if (if_block1) if_block1.c();
attr(header, "class", "shepherd-header");
},
m(target, anchor) {
insert(target, header, anchor);
if (if_block0) if_block0.m(header, null);
append(header, t);
if (if_block1) if_block1.m(header, null);
current = true;
},
p(ctx, [dirty]) {
if ( /*title*/ctx[2]) {
if (if_block0) {
if_block0.p(ctx, dirty);
if (dirty & /*title*/4) {
transition_in(if_block0, 1);
}
} else {
if_block0 = create_if_block_1$1(ctx);
if_block0.c();
transition_in(if_block0, 1);
if_block0.m(header, t);
}
} else if (if_block0) {
group_outros();
transition_out(if_block0, 1, 1, () => {
if_block0 = null;
});
check_outros();
}
if ( /*cancelIcon*/ctx[3] && /*cancelIcon*/ctx[3].enabled) {
if (if_block1) {
if_block1.p(ctx, dirty);
if (dirty & /*cancelIcon*/8) {
transition_in(if_block1, 1);
}
} else {
if_block1 = create_if_block$2(ctx);
if_block1.c();
transition_in(if_block1, 1);
if_block1.m(header, null);
}
} else if (if_block1) {
group_outros();
transition_out(if_block1, 1, 1, () => {
if_block1 = null;
});
check_outros();
}
},
i(local) {
if (current) return;
transition_in(if_block0);
transition_in(if_block1);
current = true;
},
o(local) {
transition_out(if_block0);
transition_out(if_block1);
current = false;
},
d(detaching) {
if (detaching) detach(header);
if (if_block0) if_block0.d();
if (if_block1) if_block1.d();
}
};
}
function instance$4($$self, $$props, $$invalidate) {
let {
labelId,
step
} = $$props;
let title, cancelIcon;
$$self.$$set = $$props => {
if ('labelId' in $$props) $$invalidate(0, labelId = $$props.labelId);
if ('step' in $$props) $$invalidate(1, step = $$props.step);
};
$$self.$$.update = () => {
if ($$self.$$.dirty & /*step*/2) {
{
$$invalidate(2, title = step.options.title);
$$invalidate(3, cancelIcon = step.options.cancelIcon);
}
}
};
return [labelId, step, title, cancelIcon];
}
class Shepherd_header extends SvelteComponent {
constructor(options) {
super();
init(this, options, instance$4, create_fragment$4, safe_not_equal, {
labelId: 0,
step: 1
});
}
}
/* src/js/components/shepherd-text.svelte generated by Svelte v3.59.2 */
function create_fragment$3(ctx) {
let div;
return {
c() {
div = element("div");
attr(div, "class", "shepherd-text");
attr(div, "id", /*descriptionId*/ctx[1]);
},
m(target, anchor) {
insert(target, div, anchor);
/*div_binding*/
ctx[3](div);
},
p(ctx, [dirty]) {
if (dirty & /*descriptionId*/2) {
attr(div, "id", /*descriptionId*/ctx[1]);
}
},
i: noop,
o: noop,
d(detaching) {
if (detaching) detach(div);
/*div_binding*/
ctx[3](null);
}
};
}
function instance$3($$self, $$props, $$invalidate) {
let {
descriptionId,
element,
step
} = $$props;
afterUpdate(() => {
let {
text
} = step.options;
if (isFunction(text)) {
text = text.call(step);
}
if (isHTMLElement$1(text)) {
element.appendChild(text);
} else {
$$invalidate(0, element.innerHTML = text, element);
}
});
function div_binding($$value) {
binding_callbacks[$$value ? 'unshift' : 'push'](() => {
element = $$value;
$$invalidate(0, element);
});
}
$$self.$$set = $$props => {
if ('descriptionId' in $$props) $$invalidate(1, descriptionId = $$props.descriptionId);
if ('element' in $$props) $$invalidate(0, element = $$props.element);
if ('step' in $$props) $$invalidate(2, step = $$props.step);
};
return [element, descriptionId, step, div_binding];
}
class Shepherd_text extends SvelteComponent {
constructor(options) {
super();
init(this, options, instance$3, create_fragment$3, safe_not_equal, {
descriptionId: 1,
element: 0,
step: 2
});
}
}
/* src/js/components/shepherd-content.svelte generated by Svelte v3.59.2 */
function create_if_block_2(ctx) {
let shepherdheader;
let current;
shepherdheader = new Shepherd_header({
props: {
labelId: /*labelId*/ctx[1],
step: /*step*/ctx[2]
}
});
return {
c() {
create_component(shepherdheader.$$.fragment);
},
m(target, anchor) {
mount_component(shepherdheader, target, anchor);
current = true;
},
p(ctx, dirty) {
const shepherdheader_changes = {};
if (dirty & /*labelId*/2) shepherdheader_changes.labelId = /*labelId*/ctx[1];
if (dirty & /*step*/4) shepherdheader_changes.step = /*step*/ctx[2];
shepherdheader.$set(shepherdheader_changes);
},
i(local) {
if (current) return;
transition_in(shepherdheader.$$.fragment, local);
current = true;
},
o(local) {
transition_out(shepherdheader.$$.fragment, local);
current = false;
},
d(detaching) {
destroy_component(shepherdheader, detaching);
}
};
}
// (28:2) {#if !isUndefined(step.options.text)}
function create_if_block_1(ctx) {
let shepherdtext;
let current;
shepherdtext = new Shepherd_text({
props: {
descriptionId: /*descriptionId*/ctx[0],
step: /*step*/ctx[2]
}
});
return {
c() {
create_component(shepherdtext.$$.fragment);
},
m(target, anchor) {
mount_component(shepherdtext, target, anchor);
current = true;
},
p(ctx, dirty) {
const shepherdtext_changes = {};
if (dirty & /*descriptionId*/1) shepherdtext_changes.descriptionId = /*descriptionId*/ctx[0];
if (dirty & /*step*/4) shepherdtext_changes.step = /*step*/ctx[2];
shepherdtext.$set(shepherdtext_changes);
},
i(local) {
if (current) return;
transition_in(shepherdtext.$$.fragment, local);
current = true;
},
o(local) {
transition_out(shepherdtext.$$.fragment, local);
current = false;
},
d(detaching) {
destroy_component(shepherdtext, detaching);
}
};
}
// (35:2) {#if Array.isArray(step.options.buttons) && step.options.buttons.length}
function create_if_block$1(ctx) {
let shepherdfooter;
let current;
shepherdfooter = new Shepherd_footer({
props: {
step: /*step*/ctx[2]
}
});
return {
c() {
create_component(shepherdfooter.$$.fragment);
},
m(target, anchor) {
mount_component(shepherdfooter, target, anchor);
current = true;
},
p(ctx, dirty) {
const shepherdfooter_changes = {};
if (dirty & /*step*/4) shepherdfooter_changes.step = /*step*/ctx[2];
shepherdfooter.$set(shepherdfooter_changes);
},
i(local) {
if (current) return;
transition_in(shepherdfooter.$$.fragment, local);
current = true;
},
o(local) {
transition_out(shepherdfooter.$$.fragment, local);
current = false;
},
d(detaching) {
destroy_component(shepherdfooter, detaching);
}
};
}
function create_fragment$2(ctx) {
let div;
let show_if_2 = !isUndefined( /*step*/ctx[2].options.title) || /*step*/ctx[2].options.cancelIcon && /*step*/ctx[2].options.cancelIcon.enabled;
let t0;
let show_if_1 = !isUndefined( /*step*/ctx[2].options.text);
let t1;
let show_if = Array.isArray( /*step*/ctx[2].options.buttons) && /*step*/ctx[2].options.buttons.length;
let current;
let if_block0 = show_if_2 && create_if_block_2(ctx);
let if_block1 = show_if_1 && create_if_block_1(ctx);
let if_block2 = show_if && create_if_block$1(ctx);
return {
c() {
div = element("div");
if (if_block0) if_block0.c();
t0 = space();
if (if_block1) if_block1.c();
t1 = space();
if (if_block2) if_block2.c();
attr(div, "class", "shepherd-content");
},
m(target, anchor) {
insert(target, div, anchor);
if (if_block0) if_block0.m(div, null);
append(div, t0);
if (if_block1) if_block1.m(div, null);
append(div, t1);
if (if_block2) if_block2.m(div, null);
current = true;
},
p(ctx, [dirty]) {
if (dirty & /*step*/4) show_if_2 = !isUndefined( /*step*/ctx[2].options.title) || /*step*/ctx[2].options.cancelIcon && /*step*/ctx[2].options.cancelIcon.enabled;
if (show_if_2) {
if (if_block0) {
if_block0.p(ctx, dirty);
if (dirty & /*step*/4) {
transition_in(if_block0, 1);
}
} else {
if_block0 = create_if_block_2(ctx);
if_block0.c();
transition_in(if_block0, 1);
if_block0.m(div, t0);
}
} else if (if_block0) {
group_outros();
transition_out(if_block0, 1, 1, () => {
if_block0 = null;
});
check_outros();
}
if (dirty & /*step*/4) show_if_1 = !isUndefined( /*step*/ctx[2].options.text);
if (show_if_1) {
if (if_block1) {
if_block1.p(ctx, dirty);
if (dirty & /*step*/4) {
transition_in(if_block1, 1);
}
} else {
if_block1 = create_if_block_1(ctx);
if_block1.c();
transition_in(if_block1, 1);
if_block1.m(div, t1);
}
} else if (if_block1) {
group_outros();
transition_out(if_block1, 1, 1, () => {
if_block1 = null;
});
check_outros();
}
if (dirty & /*step*/4) show_if = Array.isArray( /*step*/ctx[2].options.buttons) && /*step*/ctx[2].options.buttons.length;
if (show_if) {
if (if_block2) {
if_block2.p(ctx, dirty);
if (dirty & /*step*/4) {
transition_in(if_block2, 1);
}
} else {
if_block2 = create_if_block$1(ctx);
if_block2.c();
transition_in(if_block2, 1);
if_block2.m(div, null);
}
} else if (if_block2) {
group_outros();
transition_out(if_block2, 1, 1, () => {
if_block2 = null;
});
check_outros();
}
},
i(local) {
if (current) return;
transition_in(if_block0);
transition_in(if_block1);
transition_in(if_block2);
current = true;
},
o(local) {
transition_out(if_block0);
transition_out(if_block1);
transition_out(if_block2);
current = false;
},
d(detaching) {
if (detaching) detach(div);
if (if_block0) if_block0.d();
if (if_block1) if_block1.d();
if (if_block2) if_block2.d();
}
};
}
function instance$2($$self, $$props, $$invalidate) {
let {
descriptionId,
labelId,
step
} = $$props;
$$self.$$set = $$props => {
if ('descriptionId' in $$props) $$invalidate(0, descriptionId = $$props.descriptionId);
if ('labelId' in $$props) $$invalidate(1, labelId = $$props.labelId);
if ('step' in $$props) $$invalidate(2, step = $$props.step);
};
return [descriptionId, labelId, step];
}
class Shepherd_content extends SvelteComponent {
constructor(options) {
super();
init(this, options, instance$2, create_fragment$2, safe_not_equal, {
descriptionId: 0,
labelId: 1,
step: 2
});
}
}
/* src/js/components/shepherd-element.svelte generated by Svelte v3.59.2 */
function create_if_block(ctx) {
let div;
return {
c() {
div = element("div");
attr(div, "class", "shepherd-arrow");
attr(div, "data-popper-arrow", "");
},
m(target, anchor) {
insert(target, div, anchor);
},
d(detaching) {
if (detaching) detach(div);
}
};
}
function create_fragment$1(ctx) {
let div;
let t;
let shepherdcontent;
let div_aria_describedby_value;
let div_aria_labelledby_value;
let current;
let mounted;
let dispose;
let if_block = /*step*/ctx[4].options.arrow && /*step*/ctx[4].options.attachTo && /*step*/ctx[4].options.attachTo.element && /*step*/ctx[4].options.attachTo.on && create_if_block();
shepherdcontent = new Shepherd_content({
props: {
descriptionId: /*descriptionId*/ctx[2],
labelId: /*labelId*/ctx[3],
step: /*step*/ctx[4]
}
});
let div_levels = [{
"aria-describedby": div_aria_describedby_value = !isUndefined( /*step*/ctx[4].options.text) ? /*descriptionId*/ctx[2] : null
}, {
"aria-labelledby": div_aria_labelledby_value = /*step*/ctx[4].options.title ? /*labelId*/ctx[3] : null
}, /*dataStepId*/ctx[1], {
role: "dialog"
}, {
tabindex: "0"
}];
let div_data = {};
for (let i = 0; i < div_levels.length; i += 1) {
div_data = assign(div_data, div_levels[i]);
}
return {
c() {
div = element("div");
if (if_block) if_block.c();
t = space();
create_component(shepherdcontent.$$.fragment);
set_attributes(div, div_data);
toggle_class(div, "shepherd-has-cancel-icon", /*hasCancelIcon*/ctx[5]);
toggle_class(div, "shepherd-has-title", /*hasTitle*/ctx[6]);
toggle_class(div, "shepherd-element", true);
},
m(target, anchor) {
insert(target, div, anchor);
if (if_block) if_block.m(div, null);
append(div, t);
mount_component(shepherdcontent, div, null);
/*div_binding*/
ctx[13](div);
current = true;
if (!mounted) {
dispose = listen(div, "keydown", /*handleKeyDown*/ctx[7]);
mounted = true;
}
},
p(ctx, [dirty]) {
if ( /*step*/ctx[4].options.arrow && /*step*/ctx[4].options.attachTo && /*step*/ctx[4].options.attachTo.element && /*step*/ctx[4].options.attachTo.on) {
if (if_block) ; else {
if_block = create_if_block();
if_block.c();
if_block.m(div, t);
}
} else if (if_block) {
if_block.d(1);
if_block = null;
}
const shepherdcontent_changes = {};
if (dirty & /*descriptionId*/4) shepherdcontent_changes.descriptionId = /*descriptionId*/ctx[2];
if (dirty & /*labelId*/8) shepherdcontent_changes.labelId = /*labelId*/ctx[3];
if (dirty & /*step*/16) shepherdcontent_changes.step = /*step*/ctx[4];
shepherdcontent.$set(shepherdcontent_changes);
set_attributes(div, div_data = get_spread_update(div_levels, [(!current || dirty & /*step, descriptionId*/20 && div_aria_describedby_value !== (div_aria_describedby_value = !isUndefined( /*step*/ctx[4].options.text) ? /*descriptionId*/ctx[2] : null)) && {
"aria-describedby": div_aria_describedby_value
}, (!current || dirty & /*step, labelId*/24 && div_aria_labelledby_value !== (div_aria_labelledby_value = /*step*/ctx[4].options.title ? /*labelId*/ctx[3] : null)) && {
"aria-labelledby": div_aria_labelledby_value
}, dirty & /*dataStepId*/2 && /*dataStepId*/ctx[1], {
role: "dialog"
}, {
tabindex: "0"
}]));
toggle_class(div, "shepherd-has-cancel-icon", /*hasCancelIcon*/ctx[5]);
toggle_class(div, "shepherd-has-title", /*hasTitle*/ctx[6]);
toggle_class(div, "shepherd-element", true);
},
i(local) {
if (current) return;
transition_in(shepherdcontent.$$.fragment, local);
current = true;
},
o(local) {
transition_out(shepherdcontent.$$.fragment, local);
current = false;
},
d(detaching) {
if (detaching) detach(div);
if (if_block) if_block.d();
destroy_component(shepherdcontent);
/*div_binding*/
ctx[13](null);
mounted = false;
dispose();
}
};
}
const KEY_TAB = 9;
const KEY_ESC = 27;
const LEFT_ARROW = 37;
const RIGHT_ARROW = 39;
function getClassesArray(classes) {
return classes.split(' ').filter(className => !!className.length);
}
function instance$1($$self, $$props, $$invalidate) {
let {
classPrefix,
element,
descriptionId,
firstFocusableElement,
focusableElements,
labelId,
lastFocusableElement,
step,
dataStepId
} = $$props;
let hasCancelIcon, hasTitle, classes;
const getElement = () => element;
onMount(() => {
// Get all elements that are focusable
$$invalidate(1, dataStepId = {
[`data-${classPrefix}shepherd-step-id`]: step.id
});
$$invalidate(9, focusableElements = element.querySelectorAll('a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), [tabindex="0"]'));
$$invalidate(8, firstFocusableElement = focusableElements[0]);
$$invalidate(10, lastFocusableElement = focusableElements[focusableElements.length - 1]);
});
afterUpdate(() => {
if (classes !== step.options.classes) {
updateDynamicClasses();
}
});
function updateDynamicClasses() {
removeClasses(classes);
classes = step.options.classes;
addClasses(classes);
}
function removeClasses(classes) {
if (isString(classes)) {
const oldClasses = getClassesArray(classes);
if (oldClasses.length) {
element.classList.remove(...oldClasses);
}
}
}
function addClasses(classes) {
if (isString(classes)) {
const newClasses = getClassesArray(classes);
if (newClasses.length) {
element.classList.add(...newClasses);
}
}
}
/**
* Setup keydown events to allow closing the modal with ESC
*
* Borrowed from this great post! https://bitsofco.de/accessible-modal-dialog/
*
* @private
*/
const handleKeyDown = e => {
const {
tour
} = step;
switch (e.keyCode) {
case KEY_TAB:
if (focusableElements.length === 0) {
e.preventDefault();
break;
}
// Backward tab
if (e.shiftKey) {
if (document.activeElement === firstFocusableElement || document.activeElement.classList.contains('shepherd-element')) {
e.preventDefault();
lastFocusableElement.focus();
}
} else {
if (document.activeElement === lastFocusableElement) {
e.preventDefault();
firstFocusableElement.focus();
}
}
break;
case KEY_ESC:
if (tour.options.exitOnEsc) {
e.stopPropagation();
step.cancel();
}
break;
case LEFT_ARROW:
if (tour.options.keyboardNavigation) {
e.stopPropagation();
tour.back();
}
break;
case RIGHT_ARROW:
if (tour.options.keyboardNavigation) {
e.stopPropagation();
tour.next();
}
break;
}
};
function div_binding($$value) {
binding_callbacks[$$value ? 'unshift' : 'push'](() => {
element = $$value;
$$invalidate(0, element);
});
}
$$self.$$set = $$props => {
if ('classPrefix' in $$props) $$invalidate(11, classPrefix = $$props.classPrefix);
if ('element' in $$props) $$invalidate(0, element = $$props.element);
if ('descriptionId' in $$props) $$invalidate(2, descriptionId = $$props.descriptionId);
if ('firstFocusableElement' in $$props) $$invalidate(8, firstFocusableElement = $$props.firstFocusableElement);
if ('focusableElements' in $$props) $$invalidate(9, focusableElements = $$props.focusableElements);
if ('labelId' in $$props) $$invalidate(3, labelId = $$props.labelId);
if ('lastFocusableElement' in $$props) $$invalidate(10, lastFocusableElement = $$props.lastFocusableElement);
if ('step' in $$props) $$invalidate(4, step = $$props.step);
if ('dataStepId' in $$props) $$invalidate(1, dataStepId = $$props.dataStepId);
};
$$self.$$.update = () => {
if ($$self.$$.dirty & /*step*/16) {
{
$$invalidate(5, hasCancelIcon = step.options && step.options.cancelIcon && step.options.cancelIcon.enabled);
$$invalidate(6, hasTitle = step.options && step.options.title);
}
}
};
return [element, dataStepId, descriptionId, labelId, step, hasCancelIcon, hasTitle, handleKeyDown, firstFocusableElement, focusableElements, lastFocusableElement, classPrefix, getElement, div_binding];
}
class Shepherd_element extends SvelteComponent {
constructor(options) {
super();
init(this, options, instance$1, create_fragment$1, safe_not_equal, {
classPrefix: 11,
element: 0,
descriptionId: 2,
firstFocusableElement: 8,
focusableElements: 9,
labelId: 3,
lastFocusableElement: 10,
step: 4,
dataStepId: 1,
getElement: 12
});
}
get getElement() {
return this.$$.ctx[12];
}
}
/**
* A class representing steps to be added to a tour.
* @extends {Evented}
*/
class Step extends Evented {
/**
* Create a step
* @param {Tour} tour The tour for the step
* @param {object} options The options for the step
* @param {boolean} options.arrow Whether to display the arrow for the tooltip or not. Defaults to `true`.
* @param {object} options.attachTo The element the step should be attached to on the page.
* An object with properties `element` and `on`.
*
* ```js
* const step = new Step(tour, {
* attachTo: { element: '.some .selector-path', on: 'left' },
* ...moreOptions
* });
* ```
*
* If you dont specify an `attachTo` the element will appear in the middle of the screen. The same will happen if your `attachTo.element` callback returns `null`, `undefined`, or a selector that does not exist in the DOM.
* If you omit the `on` portion of `attachTo`, the element will still be highlighted, but the tooltip will appear
* in the middle of the screen, without an arrow pointing to the target.
* If the element to highlight does not yet exist while instantiating tour steps, you may use lazy evaluation by supplying a function to `attachTo.element`. The function will be called in the `before-show` phase.
* @param {string|HTMLElement|function} options.attachTo.element An element selector string, DOM element, or a function (returning a selector, a DOM element, `null` or `undefined`).
* @param {string} options.attachTo.on The optional direction to place the FloatingUI tooltip relative to the element.
* - Possible string values: 'top', 'top-start', 'top-end', 'bottom', 'bottom-start', 'bottom-end', 'right', 'right-start', 'right-end', 'left', 'left-start', 'left-end'
* @param {Object} options.advanceOn An action on the page which should advance shepherd to the next step.
* It should be an object with a string `selector` and an `event` name
* ```js
* const step = new Step(tour, {
* advanceOn: { selector: '.some .selector-path', event: 'click' },
* ...moreOptions
* });
* ```
* `event` doesnt have to be an event inside the tour, it can be any event fired on any element on the page.
* You can also always manually advance the Tour by calling `myTour.next()`.
* @param {function} options.beforeShowPromise A function that returns a promise.
* When the promise resolves, the rest of the `show` code for the step will execute.
* @param {Object[]} options.buttons An array of buttons to add to the step. These will be rendered in a
* footer below the main body text.
* @param {function} options.buttons.button.action A function executed when the button is clicked on.
* It is automatically bound to the `tour` the step is associated with, so things like `this.next` will
* work inside the action.
* You can use action to skip steps or navigate to specific steps, with something like:
* ```js
* action() {
* return this.show('some_step_name');
* }
* ```
* @param {string} options.buttons.button.classes Extra classes to apply to the `<a>`
* @param {boolean} options.buttons.button.disabled Should the button be disabled?
* @param {string} options.buttons.button.label The aria-label text of the button
* @param {boolean} options.buttons.button.secondary If true, a shepherd-button-secondary class is applied to the button
* @param {string} options.buttons.button.text The HTML text of the button
* @param {boolean} options.canClickTarget A boolean, that when set to false, will set `pointer-events: none` on the target
* @param {object} options.cancelIcon Options for the cancel icon
* @param {boolean} options.cancelIcon.enabled Should a cancel “✕” be shown in the header of the step?
* @param {string} options.cancelIcon.label The label to add for `aria-label`
* @param {string} options.classes A string of extra classes to add to the step's content element.
* @param {string} options.highlightClass An extra class to apply to the `attachTo` element when it is
* highlighted (that is, when its step is active). You can then target that selector in your CSS.
* @param {string} options.id The string to use as the `id` for the step.
* @param {number} options.modalOverlayOpeningPadding An amount of padding to add around the modal overlay opening
* @param {number | { topLeft: number, bottomLeft: number, bottomRight: number, topRight: number }} options.modalOverlayOpeningRadius An amount of border radius to add around the modal overlay opening
* @param {object} options.floatingUIOptions Extra options to pass to FloatingUI
* @param {boolean|Object} options.scrollTo Should the element be scrolled to when this step is shown? If true, uses the default `scrollIntoView`,
* if an object, passes that object as the params to `scrollIntoView` i.e. `{behavior: 'smooth', block: 'center'}`
* @param {function} options.scrollToHandler A function that lets you override the default scrollTo behavior and
* define a custom action to do the scrolling, and possibly other logic.
* @param {function} options.showOn A function that, when it returns `true`, will show the step.
* If it returns false, the step will be skipped.
* @param {string} options.text The text in the body of the step. It can be one of three types:
* ```
* - HTML string
* - `HTMLElement` object
* - `Function` to be executed when the step is built. It must return one the two options above.
* ```
* @param {string} options.title The step's title. It becomes an `h3` at the top of the step. It can be one of two types:
* ```
* - HTML string
* - `Function` to be executed when the step is built. It must return HTML string.
* ```
* @param {object} options.when You can define `show`, `hide`, etc events inside `when`. For example:
* ```js
* when: {
* show: function() {
* window.scrollTo(0, 0);
* }
* }
* ```
* @return {Step} The newly created Step instance
*/
constructor(tour, options = {}) {
super(tour, options);
this.tour = tour;
this.classPrefix = this.tour.options ? normalizePrefix(this.tour.options.classPrefix) : '';
this.styles = tour.styles;
/**
* Resolved attachTo options. Due to lazy evaluation, we only resolve the options during `before-show` phase.
* Do not use this directly, use the _getResolvedAttachToOptions method instead.
* @type {null|{}|{element, to}}
* @private
*/
this._resolvedAttachTo = null;
autoBind(this);
this._setOptions(options);
return this;
}
/**
* Cancel the tour
* Triggers the `cancel` event
*/
cancel() {
this.tour.cancel();
this.trigger('cancel');
}
/**
* Complete the tour
* Triggers the `complete` event
*/
complete() {
this.tour.complete();
this.trigger('complete');
}
/**
* Remove the step, delete the step's element, and destroy the FloatingUI instance for the step.
* Triggers `destroy` event
*/
destroy() {
destroyTooltip(this);
if (isHTMLElement$1(this.el)) {
this.el.remove();
this.el = null;
}
this._updateStepTargetOnHide();
this.trigger('destroy');
}
/**
* Returns the tour for the step
* @return {Tour} The tour instance
*/
getTour() {
return this.tour;
}
/**
* Hide the step
*/
hide() {
this.tour.modal.hide();
this.trigger('before-hide');
if (this.el) {
this.el.hidden = true;
}
this._updateStepTargetOnHide();
this.trigger('hide');
}
/**
* Resolves attachTo options.
* @returns {{}|{element, on}}
* @private
*/
_resolveAttachToOptions() {
this._resolvedAttachTo = parseAttachTo(this);
return this._resolvedAttachTo;
}
/**
* A selector for resolved attachTo options.
* @returns {{}|{element, on}}
* @private
*/
_getResolvedAttachToOptions() {
if (this._resolvedAttachTo === null) {
return this._resolveAttachToOptions();
}
return this._resolvedAttachTo;
}
/**
* Check if the step is open and visible
* @return {boolean} True if the step is open and visible
*/
isOpen() {
return Boolean(this.el && !this.el.hidden);
}
/**
* Wraps `_show` and ensures `beforeShowPromise` resolves before calling show
* @return {*|Promise}
*/
show() {
if (isFunction(this.options.beforeShowPromise)) {
return Promise.resolve(this.options.beforeShowPromise()).then(() => this._show());
}
return Promise.resolve(this._show());
}
/**
* Updates the options of the step.
*
* @param {Object} options The options for the step
*/
updateStepOptions(options) {
Object.assign(this.options, options);
if (this.shepherdElementComponent) {
this.shepherdElementComponent.$set({
step: this
});
}
}
/**
* Returns the element for the step
* @return {HTMLElement|null|undefined} The element instance. undefined if it has never been shown, null if it has been destroyed
*/
getElement() {
return this.el;
}
/**
* Returns the target for the step
* @return {HTMLElement|null|undefined} The element instance. undefined if it has never been shown, null if query string has not been found
*/
getTarget() {
return this.target;
}
/**
* Creates Shepherd element for step based on options
*
* @return {Element} The DOM element for the step tooltip
* @private
*/
_createTooltipContent() {
const descriptionId = `${this.id}-description`;
const labelId = `${this.id}-label`;
this.shepherdElementComponent = new Shepherd_element({
target: this.tour.options.stepsContainer || document.body,
props: {
classPrefix: this.classPrefix,
descriptionId,
labelId,
step: this,
styles: this.styles
}
});
return this.shepherdElementComponent.getElement();
}
/**
* If a custom scrollToHandler is defined, call that, otherwise do the generic
* scrollIntoView call.
*
* @param {boolean|Object} scrollToOptions If true, uses the default `scrollIntoView`,
* if an object, passes that object as the params to `scrollIntoView` i.e. `{ behavior: 'smooth', block: 'center' }`
* @private
*/
_scrollTo(scrollToOptions) {
const {
element
} = this._getResolvedAttachToOptions();
if (isFunction(this.options.scrollToHandler)) {
this.options.scrollToHandler(element);
} else if (isElement$1(element) && typeof element.scrollIntoView === 'function') {
element.scrollIntoView(scrollToOptions);
}
}
/**
* _getClassOptions gets all possible classes for the step
* @param {Object} stepOptions The step specific options
* @returns {String} unique string from array of classes
* @private
*/
_getClassOptions(stepOptions) {
const defaultStepOptions = this.tour && this.tour.options && this.tour.options.defaultStepOptions;
const stepClasses = stepOptions.classes ? stepOptions.classes : '';
const defaultStepOptionsClasses = defaultStepOptions && defaultStepOptions.classes ? defaultStepOptions.classes : '';
const allClasses = [...stepClasses.split(' '), ...defaultStepOptionsClasses.split(' ')];
const uniqClasses = new Set(allClasses);
return Array.from(uniqClasses).join(' ').trim();
}
/**
* Sets the options for the step, maps `when` to events, sets up buttons
* @param {Object} options The options for the step
* @private
*/
_setOptions(options = {}) {
let tourOptions = this.tour && this.tour.options && this.tour.options.defaultStepOptions;
tourOptions = cjs({}, tourOptions || {});
this.options = Object.assign({
arrow: true
}, tourOptions, options, mergeTooltipConfig(tourOptions, options));
const {
when
} = this.options;
this.options.classes = this._getClassOptions(options);
this.destroy();
this.id = this.options.id || `step-${uuid()}`;
if (when) {
Object.keys(when).forEach(event => {
this.on(event, when[event], this);
});
}
}
/**
* Create the element and set up the FloatingUI instance
* @private
*/
_setupElements() {
if (!isUndefined(this.el)) {
this.destroy();
}
this.el = this._createTooltipContent();
if (this.options.advanceOn) {
bindAdvance(this);
}
// The tooltip implementation details are handled outside of the Step
// object.
setupTooltip(this);
}
/**
* Triggers `before-show`, generates the tooltip DOM content,
* sets up a FloatingUI instance for the tooltip, then triggers `show`.
* @private
*/
_show() {
this.trigger('before-show');
// Force resolve to make sure the options are updated on subsequent shows.
this._resolveAttachToOptions();
this._setupElements();
if (!this.tour.modal) {
this.tour._setupModal();
}
this.tour.modal.setupForStep(this);
this._styleTargetElementForStep(this);
this.el.hidden = false;
// start scrolling to target before showing the step
if (this.options.scrollTo) {
setTimeout(() => {
this._scrollTo(this.options.scrollTo);
});
}
this.el.hidden = false;
const content = this.shepherdElementComponent.getElement();
const target = this.target || document.body;
target.classList.add(`${this.classPrefix}shepherd-enabled`);
target.classList.add(`${this.classPrefix}shepherd-target`);
content.classList.add('shepherd-enabled');
this.trigger('show');
}
/**
* Modulates the styles of the passed step's target element, based on the step's options and
* the tour's `modal` option, to visually emphasize the element
*
* @param step The step object that attaches to the element
* @private
*/
_styleTargetElementForStep(step) {
const targetElement = step.target;
if (!targetElement) {
return;
}
if (step.options.highlightClass) {
targetElement.classList.add(step.options.highlightClass);
}
targetElement.classList.remove('shepherd-target-click-disabled');
if (step.options.canClickTarget === false) {
targetElement.classList.add('shepherd-target-click-disabled');
}
}
/**
* When a step is hidden, remove the highlightClass and 'shepherd-enabled'
* and 'shepherd-target' classes
* @private
*/
_updateStepTargetOnHide() {
const target = this.target || document.body;
if (this.options.highlightClass) {
target.classList.remove(this.options.highlightClass);
}
target.classList.remove('shepherd-target-click-disabled', `${this.classPrefix}shepherd-enabled`, `${this.classPrefix}shepherd-target`);
}
}
/**
* Cleanup the steps and set pointerEvents back to 'auto'
* @param tour The tour object
*/
function cleanupSteps(tour) {
if (tour) {
const {
steps
} = tour;
steps.forEach(step => {
if (step.options && step.options.canClickTarget === false && step.options.attachTo) {
if (step.target instanceof HTMLElement) {
step.target.classList.remove('shepherd-target-click-disabled');
}
}
});
}
}
/**
* Generates the svg path data for a rounded rectangle overlay
* @param {Object} dimension - Dimensions of rectangle.
* @param {number} width - Width.
* @param {number} height - Height.
* @param {number} [x=0] - Offset from top left corner in x axis. default 0.
* @param {number} [y=0] - Offset from top left corner in y axis. default 0.
* @param {number | { topLeft: number, topRight: number, bottomRight: number, bottomLeft: number }} [r=0] - Corner Radius. Keep this smaller than half of width or height.
* @returns {string} - Rounded rectangle overlay path data.
*/
function makeOverlayPath({
width,
height,
x = 0,
y = 0,
r = 0
}) {
const {
innerWidth: w,
innerHeight: h
} = window;
const {
topLeft = 0,
topRight = 0,
bottomRight = 0,
bottomLeft = 0
} = typeof r === 'number' ? {
topLeft: r,
topRight: r,
bottomRight: r,
bottomLeft: r
} : r;
return `M${w},${h}\
H0\
V0\
H${w}\
V${h}\
Z\
M${x + topLeft},${y}\
a${topLeft},${topLeft},0,0,0-${topLeft},${topLeft}\
V${height + y - bottomLeft}\
a${bottomLeft},${bottomLeft},0,0,0,${bottomLeft},${bottomLeft}\
H${width + x - bottomRight}\
a${bottomRight},${bottomRight},0,0,0,${bottomRight}-${bottomRight}\
V${y + topRight}\
a${topRight},${topRight},0,0,0-${topRight}-${topRight}\
Z`;
}
/* src/js/components/shepherd-modal.svelte generated by Svelte v3.59.2 */
function create_fragment(ctx) {
let svg;
let path;
let svg_class_value;
let mounted;
let dispose;
return {
c() {
svg = svg_element("svg");
path = svg_element("path");
attr(path, "d", /*pathDefinition*/ctx[2]);
attr(svg, "class", svg_class_value = `${/*modalIsVisible*/ctx[1] ? 'shepherd-modal-is-visible' : ''} shepherd-modal-overlay-container`);
},
m(target, anchor) {
insert(target, svg, anchor);
append(svg, path);
/*svg_binding*/
ctx[11](svg);
if (!mounted) {
dispose = listen(svg, "touchmove", /*_preventModalOverlayTouch*/ctx[3]);
mounted = true;
}
},
p(ctx, [dirty]) {
if (dirty & /*pathDefinition*/4) {
attr(path, "d", /*pathDefinition*/ctx[2]);
}
if (dirty & /*modalIsVisible*/2 && svg_class_value !== (svg_class_value = `${/*modalIsVisible*/ctx[1] ? 'shepherd-modal-is-visible' : ''} shepherd-modal-overlay-container`)) {
attr(svg, "class", svg_class_value);
}
},
i: noop,
o: noop,
d(detaching) {
if (detaching) detach(svg);
/*svg_binding*/
ctx[11](null);
mounted = false;
dispose();
}
};
}
function _getScrollParent(element) {
if (!element) {
return null;
}
const isHtmlElement = element instanceof HTMLElement;
const overflowY = isHtmlElement && window.getComputedStyle(element).overflowY;
const isScrollable = overflowY !== 'hidden' && overflowY !== 'visible';
if (isScrollable && element.scrollHeight >= element.clientHeight) {
return element;
}
return _getScrollParent(element.parentElement);
}
/**
* Get the visible height of the target element relative to its scrollParent.
* If there is no scroll parent, the height of the element is returned.
*
* @param {HTMLElement} element The target element
* @param {HTMLElement} [scrollParent] The scrollable parent element
* @returns {{y: number, height: number}}
* @private
*/
function _getVisibleHeight(element, scrollParent) {
const elementRect = element.getBoundingClientRect();
let top = elementRect.y || elementRect.top;
let bottom = elementRect.bottom || top + elementRect.height;
if (scrollParent) {
const scrollRect = scrollParent.getBoundingClientRect();
const scrollTop = scrollRect.y || scrollRect.top;
const scrollBottom = scrollRect.bottom || scrollTop + scrollRect.height;
top = Math.max(top, scrollTop);
bottom = Math.min(bottom, scrollBottom);
}
const height = Math.max(bottom - top, 0); // Default to 0 if height is negative
return {
y: top,
height
};
}
function instance($$self, $$props, $$invalidate) {
let {
element,
openingProperties
} = $$props;
uuid();
let modalIsVisible = false;
let rafId = undefined;
let pathDefinition;
closeModalOpening();
const getElement = () => element;
function closeModalOpening() {
$$invalidate(4, openingProperties = {
width: 0,
height: 0,
x: 0,
y: 0,
r: 0
});
}
function hide() {
$$invalidate(1, modalIsVisible = false);
// Ensure we cleanup all event listeners when we hide the modal
_cleanupStepEventListeners();
}
function positionModal(modalOverlayOpeningPadding = 0, modalOverlayOpeningRadius = 0, scrollParent, targetElement) {
if (targetElement) {
const {
y,
height
} = _getVisibleHeight(targetElement, scrollParent);
const {
x,
width,
left
} = targetElement.getBoundingClientRect();
// getBoundingClientRect is not consistent. Some browsers use x and y, while others use left and top
$$invalidate(4, openingProperties = {
width: width + modalOverlayOpeningPadding * 2,
height: height + modalOverlayOpeningPadding * 2,
x: (x || left) - modalOverlayOpeningPadding,
y: y - modalOverlayOpeningPadding,
r: modalOverlayOpeningRadius
});
} else {
closeModalOpening();
}
}
function setupForStep(step) {
// Ensure we move listeners from the previous step, before we setup new ones
_cleanupStepEventListeners();
if (step.tour.options.useModalOverlay) {
_styleForStep(step);
show();
} else {
hide();
}
}
function show() {
$$invalidate(1, modalIsVisible = true);
}
const _preventModalBodyTouch = e => {
e.preventDefault();
};
const _preventModalOverlayTouch = e => {
e.stopPropagation();
};
/**
* Add touchmove event listener
* @private
*/
function _addStepEventListeners() {
// Prevents window from moving on touch.
window.addEventListener('touchmove', _preventModalBodyTouch, {
passive: false
});
}
/**
* Cancel the requestAnimationFrame loop and remove touchmove event listeners
* @private
*/
function _cleanupStepEventListeners() {
if (rafId) {
cancelAnimationFrame(rafId);
rafId = undefined;
}
window.removeEventListener('touchmove', _preventModalBodyTouch, {
passive: false
});
}
/**
* Style the modal for the step
* @param {Step} step The step to style the opening for
* @private
*/
function _styleForStep(step) {
const {
modalOverlayOpeningPadding,
modalOverlayOpeningRadius
} = step.options;
const scrollParent = _getScrollParent(step.target);
// Setup recursive function to call requestAnimationFrame to update the modal opening position
const rafLoop = () => {
rafId = undefined;
positionModal(modalOverlayOpeningPadding, modalOverlayOpeningRadius, scrollParent, step.target);
rafId = requestAnimationFrame(rafLoop);
};
rafLoop();
_addStepEventListeners();
}
function svg_binding($$value) {
binding_callbacks[$$value ? 'unshift' : 'push'](() => {
element = $$value;
$$invalidate(0, element);
});
}
$$self.$$set = $$props => {
if ('element' in $$props) $$invalidate(0, element = $$props.element);
if ('openingProperties' in $$props) $$invalidate(4, openingProperties = $$props.openingProperties);
};
$$self.$$.update = () => {
if ($$self.$$.dirty & /*openingProperties*/16) {
$$invalidate(2, pathDefinition = makeOverlayPath(openingProperties));
}
};
return [element, modalIsVisible, pathDefinition, _preventModalOverlayTouch, openingProperties, getElement, closeModalOpening, hide, positionModal, setupForStep, show, svg_binding];
}
class Shepherd_modal extends SvelteComponent {
constructor(options) {
super();
init(this, options, instance, create_fragment, safe_not_equal, {
element: 0,
openingProperties: 4,
getElement: 5,
closeModalOpening: 6,
hide: 7,
positionModal: 8,
setupForStep: 9,
show: 10
});
}
get getElement() {
return this.$$.ctx[5];
}
get closeModalOpening() {
return this.$$.ctx[6];
}
get hide() {
return this.$$.ctx[7];
}
get positionModal() {
return this.$$.ctx[8];
}
get setupForStep() {
return this.$$.ctx[9];
}
get show() {
return this.$$.ctx[10];
}
}
const Shepherd = new Evented();
/**
* Class representing the site tour
* @extends {Evented}
*/
class Tour extends Evented {
/**
* @param {Object} options The options for the tour
* @param {boolean | function(): boolean | Promise<boolean> | function(): Promise<boolean>} options.confirmCancel If true, will issue a `window.confirm` before cancelling.
* If it is a function(support Async Function), it will be called and wait for the return value, and will only be cancelled if the value returned is true
* @param {string} options.confirmCancelMessage The message to display in the `window.confirm` dialog
* @param {string} options.classPrefix The prefix to add to the `shepherd-enabled` and `shepherd-target` class names as well as the `data-shepherd-step-id`.
* @param {Object} options.defaultStepOptions Default options for Steps ({@link Step#constructor}), created through `addStep`
* @param {boolean} options.exitOnEsc Exiting the tour with the escape key will be enabled unless this is explicitly
* set to false.
* @param {boolean} options.keyboardNavigation Navigating the tour via left and right arrow keys will be enabled
* unless this is explicitly set to false.
* @param {HTMLElement} options.stepsContainer An optional container element for the steps.
* If not set, the steps will be appended to `document.body`.
* @param {HTMLElement} options.modalContainer An optional container element for the modal.
* If not set, the modal will be appended to `document.body`.
* @param {object[] | Step[]} options.steps An array of step options objects or Step instances to initialize the tour with
* @param {string} options.tourName An optional "name" for the tour. This will be appended to the the tour's
* dynamically generated `id` property.
* @param {boolean} options.useModalOverlay Whether or not steps should be placed above a darkened
* modal overlay. If true, the overlay will create an opening around the target element so that it
* can remain interactive
* @returns {Tour}
*/
constructor(options = {}) {
super(options);
autoBind(this);
const defaultTourOptions = {
exitOnEsc: true,
keyboardNavigation: true
};
this.options = Object.assign({}, defaultTourOptions, options);
this.classPrefix = normalizePrefix(this.options.classPrefix);
this.steps = [];
this.addSteps(this.options.steps);
// Pass these events onto the global Shepherd object
const events = ['active', 'cancel', 'complete', 'inactive', 'show', 'start'];
events.map(event => {
(e => {
this.on(e, opts => {
opts = opts || {};
opts.tour = this;
Shepherd.trigger(e, opts);
});
})(event);
});
this._setTourID();
return this;
}
/**
* Adds a new step to the tour
* @param {Object|Step} options An object containing step options or a Step instance
* @param {number} index The optional index to insert the step at. If undefined, the step
* is added to the end of the array.
* @return {Step} The newly added step
*/
addStep(options, index) {
let step = options;
if (!(step instanceof Step)) {
step = new Step(this, step);
} else {
step.tour = this;
}
if (!isUndefined(index)) {
this.steps.splice(index, 0, step);
} else {
this.steps.push(step);
}
return step;
}
/**
* Add multiple steps to the tour
* @param {Array<object> | Array<Step>} steps The steps to add to the tour
*/
addSteps(steps) {
if (Array.isArray(steps)) {
steps.forEach(step => {
this.addStep(step);
});
}
return this;
}
/**
* Go to the previous step in the tour
*/
back() {
const index = this.steps.indexOf(this.currentStep);
this.show(index - 1, false);
}
/**
* Calls _done() triggering the 'cancel' event
* If `confirmCancel` is true, will show a window.confirm before cancelling
* If `confirmCancel` is a function, will call it and wait for the return value,
* and only cancel when the value returned is true
*/
async cancel() {
if (this.options.confirmCancel) {
const confirmCancelIsFunction = typeof this.options.confirmCancel === 'function';
const cancelMessage = this.options.confirmCancelMessage || 'Are you sure you want to stop the tour?';
const stopTour = confirmCancelIsFunction ? await this.options.confirmCancel() : window.confirm(cancelMessage);
if (stopTour) {
this._done('cancel');
}
} else {
this._done('cancel');
}
}
/**
* Calls _done() triggering the `complete` event
*/
complete() {
this._done('complete');
}
/**
* Gets the step from a given id
* @param {Number|String} id The id of the step to retrieve
* @return {Step} The step corresponding to the `id`
*/
getById(id) {
return this.steps.find(step => {
return step.id === id;
});
}
/**
* Gets the current step
* @returns {Step|null}
*/
getCurrentStep() {
return this.currentStep;
}
/**
* Hide the current step
*/
hide() {
const currentStep = this.getCurrentStep();
if (currentStep) {
return currentStep.hide();
}
}
/**
* Check if the tour is active
* @return {boolean}
*/
isActive() {
return Shepherd.activeTour === this;
}
/**
* Go to the next step in the tour
* If we are at the end, call `complete`
*/
next() {
const index = this.steps.indexOf(this.currentStep);
if (index === this.steps.length - 1) {
this.complete();
} else {
this.show(index + 1, true);
}
}
/**
* Removes the step from the tour
* @param {String} name The id for the step to remove
*/
removeStep(name) {
const current = this.getCurrentStep();
// Find the step, destroy it and remove it from this.steps
this.steps.some((step, i) => {
if (step.id === name) {
if (step.isOpen()) {
step.hide();
}
step.destroy();
this.steps.splice(i, 1);
return true;
}
});
if (current && current.id === name) {
this.currentStep = undefined;
// If we have steps left, show the first one, otherwise just cancel the tour
this.steps.length ? this.show(0) : this.cancel();
}
}
/**
* Show a specific step in the tour
* @param {Number|String} key The key to look up the step by
* @param {Boolean} forward True if we are going forward, false if backward
*/
show(key = 0, forward = true) {
const step = isString(key) ? this.getById(key) : this.steps[key];
if (step) {
this._updateStateBeforeShow();
const shouldSkipStep = isFunction(step.options.showOn) && !step.options.showOn();
// If `showOn` returns false, we want to skip the step, otherwise, show the step like normal
if (shouldSkipStep) {
this._skipStep(step, forward);
} else {
this.trigger('show', {
step,
previous: this.currentStep
});
this.currentStep = step;
step.show();
}
}
}
/**
* Start the tour
*/
start() {
this.trigger('start');
// Save the focused element before the tour opens
this.focusedElBeforeOpen = document.activeElement;
this.currentStep = null;
this._setupModal();
this._setupActiveTour();
this.next();
}
/**
* Called whenever the tour is cancelled or completed, basically anytime we exit the tour
* @param {String} event The event name to trigger
* @private
*/
_done(event) {
const index = this.steps.indexOf(this.currentStep);
if (Array.isArray(this.steps)) {
this.steps.forEach(step => step.destroy());
}
cleanupSteps(this);
this.trigger(event, {
index
});
Shepherd.activeTour = null;
this.trigger('inactive', {
tour: this
});
if (this.modal) {
this.modal.hide();
}
if (event === 'cancel' || event === 'complete') {
if (this.modal) {
const modalContainer = document.querySelector('.shepherd-modal-overlay-container');
if (modalContainer) {
modalContainer.remove();
}
}
}
// Focus the element that was focused before the tour started
if (isHTMLElement$1(this.focusedElBeforeOpen)) {
this.focusedElBeforeOpen.focus();
}
}
/**
* Make this tour "active"
* @private
*/
_setupActiveTour() {
this.trigger('active', {
tour: this
});
Shepherd.activeTour = this;
}
/**
* _setupModal create the modal container and instance
* @private
*/
_setupModal() {
this.modal = new Shepherd_modal({
target: this.options.modalContainer || document.body,
props: {
classPrefix: this.classPrefix,
styles: this.styles
}
});
}
/**
* Called when `showOn` evaluates to false, to skip the step or complete the tour if it's the last step
* @param {Step} step The step to skip
* @param {Boolean} forward True if we are going forward, false if backward
* @private
*/
_skipStep(step, forward) {
const index = this.steps.indexOf(step);
if (index === this.steps.length - 1) {
this.complete();
} else {
const nextIndex = forward ? index + 1 : index - 1;
this.show(nextIndex, forward);
}
}
/**
* Before showing, hide the current step and if the tour is not
* already active, call `this._setupActiveTour`.
* @private
*/
_updateStateBeforeShow() {
if (this.currentStep) {
this.currentStep.hide();
}
if (!this.isActive()) {
this._setupActiveTour();
}
}
/**
* Sets this.id to `${tourName}--${uuid}`
* @private
*/
_setTourID() {
const tourName = this.options.tourName || 'tour';
this.id = `${tourName}--${uuid()}`;
}
}
const isServerSide = typeof window === 'undefined';
class NoOp {
constructor() {}
}
if (isServerSide) {
Object.assign(Shepherd, {
Tour: NoOp,
Step: NoOp
});
} else {
Object.assign(Shepherd, {
Tour,
Step
});
}
export { Shepherd as default };
//# sourceMappingURL=shepherd.esm.js.map