flytask-joyride
Version: 
Flytask Joyride
1,623 lines (1,595 loc) • 66.8 kB
JavaScript
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.tsx
var index_exports = {};
__export(index_exports, {
  ACTIONS: () => ACTIONS,
  EVENTS: () => EVENTS,
  LIFECYCLE: () => LIFECYCLE,
  ORIGIN: () => ORIGIN,
  STATUS: () => STATUS,
  default: () => components_default
});
module.exports = __toCommonJS(index_exports);
// src/components/index.tsx
var React9 = __toESM(require("react"));
var import_deep_equal = __toESM(require("@gilbarbara/deep-equal"));
var import_is_lite6 = __toESM(require("is-lite"));
var import_tree_changes3 = __toESM(require("tree-changes"));
// src/modules/dom.ts
var import_scroll = __toESM(require("scroll"));
var import_scrollparent = __toESM(require("scrollparent"));
function canUseDOM() {
  var _a;
  return !!(typeof window !== "undefined" && ((_a = window.document) == null ? void 0 : _a.createElement));
}
function getClientRect(element) {
  if (!element) {
    return null;
  }
  return element.getBoundingClientRect();
}
function getDocumentHeight(median = false) {
  const { body, documentElement } = document;
  if (!body || !documentElement) {
    return 0;
  }
  if (median) {
    const heights = [
      body.scrollHeight,
      body.offsetHeight,
      documentElement.clientHeight,
      documentElement.scrollHeight,
      documentElement.offsetHeight
    ].sort((a, b) => a - b);
    const middle = Math.floor(heights.length / 2);
    if (heights.length % 2 === 0) {
      return (heights[middle - 1] + heights[middle]) / 2;
    }
    return heights[middle];
  }
  return Math.max(
    body.scrollHeight,
    body.offsetHeight,
    documentElement.clientHeight,
    documentElement.scrollHeight,
    documentElement.offsetHeight
  );
}
function getElement(element) {
  if (typeof element === "string") {
    try {
      return document.querySelector(element);
    } catch (error) {
      if (process.env.NODE_ENV !== "production") {
        console.error(error);
      }
      return null;
    }
  }
  return element;
}
function getStyleComputedProperty(el) {
  if (!el || el.nodeType !== 1) {
    return null;
  }
  return getComputedStyle(el);
}
function getScrollParent(element, skipFix, forListener) {
  if (!element) {
    return scrollDocument();
  }
  const parent = (0, import_scrollparent.default)(element);
  if (parent) {
    if (parent.isSameNode(scrollDocument())) {
      if (forListener) {
        return document;
      }
      return scrollDocument();
    }
    const hasScrolling = parent.scrollHeight > parent.offsetHeight;
    if (!hasScrolling && !skipFix) {
      parent.style.overflow = "initial";
      return scrollDocument();
    }
  }
  return parent;
}
function hasCustomScrollParent(element, skipFix) {
  if (!element) {
    return false;
  }
  const parent = getScrollParent(element, skipFix);
  return parent ? !parent.isSameNode(scrollDocument()) : false;
}
function hasCustomOffsetParent(element) {
  return element.offsetParent !== document.body;
}
function hasPosition(el, type = "fixed") {
  if (!el || !(el instanceof HTMLElement)) {
    return false;
  }
  const { nodeName } = el;
  const styles = getStyleComputedProperty(el);
  if (nodeName === "BODY" || nodeName === "HTML") {
    return false;
  }
  if (styles && styles.position === type) {
    return true;
  }
  if (!el.parentNode) {
    return false;
  }
  return hasPosition(el.parentNode, type);
}
function isElementVisible(element) {
  var _a;
  if (!element) {
    return false;
  }
  let parentElement = element;
  while (parentElement) {
    if (parentElement === document.body) {
      break;
    }
    if (parentElement instanceof HTMLElement) {
      const { display, visibility } = getComputedStyle(parentElement);
      if (display === "none" || visibility === "hidden") {
        return false;
      }
    }
    parentElement = (_a = parentElement.parentElement) != null ? _a : null;
  }
  return true;
}
function getElementPosition(element, offset, skipFix) {
  var _a;
  const elementRect = getClientRect(element);
  const parent = getScrollParent(element, skipFix);
  const hasScrollParent = hasCustomScrollParent(element, skipFix);
  let parentTop = 0;
  let top = (_a = elementRect == null ? void 0 : elementRect.top) != null ? _a : 0;
  if (parent instanceof HTMLElement) {
    parentTop = parent.scrollTop;
    if (!hasScrollParent && !hasPosition(element)) {
      top += parentTop;
    }
    if (!parent.isSameNode(scrollDocument())) {
      top += scrollDocument().scrollTop;
    }
  }
  return Math.floor(top - offset);
}
function getScrollTo(element, offset, skipFix) {
  var _a;
  if (!element) {
    return 0;
  }
  const { offsetTop = 0, scrollTop = 0 } = (_a = (0, import_scrollparent.default)(element)) != null ? _a : {};
  let top = element.getBoundingClientRect().top + scrollTop;
  if (!!offsetTop && (hasCustomScrollParent(element, skipFix) || hasCustomOffsetParent(element))) {
    top -= offsetTop;
  }
  const output = Math.floor(top - offset);
  return output < 0 ? 0 : output;
}
function scrollDocument() {
  var _a;
  return (_a = document.scrollingElement) != null ? _a : document.documentElement;
}
function scrollTo(value, options) {
  const { duration, element } = options;
  return new Promise((resolve, reject) => {
    const { scrollTop } = element;
    const limit = value > scrollTop ? value - scrollTop : scrollTop - value;
    import_scroll.default.top(element, value, { duration: limit < 100 ? 50 : duration }, (error) => {
      if (error && error.message !== "Element already at target scroll position") {
        return reject(error);
      }
      return resolve();
    });
  });
}
// src/modules/helpers.ts
var import_react = require("react");
var import_react_dom = require("react-dom");
var import_is_lite = __toESM(require("is-lite"));
// src/literals/index.ts
var ACTIONS = {
  INIT: "init",
  START: "start",
  STOP: "stop",
  RESET: "reset",
  PREV: "prev",
  NEXT: "next",
  GO: "go",
  CLOSE: "close",
  SKIP: "skip",
  UPDATE: "update"
};
var EVENTS = {
  TOUR_START: "tour:start",
  STEP_BEFORE: "step:before",
  BEACON: "beacon",
  TOOLTIP: "tooltip",
  STEP_AFTER: "step:after",
  TOUR_END: "tour:end",
  TOUR_STATUS: "tour:status",
  TARGET_NOT_FOUND: "error:target_not_found",
  ERROR: "error"
};
var LIFECYCLE = {
  INIT: "init",
  READY: "ready",
  BEACON: "beacon",
  TOOLTIP: "tooltip",
  COMPLETE: "complete",
  ERROR: "error"
};
var ORIGIN = {
  BUTTON_CLOSE: "button_close",
  BUTTON_PRIMARY: "button_primary",
  KEYBOARD: "keyboard",
  OVERLAY: "overlay"
};
var STATUS = {
  IDLE: "idle",
  READY: "ready",
  WAITING: "waiting",
  RUNNING: "running",
  PAUSED: "paused",
  SKIPPED: "skipped",
  FINISHED: "finished",
  ERROR: "error"
};
// src/modules/helpers.ts
var isReact16 = import_react_dom.createPortal !== void 0;
function getBrowser(userAgent = navigator.userAgent) {
  let browser = userAgent;
  if (typeof window === "undefined") {
    browser = "node";
  } else if (document.documentMode) {
    browser = "ie";
  } else if (/Edge/.test(userAgent)) {
    browser = "edge";
  } else if (Boolean(window.opera) || userAgent.includes(" OPR/")) {
    browser = "opera";
  } else if (typeof window.InstallTrigger !== "undefined") {
    browser = "firefox";
  } else if (window.chrome) {
    browser = "chrome";
  } else if (/(Version\/([\d._]+).*Safari|CriOS|FxiOS| Mobile\/)/.test(userAgent)) {
    browser = "safari";
  }
  return browser;
}
function getText(root) {
  const content = [];
  const recurse = (child) => {
    if (typeof child === "string" || typeof child === "number") {
      content.push(child);
    } else if (Array.isArray(child)) {
      child.forEach((c) => recurse(c));
    } else if ((0, import_react.isValidElement)(child)) {
      const { children } = child.props;
      if (Array.isArray(children)) {
        children.forEach((c) => recurse(c));
      } else {
        recurse(children);
      }
    }
  };
  recurse(root);
  return content.join(" ").trim();
}
function hasValidKeys(object, keys) {
  if (!import_is_lite.default.plainObject(object) || !import_is_lite.default.array(keys)) {
    return false;
  }
  return Object.keys(object).every((d) => keys.includes(d));
}
function hexToRGB(hex) {
  const shorthandRegex = /^#?([\da-f])([\da-f])([\da-f])$/i;
  const properHex = hex.replace(shorthandRegex, (_m, r, g, b) => r + r + g + g + b + b);
  const result = /^#?([\da-f]{2})([\da-f]{2})([\da-f]{2})$/i.exec(properHex);
  return result ? [parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16)] : [];
}
function hideBeacon(step) {
  return step.disableBeacon || step.placement === "center";
}
function isLegacy() {
  return !["chrome", "safari", "firefox", "opera"].includes(getBrowser());
}
function log({ data, debug = false, title, warn = false }) {
  const logFn = warn ? console.warn || console.error : console.log;
  if (debug) {
    if (title && data) {
      console.groupCollapsed(
        `%creact-joyride: ${title}`,
        "color: #ff0044; font-weight: bold; font-size: 12px;"
      );
      if (Array.isArray(data)) {
        data.forEach((d) => {
          if (import_is_lite.default.plainObject(d) && d.key) {
            logFn.apply(console, [d.key, d.value]);
          } else {
            logFn.apply(console, [d]);
          }
        });
      } else {
        logFn.apply(console, [data]);
      }
      console.groupEnd();
    } else {
      console.error("Missing title or data props");
    }
  }
}
function objectKeys(input) {
  return Object.keys(input);
}
function omit(input, ...filter) {
  if (!import_is_lite.default.plainObject(input)) {
    throw new TypeError("Expected an object");
  }
  const output = {};
  for (const key in input) {
    if ({}.hasOwnProperty.call(input, key)) {
      if (!filter.includes(key)) {
        output[key] = input[key];
      }
    }
  }
  return output;
}
function pick(input, ...filter) {
  if (!import_is_lite.default.plainObject(input)) {
    throw new TypeError("Expected an object");
  }
  if (!filter.length) {
    return input;
  }
  const output = {};
  for (const key in input) {
    if ({}.hasOwnProperty.call(input, key)) {
      if (filter.includes(key)) {
        output[key] = input[key];
      }
    }
  }
  return output;
}
function shouldScroll(options) {
  const { isFirstStep, lifecycle, previousLifecycle, scrollToFirstStep, step, target } = options;
  return !step.disableScrolling && (!isFirstStep || scrollToFirstStep || lifecycle === LIFECYCLE.TOOLTIP) && step.placement !== "center" && (!step.isFixed || !hasPosition(target)) && // fixed steps don't need to scroll
  previousLifecycle !== lifecycle && [LIFECYCLE.BEACON, LIFECYCLE.TOOLTIP].includes(lifecycle);
}
// src/modules/step.ts
var import_deepmerge2 = __toESM(require("deepmerge"));
var import_is_lite2 = __toESM(require("is-lite"));
// src/defaults.ts
var import_lodash = require("lodash");
var defaultFloaterProps = {
  options: {
    preventOverflow: {
      boundariesElement: "scrollParent"
    }
  },
  wrapperOptions: {
    offset: -18,
    position: true
  }
};
var defaultLocale = {
  back: "Back",
  close: "Close",
  last: "Last",
  next: "Next",
  nextLabelWithProgress: "Next (Step {step} of {steps})",
  open: "Open the dialog",
  skip: "Skip"
};
var defaultStep = {
  event: "click",
  placement: "bottom",
  offset: 10,
  disableBeacon: false,
  disableCloseOnEsc: false,
  disableOverlay: false,
  disableOverlayClose: false,
  disableScrollParentFix: false,
  disableScrolling: false,
  hideBackButton: false,
  hideCloseButton: false,
  hideFooter: false,
  isFixed: false,
  locale: defaultLocale,
  showProgress: false,
  showSkipButton: false,
  spotlightClicks: false,
  spotlightPadding: 10
};
var defaultProps = {
  continuous: false,
  debug: false,
  disableCloseOnEsc: false,
  disableOverlay: false,
  disableOverlayClose: false,
  disableScrolling: false,
  disableScrollParentFix: false,
  getHelpers: (0, import_lodash.noop)(),
  hideBackButton: false,
  run: true,
  scrollOffset: 20,
  scrollDuration: 300,
  scrollToFirstStep: false,
  showSkipButton: false,
  showProgress: false,
  spotlightClicks: false,
  spotlightPadding: 10,
  steps: []
};
// src/styles.ts
var import_deepmerge = __toESM(require("deepmerge"));
var defaultOptions = {
  arrowColor: "#fff",
  backgroundColor: "#fff",
  beaconSize: 36,
  overlayColor: "rgba(0, 0, 0, 0.5)",
  primaryColor: "#f04",
  spotlightShadow: "0 0 15px rgba(0, 0, 0, 0.5)",
  textColor: "#333",
  width: 380,
  zIndex: 100
};
var buttonBase = {
  backgroundColor: "transparent",
  border: 0,
  borderRadius: 0,
  color: "#555",
  cursor: "pointer",
  fontSize: 16,
  lineHeight: 1,
  padding: 8,
  WebkitAppearance: "none"
};
var spotlight = {
  borderRadius: 4,
  position: "absolute"
};
function getStyles(props, step) {
  var _a, _b, _c, _d, _e;
  const { floaterProps, styles } = props;
  const mergedFloaterProps = (0, import_deepmerge.default)((_a = step.floaterProps) != null ? _a : {}, floaterProps != null ? floaterProps : {});
  const mergedStyles = (0, import_deepmerge.default)(styles != null ? styles : {}, (_b = step.styles) != null ? _b : {});
  const options = (0, import_deepmerge.default)(defaultOptions, mergedStyles.options || {});
  const hideBeacon2 = step.placement === "center" || step.disableBeacon;
  let { width } = options;
  if (window.innerWidth > 480) {
    width = 380;
  }
  if ("width" in options) {
    width = typeof options.width === "number" && window.innerWidth < options.width ? window.innerWidth - 30 : options.width;
  }
  const overlay = {
    bottom: 0,
    left: 0,
    overflow: "hidden",
    position: "absolute",
    right: 0,
    top: 0,
    zIndex: options.zIndex
  };
  const defaultStyles = {
    beacon: {
      ...buttonBase,
      display: hideBeacon2 ? "none" : "inline-block",
      height: options.beaconSize,
      position: "relative",
      width: options.beaconSize,
      zIndex: options.zIndex
    },
    beaconInner: {
      animation: "joyride-beacon-inner 1.2s infinite ease-in-out",
      backgroundColor: options.primaryColor,
      borderRadius: "50%",
      display: "block",
      height: "50%",
      left: "50%",
      opacity: 0.7,
      position: "absolute",
      top: "50%",
      transform: "translate(-50%, -50%)",
      width: "50%"
    },
    beaconOuter: {
      animation: "joyride-beacon-outer 1.2s infinite ease-in-out",
      backgroundColor: `rgba(${hexToRGB(options.primaryColor).join(",")}, 0.2)`,
      border: `2px solid ${options.primaryColor}`,
      borderRadius: "50%",
      boxSizing: "border-box",
      display: "block",
      height: "100%",
      left: 0,
      opacity: 0.9,
      position: "absolute",
      top: 0,
      transformOrigin: "center",
      width: "100%"
    },
    tooltip: {
      backgroundColor: options.backgroundColor,
      borderRadius: 5,
      boxSizing: "border-box",
      color: options.textColor,
      fontSize: 16,
      maxWidth: "100%",
      padding: 15,
      position: "relative",
      width
    },
    tooltipContainer: {
      lineHeight: 1.4,
      textAlign: "center"
    },
    tooltipTitle: {
      fontSize: 18,
      margin: 0
    },
    tooltipContent: {
      padding: "20px 10px"
    },
    tooltipFooter: {
      alignItems: "center",
      display: "flex",
      justifyContent: "flex-end",
      marginTop: 15
    },
    tooltipFooterSpacer: {
      flex: 1
    },
    buttonNext: {
      ...buttonBase,
      backgroundColor: options.primaryColor,
      borderRadius: 4,
      color: "#fff"
    },
    buttonBack: {
      ...buttonBase,
      color: options.primaryColor,
      marginLeft: "auto",
      marginRight: 5
    },
    buttonClose: {
      ...buttonBase,
      color: options.textColor,
      height: 14,
      padding: 15,
      position: "absolute",
      right: 0,
      top: 0,
      width: 14
    },
    buttonSkip: {
      ...buttonBase,
      color: options.textColor,
      fontSize: 14
    },
    overlay: {
      ...overlay,
      backgroundColor: options.overlayColor,
      mixBlendMode: "hard-light"
    },
    overlayLegacy: {
      ...overlay
    },
    overlayLegacyCenter: {
      ...overlay,
      backgroundColor: options.overlayColor
    },
    spotlight: {
      ...spotlight,
      backgroundColor: "gray"
    },
    spotlightLegacy: {
      ...spotlight,
      boxShadow: `0 0 0 9999px ${options.overlayColor}, ${options.spotlightShadow}`
    },
    floaterStyles: {
      arrow: {
        color: (_e = (_d = (_c = mergedFloaterProps == null ? void 0 : mergedFloaterProps.styles) == null ? void 0 : _c.arrow) == null ? void 0 : _d.color) != null ? _e : options.arrowColor
      },
      options: {
        zIndex: options.zIndex + 100
      }
    },
    options
  };
  return (0, import_deepmerge.default)(defaultStyles, mergedStyles);
}
// src/modules/step.ts
function getTourProps(props) {
  return pick(
    props,
    "beaconComponent",
    "disableCloseOnEsc",
    "disableOverlay",
    "disableOverlayClose",
    "disableScrolling",
    "disableScrollParentFix",
    "floaterProps",
    "hideBackButton",
    "hideCloseButton",
    "locale",
    "showProgress",
    "showSkipButton",
    "spotlightClicks",
    "spotlightPadding",
    "styles",
    "tooltipComponent"
  );
}
function getMergedStep(props, currentStep) {
  var _a, _b, _c, _d, _e, _f;
  const step = currentStep != null ? currentStep : {};
  const mergedStep = import_deepmerge2.default.all([defaultStep, getTourProps(props), step], {
    isMergeableObject: import_is_lite2.default.plainObject
  });
  const mergedStyles = getStyles(props, mergedStep);
  const scrollParent2 = hasCustomScrollParent(
    getElement(mergedStep.target),
    mergedStep.disableScrollParentFix
  );
  const floaterProps = import_deepmerge2.default.all([
    defaultFloaterProps,
    (_a = props.floaterProps) != null ? _a : {},
    (_b = mergedStep.floaterProps) != null ? _b : {}
  ]);
  floaterProps.offset = mergedStep.offset;
  floaterProps.styles = (0, import_deepmerge2.default)((_c = floaterProps.styles) != null ? _c : {}, mergedStyles.floaterStyles);
  floaterProps.offset += (_e = (_d = props.spotlightPadding) != null ? _d : mergedStep.spotlightPadding) != null ? _e : 0;
  if (mergedStep.placementBeacon && floaterProps.wrapperOptions) {
    floaterProps.wrapperOptions.placement = mergedStep.placementBeacon;
  }
  if (scrollParent2 && floaterProps.options.preventOverflow) {
    floaterProps.options.preventOverflow.boundariesElement = "window";
  }
  return {
    ...mergedStep,
    locale: import_deepmerge2.default.all([defaultLocale, (_f = props.locale) != null ? _f : {}, mergedStep.locale || {}]),
    floaterProps,
    styles: omit(mergedStyles, "floaterStyles")
  };
}
function validateStep(step, debug = false) {
  if (!import_is_lite2.default.plainObject(step)) {
    log({
      title: "validateStep",
      data: "step must be an object",
      warn: true,
      debug
    });
    return false;
  }
  if (!step.target) {
    log({
      title: "validateStep",
      data: "target is missing from the step",
      warn: true,
      debug
    });
    return false;
  }
  return true;
}
function validateSteps(steps, debug = false) {
  if (!import_is_lite2.default.array(steps)) {
    log({
      title: "validateSteps",
      data: "steps must be an array",
      warn: true,
      debug
    });
    return false;
  }
  return steps.every((d) => validateStep(d, debug));
}
// src/modules/store.ts
var import_is_lite3 = __toESM(require("is-lite"));
var defaultState = {
  action: "init",
  controlled: false,
  index: 0,
  lifecycle: LIFECYCLE.INIT,
  origin: null,
  size: 0,
  status: STATUS.IDLE
};
var validKeys = objectKeys(omit(defaultState, "controlled", "size"));
var Store = class {
  constructor(options) {
    this.data = /* @__PURE__ */ new Map();
    this.store = /* @__PURE__ */ new Map();
    this.addListener = (listener) => {
      this.listener = listener;
    };
    this.setSteps = (steps) => {
      const { size, status } = this.getState();
      const state = {
        size: steps.length,
        status
      };
      this.data.set("steps", steps);
      if (status === STATUS.WAITING && !size && steps.length) {
        state.status = STATUS.RUNNING;
      }
      this.setState(state);
    };
    this.getPopper = (name) => {
      if (name === "beacon") {
        return this.beaconPopper;
      }
      return this.tooltipPopper;
    };
    this.setPopper = (name, popper) => {
      if (name === "beacon") {
        this.beaconPopper = popper;
      } else {
        this.tooltipPopper = popper;
      }
    };
    this.cleanupPoppers = () => {
      this.beaconPopper = null;
      this.tooltipPopper = null;
    };
    this.close = (origin = null) => {
      const { index, status } = this.getState();
      if (status !== STATUS.RUNNING) {
        return;
      }
      this.setState({
        ...this.getNextState({ action: ACTIONS.CLOSE, index: index + 1, origin })
      });
    };
    this.go = (nextIndex) => {
      const { controlled, status } = this.getState();
      if (controlled || status !== STATUS.RUNNING) {
        return;
      }
      const step = this.getSteps()[nextIndex];
      this.setState({
        ...this.getNextState({ action: ACTIONS.GO, index: nextIndex }),
        status: step ? status : STATUS.FINISHED
      });
    };
    this.info = () => this.getState();
    this.next = () => {
      const { index, status } = this.getState();
      if (status !== STATUS.RUNNING) {
        return;
      }
      this.setState(this.getNextState({ action: ACTIONS.NEXT, index: index + 1 }));
    };
    this.open = () => {
      const { status } = this.getState();
      if (status !== STATUS.RUNNING) {
        return;
      }
      this.setState({
        ...this.getNextState({ action: ACTIONS.UPDATE, lifecycle: LIFECYCLE.TOOLTIP })
      });
    };
    this.prev = () => {
      const { index, status } = this.getState();
      if (status !== STATUS.RUNNING) {
        return;
      }
      this.setState({
        ...this.getNextState({ action: ACTIONS.PREV, index: index - 1 })
      });
    };
    this.reset = (restart = false) => {
      const { controlled } = this.getState();
      if (controlled) {
        return;
      }
      this.setState({
        ...this.getNextState({ action: ACTIONS.RESET, index: 0 }),
        status: restart ? STATUS.RUNNING : STATUS.READY
      });
    };
    this.skip = () => {
      const { status } = this.getState();
      if (status !== STATUS.RUNNING) {
        return;
      }
      this.setState({
        action: ACTIONS.SKIP,
        lifecycle: LIFECYCLE.INIT,
        status: STATUS.SKIPPED
      });
    };
    this.start = (nextIndex) => {
      const { index, size } = this.getState();
      this.setState({
        ...this.getNextState(
          {
            action: ACTIONS.START,
            index: import_is_lite3.default.number(nextIndex) ? nextIndex : index
          },
          true
        ),
        status: size ? STATUS.RUNNING : STATUS.WAITING
      });
    };
    this.stop = (advance = false) => {
      const { index, status } = this.getState();
      if ([STATUS.FINISHED, STATUS.SKIPPED].includes(status)) {
        return;
      }
      this.setState({
        ...this.getNextState({ action: ACTIONS.STOP, index: index + (advance ? 1 : 0) }),
        status: STATUS.PAUSED
      });
    };
    this.update = (state) => {
      var _a, _b;
      if (!hasValidKeys(state, validKeys)) {
        throw new Error(`State is not valid. Valid keys: ${validKeys.join(", ")}`);
      }
      this.setState({
        ...this.getNextState(
          {
            ...this.getState(),
            ...state,
            action: (_a = state.action) != null ? _a : ACTIONS.UPDATE,
            origin: (_b = state.origin) != null ? _b : null
          },
          true
        )
      });
    };
    const { continuous = false, stepIndex, steps = [] } = options != null ? options : {};
    this.setState(
      {
        action: ACTIONS.INIT,
        controlled: import_is_lite3.default.number(stepIndex),
        continuous,
        index: import_is_lite3.default.number(stepIndex) ? stepIndex : 0,
        lifecycle: LIFECYCLE.INIT,
        origin: null,
        status: steps.length ? STATUS.READY : STATUS.IDLE
      },
      true
    );
    this.beaconPopper = null;
    this.tooltipPopper = null;
    this.listener = null;
    this.setSteps(steps);
  }
  getState() {
    if (!this.store.size) {
      return { ...defaultState };
    }
    return {
      action: this.store.get("action") || "",
      controlled: this.store.get("controlled") || false,
      index: parseInt(this.store.get("index"), 10),
      lifecycle: this.store.get("lifecycle") || "",
      origin: this.store.get("origin") || null,
      size: this.store.get("size") || 0,
      status: this.store.get("status") || ""
    };
  }
  getNextState(state, force = false) {
    var _a, _b, _c, _d, _e;
    const { action, controlled, index, size, status } = this.getState();
    const newIndex = import_is_lite3.default.number(state.index) ? state.index : index;
    const nextIndex = controlled && !force ? index : Math.min(Math.max(newIndex, 0), size);
    return {
      action: (_a = state.action) != null ? _a : action,
      controlled,
      index: nextIndex,
      lifecycle: (_b = state.lifecycle) != null ? _b : LIFECYCLE.INIT,
      origin: (_c = state.origin) != null ? _c : null,
      size: (_d = state.size) != null ? _d : size,
      status: nextIndex === size ? STATUS.FINISHED : (_e = state.status) != null ? _e : status
    };
  }
  getSteps() {
    const steps = this.data.get("steps");
    return Array.isArray(steps) ? steps : [];
  }
  hasUpdatedState(oldState) {
    const before = JSON.stringify(oldState);
    const after = JSON.stringify(this.getState());
    return before !== after;
  }
  setState(nextState, initial = false) {
    const state = this.getState();
    const {
      action,
      index,
      lifecycle,
      origin = null,
      size,
      status
    } = {
      ...state,
      ...nextState
    };
    this.store.set("action", action);
    this.store.set("index", index);
    this.store.set("lifecycle", lifecycle);
    this.store.set("origin", origin);
    this.store.set("size", size);
    this.store.set("status", status);
    if (initial) {
      this.store.set("controlled", nextState.controlled);
      this.store.set("continuous", nextState.continuous);
    }
    if (this.listener && this.hasUpdatedState(state)) {
      this.listener(this.getState());
    }
  }
  getHelpers() {
    return {
      close: this.close,
      go: this.go,
      info: this.info,
      next: this.next,
      open: this.open,
      prev: this.prev,
      reset: this.reset,
      skip: this.skip
    };
  }
};
function createStore(options) {
  return new Store(options);
}
// src/components/Overlay.tsx
var React2 = __toESM(require("react"));
var import_tree_changes = __toESM(require("tree-changes"));
// src/components/Spotlight.tsx
var React = __toESM(require("react"));
function JoyrideSpotlight({ styles }) {
  return /* @__PURE__ */ React.createElement(
    "div",
    {
      key: "JoyrideSpotlight",
      className: "react-joyride__spotlight",
      "data-test-id": "spotlight",
      style: styles
    }
  );
}
var Spotlight_default = JoyrideSpotlight;
// src/components/Overlay.tsx
var JoyrideOverlay = class extends React2.Component {
  constructor() {
    super(...arguments);
    this.isActive = false;
    this.state = {
      isScrolling: false,
      mouseOverSpotlight: false,
      showSpotlight: true
    };
    this.hideSpotlight = () => {
      const { continuous, disableOverlay, lifecycle } = this.props;
      const hiddenLifecycles = [
        LIFECYCLE.INIT,
        LIFECYCLE.BEACON,
        LIFECYCLE.COMPLETE,
        LIFECYCLE.ERROR
      ];
      return disableOverlay || (continuous ? hiddenLifecycles.includes(lifecycle) : lifecycle !== LIFECYCLE.TOOLTIP);
    };
    this.handleMouseMove = (event) => {
      const { mouseOverSpotlight } = this.state;
      const { height, left, position, top, width } = this.spotlightStyles;
      const offsetY = position === "fixed" ? event.clientY : event.pageY;
      const offsetX = position === "fixed" ? event.clientX : event.pageX;
      const inSpotlightHeight = offsetY >= top && offsetY <= top + height;
      const inSpotlightWidth = offsetX >= left && offsetX <= left + width;
      const inSpotlight = inSpotlightWidth && inSpotlightHeight;
      if (inSpotlight !== mouseOverSpotlight) {
        this.updateState({ mouseOverSpotlight: inSpotlight });
      }
    };
    this.handleScroll = () => {
      const { target } = this.props;
      const element = getElement(target);
      if (this.scrollParent !== document) {
        const { isScrolling } = this.state;
        if (!isScrolling) {
          this.updateState({ isScrolling: true, showSpotlight: false });
        }
        clearTimeout(this.scrollTimeout);
        this.scrollTimeout = window.setTimeout(() => {
          this.updateState({ isScrolling: false, showSpotlight: true });
        }, 50);
      } else if (hasPosition(element, "sticky")) {
        this.updateState({});
      }
    };
    this.handleResize = () => {
      clearTimeout(this.resizeTimeout);
      this.resizeTimeout = window.setTimeout(() => {
        if (!this.isActive) {
          return;
        }
        this.forceUpdate();
      }, 100);
    };
  }
  componentDidMount() {
    const { debug, disableScrolling, disableScrollParentFix = false, target } = this.props;
    const element = getElement(target);
    this.scrollParent = getScrollParent(element != null ? element : document.body, disableScrollParentFix, true);
    this.isActive = true;
    if (process.env.NODE_ENV !== "production") {
      if (!disableScrolling && hasCustomScrollParent(element, true)) {
        log({
          title: "step has a custom scroll parent and can cause trouble with scrolling",
          data: [{ key: "parent", value: this.scrollParent }],
          debug
        });
      }
    }
    window.addEventListener("resize", this.handleResize);
  }
  componentDidUpdate(previousProps) {
    var _a;
    const { lifecycle, spotlightClicks } = this.props;
    const { changed } = (0, import_tree_changes.default)(previousProps, this.props);
    if (changed("lifecycle", LIFECYCLE.TOOLTIP)) {
      (_a = this.scrollParent) == null ? void 0 : _a.addEventListener("scroll", this.handleScroll, { passive: true });
      setTimeout(() => {
        const { isScrolling } = this.state;
        if (!isScrolling) {
          this.updateState({ showSpotlight: true });
        }
      }, 100);
    }
    if (changed("spotlightClicks") || changed("disableOverlay") || changed("lifecycle")) {
      if (spotlightClicks && lifecycle === LIFECYCLE.TOOLTIP) {
        window.addEventListener("mousemove", this.handleMouseMove, false);
      } else if (lifecycle !== LIFECYCLE.TOOLTIP) {
        window.removeEventListener("mousemove", this.handleMouseMove);
      }
    }
  }
  componentWillUnmount() {
    var _a;
    this.isActive = false;
    window.removeEventListener("mousemove", this.handleMouseMove);
    window.removeEventListener("resize", this.handleResize);
    clearTimeout(this.resizeTimeout);
    clearTimeout(this.scrollTimeout);
    (_a = this.scrollParent) == null ? void 0 : _a.removeEventListener("scroll", this.handleScroll);
  }
  get overlayStyles() {
    const { mouseOverSpotlight } = this.state;
    const { disableOverlayClose, placement, styles } = this.props;
    let baseStyles = styles.overlay;
    if (isLegacy()) {
      baseStyles = placement === "center" ? styles.overlayLegacyCenter : styles.overlayLegacy;
    }
    return {
      cursor: disableOverlayClose ? "default" : "pointer",
      height: getDocumentHeight(),
      pointerEvents: mouseOverSpotlight ? "none" : "auto",
      ...baseStyles
    };
  }
  get spotlightStyles() {
    var _a, _b, _c;
    const { showSpotlight } = this.state;
    const {
      disableScrollParentFix = false,
      spotlightClicks,
      spotlightPadding = 0,
      styles,
      target
    } = this.props;
    const element = getElement(target);
    const elementRect = getClientRect(element);
    const isFixedTarget = hasPosition(element);
    const top = getElementPosition(element, spotlightPadding, disableScrollParentFix);
    return {
      ...isLegacy() ? styles.spotlightLegacy : styles.spotlight,
      height: Math.round(((_a = elementRect == null ? void 0 : elementRect.height) != null ? _a : 0) + spotlightPadding * 2),
      left: Math.round(((_b = elementRect == null ? void 0 : elementRect.left) != null ? _b : 0) - spotlightPadding),
      opacity: showSpotlight ? 1 : 0,
      pointerEvents: spotlightClicks ? "none" : "auto",
      position: isFixedTarget ? "fixed" : "absolute",
      top,
      transition: "opacity 0.2s",
      width: Math.round(((_c = elementRect == null ? void 0 : elementRect.width) != null ? _c : 0) + spotlightPadding * 2)
    };
  }
  updateState(state) {
    if (!this.isActive) {
      return;
    }
    this.setState((previousState) => ({ ...previousState, ...state }));
  }
  render() {
    const { showSpotlight } = this.state;
    const { onClickOverlay, placement } = this.props;
    const { hideSpotlight, overlayStyles, spotlightStyles } = this;
    if (hideSpotlight()) {
      return null;
    }
    let spotlight2 = placement !== "center" && showSpotlight && /* @__PURE__ */ React2.createElement(Spotlight_default, { styles: spotlightStyles });
    if (getBrowser() === "safari") {
      const { mixBlendMode, zIndex, ...safariOverlay } = overlayStyles;
      spotlight2 = /* @__PURE__ */ React2.createElement("div", { style: { ...safariOverlay } }, spotlight2);
      delete overlayStyles.backgroundColor;
    }
    return /* @__PURE__ */ React2.createElement(
      "div",
      {
        className: "react-joyride__overlay",
        "data-test-id": "overlay",
        onClick: onClickOverlay,
        role: "presentation",
        style: overlayStyles
      },
      spotlight2
    );
  }
};
// src/components/Portal.tsx
var React3 = __toESM(require("react"));
var ReactDOM = __toESM(require("react-dom"));
var import_client = require("react-dom/client");
var JoyridePortal = class extends React3.Component {
  constructor() {
    super(...arguments);
    this.node = null;
    this.rootNode = null;
  }
  componentDidMount() {
    const { id } = this.props;
    if (!canUseDOM()) {
      return;
    }
    this.node = document.createElement("div");
    this.node.id = id;
    document.body.appendChild(this.node);
    if (!isReact16) {
      throw new Error("react-joyride requires React 16.3 or later.");
    }
    this.rootNode = (0, import_client.createRoot)(this.node);
    this.rootNode.render(this.props.children);
  }
  componentDidUpdate() {
    if (!canUseDOM()) {
      return;
    }
    if (!isReact16) {
      throw new Error("react-joyride requires React 16.3 or later.");
    }
  }
  componentWillUnmount() {
    var _a;
    if (!canUseDOM() || !this.node) {
      return;
    }
    if (!isReact16) {
      (_a = this.rootNode) == null ? void 0 : _a.unmount();
    }
    if (this.node.parentNode === document.body) {
      document.body.removeChild(this.node);
      this.node = null;
    }
  }
  renderReact16() {
    if (!canUseDOM() || !isReact16 || !this.node) {
      return null;
    }
    const { children } = this.props;
    return ReactDOM.createPortal(children, this.node);
  }
  render() {
    if (!isReact16) {
      return null;
    }
    return this.renderReact16();
  }
};
// src/components/Step.tsx
var React8 = __toESM(require("react"));
var import_react_floater = __toESM(require("react-floater"));
var import_is_lite5 = __toESM(require("is-lite"));
var import_tree_changes2 = __toESM(require("tree-changes"));
// src/modules/scope.ts
var Scope = class {
  constructor(element, options) {
    this.canBeTabbed = (element) => {
      const { tabIndex } = element;
      if (tabIndex === null || tabIndex < 0) {
        return false;
      }
      return this.canHaveFocus(element);
    };
    this.canHaveFocus = (element) => {
      const validTabNodes = /input|select|textarea|button|object/;
      const nodeName = element.nodeName.toLowerCase();
      const isValid = validTabNodes.test(nodeName) && !element.getAttribute("disabled") || nodeName === "a" && !!element.getAttribute("href");
      return isValid && this.isVisible(element);
    };
    this.findValidTabElements = () => [].slice.call(this.element.querySelectorAll("*"), 0).filter(this.canBeTabbed);
    this.handleKeyDown = (event) => {
      const { code = "Tab" } = this.options;
      if (event.code === code) {
        this.interceptTab(event);
      }
    };
    this.interceptTab = (event) => {
      event.preventDefault();
      const elements = this.findValidTabElements();
      const { shiftKey } = event;
      if (!elements.length) {
        return;
      }
      let x = document.activeElement ? elements.indexOf(document.activeElement) : 0;
      if (x === -1 || !shiftKey && x + 1 === elements.length) {
        x = 0;
      } else if (shiftKey && x === 0) {
        x = elements.length - 1;
      } else {
        x += shiftKey ? -1 : 1;
      }
      elements[x].focus();
    };
    // eslint-disable-next-line class-methods-use-this
    this.isHidden = (element) => {
      const noSize = element.offsetWidth <= 0 && element.offsetHeight <= 0;
      const style = window.getComputedStyle(element);
      if (noSize && !element.innerHTML) {
        return true;
      }
      return noSize && style.getPropertyValue("overflow") !== "visible" || style.getPropertyValue("display") === "none";
    };
    this.isVisible = (element) => {
      let parentElement = element;
      while (parentElement) {
        if (parentElement instanceof HTMLElement) {
          if (parentElement === document.body) {
            break;
          }
          if (this.isHidden(parentElement)) {
            return false;
          }
          parentElement = parentElement.parentNode;
        }
      }
      return true;
    };
    this.removeScope = () => {
      window.removeEventListener("keydown", this.handleKeyDown);
    };
    this.checkFocus = (target) => {
      if (document.activeElement !== target) {
        target.focus();
        window.requestAnimationFrame(() => this.checkFocus(target));
      }
    };
    this.setFocus = () => {
      const { selector } = this.options;
      if (!selector) {
        return;
      }
      const target = this.element.querySelector(selector);
      if (target) {
        window.requestAnimationFrame(() => this.checkFocus(target));
      }
    };
    if (!(element instanceof HTMLElement)) {
      throw new TypeError("Invalid parameter: element must be an HTMLElement");
    }
    this.element = element;
    this.options = options;
    window.addEventListener("keydown", this.handleKeyDown, false);
    this.setFocus();
  }
};
// src/components/Beacon.tsx
var React4 = __toESM(require("react"));
var import_react_innertext = __toESM(require("react-innertext"));
var import_is_lite4 = __toESM(require("is-lite"));
var JoyrideBeacon = class extends React4.Component {
  constructor(props) {
    super(props);
    this.beacon = null;
    this.setBeaconRef = (c) => {
      this.beacon = c;
    };
    if (props.beaconComponent) {
      return;
    }
    const head = document.head || document.getElementsByTagName("head")[0];
    const style = document.createElement("style");
    style.id = "joyride-beacon-animation";
    if (props.nonce) {
      style.setAttribute("nonce", props.nonce);
    }
    const css = `
        @keyframes joyride-beacon-inner {
          20% {
            opacity: 0.9;
          }
        
          90% {
            opacity: 0.7;
          }
        }
        
        @keyframes joyride-beacon-outer {
          0% {
            transform: scale(1);
          }
        
          45% {
            opacity: 0.7;
            transform: scale(0.75);
          }
        
          100% {
            opacity: 0.9;
            transform: scale(1);
          }
        }
      `;
    style.appendChild(document.createTextNode(css));
    head.appendChild(style);
  }
  componentDidMount() {
    const { shouldFocus } = this.props;
    if (process.env.NODE_ENV !== "production") {
      if (!import_is_lite4.default.domElement(this.beacon)) {
        console.warn("beacon is not a valid DOM element");
      }
    }
    setTimeout(() => {
      if (import_is_lite4.default.domElement(this.beacon) && shouldFocus) {
        this.beacon.focus();
      }
    }, 0);
  }
  componentWillUnmount() {
    const style = document.getElementById("joyride-beacon-animation");
    if (style == null ? void 0 : style.parentNode) {
      style.parentNode.removeChild(style);
    }
  }
  render() {
    const {
      beaconComponent,
      continuous,
      index,
      isLastStep,
      locale,
      onClickOrHover,
      size,
      step,
      styles
    } = this.props;
    const title = import_is_lite4.default.string(locale.open) ? locale.open : (0, import_react_innertext.default)(locale.open);
    const sharedProps = {
      "aria-label": title,
      onClick: onClickOrHover,
      onMouseEnter: onClickOrHover,
      ref: this.setBeaconRef,
      title
    };
    let component;
    if (beaconComponent) {
      const BeaconComponent = beaconComponent;
      component = /* @__PURE__ */ React4.createElement(
        BeaconComponent,
        {
          continuous,
          index,
          isLastStep,
          size,
          step,
          ...sharedProps
        }
      );
    } else {
      component = /* @__PURE__ */ React4.createElement(
        "button",
        {
          key: "JoyrideBeacon",
          className: "react-joyride__beacon",
          "data-test-id": "button-beacon",
          style: styles.beacon,
          type: "button",
          ...sharedProps
        },
        /* @__PURE__ */ React4.createElement("span", { style: styles.beaconInner }),
        /* @__PURE__ */ React4.createElement("span", { style: styles.beaconOuter })
      );
    }
    return component;
  }
};
// src/components/Tooltip/index.tsx
var React7 = __toESM(require("react"));
// src/components/Tooltip/Container.tsx
var React6 = __toESM(require("react"));
// src/components/Tooltip/CloseButton.tsx
var import_react2 = __toESM(require("react"));
function JoyrideTooltipCloseButton({ styles, ...props }) {
  const { color, height, width, ...style } = styles;
  return /* @__PURE__ */ import_react2.default.createElement("button", { style, type: "button", ...props }, /* @__PURE__ */ import_react2.default.createElement(
    "svg",
    {
      height: typeof height === "number" ? `${height}px` : height,
      preserveAspectRatio: "xMidYMid",
      version: "1.1",
      viewBox: "0 0 18 18",
      width: typeof width === "number" ? `${width}px` : width,
      xmlns: "http://www.w3.org/2000/svg"
    },
    /* @__PURE__ */ import_react2.default.createElement("g", null, /* @__PURE__ */ import_react2.default.createElement(
      "path",
      {
        d: "M8.13911129,9.00268191 L0.171521827,17.0258467 C-0.0498027049,17.248715 -0.0498027049,17.6098394 0.171521827,17.8327545 C0.28204354,17.9443526 0.427188206,17.9998706 0.572051765,17.9998706 C0.71714958,17.9998706 0.862013139,17.9443526 0.972581703,17.8327545 L9.0000937,9.74924618 L17.0276057,17.8327545 C17.1384085,17.9443526 17.2832721,17.9998706 17.4281356,17.9998706 C17.5729992,17.9998706 17.718097,17.9443526 17.8286656,17.8327545 C18.0499901,17.6098862 18.0499901,17.2487618 17.8286656,17.0258467 L9.86135722,9.00268191 L17.8340066,0.973848225 C18.0553311,0.750979934 18.0553311,0.389855532 17.8340066,0.16694039 C17.6126821,-0.0556467968 17.254037,-0.0556467968 17.0329467,0.16694039 L9.00042166,8.25611765 L0.967006424,0.167268345 C0.745681892,-0.0553188426 0.387317931,-0.0553188426 0.165993399,0.167268345 C-0.0553311331,0.390136635 -0.0553311331,0.751261038 0.165993399,0.974176179 L8.13920499,9.00268191 L8.13911129,9.00268191 Z",
        fill: color
      }
    ))
  ));
}
var CloseButton_default = JoyrideTooltipCloseButton;
// src/components/Tooltip/Container.tsx
function JoyrideTooltipContainer(props) {
  const { backProps, closeProps, index, isLastStep, primaryProps, skipProps, step, tooltipProps } = props;
  const { content, hideBackButton, hideCloseButton, hideFooter, showSkipButton, styles, title } = step;
  const output = {
    primary: primaryProps.title
  };
  if (output.primary) {
    output.primary = /* @__PURE__ */ React6.createElement(
      "button",
      {
        "data-test-id": "button-primary",
        style: styles.buttonNext,
        type: "button",
        ...primaryProps
      },
      output.primary
    );
  }
  if (showSkipButton && !isLastStep) {
    output.skip = /* @__PURE__ */ React6.createElement(
      "button",
      {
        "aria-live": "off",
        "data-test-id": "button-skip",
        style: styles.buttonSkip,
        type: "button",
        ...skipProps
      },
      skipProps.title
    );
  }
  if (!hideBackButton && index > 0) {
    output.back = /* @__PURE__ */ React6.createElement("button", { "data-test-id": "button-back", style: styles.buttonBack, type: "button", ...backProps }, backProps.title);
  }
  output.close = !hideCloseButton && /* @__PURE__ */ React6.createElement(CloseButton_default, { "data-test-id": "button-close", styles: styles.buttonClose, ...closeProps });
  return /* @__PURE__ */ React6.createElement(
    "div",
    {
      key: "JoyrideTooltip",
      "aria-label": getText(title) || getText(content),
      className: "react-joyride__tooltip",
      style: styles.tooltip,
      ...tooltipProps
    },
    /* @__PURE__ */ React6.createElement("div", { style: styles.tooltipContainer }, title && /* @__PURE__ */ React6.createElement("h1", { "aria-label": getText(title), style: styles.tooltipTitle }, title), /* @__PURE__ */ React6.createElement("div", { style: styles.tooltipContent }, content)),
    !hideFooter && /* @__PURE__ */ React6.createElement("div", { style: styles.tooltipFooter }, /* @__PURE__ */ React6.createElement("div", { style: styles.tooltipFooterSpacer }, output.skip), output.back, output.primary),
    output.close
  );
}
var Container_default = JoyrideTooltipContainer;
// src/components/Tooltip/index.tsx
var JoyrideTooltip = class extends React7.Component {
  constructor() {
    super(...arguments);
    this.handleClickBack = (event) => {
      event.preventDefault();
      const { helpers } = this.props;
      helpers.prev();
    };
    this.handleClickClose = (event) => {
      event.preventDefault();
      const { helpers } = this.props;
      helpers.close("button_close");
    };
    this.handleClickPrimary = (event) => {
      event.preventDefault();
      const { continuous, helpers } = this.props;
      if (!continuous) {
        helpers.close("button_primary");
        return;
      }
      helpers.next();
    };
    this.handleClickSkip = (event) => {
      event.preventDefault();
      const { helpers } = this.props;
      helpers.skip();
    };
    this.getElementsProps = () => {
      const { continuous, index, isLastStep, setTooltipRef, size, step } = this.props;
      const back = getText(step.locale.back);
      const close = getText(step.locale.close);
      const last = getText(step.locale.last);
      const next = getText(step.locale.next);
      const skip = getText(step.locale.skip);
      let primaryLabel = close;
      let primaryText = close;
      if (continuous) {
        primaryLabel = next;
        primaryText = next;
        if (step.showProgress && !isLastStep) {
          primaryLabel = getText(step.locale.nextLabelWithProgress).replace("{step}", String(index + 1)).replace("{steps}", String(size));
          primaryText = `${next} (${index + 1}/${size})`;
        }
        if (isLastStep) {
          primaryLabel = last;
          primaryText = last;
        }
      }
      return {
        backProps: {
          "aria-label": back,
          "data-action": "back",
          onClick: this.handleClickBack,
          role: "button",
          title: back
        },
        closeProps: {
          "aria-label": close,
          "data-action": "close",
          onClick: this.handleClickClose,
          role: "button",
          title: close
        },
        primaryProps: {
          "aria-label": primaryLabel,
          "data-action": "primary",
          onClick: this.handleClickPrimary,
          role: "button",
          title: primaryText
        },
        skipProps: {
          "aria-label": skip,
          "data-action": "skip",