index.mjs 61 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070
  1. var __defProp = Object.defineProperty;
  2. var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
  3. var __publicField = (obj, key, value) => {
  4. __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
  5. return value;
  6. };
  7. // src/literals/index.ts
  8. var ACTIONS = {
  9. INIT: "init",
  10. START: "start",
  11. STOP: "stop",
  12. RESET: "reset",
  13. PREV: "prev",
  14. NEXT: "next",
  15. GO: "go",
  16. CLOSE: "close",
  17. SKIP: "skip",
  18. UPDATE: "update"
  19. };
  20. var EVENTS = {
  21. TOUR_START: "tour:start",
  22. STEP_BEFORE: "step:before",
  23. BEACON: "beacon",
  24. TOOLTIP: "tooltip",
  25. STEP_AFTER: "step:after",
  26. TOUR_END: "tour:end",
  27. TOUR_STATUS: "tour:status",
  28. TARGET_NOT_FOUND: "error:target_not_found",
  29. ERROR: "error"
  30. };
  31. var LIFECYCLE = {
  32. INIT: "init",
  33. READY: "ready",
  34. BEACON: "beacon",
  35. TOOLTIP: "tooltip",
  36. COMPLETE: "complete",
  37. ERROR: "error"
  38. };
  39. var STATUS = {
  40. IDLE: "idle",
  41. READY: "ready",
  42. WAITING: "waiting",
  43. RUNNING: "running",
  44. PAUSED: "paused",
  45. SKIPPED: "skipped",
  46. FINISHED: "finished",
  47. ERROR: "error"
  48. };
  49. // src/components/index.tsx
  50. import * as React9 from "react";
  51. import isEqual from "@gilbarbara/deep-equal";
  52. import is6 from "is-lite";
  53. import treeChanges3 from "tree-changes";
  54. // src/modules/dom.ts
  55. import scroll from "scroll";
  56. import scrollParent from "scrollparent";
  57. function canUseDOM() {
  58. return !!(typeof window !== "undefined" && window.document && window.document.createElement);
  59. }
  60. function getClientRect(element) {
  61. if (!element) {
  62. return null;
  63. }
  64. return element.getBoundingClientRect();
  65. }
  66. function getDocumentHeight() {
  67. const { body, documentElement } = document;
  68. if (!body || !documentElement) {
  69. return 0;
  70. }
  71. return Math.max(
  72. body.scrollHeight,
  73. body.offsetHeight,
  74. documentElement.clientHeight,
  75. documentElement.scrollHeight,
  76. documentElement.offsetHeight
  77. );
  78. }
  79. function getElement(element) {
  80. if (typeof element === "string") {
  81. return document.querySelector(element);
  82. }
  83. return element;
  84. }
  85. function getStyleComputedProperty(el) {
  86. if (!el || el.nodeType !== 1) {
  87. return null;
  88. }
  89. return getComputedStyle(el);
  90. }
  91. function getScrollParent(element, skipFix, forListener) {
  92. if (!element) {
  93. return scrollDocument();
  94. }
  95. const parent = scrollParent(element);
  96. if (parent) {
  97. if (parent.isSameNode(scrollDocument())) {
  98. if (forListener) {
  99. return document;
  100. }
  101. return scrollDocument();
  102. }
  103. const hasScrolling = parent.scrollHeight > parent.offsetHeight;
  104. if (!hasScrolling && !skipFix) {
  105. parent.style.overflow = "initial";
  106. return scrollDocument();
  107. }
  108. }
  109. return parent;
  110. }
  111. function hasCustomScrollParent(element, skipFix) {
  112. if (!element) {
  113. return false;
  114. }
  115. const parent = getScrollParent(element, skipFix);
  116. return parent ? !parent.isSameNode(scrollDocument()) : false;
  117. }
  118. function hasCustomOffsetParent(element) {
  119. return element.offsetParent !== document.body;
  120. }
  121. function hasPosition(el, type = "fixed") {
  122. if (!el || !(el instanceof HTMLElement)) {
  123. return false;
  124. }
  125. const { nodeName } = el;
  126. const styles = getStyleComputedProperty(el);
  127. if (nodeName === "BODY" || nodeName === "HTML") {
  128. return false;
  129. }
  130. if (styles && styles.position === type) {
  131. return true;
  132. }
  133. if (!el.parentNode) {
  134. return false;
  135. }
  136. return hasPosition(el.parentNode, type);
  137. }
  138. function isElementVisible(element) {
  139. var _a;
  140. if (!element) {
  141. return false;
  142. }
  143. let parentElement = element;
  144. while (parentElement) {
  145. if (parentElement === document.body) {
  146. break;
  147. }
  148. if (parentElement instanceof HTMLElement) {
  149. const { display, visibility } = getComputedStyle(parentElement);
  150. if (display === "none" || visibility === "hidden") {
  151. return false;
  152. }
  153. }
  154. parentElement = (_a = parentElement.parentElement) != null ? _a : null;
  155. }
  156. return true;
  157. }
  158. function getElementPosition(element, offset, skipFix) {
  159. var _a;
  160. const elementRect = getClientRect(element);
  161. const parent = getScrollParent(element, skipFix);
  162. const hasScrollParent = hasCustomScrollParent(element, skipFix);
  163. let parentTop = 0;
  164. let top = (_a = elementRect == null ? void 0 : elementRect.top) != null ? _a : 0;
  165. if (parent instanceof HTMLElement) {
  166. parentTop = parent.scrollTop;
  167. if (!hasScrollParent && !hasPosition(element)) {
  168. top += parentTop;
  169. }
  170. if (!parent.isSameNode(scrollDocument())) {
  171. top += scrollDocument().scrollTop;
  172. }
  173. }
  174. return Math.floor(top - offset);
  175. }
  176. function getScrollTo(element, offset, skipFix) {
  177. var _a;
  178. if (!element) {
  179. return 0;
  180. }
  181. const { offsetTop = 0, scrollTop = 0 } = (_a = scrollParent(element)) != null ? _a : {};
  182. let top = element.getBoundingClientRect().top + scrollTop;
  183. if (!!offsetTop && (hasCustomScrollParent(element, skipFix) || hasCustomOffsetParent(element))) {
  184. top -= offsetTop;
  185. }
  186. const output = Math.floor(top - offset);
  187. return output < 0 ? 0 : output;
  188. }
  189. function scrollDocument() {
  190. var _a;
  191. return (_a = document.scrollingElement) != null ? _a : document.documentElement;
  192. }
  193. function scrollTo(value, options) {
  194. const { duration, element } = options;
  195. return new Promise((resolve, reject) => {
  196. const { scrollTop } = element;
  197. const limit = value > scrollTop ? value - scrollTop : scrollTop - value;
  198. scroll.top(element, value, { duration: limit < 100 ? 50 : duration }, (error) => {
  199. if (error && error.message !== "Element already at target scroll position") {
  200. return reject(error);
  201. }
  202. return resolve();
  203. });
  204. });
  205. }
  206. // src/modules/helpers.ts
  207. import { isValidElement } from "react";
  208. import { createPortal } from "react-dom";
  209. import is from "is-lite";
  210. var isReact16 = createPortal !== void 0;
  211. function getBrowser(userAgent = navigator.userAgent) {
  212. let browser = userAgent;
  213. if (typeof window === "undefined") {
  214. browser = "node";
  215. } else if (document.documentMode) {
  216. browser = "ie";
  217. } else if (/Edge/.test(userAgent)) {
  218. browser = "edge";
  219. } else if (Boolean(window.opera) || userAgent.includes(" OPR/")) {
  220. browser = "opera";
  221. } else if (typeof window.InstallTrigger !== "undefined") {
  222. browser = "firefox";
  223. } else if (window.chrome) {
  224. browser = "chrome";
  225. } else if (/(Version\/([\d._]+).*Safari|CriOS|FxiOS| Mobile\/)/.test(userAgent)) {
  226. browser = "safari";
  227. }
  228. return browser;
  229. }
  230. function getText(root) {
  231. const content = [];
  232. const recurse = (child) => {
  233. if (typeof child === "string" || typeof child === "number") {
  234. content.push(child);
  235. } else if (Array.isArray(child)) {
  236. child.forEach((c) => recurse(c));
  237. } else if (isValidElement(child)) {
  238. const { children } = child.props;
  239. if (Array.isArray(children)) {
  240. children.forEach((c) => recurse(c));
  241. } else {
  242. recurse(children);
  243. }
  244. }
  245. };
  246. recurse(root);
  247. return content.join(" ").trim();
  248. }
  249. function hasValidKeys(object, keys) {
  250. if (!is.plainObject(object) || !is.array(keys)) {
  251. return false;
  252. }
  253. return Object.keys(object).every((d) => keys.includes(d));
  254. }
  255. function hexToRGB(hex) {
  256. const shorthandRegex = /^#?([\da-f])([\da-f])([\da-f])$/i;
  257. const properHex = hex.replace(shorthandRegex, (_m, r, g, b) => r + r + g + g + b + b);
  258. const result = /^#?([\da-f]{2})([\da-f]{2})([\da-f]{2})$/i.exec(properHex);
  259. return result ? [parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16)] : [];
  260. }
  261. function hideBeacon(step) {
  262. return step.disableBeacon || step.placement === "center";
  263. }
  264. function isLegacy() {
  265. return !["chrome", "safari", "firefox", "opera"].includes(getBrowser());
  266. }
  267. function log({ data, debug = false, title, warn = false }) {
  268. const logFn = warn ? console.warn || console.error : console.log;
  269. if (debug) {
  270. if (title && data) {
  271. console.groupCollapsed(
  272. `%creact-joyride: ${title}`,
  273. "color: #ff0044; font-weight: bold; font-size: 12px;"
  274. );
  275. if (Array.isArray(data)) {
  276. data.forEach((d) => {
  277. if (is.plainObject(d) && d.key) {
  278. logFn.apply(console, [d.key, d.value]);
  279. } else {
  280. logFn.apply(console, [d]);
  281. }
  282. });
  283. } else {
  284. logFn.apply(console, [data]);
  285. }
  286. console.groupEnd();
  287. } else {
  288. console.error("Missing title or data props");
  289. }
  290. }
  291. }
  292. function shouldScroll(options) {
  293. const { isFirstStep, lifecycle, previousLifecycle, scrollToFirstStep, step, target } = options;
  294. return !step.disableScrolling && (!isFirstStep || scrollToFirstStep || lifecycle === LIFECYCLE.TOOLTIP) && step.placement !== "center" && (!step.isFixed || !hasPosition(target)) && // fixed steps don't need to scroll
  295. previousLifecycle !== lifecycle && [LIFECYCLE.BEACON, LIFECYCLE.TOOLTIP].includes(lifecycle);
  296. }
  297. // src/modules/step.ts
  298. import { omit, pick } from "@gilbarbara/helpers";
  299. import deepmerge2 from "deepmerge";
  300. import is2 from "is-lite";
  301. // src/defaults.ts
  302. import { noop } from "@gilbarbara/helpers";
  303. var defaultFloaterProps = {
  304. options: {
  305. preventOverflow: {
  306. boundariesElement: "scrollParent"
  307. }
  308. },
  309. wrapperOptions: {
  310. offset: -18,
  311. position: true
  312. }
  313. };
  314. var defaultLocale = {
  315. back: "Back",
  316. close: "Close",
  317. last: "Last",
  318. next: "Next",
  319. open: "Open the dialog",
  320. skip: "Skip"
  321. };
  322. var defaultStep = {
  323. event: "click",
  324. placement: "bottom",
  325. offset: 10,
  326. disableBeacon: false,
  327. disableCloseOnEsc: false,
  328. disableOverlay: false,
  329. disableOverlayClose: false,
  330. disableScrollParentFix: false,
  331. disableScrolling: false,
  332. hideBackButton: false,
  333. hideCloseButton: false,
  334. hideFooter: false,
  335. isFixed: false,
  336. locale: defaultLocale,
  337. showProgress: false,
  338. showSkipButton: false,
  339. spotlightClicks: false,
  340. spotlightPadding: 10
  341. };
  342. var defaultProps = {
  343. continuous: false,
  344. debug: false,
  345. disableCloseOnEsc: false,
  346. disableOverlay: false,
  347. disableOverlayClose: false,
  348. disableScrolling: false,
  349. disableScrollParentFix: false,
  350. getHelpers: noop(),
  351. hideBackButton: false,
  352. run: true,
  353. scrollOffset: 20,
  354. scrollDuration: 300,
  355. scrollToFirstStep: false,
  356. showSkipButton: false,
  357. showProgress: false,
  358. spotlightClicks: false,
  359. spotlightPadding: 10,
  360. steps: []
  361. };
  362. // src/styles.ts
  363. import deepmerge from "deepmerge";
  364. var defaultOptions = {
  365. arrowColor: "#fff",
  366. backgroundColor: "#fff",
  367. beaconSize: 36,
  368. overlayColor: "rgba(0, 0, 0, 0.5)",
  369. primaryColor: "#f04",
  370. spotlightShadow: "0 0 15px rgba(0, 0, 0, 0.5)",
  371. textColor: "#333",
  372. width: 380,
  373. zIndex: 100
  374. };
  375. var buttonBase = {
  376. backgroundColor: "transparent",
  377. border: 0,
  378. borderRadius: 0,
  379. color: "#555",
  380. cursor: "pointer",
  381. fontSize: 16,
  382. lineHeight: 1,
  383. padding: 8,
  384. WebkitAppearance: "none"
  385. };
  386. var spotlight = {
  387. borderRadius: 4,
  388. position: "absolute"
  389. };
  390. function getStyles(propsStyles, stepStyles) {
  391. const mergedStyles = deepmerge(propsStyles != null ? propsStyles : {}, stepStyles != null ? stepStyles : {});
  392. const options = deepmerge(defaultOptions, mergedStyles.options || {});
  393. let { width } = options;
  394. if (window.innerWidth > 480) {
  395. width = 380;
  396. }
  397. if ("width" in options) {
  398. width = typeof options.width === "number" && window.innerWidth < options.width ? window.innerWidth - 30 : options.width;
  399. }
  400. const overlay = {
  401. bottom: 0,
  402. left: 0,
  403. overflow: "hidden",
  404. position: "absolute",
  405. right: 0,
  406. top: 0,
  407. zIndex: options.zIndex
  408. };
  409. const defaultStyles = {
  410. beacon: {
  411. ...buttonBase,
  412. display: "inline-block",
  413. height: options.beaconSize,
  414. position: "relative",
  415. width: options.beaconSize,
  416. zIndex: options.zIndex
  417. },
  418. beaconInner: {
  419. animation: "joyride-beacon-inner 1.2s infinite ease-in-out",
  420. backgroundColor: options.primaryColor,
  421. borderRadius: "50%",
  422. display: "block",
  423. height: "50%",
  424. left: "50%",
  425. opacity: 0.7,
  426. position: "absolute",
  427. top: "50%",
  428. transform: "translate(-50%, -50%)",
  429. width: "50%"
  430. },
  431. beaconOuter: {
  432. animation: "joyride-beacon-outer 1.2s infinite ease-in-out",
  433. backgroundColor: `rgba(${hexToRGB(options.primaryColor).join(",")}, 0.2)`,
  434. border: `2px solid ${options.primaryColor}`,
  435. borderRadius: "50%",
  436. boxSizing: "border-box",
  437. display: "block",
  438. height: "100%",
  439. left: 0,
  440. opacity: 0.9,
  441. position: "absolute",
  442. top: 0,
  443. transformOrigin: "center",
  444. width: "100%"
  445. },
  446. tooltip: {
  447. backgroundColor: options.backgroundColor,
  448. borderRadius: 5,
  449. boxSizing: "border-box",
  450. color: options.textColor,
  451. fontSize: 16,
  452. maxWidth: "100%",
  453. padding: 15,
  454. position: "relative",
  455. width
  456. },
  457. tooltipContainer: {
  458. lineHeight: 1.4,
  459. textAlign: "center"
  460. },
  461. tooltipTitle: {
  462. fontSize: 18,
  463. margin: 0
  464. },
  465. tooltipContent: {
  466. padding: "20px 10px"
  467. },
  468. tooltipFooter: {
  469. alignItems: "center",
  470. display: "flex",
  471. justifyContent: "flex-end",
  472. marginTop: 15
  473. },
  474. tooltipFooterSpacer: {
  475. flex: 1
  476. },
  477. buttonNext: {
  478. ...buttonBase,
  479. backgroundColor: options.primaryColor,
  480. borderRadius: 4,
  481. color: "#fff"
  482. },
  483. buttonBack: {
  484. ...buttonBase,
  485. color: options.primaryColor,
  486. marginLeft: "auto",
  487. marginRight: 5
  488. },
  489. buttonClose: {
  490. ...buttonBase,
  491. color: options.textColor,
  492. height: 14,
  493. padding: 15,
  494. position: "absolute",
  495. right: 0,
  496. top: 0,
  497. width: 14
  498. },
  499. buttonSkip: {
  500. ...buttonBase,
  501. color: options.textColor,
  502. fontSize: 14
  503. },
  504. overlay: {
  505. ...overlay,
  506. backgroundColor: options.overlayColor,
  507. mixBlendMode: "hard-light"
  508. },
  509. overlayLegacy: {
  510. ...overlay
  511. },
  512. overlayLegacyCenter: {
  513. ...overlay,
  514. backgroundColor: options.overlayColor
  515. },
  516. spotlight: {
  517. ...spotlight,
  518. backgroundColor: "gray"
  519. },
  520. spotlightLegacy: {
  521. ...spotlight,
  522. boxShadow: `0 0 0 9999px ${options.overlayColor}, ${options.spotlightShadow}`
  523. },
  524. floaterStyles: {
  525. arrow: {
  526. color: options.arrowColor
  527. },
  528. options: {
  529. zIndex: options.zIndex + 100
  530. }
  531. },
  532. options
  533. };
  534. return deepmerge(defaultStyles, mergedStyles);
  535. }
  536. // src/modules/step.ts
  537. function getTourProps(props) {
  538. return pick(
  539. props,
  540. "beaconComponent",
  541. "disableCloseOnEsc",
  542. "disableOverlay",
  543. "disableOverlayClose",
  544. "disableScrolling",
  545. "disableScrollParentFix",
  546. "floaterProps",
  547. "hideBackButton",
  548. "hideCloseButton",
  549. "locale",
  550. "showProgress",
  551. "showSkipButton",
  552. "spotlightClicks",
  553. "spotlightPadding",
  554. "styles",
  555. "tooltipComponent"
  556. );
  557. }
  558. function getMergedStep(currentStep, props) {
  559. var _a, _b, _c, _d, _e, _f;
  560. const step = currentStep != null ? currentStep : {};
  561. const mergedStep = deepmerge2.all([defaultStep, getTourProps(props), step], {
  562. isMergeableObject: is2.plainObject
  563. });
  564. const mergedStyles = getStyles(props.styles, mergedStep.styles);
  565. const scrollParent2 = hasCustomScrollParent(
  566. getElement(mergedStep.target),
  567. mergedStep.disableScrollParentFix
  568. );
  569. const floaterProps = deepmerge2.all([
  570. defaultFloaterProps,
  571. (_a = props.floaterProps) != null ? _a : {},
  572. (_b = mergedStep.floaterProps) != null ? _b : {}
  573. ]);
  574. floaterProps.offset = mergedStep.offset;
  575. floaterProps.styles = deepmerge2((_c = floaterProps.styles) != null ? _c : {}, mergedStyles.floaterStyles);
  576. floaterProps.offset += (_e = (_d = props.spotlightPadding) != null ? _d : mergedStep.spotlightPadding) != null ? _e : 0;
  577. if (mergedStep.placementBeacon && floaterProps.wrapperOptions) {
  578. floaterProps.wrapperOptions.placement = mergedStep.placementBeacon;
  579. }
  580. if (scrollParent2 && floaterProps.options.preventOverflow) {
  581. floaterProps.options.preventOverflow.boundariesElement = "window";
  582. }
  583. return {
  584. ...mergedStep,
  585. locale: deepmerge2.all([defaultLocale, (_f = props.locale) != null ? _f : {}, mergedStep.locale || {}]),
  586. floaterProps,
  587. styles: omit(mergedStyles, "floaterStyles")
  588. };
  589. }
  590. function validateStep(step, debug = false) {
  591. if (!is2.plainObject(step)) {
  592. log({
  593. title: "validateStep",
  594. data: "step must be an object",
  595. warn: true,
  596. debug
  597. });
  598. return false;
  599. }
  600. if (!step.target) {
  601. log({
  602. title: "validateStep",
  603. data: "target is missing from the step",
  604. warn: true,
  605. debug
  606. });
  607. return false;
  608. }
  609. return true;
  610. }
  611. function validateSteps(steps, debug = false) {
  612. if (!is2.array(steps)) {
  613. log({
  614. title: "validateSteps",
  615. data: "steps must be an array",
  616. warn: true,
  617. debug
  618. });
  619. return false;
  620. }
  621. return steps.every((d) => validateStep(d, debug));
  622. }
  623. // src/modules/store.ts
  624. import is3 from "is-lite";
  625. var defaultState = {
  626. action: "init",
  627. controlled: false,
  628. index: 0,
  629. lifecycle: LIFECYCLE.INIT,
  630. size: 0,
  631. status: STATUS.IDLE
  632. };
  633. var validKeys = ["action", "index", "lifecycle", "status"];
  634. var Store = class {
  635. constructor(options) {
  636. __publicField(this, "beaconPopper");
  637. __publicField(this, "tooltipPopper");
  638. __publicField(this, "data", /* @__PURE__ */ new Map());
  639. __publicField(this, "listener");
  640. __publicField(this, "store", /* @__PURE__ */ new Map());
  641. __publicField(this, "addListener", (listener) => {
  642. this.listener = listener;
  643. });
  644. __publicField(this, "setSteps", (steps) => {
  645. const { size, status } = this.getState();
  646. const state = {
  647. size: steps.length,
  648. status
  649. };
  650. this.data.set("steps", steps);
  651. if (status === STATUS.WAITING && !size && steps.length) {
  652. state.status = STATUS.RUNNING;
  653. }
  654. this.setState(state);
  655. });
  656. __publicField(this, "getPopper", (name) => {
  657. if (name === "beacon") {
  658. return this.beaconPopper;
  659. }
  660. return this.tooltipPopper;
  661. });
  662. __publicField(this, "setPopper", (name, popper) => {
  663. if (name === "beacon") {
  664. this.beaconPopper = popper;
  665. } else {
  666. this.tooltipPopper = popper;
  667. }
  668. });
  669. __publicField(this, "cleanupPoppers", () => {
  670. this.beaconPopper = null;
  671. this.tooltipPopper = null;
  672. });
  673. __publicField(this, "close", () => {
  674. const { index, status } = this.getState();
  675. if (status !== STATUS.RUNNING) {
  676. return;
  677. }
  678. this.setState({
  679. ...this.getNextState({ action: ACTIONS.CLOSE, index: index + 1 })
  680. });
  681. });
  682. __publicField(this, "go", (nextIndex) => {
  683. const { controlled, status } = this.getState();
  684. if (controlled || status !== STATUS.RUNNING) {
  685. return;
  686. }
  687. const step = this.getSteps()[nextIndex];
  688. this.setState({
  689. ...this.getNextState({ action: ACTIONS.GO, index: nextIndex }),
  690. status: step ? status : STATUS.FINISHED
  691. });
  692. });
  693. __publicField(this, "info", () => this.getState());
  694. __publicField(this, "next", () => {
  695. const { index, status } = this.getState();
  696. if (status !== STATUS.RUNNING) {
  697. return;
  698. }
  699. this.setState(this.getNextState({ action: ACTIONS.NEXT, index: index + 1 }));
  700. });
  701. __publicField(this, "open", () => {
  702. const { status } = this.getState();
  703. if (status !== STATUS.RUNNING) {
  704. return;
  705. }
  706. this.setState({
  707. ...this.getNextState({ action: ACTIONS.UPDATE, lifecycle: LIFECYCLE.TOOLTIP })
  708. });
  709. });
  710. __publicField(this, "prev", () => {
  711. const { index, status } = this.getState();
  712. if (status !== STATUS.RUNNING) {
  713. return;
  714. }
  715. this.setState({
  716. ...this.getNextState({ action: ACTIONS.PREV, index: index - 1 })
  717. });
  718. });
  719. __publicField(this, "reset", (restart = false) => {
  720. const { controlled } = this.getState();
  721. if (controlled) {
  722. return;
  723. }
  724. this.setState({
  725. ...this.getNextState({ action: ACTIONS.RESET, index: 0 }),
  726. status: restart ? STATUS.RUNNING : STATUS.READY
  727. });
  728. });
  729. __publicField(this, "skip", () => {
  730. const { status } = this.getState();
  731. if (status !== STATUS.RUNNING) {
  732. return;
  733. }
  734. this.setState({
  735. action: ACTIONS.SKIP,
  736. lifecycle: LIFECYCLE.INIT,
  737. status: STATUS.SKIPPED
  738. });
  739. });
  740. __publicField(this, "start", (nextIndex) => {
  741. const { index, size } = this.getState();
  742. this.setState({
  743. ...this.getNextState(
  744. {
  745. action: ACTIONS.START,
  746. index: is3.number(nextIndex) ? nextIndex : index
  747. },
  748. true
  749. ),
  750. status: size ? STATUS.RUNNING : STATUS.WAITING
  751. });
  752. });
  753. __publicField(this, "stop", (advance = false) => {
  754. const { index, status } = this.getState();
  755. if ([STATUS.FINISHED, STATUS.SKIPPED].includes(status)) {
  756. return;
  757. }
  758. this.setState({
  759. ...this.getNextState({ action: ACTIONS.STOP, index: index + (advance ? 1 : 0) }),
  760. status: STATUS.PAUSED
  761. });
  762. });
  763. __publicField(this, "update", (state) => {
  764. var _a;
  765. if (!hasValidKeys(state, validKeys)) {
  766. throw new Error(`State is not valid. Valid keys: ${validKeys.join(", ")}`);
  767. }
  768. this.setState({
  769. ...this.getNextState(
  770. {
  771. ...this.getState(),
  772. ...state,
  773. action: (_a = state.action) != null ? _a : ACTIONS.UPDATE
  774. },
  775. true
  776. )
  777. });
  778. });
  779. const { continuous = false, stepIndex, steps = [] } = options != null ? options : {};
  780. this.setState(
  781. {
  782. action: ACTIONS.INIT,
  783. controlled: is3.number(stepIndex),
  784. continuous,
  785. index: is3.number(stepIndex) ? stepIndex : 0,
  786. lifecycle: LIFECYCLE.INIT,
  787. status: steps.length ? STATUS.READY : STATUS.IDLE
  788. },
  789. true
  790. );
  791. this.beaconPopper = null;
  792. this.tooltipPopper = null;
  793. this.listener = null;
  794. this.setSteps(steps);
  795. }
  796. getState() {
  797. if (!this.store.size) {
  798. return { ...defaultState };
  799. }
  800. return {
  801. action: this.store.get("action") || "",
  802. controlled: this.store.get("controlled") || false,
  803. index: parseInt(this.store.get("index"), 10),
  804. lifecycle: this.store.get("lifecycle") || "",
  805. size: this.store.get("size") || 0,
  806. status: this.store.get("status") || ""
  807. };
  808. }
  809. getNextState(state, force = false) {
  810. var _a, _b, _c, _d;
  811. const { action, controlled, index, size, status } = this.getState();
  812. const newIndex = is3.number(state.index) ? state.index : index;
  813. const nextIndex = controlled && !force ? index : Math.min(Math.max(newIndex, 0), size);
  814. return {
  815. action: (_a = state.action) != null ? _a : action,
  816. controlled,
  817. index: nextIndex,
  818. lifecycle: (_b = state.lifecycle) != null ? _b : LIFECYCLE.INIT,
  819. size: (_c = state.size) != null ? _c : size,
  820. status: nextIndex === size ? STATUS.FINISHED : (_d = state.status) != null ? _d : status
  821. };
  822. }
  823. getSteps() {
  824. const steps = this.data.get("steps");
  825. return Array.isArray(steps) ? steps : [];
  826. }
  827. hasUpdatedState(oldState) {
  828. const before = JSON.stringify(oldState);
  829. const after = JSON.stringify(this.getState());
  830. return before !== after;
  831. }
  832. setState(nextState, initial = false) {
  833. const state = this.getState();
  834. const { action, index, lifecycle, size, status } = {
  835. ...state,
  836. ...nextState
  837. };
  838. this.store.set("action", action);
  839. this.store.set("index", index);
  840. this.store.set("lifecycle", lifecycle);
  841. this.store.set("size", size);
  842. this.store.set("status", status);
  843. if (initial) {
  844. this.store.set("controlled", nextState.controlled);
  845. this.store.set("continuous", nextState.continuous);
  846. }
  847. if (this.listener && this.hasUpdatedState(state)) {
  848. this.listener(this.getState());
  849. }
  850. }
  851. getHelpers() {
  852. return {
  853. close: this.close,
  854. go: this.go,
  855. info: this.info,
  856. next: this.next,
  857. open: this.open,
  858. prev: this.prev,
  859. reset: this.reset,
  860. skip: this.skip
  861. };
  862. }
  863. };
  864. function createStore(options) {
  865. return new Store(options);
  866. }
  867. // src/components/Step.tsx
  868. import * as React8 from "react";
  869. import Floater from "react-floater";
  870. import is5 from "is-lite";
  871. import treeChanges2 from "tree-changes";
  872. // src/modules/scope.ts
  873. var Scope = class {
  874. constructor(element, options) {
  875. __publicField(this, "element");
  876. __publicField(this, "options");
  877. __publicField(this, "canBeTabbed", (element) => {
  878. const { tabIndex } = element;
  879. if (tabIndex === null || tabIndex < 0) {
  880. return false;
  881. }
  882. return this.canHaveFocus(element);
  883. });
  884. __publicField(this, "canHaveFocus", (element) => {
  885. const validTabNodes = /input|select|textarea|button|object/;
  886. const nodeName = element.nodeName.toLowerCase();
  887. const isValid = validTabNodes.test(nodeName) && !element.getAttribute("disabled") || nodeName === "a" && !!element.getAttribute("href");
  888. return isValid && this.isVisible(element);
  889. });
  890. __publicField(this, "findValidTabElements", () => [].slice.call(this.element.querySelectorAll("*"), 0).filter(this.canBeTabbed));
  891. __publicField(this, "handleKeyDown", (event) => {
  892. const { code = "Tab" } = this.options;
  893. if (event.code === code) {
  894. this.interceptTab(event);
  895. }
  896. });
  897. __publicField(this, "interceptTab", (event) => {
  898. event.preventDefault();
  899. const elements = this.findValidTabElements();
  900. const { shiftKey } = event;
  901. if (!elements.length) {
  902. return;
  903. }
  904. let x = document.activeElement ? elements.indexOf(document.activeElement) : 0;
  905. if (x === -1 || !shiftKey && x + 1 === elements.length) {
  906. x = 0;
  907. } else if (shiftKey && x === 0) {
  908. x = elements.length - 1;
  909. } else {
  910. x += shiftKey ? -1 : 1;
  911. }
  912. elements[x].focus();
  913. });
  914. // eslint-disable-next-line class-methods-use-this
  915. __publicField(this, "isHidden", (element) => {
  916. const noSize = element.offsetWidth <= 0 && element.offsetHeight <= 0;
  917. const style = window.getComputedStyle(element);
  918. if (noSize && !element.innerHTML) {
  919. return true;
  920. }
  921. return noSize && style.getPropertyValue("overflow") !== "visible" || style.getPropertyValue("display") === "none";
  922. });
  923. __publicField(this, "isVisible", (element) => {
  924. let parentElement = element;
  925. while (parentElement) {
  926. if (parentElement instanceof HTMLElement) {
  927. if (parentElement === document.body) {
  928. break;
  929. }
  930. if (this.isHidden(parentElement)) {
  931. return false;
  932. }
  933. parentElement = parentElement.parentNode;
  934. }
  935. }
  936. return true;
  937. });
  938. __publicField(this, "removeScope", () => {
  939. window.removeEventListener("keydown", this.handleKeyDown);
  940. });
  941. __publicField(this, "checkFocus", (target) => {
  942. if (document.activeElement !== target) {
  943. target.focus();
  944. window.requestAnimationFrame(() => this.checkFocus(target));
  945. }
  946. });
  947. __publicField(this, "setFocus", () => {
  948. const { selector } = this.options;
  949. if (!selector) {
  950. return;
  951. }
  952. const target = this.element.querySelector(selector);
  953. if (target) {
  954. window.requestAnimationFrame(() => this.checkFocus(target));
  955. }
  956. });
  957. if (!(element instanceof HTMLElement)) {
  958. throw new TypeError("Invalid parameter: element must be an HTMLElement");
  959. }
  960. this.element = element;
  961. this.options = options;
  962. window.addEventListener("keydown", this.handleKeyDown, false);
  963. this.setFocus();
  964. }
  965. };
  966. // src/components/Beacon.tsx
  967. import * as React from "react";
  968. import innerText from "react-innertext";
  969. import is4 from "is-lite";
  970. var JoyrideBeacon = class extends React.Component {
  971. constructor(props) {
  972. super(props);
  973. __publicField(this, "beacon", null);
  974. __publicField(this, "setBeaconRef", (c) => {
  975. this.beacon = c;
  976. });
  977. if (props.beaconComponent) {
  978. return;
  979. }
  980. const head = document.head || document.getElementsByTagName("head")[0];
  981. const style = document.createElement("style");
  982. style.id = "joyride-beacon-animation";
  983. if (props.nonce) {
  984. style.setAttribute("nonce", props.nonce);
  985. }
  986. const css = `
  987. @keyframes joyride-beacon-inner {
  988. 20% {
  989. opacity: 0.9;
  990. }
  991. 90% {
  992. opacity: 0.7;
  993. }
  994. }
  995. @keyframes joyride-beacon-outer {
  996. 0% {
  997. transform: scale(1);
  998. }
  999. 45% {
  1000. opacity: 0.7;
  1001. transform: scale(0.75);
  1002. }
  1003. 100% {
  1004. opacity: 0.9;
  1005. transform: scale(1);
  1006. }
  1007. }
  1008. `;
  1009. style.appendChild(document.createTextNode(css));
  1010. head.appendChild(style);
  1011. }
  1012. componentDidMount() {
  1013. const { shouldFocus } = this.props;
  1014. if (process.env.NODE_ENV !== "production") {
  1015. if (!is4.domElement(this.beacon)) {
  1016. console.warn("beacon is not a valid DOM element");
  1017. }
  1018. }
  1019. setTimeout(() => {
  1020. if (is4.domElement(this.beacon) && shouldFocus) {
  1021. this.beacon.focus();
  1022. }
  1023. }, 0);
  1024. }
  1025. componentWillUnmount() {
  1026. const style = document.getElementById("joyride-beacon-animation");
  1027. if (style == null ? void 0 : style.parentNode) {
  1028. style.parentNode.removeChild(style);
  1029. }
  1030. }
  1031. render() {
  1032. const {
  1033. beaconComponent,
  1034. continuous,
  1035. index,
  1036. isLastStep,
  1037. locale,
  1038. onClickOrHover,
  1039. size,
  1040. step,
  1041. styles
  1042. } = this.props;
  1043. const title = is4.string(locale.open) ? locale.open : innerText(locale.open);
  1044. const sharedProps = {
  1045. "aria-label": title,
  1046. onClick: onClickOrHover,
  1047. onMouseEnter: onClickOrHover,
  1048. ref: this.setBeaconRef,
  1049. title
  1050. };
  1051. let component;
  1052. if (beaconComponent) {
  1053. const BeaconComponent = beaconComponent;
  1054. component = /* @__PURE__ */ React.createElement(
  1055. BeaconComponent,
  1056. {
  1057. continuous,
  1058. index,
  1059. isLastStep,
  1060. size,
  1061. step,
  1062. ...sharedProps
  1063. }
  1064. );
  1065. } else {
  1066. component = /* @__PURE__ */ React.createElement(
  1067. "button",
  1068. {
  1069. key: "JoyrideBeacon",
  1070. className: "react-joyride__beacon",
  1071. "data-test-id": "button-beacon",
  1072. style: styles.beacon,
  1073. type: "button",
  1074. ...sharedProps
  1075. },
  1076. /* @__PURE__ */ React.createElement("span", { style: styles.beaconInner }),
  1077. /* @__PURE__ */ React.createElement("span", { style: styles.beaconOuter })
  1078. );
  1079. }
  1080. return component;
  1081. }
  1082. };
  1083. // src/components/Overlay.tsx
  1084. import * as React3 from "react";
  1085. import treeChanges from "tree-changes";
  1086. // src/components/Spotlight.tsx
  1087. import * as React2 from "react";
  1088. function JoyrideSpotlight({ styles }) {
  1089. return /* @__PURE__ */ React2.createElement(
  1090. "div",
  1091. {
  1092. key: "JoyrideSpotlight",
  1093. className: "react-joyride__spotlight",
  1094. "data-test-id": "spotlight",
  1095. style: styles
  1096. }
  1097. );
  1098. }
  1099. var Spotlight_default = JoyrideSpotlight;
  1100. // src/components/Overlay.tsx
  1101. var JoyrideOverlay = class extends React3.Component {
  1102. constructor() {
  1103. super(...arguments);
  1104. __publicField(this, "isActive", false);
  1105. __publicField(this, "resizeTimeout");
  1106. __publicField(this, "scrollTimeout");
  1107. __publicField(this, "scrollParent");
  1108. __publicField(this, "state", {
  1109. isScrolling: false,
  1110. mouseOverSpotlight: false,
  1111. showSpotlight: true
  1112. });
  1113. __publicField(this, "handleMouseMove", (event) => {
  1114. const { mouseOverSpotlight } = this.state;
  1115. const { height, left, position, top, width } = this.spotlightStyles;
  1116. const offsetY = position === "fixed" ? event.clientY : event.pageY;
  1117. const offsetX = position === "fixed" ? event.clientX : event.pageX;
  1118. const inSpotlightHeight = offsetY >= top && offsetY <= top + height;
  1119. const inSpotlightWidth = offsetX >= left && offsetX <= left + width;
  1120. const inSpotlight = inSpotlightWidth && inSpotlightHeight;
  1121. if (inSpotlight !== mouseOverSpotlight) {
  1122. this.updateState({ mouseOverSpotlight: inSpotlight });
  1123. }
  1124. });
  1125. __publicField(this, "handleScroll", () => {
  1126. const { target } = this.props;
  1127. const element = getElement(target);
  1128. if (this.scrollParent !== document) {
  1129. const { isScrolling } = this.state;
  1130. if (!isScrolling) {
  1131. this.updateState({ isScrolling: true, showSpotlight: false });
  1132. }
  1133. clearTimeout(this.scrollTimeout);
  1134. this.scrollTimeout = window.setTimeout(() => {
  1135. this.updateState({ isScrolling: false, showSpotlight: true });
  1136. }, 50);
  1137. } else if (hasPosition(element, "sticky")) {
  1138. this.updateState({});
  1139. }
  1140. });
  1141. __publicField(this, "handleResize", () => {
  1142. clearTimeout(this.resizeTimeout);
  1143. this.resizeTimeout = window.setTimeout(() => {
  1144. if (!this.isActive) {
  1145. return;
  1146. }
  1147. this.forceUpdate();
  1148. }, 100);
  1149. });
  1150. }
  1151. componentDidMount() {
  1152. const { debug, disableScrolling, disableScrollParentFix = false, target } = this.props;
  1153. const element = getElement(target);
  1154. this.scrollParent = getScrollParent(element != null ? element : document.body, disableScrollParentFix, true);
  1155. this.isActive = true;
  1156. if (process.env.NODE_ENV !== "production") {
  1157. if (!disableScrolling && hasCustomScrollParent(element, true)) {
  1158. log({
  1159. title: "step has a custom scroll parent and can cause trouble with scrolling",
  1160. data: [{ key: "parent", value: this.scrollParent }],
  1161. debug
  1162. });
  1163. }
  1164. }
  1165. window.addEventListener("resize", this.handleResize);
  1166. }
  1167. componentDidUpdate(previousProps) {
  1168. var _a;
  1169. const { lifecycle, spotlightClicks } = this.props;
  1170. const { changed } = treeChanges(previousProps, this.props);
  1171. if (changed("lifecycle", LIFECYCLE.TOOLTIP)) {
  1172. (_a = this.scrollParent) == null ? void 0 : _a.addEventListener("scroll", this.handleScroll, { passive: true });
  1173. setTimeout(() => {
  1174. const { isScrolling } = this.state;
  1175. if (!isScrolling) {
  1176. this.updateState({ showSpotlight: true });
  1177. }
  1178. }, 100);
  1179. }
  1180. if (changed("spotlightClicks") || changed("disableOverlay") || changed("lifecycle")) {
  1181. if (spotlightClicks && lifecycle === LIFECYCLE.TOOLTIP) {
  1182. window.addEventListener("mousemove", this.handleMouseMove, false);
  1183. } else if (lifecycle !== LIFECYCLE.TOOLTIP) {
  1184. window.removeEventListener("mousemove", this.handleMouseMove);
  1185. }
  1186. }
  1187. }
  1188. componentWillUnmount() {
  1189. var _a;
  1190. this.isActive = false;
  1191. window.removeEventListener("mousemove", this.handleMouseMove);
  1192. window.removeEventListener("resize", this.handleResize);
  1193. clearTimeout(this.resizeTimeout);
  1194. clearTimeout(this.scrollTimeout);
  1195. (_a = this.scrollParent) == null ? void 0 : _a.removeEventListener("scroll", this.handleScroll);
  1196. }
  1197. get spotlightStyles() {
  1198. var _a, _b, _c;
  1199. const { showSpotlight } = this.state;
  1200. const {
  1201. disableScrollParentFix = false,
  1202. spotlightClicks,
  1203. spotlightPadding = 0,
  1204. styles,
  1205. target
  1206. } = this.props;
  1207. const element = getElement(target);
  1208. const elementRect = getClientRect(element);
  1209. const isFixedTarget = hasPosition(element);
  1210. const top = getElementPosition(element, spotlightPadding, disableScrollParentFix);
  1211. return {
  1212. ...isLegacy() ? styles.spotlightLegacy : styles.spotlight,
  1213. height: Math.round(((_a = elementRect == null ? void 0 : elementRect.height) != null ? _a : 0) + spotlightPadding * 2),
  1214. left: Math.round(((_b = elementRect == null ? void 0 : elementRect.left) != null ? _b : 0) - spotlightPadding),
  1215. opacity: showSpotlight ? 1 : 0,
  1216. pointerEvents: spotlightClicks ? "none" : "auto",
  1217. position: isFixedTarget ? "fixed" : "absolute",
  1218. top,
  1219. transition: "opacity 0.2s",
  1220. width: Math.round(((_c = elementRect == null ? void 0 : elementRect.width) != null ? _c : 0) + spotlightPadding * 2)
  1221. };
  1222. }
  1223. updateState(state) {
  1224. if (!this.isActive) {
  1225. return;
  1226. }
  1227. this.setState((previousState) => ({ ...previousState, ...state }));
  1228. }
  1229. render() {
  1230. const { mouseOverSpotlight, showSpotlight } = this.state;
  1231. const { disableOverlay, disableOverlayClose, lifecycle, onClickOverlay, placement, styles } = this.props;
  1232. if (disableOverlay || lifecycle !== LIFECYCLE.TOOLTIP) {
  1233. return null;
  1234. }
  1235. let baseStyles = styles.overlay;
  1236. if (isLegacy()) {
  1237. baseStyles = placement === "center" ? styles.overlayLegacyCenter : styles.overlayLegacy;
  1238. }
  1239. const stylesOverlay = {
  1240. cursor: disableOverlayClose ? "default" : "pointer",
  1241. height: getDocumentHeight(),
  1242. pointerEvents: mouseOverSpotlight ? "none" : "auto",
  1243. ...baseStyles
  1244. };
  1245. let spotlight2 = placement !== "center" && showSpotlight && /* @__PURE__ */ React3.createElement(Spotlight_default, { styles: this.spotlightStyles });
  1246. if (getBrowser() === "safari") {
  1247. const { mixBlendMode, zIndex, ...safarOverlay } = stylesOverlay;
  1248. spotlight2 = /* @__PURE__ */ React3.createElement("div", { style: { ...safarOverlay } }, spotlight2);
  1249. delete stylesOverlay.backgroundColor;
  1250. }
  1251. return /* @__PURE__ */ React3.createElement(
  1252. "div",
  1253. {
  1254. className: "react-joyride__overlay",
  1255. "data-test-id": "overlay",
  1256. onClick: onClickOverlay,
  1257. role: "presentation",
  1258. style: stylesOverlay
  1259. },
  1260. spotlight2
  1261. );
  1262. }
  1263. };
  1264. // src/components/Portal.tsx
  1265. import * as React4 from "react";
  1266. import * as ReactDOM from "react-dom";
  1267. var JoyridePortal = class extends React4.Component {
  1268. constructor() {
  1269. super(...arguments);
  1270. __publicField(this, "node", null);
  1271. }
  1272. componentDidMount() {
  1273. const { id } = this.props;
  1274. if (!canUseDOM()) {
  1275. return;
  1276. }
  1277. this.node = document.createElement("div");
  1278. this.node.id = id;
  1279. document.body.appendChild(this.node);
  1280. if (!isReact16) {
  1281. this.renderReact15();
  1282. }
  1283. }
  1284. componentDidUpdate() {
  1285. if (!canUseDOM()) {
  1286. return;
  1287. }
  1288. if (!isReact16) {
  1289. this.renderReact15();
  1290. }
  1291. }
  1292. componentWillUnmount() {
  1293. if (!canUseDOM() || !this.node) {
  1294. return;
  1295. }
  1296. if (!isReact16) {
  1297. ReactDOM.unmountComponentAtNode(this.node);
  1298. }
  1299. if (this.node.parentNode === document.body) {
  1300. document.body.removeChild(this.node);
  1301. this.node = null;
  1302. }
  1303. }
  1304. renderReact15() {
  1305. if (!canUseDOM()) {
  1306. return;
  1307. }
  1308. const { children } = this.props;
  1309. if (this.node) {
  1310. ReactDOM.unstable_renderSubtreeIntoContainer(this, children, this.node);
  1311. }
  1312. }
  1313. renderReact16() {
  1314. if (!canUseDOM() || !isReact16) {
  1315. return null;
  1316. }
  1317. const { children } = this.props;
  1318. if (!this.node) {
  1319. return null;
  1320. }
  1321. return ReactDOM.createPortal(children, this.node);
  1322. }
  1323. render() {
  1324. if (!isReact16) {
  1325. return null;
  1326. }
  1327. return this.renderReact16();
  1328. }
  1329. };
  1330. // src/components/Tooltip/index.tsx
  1331. import * as React7 from "react";
  1332. // src/components/Tooltip/Container.tsx
  1333. import * as React6 from "react";
  1334. // src/components/Tooltip/CloseButton.tsx
  1335. import React5 from "react";
  1336. function JoyrideTooltipCloseButton({ styles, ...props }) {
  1337. const { color, height, width, ...style } = styles;
  1338. return /* @__PURE__ */ React5.createElement("button", { style, type: "button", ...props }, /* @__PURE__ */ React5.createElement(
  1339. "svg",
  1340. {
  1341. height: typeof height === "number" ? `${height}px` : height,
  1342. preserveAspectRatio: "xMidYMid",
  1343. version: "1.1",
  1344. viewBox: "0 0 18 18",
  1345. width: typeof width === "number" ? `${width}px` : width,
  1346. xmlns: "http://www.w3.org/2000/svg"
  1347. },
  1348. /* @__PURE__ */ React5.createElement("g", null, /* @__PURE__ */ React5.createElement(
  1349. "path",
  1350. {
  1351. 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",
  1352. fill: color
  1353. }
  1354. ))
  1355. ));
  1356. }
  1357. var CloseButton_default = JoyrideTooltipCloseButton;
  1358. // src/components/Tooltip/Container.tsx
  1359. function JoyrideTooltipContainer(props) {
  1360. const {
  1361. backProps,
  1362. closeProps,
  1363. continuous,
  1364. index,
  1365. isLastStep,
  1366. primaryProps,
  1367. size,
  1368. skipProps,
  1369. step,
  1370. tooltipProps
  1371. } = props;
  1372. const {
  1373. content,
  1374. hideBackButton,
  1375. hideCloseButton,
  1376. hideFooter,
  1377. locale,
  1378. showProgress,
  1379. showSkipButton,
  1380. styles,
  1381. title
  1382. } = step;
  1383. const { back, close, last, next, skip } = locale;
  1384. const output = {
  1385. primary: close
  1386. };
  1387. if (continuous) {
  1388. output.primary = isLastStep ? last : next;
  1389. if (showProgress) {
  1390. output.primary = /* @__PURE__ */ React6.createElement("span", null, output.primary, " (", index + 1, "/", size, ")");
  1391. }
  1392. }
  1393. if (showSkipButton && !isLastStep) {
  1394. output.skip = /* @__PURE__ */ React6.createElement(
  1395. "button",
  1396. {
  1397. "aria-live": "off",
  1398. "data-test-id": "button-skip",
  1399. style: styles.buttonSkip,
  1400. type: "button",
  1401. ...skipProps
  1402. },
  1403. skip
  1404. );
  1405. }
  1406. if (!hideBackButton && index > 0) {
  1407. output.back = /* @__PURE__ */ React6.createElement("button", { "data-test-id": "button-back", style: styles.buttonBack, type: "button", ...backProps }, back);
  1408. }
  1409. output.close = !hideCloseButton && /* @__PURE__ */ React6.createElement(CloseButton_default, { "data-test-id": "button-close", styles: styles.buttonClose, ...closeProps });
  1410. return /* @__PURE__ */ React6.createElement(
  1411. "div",
  1412. {
  1413. key: "JoyrideTooltip",
  1414. "aria-label": getText(title) || getText(content),
  1415. className: "react-joyride__tooltip",
  1416. style: styles.tooltip,
  1417. ...tooltipProps
  1418. },
  1419. /* @__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)),
  1420. !hideFooter && /* @__PURE__ */ React6.createElement("div", { style: styles.tooltipFooter }, /* @__PURE__ */ React6.createElement("div", { style: styles.tooltipFooterSpacer }, output.skip), output.back, /* @__PURE__ */ React6.createElement(
  1421. "button",
  1422. {
  1423. "data-test-id": "button-primary",
  1424. style: styles.buttonNext,
  1425. type: "button",
  1426. ...primaryProps
  1427. },
  1428. output.primary
  1429. )),
  1430. output.close
  1431. );
  1432. }
  1433. var Container_default = JoyrideTooltipContainer;
  1434. // src/components/Tooltip/index.tsx
  1435. var JoyrideTooltip = class extends React7.Component {
  1436. constructor() {
  1437. super(...arguments);
  1438. __publicField(this, "handleClickBack", (event) => {
  1439. event.preventDefault();
  1440. const { helpers } = this.props;
  1441. helpers.prev();
  1442. });
  1443. __publicField(this, "handleClickClose", (event) => {
  1444. event.preventDefault();
  1445. const { helpers } = this.props;
  1446. helpers.close();
  1447. });
  1448. __publicField(this, "handleClickPrimary", (event) => {
  1449. event.preventDefault();
  1450. const { continuous, helpers } = this.props;
  1451. if (!continuous) {
  1452. helpers.close();
  1453. return;
  1454. }
  1455. helpers.next();
  1456. });
  1457. __publicField(this, "handleClickSkip", (event) => {
  1458. event.preventDefault();
  1459. const { helpers } = this.props;
  1460. helpers.skip();
  1461. });
  1462. __publicField(this, "getElementsProps", () => {
  1463. const { continuous, isLastStep, setTooltipRef, step } = this.props;
  1464. const back = getText(step.locale.back);
  1465. const close = getText(step.locale.close);
  1466. const last = getText(step.locale.last);
  1467. const next = getText(step.locale.next);
  1468. const skip = getText(step.locale.skip);
  1469. let primaryText = continuous ? next : close;
  1470. if (isLastStep) {
  1471. primaryText = last;
  1472. }
  1473. return {
  1474. backProps: {
  1475. "aria-label": back,
  1476. "data-action": "back",
  1477. onClick: this.handleClickBack,
  1478. role: "button",
  1479. title: back
  1480. },
  1481. closeProps: {
  1482. "aria-label": close,
  1483. "data-action": "close",
  1484. onClick: this.handleClickClose,
  1485. role: "button",
  1486. title: close
  1487. },
  1488. primaryProps: {
  1489. "aria-label": primaryText,
  1490. "data-action": "primary",
  1491. onClick: this.handleClickPrimary,
  1492. role: "button",
  1493. title: primaryText
  1494. },
  1495. skipProps: {
  1496. "aria-label": skip,
  1497. "data-action": "skip",
  1498. onClick: this.handleClickSkip,
  1499. role: "button",
  1500. title: skip
  1501. },
  1502. tooltipProps: {
  1503. "aria-modal": true,
  1504. ref: setTooltipRef,
  1505. role: "alertdialog"
  1506. }
  1507. };
  1508. });
  1509. }
  1510. render() {
  1511. const { continuous, index, isLastStep, setTooltipRef, size, step } = this.props;
  1512. const { beaconComponent, tooltipComponent, ...cleanStep } = step;
  1513. let component;
  1514. if (tooltipComponent) {
  1515. const renderProps = {
  1516. ...this.getElementsProps(),
  1517. continuous,
  1518. index,
  1519. isLastStep,
  1520. size,
  1521. step: cleanStep,
  1522. setTooltipRef
  1523. };
  1524. const TooltipComponent = tooltipComponent;
  1525. component = /* @__PURE__ */ React7.createElement(TooltipComponent, { ...renderProps });
  1526. } else {
  1527. component = /* @__PURE__ */ React7.createElement(
  1528. Container_default,
  1529. {
  1530. ...this.getElementsProps(),
  1531. continuous,
  1532. index,
  1533. isLastStep,
  1534. size,
  1535. step
  1536. }
  1537. );
  1538. }
  1539. return component;
  1540. }
  1541. };
  1542. // src/components/Step.tsx
  1543. var JoyrideStep = class extends React8.Component {
  1544. constructor() {
  1545. super(...arguments);
  1546. __publicField(this, "scope", null);
  1547. __publicField(this, "tooltip", null);
  1548. /**
  1549. * Beacon click/hover event listener
  1550. */
  1551. __publicField(this, "handleClickHoverBeacon", (event) => {
  1552. const { step, store } = this.props;
  1553. if (event.type === "mouseenter" && step.event !== "hover") {
  1554. return;
  1555. }
  1556. store.update({ lifecycle: LIFECYCLE.TOOLTIP });
  1557. });
  1558. __publicField(this, "handleClickOverlay", () => {
  1559. const { helpers, step } = this.props;
  1560. if (!step.disableOverlayClose) {
  1561. helpers.close();
  1562. }
  1563. });
  1564. __publicField(this, "setTooltipRef", (element) => {
  1565. this.tooltip = element;
  1566. });
  1567. __publicField(this, "setPopper", (popper, type) => {
  1568. var _a;
  1569. const { action, step, store } = this.props;
  1570. if (type === "wrapper") {
  1571. store.setPopper("beacon", popper);
  1572. } else {
  1573. store.setPopper("tooltip", popper);
  1574. }
  1575. if (store.getPopper("beacon") && store.getPopper("tooltip")) {
  1576. store.update({
  1577. action,
  1578. lifecycle: LIFECYCLE.READY
  1579. });
  1580. }
  1581. if ((_a = step.floaterProps) == null ? void 0 : _a.getPopper) {
  1582. step.floaterProps.getPopper(popper, type);
  1583. }
  1584. });
  1585. __publicField(this, "renderTooltip", (renderProps) => {
  1586. const { continuous, helpers, index, size, step } = this.props;
  1587. return /* @__PURE__ */ React8.createElement(
  1588. JoyrideTooltip,
  1589. {
  1590. continuous,
  1591. helpers,
  1592. index,
  1593. isLastStep: index + 1 === size,
  1594. setTooltipRef: this.setTooltipRef,
  1595. size,
  1596. step,
  1597. ...renderProps
  1598. }
  1599. );
  1600. });
  1601. }
  1602. componentDidMount() {
  1603. const { debug, index } = this.props;
  1604. log({
  1605. title: `step:${index}`,
  1606. data: [{ key: "props", value: this.props }],
  1607. debug
  1608. });
  1609. }
  1610. componentDidUpdate(previousProps) {
  1611. var _a;
  1612. const {
  1613. action,
  1614. callback,
  1615. continuous,
  1616. controlled,
  1617. debug,
  1618. index,
  1619. lifecycle,
  1620. size,
  1621. status,
  1622. step,
  1623. store
  1624. } = this.props;
  1625. const { changed, changedFrom } = treeChanges2(previousProps, this.props);
  1626. const state = { action, controlled, index, lifecycle, size, status };
  1627. const skipBeacon = continuous && action !== ACTIONS.CLOSE && (index > 0 || action === ACTIONS.PREV);
  1628. const hasStoreChanged = changed("action") || changed("index") || changed("lifecycle") || changed("status");
  1629. const isInitial = changedFrom("lifecycle", [LIFECYCLE.TOOLTIP, LIFECYCLE.INIT], LIFECYCLE.INIT);
  1630. const isAfterAction = changed("action", [
  1631. ACTIONS.NEXT,
  1632. ACTIONS.PREV,
  1633. ACTIONS.SKIP,
  1634. ACTIONS.CLOSE
  1635. ]);
  1636. const isControlled = controlled && index === previousProps.index;
  1637. if (isAfterAction && (isInitial || isControlled)) {
  1638. callback({
  1639. ...state,
  1640. index: previousProps.index,
  1641. lifecycle: LIFECYCLE.COMPLETE,
  1642. step: previousProps.step,
  1643. type: EVENTS.STEP_AFTER
  1644. });
  1645. }
  1646. if (step.placement === "center" && status === STATUS.RUNNING && changed("index") && action !== ACTIONS.START && lifecycle === LIFECYCLE.INIT) {
  1647. store.update({ lifecycle: LIFECYCLE.READY });
  1648. }
  1649. if (hasStoreChanged) {
  1650. const element = getElement(step.target);
  1651. const elementExists = !!element;
  1652. const hasRenderedTarget = elementExists && isElementVisible(element);
  1653. if (hasRenderedTarget) {
  1654. if (changedFrom("status", STATUS.READY, STATUS.RUNNING) || changedFrom("lifecycle", LIFECYCLE.INIT, LIFECYCLE.READY)) {
  1655. callback({
  1656. ...state,
  1657. step,
  1658. type: EVENTS.STEP_BEFORE
  1659. });
  1660. }
  1661. } else {
  1662. console.warn(elementExists ? "Target not visible" : "Target not mounted", step);
  1663. callback({
  1664. ...state,
  1665. type: EVENTS.TARGET_NOT_FOUND,
  1666. step
  1667. });
  1668. if (!controlled) {
  1669. store.update({ index: index + (action === ACTIONS.PREV ? -1 : 1) });
  1670. }
  1671. }
  1672. }
  1673. if (changedFrom("lifecycle", LIFECYCLE.INIT, LIFECYCLE.READY)) {
  1674. store.update({
  1675. lifecycle: hideBeacon(step) || skipBeacon ? LIFECYCLE.TOOLTIP : LIFECYCLE.BEACON
  1676. });
  1677. }
  1678. if (changed("index")) {
  1679. log({
  1680. title: `step:${lifecycle}`,
  1681. data: [{ key: "props", value: this.props }],
  1682. debug
  1683. });
  1684. }
  1685. if (changed("lifecycle", LIFECYCLE.BEACON)) {
  1686. callback({
  1687. ...state,
  1688. step,
  1689. type: EVENTS.BEACON
  1690. });
  1691. }
  1692. if (changed("lifecycle", LIFECYCLE.TOOLTIP)) {
  1693. callback({
  1694. ...state,
  1695. step,
  1696. type: EVENTS.TOOLTIP
  1697. });
  1698. if (this.tooltip) {
  1699. this.scope = new Scope(this.tooltip, { selector: "[data-action=primary]" });
  1700. this.scope.setFocus();
  1701. }
  1702. }
  1703. if (changedFrom("lifecycle", [LIFECYCLE.TOOLTIP, LIFECYCLE.INIT], LIFECYCLE.INIT)) {
  1704. (_a = this.scope) == null ? void 0 : _a.removeScope();
  1705. store.cleanupPoppers();
  1706. }
  1707. }
  1708. componentWillUnmount() {
  1709. var _a;
  1710. (_a = this.scope) == null ? void 0 : _a.removeScope();
  1711. }
  1712. get open() {
  1713. const { lifecycle, step } = this.props;
  1714. return hideBeacon(step) || lifecycle === LIFECYCLE.TOOLTIP;
  1715. }
  1716. render() {
  1717. const { continuous, debug, index, lifecycle, nonce, shouldScroll: shouldScroll2, size, step } = this.props;
  1718. const target = getElement(step.target);
  1719. if (!validateStep(step) || !is5.domElement(target)) {
  1720. return null;
  1721. }
  1722. return /* @__PURE__ */ React8.createElement("div", { key: `JoyrideStep-${index}`, className: "react-joyride__step" }, /* @__PURE__ */ React8.createElement(JoyridePortal, { id: "react-joyride-portal" }, /* @__PURE__ */ React8.createElement(
  1723. JoyrideOverlay,
  1724. {
  1725. ...step,
  1726. debug,
  1727. lifecycle,
  1728. onClickOverlay: this.handleClickOverlay
  1729. }
  1730. )), /* @__PURE__ */ React8.createElement(
  1731. Floater,
  1732. {
  1733. ...step.floaterProps,
  1734. component: this.renderTooltip,
  1735. debug,
  1736. getPopper: this.setPopper,
  1737. id: `react-joyride-step-${index}`,
  1738. open: this.open,
  1739. placement: step.placement,
  1740. target: step.target
  1741. },
  1742. /* @__PURE__ */ React8.createElement(
  1743. JoyrideBeacon,
  1744. {
  1745. beaconComponent: step.beaconComponent,
  1746. continuous,
  1747. index,
  1748. isLastStep: index + 1 === size,
  1749. locale: step.locale,
  1750. nonce,
  1751. onClickOrHover: this.handleClickHoverBeacon,
  1752. shouldFocus: shouldScroll2,
  1753. size,
  1754. step,
  1755. styles: step.styles
  1756. }
  1757. )
  1758. ));
  1759. }
  1760. };
  1761. // src/components/index.tsx
  1762. var Joyride = class extends React9.Component {
  1763. constructor(props) {
  1764. super(props);
  1765. __publicField(this, "helpers");
  1766. __publicField(this, "store");
  1767. /**
  1768. * Trigger the callback.
  1769. */
  1770. __publicField(this, "callback", (data) => {
  1771. const { callback } = this.props;
  1772. if (is6.function(callback)) {
  1773. callback(data);
  1774. }
  1775. });
  1776. /**
  1777. * Keydown event listener
  1778. */
  1779. __publicField(this, "handleKeyboard", (event) => {
  1780. const { index, lifecycle } = this.state;
  1781. const { steps } = this.props;
  1782. const step = steps[index];
  1783. if (lifecycle === LIFECYCLE.TOOLTIP) {
  1784. if (event.code === "Escape" && step && !step.disableCloseOnEsc) {
  1785. this.store.close();
  1786. }
  1787. }
  1788. });
  1789. /**
  1790. * Sync the store with the component's state
  1791. */
  1792. __publicField(this, "syncState", (state) => {
  1793. this.setState(state);
  1794. });
  1795. const { debug, getHelpers, run, stepIndex } = props;
  1796. this.store = createStore({
  1797. ...props,
  1798. controlled: run && is6.number(stepIndex)
  1799. });
  1800. this.helpers = this.store.getHelpers();
  1801. const { addListener } = this.store;
  1802. log({
  1803. title: "init",
  1804. data: [
  1805. { key: "props", value: this.props },
  1806. { key: "state", value: this.state }
  1807. ],
  1808. debug
  1809. });
  1810. addListener(this.syncState);
  1811. if (getHelpers) {
  1812. getHelpers(this.helpers);
  1813. }
  1814. this.state = this.store.getState();
  1815. }
  1816. componentDidMount() {
  1817. if (!canUseDOM()) {
  1818. return;
  1819. }
  1820. const { debug, disableCloseOnEsc, run, steps } = this.props;
  1821. const { start } = this.store;
  1822. if (validateSteps(steps, debug) && run) {
  1823. start();
  1824. }
  1825. if (!disableCloseOnEsc) {
  1826. document.body.addEventListener("keydown", this.handleKeyboard, { passive: true });
  1827. }
  1828. }
  1829. componentDidUpdate(previousProps, previousState) {
  1830. if (!canUseDOM()) {
  1831. return;
  1832. }
  1833. const { action, controlled, index, lifecycle, status } = this.state;
  1834. const { debug, run, stepIndex, steps } = this.props;
  1835. const { stepIndex: previousStepIndex, steps: previousSteps } = previousProps;
  1836. const { reset, setSteps, start, stop, update } = this.store;
  1837. const { changed: changedProps } = treeChanges3(previousProps, this.props);
  1838. const { changed, changedFrom } = treeChanges3(previousState, this.state);
  1839. const step = getMergedStep(steps[index], this.props);
  1840. const stepsChanged = !isEqual(previousSteps, steps);
  1841. const stepIndexChanged = is6.number(stepIndex) && changedProps("stepIndex");
  1842. const target = getElement(step.target);
  1843. if (stepsChanged) {
  1844. if (validateSteps(steps, debug)) {
  1845. setSteps(steps);
  1846. } else {
  1847. console.warn("Steps are not valid", steps);
  1848. }
  1849. }
  1850. if (changedProps("run")) {
  1851. if (run) {
  1852. start(stepIndex);
  1853. } else {
  1854. stop();
  1855. }
  1856. }
  1857. if (stepIndexChanged) {
  1858. let nextAction = is6.number(previousStepIndex) && previousStepIndex < stepIndex ? ACTIONS.NEXT : ACTIONS.PREV;
  1859. if (action === ACTIONS.STOP) {
  1860. nextAction = ACTIONS.START;
  1861. }
  1862. if (![STATUS.FINISHED, STATUS.SKIPPED].includes(status)) {
  1863. update({
  1864. action: action === ACTIONS.CLOSE ? ACTIONS.CLOSE : nextAction,
  1865. index: stepIndex,
  1866. lifecycle: LIFECYCLE.INIT
  1867. });
  1868. }
  1869. }
  1870. if (!controlled && status === STATUS.RUNNING && index === 0 && !target) {
  1871. this.store.update({ index: index + 1 });
  1872. this.callback({
  1873. ...this.state,
  1874. type: EVENTS.TARGET_NOT_FOUND,
  1875. step
  1876. });
  1877. }
  1878. const callbackData = {
  1879. ...this.state,
  1880. index,
  1881. step
  1882. };
  1883. const isAfterAction = changed("action", [
  1884. ACTIONS.NEXT,
  1885. ACTIONS.PREV,
  1886. ACTIONS.SKIP,
  1887. ACTIONS.CLOSE
  1888. ]);
  1889. if (isAfterAction && changed("status", STATUS.PAUSED)) {
  1890. const previousStep = getMergedStep(steps[previousState.index], this.props);
  1891. this.callback({
  1892. ...callbackData,
  1893. index: previousState.index,
  1894. lifecycle: LIFECYCLE.COMPLETE,
  1895. step: previousStep,
  1896. type: EVENTS.STEP_AFTER
  1897. });
  1898. }
  1899. if (changed("status", [STATUS.FINISHED, STATUS.SKIPPED])) {
  1900. const previousStep = getMergedStep(steps[previousState.index], this.props);
  1901. if (!controlled) {
  1902. this.callback({
  1903. ...callbackData,
  1904. index: previousState.index,
  1905. lifecycle: LIFECYCLE.COMPLETE,
  1906. step: previousStep,
  1907. type: EVENTS.STEP_AFTER
  1908. });
  1909. }
  1910. this.callback({
  1911. ...callbackData,
  1912. type: EVENTS.TOUR_END,
  1913. // Return the last step when the tour is finished
  1914. step: previousStep,
  1915. index: previousState.index
  1916. });
  1917. reset();
  1918. } else if (changedFrom("status", [STATUS.IDLE, STATUS.READY], STATUS.RUNNING)) {
  1919. this.callback({
  1920. ...callbackData,
  1921. type: EVENTS.TOUR_START
  1922. });
  1923. } else if (changed("status") || changed("action", ACTIONS.RESET)) {
  1924. this.callback({
  1925. ...callbackData,
  1926. type: EVENTS.TOUR_STATUS
  1927. });
  1928. }
  1929. this.scrollToStep(previousState);
  1930. if (step.placement === "center" && status === STATUS.RUNNING && lifecycle === LIFECYCLE.INIT) {
  1931. this.store.update({ lifecycle: LIFECYCLE.READY });
  1932. }
  1933. }
  1934. componentWillUnmount() {
  1935. const { disableCloseOnEsc } = this.props;
  1936. if (!disableCloseOnEsc) {
  1937. document.body.removeEventListener("keydown", this.handleKeyboard);
  1938. }
  1939. }
  1940. scrollToStep(previousState) {
  1941. const { index, lifecycle, status } = this.state;
  1942. const {
  1943. debug,
  1944. disableScrollParentFix = false,
  1945. scrollDuration,
  1946. scrollOffset = 20,
  1947. scrollToFirstStep = false,
  1948. steps
  1949. } = this.props;
  1950. const step = getMergedStep(steps[index], this.props);
  1951. const target = getElement(step.target);
  1952. const shouldScrollToStep = shouldScroll({
  1953. isFirstStep: index === 0,
  1954. lifecycle,
  1955. previousLifecycle: previousState.lifecycle,
  1956. scrollToFirstStep,
  1957. step,
  1958. target
  1959. });
  1960. if (status === STATUS.RUNNING && shouldScrollToStep) {
  1961. const hasCustomScroll = hasCustomScrollParent(target, disableScrollParentFix);
  1962. const scrollParent2 = getScrollParent(target, disableScrollParentFix);
  1963. let scrollY = Math.floor(getScrollTo(target, scrollOffset, disableScrollParentFix)) || 0;
  1964. log({
  1965. title: "scrollToStep",
  1966. data: [
  1967. { key: "index", value: index },
  1968. { key: "lifecycle", value: lifecycle },
  1969. { key: "status", value: status }
  1970. ],
  1971. debug
  1972. });
  1973. const beaconPopper = this.store.getPopper("beacon");
  1974. const tooltipPopper = this.store.getPopper("tooltip");
  1975. if (lifecycle === LIFECYCLE.BEACON && beaconPopper) {
  1976. const { offsets, placement } = beaconPopper;
  1977. if (!["bottom"].includes(placement) && !hasCustomScroll) {
  1978. scrollY = Math.floor(offsets.popper.top - scrollOffset);
  1979. }
  1980. } else if (lifecycle === LIFECYCLE.TOOLTIP && tooltipPopper) {
  1981. const { flipped, offsets, placement } = tooltipPopper;
  1982. if (["top", "right", "left"].includes(placement) && !flipped && !hasCustomScroll) {
  1983. scrollY = Math.floor(offsets.popper.top - scrollOffset);
  1984. } else {
  1985. scrollY -= step.spotlightPadding;
  1986. }
  1987. }
  1988. scrollY = scrollY >= 0 ? scrollY : 0;
  1989. if (status === STATUS.RUNNING) {
  1990. scrollTo(scrollY, { element: scrollParent2, duration: scrollDuration }).then(
  1991. () => {
  1992. setTimeout(() => {
  1993. var _a;
  1994. (_a = this.store.getPopper("tooltip")) == null ? void 0 : _a.instance.update();
  1995. }, 10);
  1996. }
  1997. );
  1998. }
  1999. }
  2000. }
  2001. render() {
  2002. if (!canUseDOM()) {
  2003. return null;
  2004. }
  2005. const { index, status } = this.state;
  2006. const {
  2007. continuous = false,
  2008. debug = false,
  2009. nonce,
  2010. scrollToFirstStep = false,
  2011. steps
  2012. } = this.props;
  2013. let output;
  2014. if (status === STATUS.RUNNING && steps[index]) {
  2015. const step = getMergedStep(steps[index], this.props);
  2016. output = /* @__PURE__ */ React9.createElement(
  2017. JoyrideStep,
  2018. {
  2019. ...this.state,
  2020. callback: this.callback,
  2021. continuous,
  2022. debug,
  2023. helpers: this.helpers,
  2024. nonce,
  2025. shouldScroll: !step.disableScrolling && (index !== 0 || scrollToFirstStep),
  2026. step,
  2027. store: this.store
  2028. }
  2029. );
  2030. }
  2031. return /* @__PURE__ */ React9.createElement("div", { className: "react-joyride" }, output);
  2032. }
  2033. };
  2034. __publicField(Joyride, "defaultProps", defaultProps);
  2035. var components_default = Joyride;
  2036. export {
  2037. ACTIONS,
  2038. EVENTS,
  2039. LIFECYCLE,
  2040. STATUS,
  2041. components_default as default
  2042. };
  2043. //# sourceMappingURL=index.mjs.map