[
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\ngithub: [kamranahmedse]\n"
  },
  {
    "path": ".gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndist-ssr\n*.local\ncoverage\n\n# Editor directories and files\n.vscode/*\n.history/*\n!.vscode/extensions.json\n.idea\n.DS_Store\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n"
  },
  {
    "path": ".prettierignore",
    "content": ".history\n.vscode\ncoverage\ndist\nnode_modules\n"
  },
  {
    "path": ".prettierrc",
    "content": "{\n  \"printWidth\": 120,\n  \"tabWidth\": 2,\n  \"singleQuote\": false,\n  \"trailingComma\": \"es5\",\n  \"arrowParens\": \"avoid\",\n  \"bracketSpacing\": true,\n  \"useTabs\": false,\n  \"endOfLine\": \"auto\",\n  \"singleAttributePerLine\": false,\n  \"bracketSameLine\": false,\n  \"jsxSingleQuote\": false,\n  \"quoteProps\": \"as-needed\",\n  \"semi\": true\n}\n"
  },
  {
    "path": "docs/.gitignore",
    "content": "# build output\ndist/\n\n# generated types\n.astro/\n\n# dependencies\nnode_modules/\n\n# logs\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\n\n# environment variables\n.env\n.env.production\n\n# macOS-specific files\n.DS_Store\n"
  },
  {
    "path": "docs/astro.config.mjs",
    "content": "import { defineConfig } from \"astro/config\";\nimport tailwind from \"@astrojs/tailwind\";\nimport react from \"@astrojs/react\";\nimport mdx from \"@astrojs/mdx\";\n\nimport compress from \"astro-compress\";\n\n// https://astro.build/config\nexport default defineConfig({\n  build: {\n    format: \"file\",\n  },\n  markdown: {\n    shikiConfig: {\n      // theme: \"material-theme\"\n      theme: \"monokai\",\n      // theme: 'poimandres'\n    },\n  },\n\n  integrations: [\n    tailwind(),\n    react(),\n    mdx(),\n    compress({\n      CSS: false,\n      JS: false,\n    }),\n  ],\n});\n"
  },
  {
    "path": "docs/package.json",
    "content": "{\n  \"name\": \"driver-docs\",\n  \"type\": \"module\",\n  \"version\": \"0.0.1\",\n  \"scripts\": {\n    \"dev\": \"astro dev\",\n    \"start\": \"astro dev\",\n    \"build\": \"astro build\",\n    \"preview\": \"astro preview\",\n    \"astro\": \"astro\"\n  },\n  \"dependencies\": {\n    \"@astrojs/mdx\": \"^1.0.0\",\n    \"@astrojs/react\": \"^3.0.0\",\n    \"@astrojs/tailwind\": \"^5.0.0\",\n    \"@types/react\": \"^18.2.21\",\n    \"@types/react-dom\": \"^18.2.7\",\n    \"astro\": \"^3.0.8\",\n    \"astro-compress\": \"^2.0.15\",\n    \"driver.js\": \"1.3.0\",\n    \"react\": \"^18.2.0\",\n    \"react-dom\": \"^18.2.0\",\n    \"react-fast-marquee\": \"^1.6.0\",\n    \"tailwindcss\": \"^3.3.3\"\n  },\n  \"devDependencies\": {\n    \"@tailwindcss/typography\": \"^0.5.9\"\n  }\n}\n"
  },
  {
    "path": "docs/src/components/Analytics/Analytics.astro",
    "content": "---\n---\n\n<script src='./analytics.ts'></script>\n<script async src=\"https://www.googletagmanager.com/gtag/js?id=G-LGE7XP5BHC\"></script>\n<script>\n    //@ts-nocheck\n    window.dataLayer = window.dataLayer || [];\n    function gtag(){dataLayer.push(arguments);}\n    gtag('js', new Date());\n\n    gtag('config', 'G-LGE7XP5BHC');\n</script>"
  },
  {
    "path": "docs/src/components/Analytics/analytics.ts",
    "content": "declare global {\n  interface Window {\n    gtag: any;\n    fireEvent: (props: {\n      action: string;\n      category: string;\n      label?: string;\n      value?: string;\n    }) => void;\n  }\n}\n\n/**\n * Tracks the event on google analytics\n * @see https://developers.google.com/analytics/devguides/collection/gtagjs/events\n * @param props Event properties\n * @returns void\n */\nwindow.fireEvent = (props) => {\n  const { action, category, label, value } = props;\n  if (!window.gtag) {\n    console.warn('Missing GTAG - Analytics disabled');\n    return;\n  }\n\n  if (import.meta.env.DEV) {\n    console.log('Analytics event fired', props);\n  }\n\n  window.gtag('event', action, {\n    event_category: category,\n    event_label: label,\n    value: value,\n  });\n};\n"
  },
  {
    "path": "docs/src/components/CodeSample.tsx",
    "content": "import type { Config, DriveStep, PopoverDOM } from \"driver.js\";\nimport { driver } from \"driver.js\";\nimport \"driver.js/dist/driver.css\";\n\ntype CodeSampleProps = {\n  heading?: string;\n\n  config?: Config;\n  highlight?: DriveStep;\n  tour?: DriveStep[];\n\n  id?: string;\n  className?: string;\n  children?: any;\n  buttonText?: string;\n};\n\nexport function removeDummyElement() {\n  const el = document.querySelector(\".dynamic-el\");\n  if (el) {\n    el.remove();\n  }\n}\n\nexport function mountDummyElement() {\n  const newDiv = (document.querySelector(\".dynamic-el\") || document.createElement(\"div\")) as HTMLElement;\n\n  newDiv.innerHTML = \"This is a new Element\";\n  newDiv.style.display = \"block\";\n  newDiv.style.padding = \"20px\";\n  newDiv.style.backgroundColor = \"black\";\n  newDiv.style.color = \"white\";\n  newDiv.style.fontSize = \"14px\";\n  newDiv.style.position = \"fixed\";\n  newDiv.style.top = `${Math.random() * (500 - 30) + 30}px`;\n  newDiv.style.left = `${Math.random() * (500 - 30) + 30}px`;\n  newDiv.className = \"dynamic-el\";\n\n  document.body.appendChild(newDiv);\n}\n\nfunction attachFirstButton(popover: PopoverDOM) {\n  const firstButton = document.createElement(\"button\");\n  firstButton.innerText = \"Go to First\";\n  popover.footerButtons.appendChild(firstButton);\n\n  firstButton.addEventListener(\"click\", () => {\n    window.driverObj.drive(0);\n  });\n}\n\nexport function CodeSample(props: CodeSampleProps) {\n  const { heading, id, children, buttonText = \"Show me an Example\", className, config, highlight, tour } = props;\n\n  if (id === \"demo-hook-theme\") {\n    config!.onPopoverRender = attachFirstButton;\n  }\n\n  function onClick() {\n    if (highlight) {\n      const driverObj = driver({\n        ...config,\n      });\n\n      window.driverObj = driverObj;\n      driverObj.highlight(highlight);\n    } else if (tour) {\n      if (id === \"confirm-destroy\") {\n        config!.onDestroyStarted = () => {\n          if (!driverObj.hasNextStep() || confirm(\"Are you sure?\")) {\n            driverObj.destroy();\n          }\n        };\n      }\n\n      if (id === \"logger-events\") {\n        config!.onNextClick = () => {\n          console.log(\"next clicked\");\n        };\n\n        config!.onNextClick = () => {\n          console.log(\"Next Button Clicked\");\n          // Implement your own functionality here\n          driverObj.moveNext();\n        };\n        config!.onPrevClick = () => {\n          console.log(\"Previous Button Clicked\");\n          // Implement your own functionality here\n          driverObj.movePrevious();\n        };\n        config!.onCloseClick = () => {\n          console.log(\"Close Button Clicked\");\n          // Implement your own functionality here\n          driverObj.destroy();\n        };\n      }\n\n      if (tour?.[2]?.popover?.title === \"Next Step is Async\") {\n        tour[2].popover.onNextClick = () => {\n          mountDummyElement();\n          driverObj.moveNext();\n        };\n\n        if (tour?.[3]?.element === \".dynamic-el\") {\n          tour[3].onDeselected = () => {\n            removeDummyElement();\n          };\n\n          // @ts-ignore\n          tour[4].popover.onPrevClick = () => {\n            mountDummyElement();\n            driverObj.movePrevious();\n          };\n\n          // @ts-ignore\n          tour[3].popover.onPrevClick = () => {\n            removeDummyElement();\n            driverObj.movePrevious();\n          };\n        }\n      }\n\n      const driverObj = driver({\n        ...config,\n        steps: tour,\n      });\n\n      window.driverObj = driverObj;\n      driverObj.drive();\n    }\n  }\n\n  return (\n    <div id={id} className={className}>\n      {heading && <p className=\"text-lg -mt-0 font-medium text-black -mb-3 rounded-md\">{heading}</p>}\n      {children && <div className=\"-mb-4\">{children}</div>}\n      <button onClick={onClick} className=\"w-full rounded-md bg-black p-2 text-white\">\n        {buttonText}\n      </button>\n    </div>\n  );\n}\n"
  },
  {
    "path": "docs/src/components/Container.astro",
    "content": "<div class=\"max-w-[1050px] mx-auto px-7 sm:px-10\">\n  <slot />\n</div>"
  },
  {
    "path": "docs/src/components/DocsHeader.tsx",
    "content": "import { useState } from \"react\";\nimport type { CollectionEntry } from \"astro:content\";\n\ntype DocsHeaderProps = {\n  groupedGuides: Record<string, CollectionEntry<\"guides\">[]>;\n  activeGuideTitle: string;\n};\n\nexport function DocsHeader(props: DocsHeaderProps) {\n  const { groupedGuides, activeGuideTitle } = props;\n  const [isActive, setIsActive] = useState(false);\n\n  return (\n    <>\n      <div className=\"border-b flex items-center justify-between\">\n        <div className=\"text-right flex justify-end py-3 px-6\">\n          <a href=\"/\" className=\"flex items-center justify-end text-xl font-bold\">\n            <img src=\"/driver-head.svg\" alt=\"Astro\" className=\"w-10 h-10 mr-2\" />\n            driver.js\n          </a>\n        </div>\n        <div className=\"flex items-center pr-12\">\n          <button onClick={() => setIsActive(!isActive)} className=\"p-[12px] -mr-[12px] hover:bg-gray-100 rounded-md\">\n            <img src={isActive ? \"/cross.svg\" : \"/burger.svg\"} alt=\"menu\" className=\"w-[14px] h-[14px]\" />\n          </button>\n        </div>\n      </div>\n      <div className={`bg-gray-50 flex flex-col gap-5 px-6 py-6 border-b ${isActive ? \"block\" : \"hidden\"}`}>\n        {Object.entries(groupedGuides).map(([category, guides]) => (\n          <div key={category} className=\"flex flex-col gap-2\">\n            <div className=\"font-bold text-gray-900 text-sm uppercase\">{category}</div>\n            <div className=\"flex flex-col\">\n              {guides.map(guide => (\n                <a key={guide.slug} href={`/docs/${guide.slug}`} className={`${activeGuideTitle === guide.data.title ? 'text-black': 'text-gray-400'} hover:text-gray-900 py-1`}>\n                  {guide.data.title}\n                </a>\n              ))}\n            </div>\n          </div>\n        ))}\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "docs/src/components/ExampleButton.tsx",
    "content": "type ExampleButtonProps = {\n  id: string;\n  onClick: () => void;\n  text: string;\n};\n\nexport function ExampleButton(props: ExampleButtonProps) {\n  const { id, onClick, text } = props;\n\n  return (\n    <button\n      id={id}\n      onClick={onClick}\n      className=\"bg-transparent rounded-lg lg:rounded-xl py-2 px-4 font-medium text-black border-2 border-black md:text-base lg:text-lg hover:bg-yellow-300 hover:text-black transition-colors duration-100\">\n      { text }\n    </button>\n  );\n}"
  },
  {
    "path": "docs/src/components/Examples.astro",
    "content": "---\nimport { ExampleButton } from \"./ExampleButton\";\n---\n<h2 class=\"text-4xl md:text-5xl lg:text-6xl font-bold mb-3 md:mb-4 lg:mb-6\" data-examples-heading>Examples</h2>\n<p class=\"text-base md:text-xl lg:text-2xl text-black leading-6\" data-examples-tagline>Here are just a few examples; find more <a\n  class=\"text-black underline underline-offset-4\" href=\"/docs/installation\">in the documentation</a>.</p>\n\n<div class=\"flex flex-wrap gap-2 md:gap-2 lg:gap-3 my-6 md:my-8 lg:my-12\" data-example-btns>\n  <ExampleButton id=\"animated-tour\" text=\"Animated Tour\" />\n  <ExampleButton id=\"static-tour\" text=\"Non-Animated Tour\" />\n  <ExampleButton id=\"async-tour\" text=\"Async Tour\" />\n  <ExampleButton id=\"no-element\" text=\"No Element\" />\n  <ExampleButton id=\"confirm-on-exit\" text=\"Confirm on Exit\" />\n  <ExampleButton id=\"show-progress\" text=\"Show Progress\" />\n  <ExampleButton id=\"simple-element-highlight\" text=\"Simple Highlight\" />\n  <ExampleButton id=\"simple-element-highlight-popover\" text=\"Highlight with Popover\" />\n  <ExampleButton id=\"prevent-close\" text=\"Prevent Closing\" />\n  <ExampleButton id=\"overlay-color\" text=\"Overlay Color\" />\n  <ExampleButton id=\"popover-position\" text=\"Popover Positioning\" />\n  <ExampleButton id=\"customizing-popover\" text=\"Customizing Popover\" />\n  <ExampleButton id=\"hooks-everything\" text=\"Hooks for Everything\" />\n  <a href=\"/docs/installation\"\n     class=\"items-center flex text-base md:text-base lg:text-lg text-gray-900 bg-yellow-300 rounded-lg lg:rounded-xl px-5 py-2 hover:bg-yellow-500 hover:text-black\">\n    and much more ...\n  </a>\n</div>\n\n<script>\n  import { driver } from \"driver.js\";\n  import \"driver.js/dist/driver.css\";\n  import { mountDummyElement, removeDummyElement } from \"../components/CodeSample\";\n\n  function markDone(btn) {\n    btn.classList.add(\"bg-gray-300\", \"hover:bg-gray-200\", \"line-through\");\n    btn.classList.remove(\"bg-transparent\");\n  }\n\n  const demoTourButton = document.querySelector(\"[data-demo-tour]\");\n  demoTourButton.addEventListener(\"click\", () => {\n    const driverObj = driver({\n      popoverClass: \"driverjs-theme\",\n      showButtons: [\"next\", \"previous\"],\n      steps: [\n        {\n          element: \"[data-hero-text]\",\n          popover: {\n            title: \"Before we start\",\n            description: \"This is just one use-case, make sure to look at the docs for more use-cases and examples.\",\n            nextBtnText: \"Okay, start!\",\n            side: \"bottom\",\n            align: \"start\"\n          }\n        },\n        {\n          element: \"[data-driver-tagline]\",\n          popover: {\n            title: \"Focus Anything\",\n            description: \"You can use it to highlight literally anything, images, text, svg, div, span, li etc.\",\n            side: \"bottom\",\n            align: \"start\"\n          }\n        },\n        {\n          element: \"[data-driver-name]\",\n          popover: {\n            title: \"Why Driver.js\",\n            description: \"It's lightweight, has no dependencies, is MIT licensed, is highly customizable, and is super easy to use.\",\n            side: \"bottom\",\n            align: \"start\"\n          }\n        },\n        {\n          element: \"[data-docs-link]\",\n          popover: {\n            title: \"More Powerful than Ever\",\n            description: \"Driver.js has been completely rewritten from scratch and is now more powerful than ever.\",\n            side: \"bottom\",\n            align: \"start\"\n          }\n        },\n        {\n          element: \"[data-example-btns]\",\n          popover: {\n            title: \"Examples\",\n            description: \"Here are some examples to give you a rough idea.\",\n            side: \"bottom\",\n            align: \"start\"\n          }\n        },\n        {\n          element: \"[data-example-btns] a:last-child\",\n          popover: {\n            title: \"Visit Docs\",\n            description: \"Make sure to visit the docs for more examples and use-cases.\",\n            side: \"top\",\n            align: \"start\"\n          }\n        },\n        {\n          element: \"[data-github-link]\",\n          popover: {\n            title: \"MIT Licensed\",\n            description: \"Driver.js is MIT licensed and is used by thousands of companies around the world.\",\n            side: \"top\",\n            align: \"start\"\n          }\n        },\n        {\n          popover: {\n            description: \"<img style='width: 270px; height: 206.65px; margin-bottom: 10px; border-radius: 5px;' src='https://i.imgur.com/3WpTnyA.gif' />That's it for now, make sure to <a class='underline font-medium' href='/docs/installation'>visit the docs</a> for more examples and use-cases.\",\n            side: \"bottom\",\n            align: \"start\",\n            showButtons: [],\n            popoverClass: \"default-theme\"\n          }\n        }\n      ]\n    });\n\n    driverObj.drive();\n  });\n\n  const animatedTourBtn = document.getElementById('animated-tour');\n  animatedTourBtn.addEventListener(\"click\", () => {\n    const driverObj = driver({\n      popoverClass: \"driverjs-theme\",\n      showButtons: [\"next\", \"previous\"],\n      steps: [\n        {\n          element: \"[data-examples-heading]\",\n          popover: {\n            title: \"Animated Tour\",\n            description: \"Animated tour can simply be achieved by setting `animate` option true.\",\n            side: \"bottom\",\n            align: \"start\"\n          }\n        },\n        {\n          element: \"[data-examples-tagline]\",\n          popover: {\n            title: \"Just an Example\",\n            description: \"We don't have many steps in this example, but you can have as many as you want.\",\n            side: \"bottom\",\n            align: \"start\"\n          }\n        },\n        {\n          element: \"[data-examples-tagline] a\",\n          popover: {\n            title: \"That's it for now\",\n            description: \"Make sure to visit the docs for more examples and use-cases.\",\n            side: \"bottom\",\n            align: \"start\"\n          }\n        },\n      ],\n      onDestroyed: () => {\n        markDone(animatedTourBtn);\n      }\n    });\n\n    driverObj.drive();\n  });\n\n  const staticTourBtn = document.getElementById('static-tour');\n  staticTourBtn.addEventListener(\"click\", () => {\n    const driverObj = driver({\n      animate: false,\n      popoverClass: \"driverjs-theme\",\n      showButtons: [\"next\", \"previous\"],\n      steps: [\n        {\n          element: \"[data-examples-heading]\",\n          popover: {\n            title: \"Static Tour\",\n            description: \"This is a static tour, which means that it won't be animated.\",\n            side: \"bottom\",\n            align: \"start\"\n          }\n        },\n        {\n          element: \"[data-examples-tagline]\",\n          popover: {\n            title: \"Just an Example\",\n            description: \"We don't have many steps in this example, but you can have as many as you want.\",\n            side: \"bottom\",\n            align: \"start\"\n          }\n        },\n        {\n          element: \"[data-examples-tagline] a\",\n          popover: {\n            title: \"That's it for now\",\n            description: \"Make sure to visit the docs for more examples and use-cases.\",\n            side: \"bottom\",\n            align: \"start\"\n          }\n        },\n      ],\n      onDestroyed: () => {\n        markDone(staticTourBtn);\n      }\n    });\n\n    driverObj.drive();\n  });\n\n  const asyncTourBtn = document.getElementById('async-tour');\n  asyncTourBtn.addEventListener(\"click\", () => {\n    const driverObj = driver({\n      animate: true,\n      popoverClass: \"driverjs-theme\",\n      showButtons: [\"next\", \"previous\"],\n      steps: [\n        {\n          popover: {\n            title: \"Async Tour\",\n            description: \"You can also use Driver.js to create async tours. Element for the next step doesn't exist -- we will create before moving next.\",\n            side: \"bottom\",\n            align: \"start\",\n            onNextClick: () => {\n              mountDummyElement();\n              driverObj.moveNext();\n            }\n          }\n        },\n        {\n          element: '.dynamic-el',\n          popover: {\n            title: \"New Element\",\n            description: \"This element was created after the first step and will be destroyed after this step.\",\n            side: \"bottom\",\n            align: \"start\",\n            onPrevClick: () => {\n              removeDummyElement();\n              driverObj.movePrevious();\n            },\n            onNextClick: () => {\n              removeDummyElement();\n              driverObj.moveNext();\n            }\n          }\n        },\n        {\n          popover: {\n            title: \"More in Docs\",\n            description: \"There is a detailed guide on <a href='/docs/async-tour/' target='_blank' class='underline font-bold'>how to create async</a> tours in the documentation.\",\n            side: \"bottom\",\n            align: \"start\",\n            onPrevClick: () => {\n              mountDummyElement();\n              driverObj.movePrevious();\n            }\n          }\n        },\n      ],\n      onDestroyed: () => {\n        markDone(asyncTourBtn);\n      }\n    });\n\n    driverObj.drive();\n  });\n\n  const exitConfirm = document.getElementById('confirm-on-exit');\n  exitConfirm.addEventListener(\"click\", () => {\n    const driverObj = driver({\n      animate: true,\n      popoverClass: \"driverjs-theme\",\n      showButtons: [\"next\", \"previous\"],\n      steps: [\n        {\n          element: \"[data-examples-heading]\",\n          popover: {\n            title: \"Confirm on Exit\",\n            description: \"You can also ask for confirmation before exiting the tour.\",\n            side: \"bottom\",\n            align: \"start\"\n          }\n        },\n        {\n          element: \"[data-examples-tagline]\",\n          popover: {\n            title: \"Just an Example\",\n            description: \"We don't have many steps in this example, but you can have as many as you want.\",\n            side: \"bottom\",\n            align: \"start\"\n          }\n        },\n        {\n          element: \"[data-examples-tagline] a\",\n          popover: {\n            title: \"That's it for now\",\n            description: \"Make sure to visit the docs for more examples and use-cases.\",\n            side: \"bottom\",\n            align: \"start\"\n          }\n        },\n      ],\n      onDestroyStarted: () => {\n        if (!driverObj.hasNextStep() || confirm(\"Are you sure?\")) {\n          driverObj.destroy();\n        }\n      },\n      onDestroyed: () => {\n        markDone(exitConfirm);\n      }\n    });\n\n    driverObj.drive();\n  });\n\n  const showProgressBtn = document.getElementById('show-progress');\n  showProgressBtn.addEventListener('click', () => {\n    const driverObj = driver({\n      animate: true,\n      showProgress: true,\n      showButtons: [\"next\", \"previous\"],\n      steps: [\n        {\n          element: \"[data-examples-heading]\",\n          popover: {\n            title: \"Show Progress\",\n            description: \"You can set `showProgress` to `true` and progress will be shown in the footer.\",\n            side: \"bottom\",\n            align: \"start\"\n          }\n        },\n        {\n          element: \"[data-examples-tagline]\",\n          popover: {\n            title: \"Just an Example\",\n            description: \"We don't have many steps in this example, but you can have as many as you want.\",\n            side: \"bottom\",\n            align: \"start\"\n          }\n        },\n        {\n          element: \"[data-examples-tagline] a\",\n          popover: {\n            title: \"That's it for now\",\n            description: \"Make sure to visit the docs for more examples and use-cases.\",\n            side: \"bottom\",\n            align: \"start\"\n          }\n        },\n      ],\n      onDestroyed: () => {\n        markDone(showProgressBtn);\n      }\n    });\n\n    driverObj.drive();\n  });\n\n  const simpleHighlightBtn = document.getElementById('simple-element-highlight');\n  simpleHighlightBtn.addEventListener('click', () => {\n    const driverObj = driver({\n      popoverClass: 'driverjs-theme',\n      onDestroyed: () => {\n        markDone(simpleHighlightBtn);\n      }\n    });\n\n    driverObj.highlight({\n      element: '[data-example-btns]'\n    })\n  });\n\n  const simpleHighlightPopoverBtn = document.getElementById('simple-element-highlight-popover');\n  simpleHighlightPopoverBtn.addEventListener('click', () => {\n    const driverObj = driver({\n      popoverClass: 'driverjs-theme',\n      onDestroyed: () => {\n        markDone(simpleHighlightPopoverBtn);\n      }\n    });\n\n    driverObj.highlight({\n      element: '[data-example-btns]',\n      popover: {\n        title: \"Popover Highlight\",\n        description: \"You can also highlight an element with a popover.\",\n        side: 'top'\n      }\n    });\n  });\n\n  const noElementbtn = document.getElementById('no-element');\n  noElementbtn.addEventListener('click', () => {\n    const driverObj = driver({\n      popoverClass: 'driverjs-theme',\n      onDestroyed: () => {\n        markDone(noElementbtn);\n      }\n    });\n\n    driverObj.highlight({\n      popover: {\n        title: \"Without Element\",\n        description: \"You can also show a popover without highlighting an element. For example, this popover is shown without highlighting anything.\",\n      }\n    });\n  });\n\n  const preventCloseBtn = document.getElementById('prevent-close');\n  preventCloseBtn.addEventListener('click', () => {\n    const driverObj = driver({\n      animate: true,\n      allowClose: false,\n      showProgress: true,\n      showButtons: [\"next\", \"previous\"],\n      steps: [\n        {\n          element: \"[data-examples-heading]\",\n          popover: {\n            title: \"Show Progress\",\n            description: \"You can set `showProgress` to `true` and progress will be shown in the footer.\",\n            side: \"bottom\",\n            align: \"start\"\n          }\n        },\n        {\n          element: \"[data-examples-tagline]\",\n          popover: {\n            title: \"Just an Example\",\n            description: \"We don't have many steps in this example, but you can have as many as you want.\",\n            side: \"bottom\",\n            align: \"start\"\n          }\n        },\n        {\n          element: \"[data-examples-tagline] a\",\n          popover: {\n            title: \"That's it for now\",\n            description: \"Make sure to visit the docs for more examples and use-cases.\",\n            side: \"bottom\",\n            align: \"start\"\n          }\n        },\n      ],\n      onDestroyed: () => {\n        markDone(preventCloseBtn);\n      }\n    });\n\n    driverObj.drive();\n  });\n\n  const overlayColorBtn = document.getElementById('overlay-color');\n  overlayColorBtn.addEventListener('click', () => {\n    const driverObj = driver({\n      overlayColor: 'red',\n      overlayOpacity: 0.5,\n      onDestroyed: () => {\n        markDone(overlayColorBtn);\n      }\n    });\n\n    driverObj.highlight({\n      element: '[data-example-btns]',\n      popover: {\n        title: \"Popover Highlight\",\n        description: \"You can also highlight an element with a popover.\",\n        side: 'top'\n      }\n    });\n  });\n\n  const popoverPositionBtn = document.getElementById('popover-position');\n  popoverPositionBtn.addEventListener('click', () => {\n    const driverObj = driver({\n      onDestroyed: () => {\n        markDone(popoverPositionBtn);\n      }\n    });\n\n    driverObj.highlight({\n      element: '#popover-position',\n      popover: {\n        title: \"Popover Position\",\n        description: \"You can also change the position of the popover using `side` and `align` options.<br /> Allowed sides are `top`, `bottom`, `left` and `right`. Allowed aligns are `start`, `center` and `end`.\",\n        side: 'top',\n        align: 'start'\n      }\n    });\n  });\n\n  const customizingBtn = document.getElementById('customizing-popover');\n  customizingBtn.addEventListener('click', () => {\n    const driverObj = driver({\n      popoverClass: 'driverjs-theme',\n      onDestroyed: () => {\n        markDone(customizingBtn);\n      }\n    });\n\n    driverObj.highlight({\n      element: '#customizing-popover',\n      popover: {\n        title: \"Customizing Popover\",\n        description: \"Add your own class using `popoverClass` or use `onPopoverRender` to get full control over the popover. <br /><br /> Visit these pages which cover <a class='font-medium underline' href='/docs/styling-popover'>styling</a> and <a class='font-medium underline' href='/docs/buttons'>customizing popovers</a> in detail.\",\n        side: 'top',\n        align: 'start'\n      }\n    });\n  });\n\n  const hooksEverythingBtn = document.getElementById('hooks-everything');\n  hooksEverythingBtn.addEventListener('click', () => {\n    const driverObj = driver({\n      popoverClass: 'driverjs-theme',\n      onDestroyed: () => {\n        markDone(hooksEverythingBtn);\n      }\n    });\n\n    driverObj.highlight({\n      element: '#hooks-everything',\n      popover: {\n        title: \"Hooks for Everything\",\n        description: \"Have a look at the <a class='font-medium underline' href='/docs/configuration'>configuration</a> page to see how you can use hooks to control the driver.\",\n        side: 'top',\n        align: 'start'\n      }\n    });\n  });\n</script>"
  },
  {
    "path": "docs/src/components/FeatureMarquee.tsx",
    "content": "import React from \"react\";\nimport Marquee from \"react-fast-marquee\";\n\nconst featureList = [\n  \"Supports all Major Browsers\",\n  \"Works on Mobile Devices\",\n  \"Highly Customizable\",\n  \"Light-weight\",\n  \"No dependencies\",\n  \"Feature Rich\",\n  \"MIT Licensed\",\n  \"Written in TypeScript\",\n  \"Vanilla JavaScript\",\n  \"Easy to use\",\n  \"Accessible\",\n  \"Frameworks Ready\",\n];\n\nexport function FeatureMarquee() {\n  return (\n    <Marquee autoFill>\n      <p className=\"py-2.5 md:py-3.5 lg:py-4 text-lg md:text-xl lg:text-2xl whitespace-nowrap\">\n        { featureList.map((featureItem, index) => (\n          <React.Fragment key={index}>\n            { featureItem }<span className=\"mx-2 md:mx-3\">&middot;</span>\n          </React.Fragment>\n        ))}\n      </p>\n    </Marquee>\n  );\n}\n"
  },
  {
    "path": "docs/src/components/Features.astro",
    "content": "---\nimport { Earth, Smartphone, Settings, Feather, Code2, Layers, Keyboard } from \"lucide-react\";\nimport Container from \"./Container.astro\";\n---\n\n<div class=\"py-0 mb-16 bg-white\">\n  <Container>\n    <div class=\"max-w-screen-lg\">\n      <h2 class=\"text-4xl md:text-5xl lg:text-6xl font-bold text-gray-900 mb-4 md:mb-6\">Nothing else like it</h2>\n      <p class=\"text-base md:text-xl lg:text-2xl text-black mb-10 md:mb-14 lg:mb-16\">\n        Lightweight with no external dependencies, supports all major browsers and is highly customizable.\n      </p>\n    </div>\n    <div class=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-8 md:gap-10 lg:gap-4\">\n      <div class=\"group bg-yellow-50 p-6 rounded-xl transition-colors\">\n        <div class=\"flex justify-center items-center mb-4 w-12 h-12 rounded-xl bg-yellow-300 lg:h-14 lg:w-14\">\n          <Earth className=\"w-6 h-6 text-black lg:w-7 lg:h-7\" />\n        </div>\n        <h3 class=\"mb-3 text-xl md:text-2xl font-bold text-black\">Browser Support</h3>\n        <p class=\"text-gray-600 md:text-lg\">\n          Works in all modern browsers including Chrome, IE9+, Safari, Firefox and Opera\n        </p>\n      </div>\n      <div class=\"group bg-yellow-50 p-6 rounded-xl transition-colors\">\n        <div class=\"flex justify-center items-center mb-4 w-12 h-12 rounded-xl bg-yellow-300 lg:h-14 lg:w-14\">\n          <Smartphone className=\"w-6 h-6 text-black lg:w-7 lg:h-7\" />\n        </div>\n        <h3 class=\"mb-3 text-xl md:text-2xl font-bold text-black\">Mobile Ready</h3>\n        <p class=\"text-gray-600 md:text-lg\">Works on desktop, tablets and mobile devices</p>\n      </div>\n      <div class=\"group bg-yellow-50 p-6 rounded-xl transition-colors\">\n        <div class=\"flex justify-center items-center mb-4 w-12 h-12 rounded-xl bg-yellow-300 lg:h-14 lg:w-14\">\n          <Settings className=\"w-6 h-6 text-black lg:w-7 lg:h-7\" />\n        </div>\n        <h3 class=\"mb-3 text-xl md:text-2xl font-bold text-black\">Highly Customizable</h3>\n        <p class=\"text-gray-600 md:text-lg\">Powerful API that allows you to customize it to your needs</p>\n      </div>\n      <div class=\"group bg-yellow-50 p-6 rounded-xl transition-colors\">\n        <div class=\"flex justify-center items-center mb-4 w-12 h-12 rounded-xl bg-yellow-300 lg:h-14 lg:w-14\">\n          <Feather className=\"w-6 h-6 text-black lg:w-7 lg:h-7\" />\n        </div>\n        <h3 class=\"mb-3 text-xl md:text-2xl font-bold text-black\">Lightweight</h3>\n        <p class=\"text-gray-600 md:text-lg\">\n          Only 5KB minified, compared to other libraries which are typically >12KB minified\n        </p>\n      </div>\n      <div class=\"group bg-yellow-50 p-6 rounded-xl transition-colors\">\n        <div class=\"flex justify-center items-center mb-4 w-12 h-12 rounded-xl bg-yellow-300 lg:h-14 lg:w-14\">\n          <Code2 className=\"w-6 h-6 text-black lg:w-7 lg:h-7\" />\n        </div>\n        <h3 class=\"mb-3 text-xl md:text-2xl font-bold text-black\">No Dependencies</h3>\n        <p class=\"text-gray-600 md:text-lg\">Simple to use with absolutely no external dependencies</p>\n      </div>\n      <div class=\"group bg-yellow-50 p-6 rounded-xl transition-colors\">\n        <div class=\"flex justify-center items-center mb-4 w-12 h-12 rounded-xl bg-yellow-300 lg:h-14 lg:w-14\">\n          <Layers className=\"w-6 h-6 text-black lg:w-7 lg:h-7\" />\n        </div>\n        <h3 class=\"mb-3 text-xl md:text-2xl font-bold text-black\">Feature Rich</h3>\n        <p class=\"text-gray-600 md:text-lg\">Create powerful feature introductions for your web applications</p>\n      </div>\n      <div class=\"group bg-yellow-50 p-6 rounded-xl transition-colors\">\n        <div class=\"flex justify-center items-center mb-4 w-12 h-12 rounded-xl bg-yellow-300 lg:h-14 lg:w-14\">\n          <span class=\"w-6 h-6 text-black lg:w-7 lg:h-7 font-black\">MIT</span>\n        </div>\n        <h3 class=\"mb-3 text-xl md:text-2xl font-bold text-black\">MIT License</h3>\n        <p class=\"text-gray-600 md:text-lg\">Free for both personal and commercial use</p>\n      </div>\n      <div class=\"group bg-yellow-50 p-6 rounded-xl transition-colors\">\n        <div class=\"flex justify-center items-center mb-4 w-12 h-12 rounded-xl bg-yellow-300 lg:h-14 lg:w-14\">\n          <Keyboard className=\"w-6 h-6 text-black lg:w-7 lg:h-7\" />\n        </div>\n        <h3 class=\"mb-3 text-xl md:text-2xl font-bold text-black\">Keyboard Control</h3>\n        <p class=\"text-gray-600 md:text-lg\">All actions can be controlled via keyboard</p>\n      </div>\n      <div class=\"group bg-yellow-50 p-6 rounded-xl transition-colors\">\n        <div class=\"flex justify-center items-center mb-4 w-12 h-12 rounded-xl bg-yellow-300 lg:h-14 lg:w-14\">\n          <span class=\"w-6 h-6 text-black lg:w-7 lg:h-7 font-black\">ALL</span>\n        </div>\n        <h3 class=\"mb-3 text-xl md:text-2xl font-bold text-black\">Highlight Anything</h3>\n        <p class=\"text-gray-600 md:text-lg\">Highlight any element on the page</p>\n      </div>\n    </div>\n  </Container>\n</div>\n"
  },
  {
    "path": "docs/src/components/FormHelp.tsx",
    "content": "import { useEffect } from \"react\";\nimport { driver } from \"driver.js\";\nimport \"driver.js/dist/driver.css\";\n\nexport function FormHelp() {\n  useEffect(() => {\n    const driverObj = driver({\n      popoverClass: \"driverjs-theme\",\n      stagePadding: 0,\n      onDestroyed: () => {\n        (document?.activeElement as any)?.blur();\n      }\n    });\n\n    const nameEl = document.getElementById(\"name\");\n    const educationEl = document.getElementById(\"education\");\n    const ageEl = document.getElementById(\"age\");\n    const addressEl = document.getElementById(\"address\");\n    const submitEl = document.getElementById(\"submit-btn\");\n\n    nameEl!.addEventListener(\"focus\", () => {\n      driverObj.highlight({\n        element: nameEl!,\n        popover: {\n          title: \"Name\",\n          description: \"Enter your name here\",\n        },\n      });\n    });\n\n    educationEl!.addEventListener(\"focus\", () => {\n      driverObj.highlight({\n        element: educationEl!,\n        popover: {\n          title: \"Education\",\n          description: \"Enter your education here\",\n        },\n      });\n    });\n\n    ageEl!.addEventListener(\"focus\", () => {\n      driverObj.highlight({\n        element: ageEl!,\n        popover: {\n          title: \"Age\",\n          description: \"Enter your age here\",\n        },\n      });\n    });\n\n    addressEl!.addEventListener(\"focus\", () => {\n      driverObj.highlight({\n        element: addressEl!,\n        popover: {\n          title: \"Address\",\n          description: \"Enter your address here\",\n        },\n      });\n    });\n\n    submitEl!.addEventListener(\"focus\", (e) => {\n      e.preventDefault();\n      driverObj.destroy();\n    });\n  });\n\n  return <></>;\n}\n"
  },
  {
    "path": "docs/src/components/HeroSection.astro",
    "content": "---\nimport Container from \"./Container.astro\";\n---\n\n<div class=\"bg-white border-b border-gray-100 select-none\">\n  <Container>\n    <div class=\"flex items-center justify-between h-16\">\n      <a href=\"/\" class=\"flex items-center justify-end text-xl font-bold text-gray-900 font-semibold gap-2.5\">\n        <img src=\"/favicon.svg\" alt=\"driver.js logo\" class=\"h-10\" />\n        driver.js\n      </a>\n      <span class=\"flex items-center gap-7\">\n        <a href=\"/docs/installation\" class=\"hover:underline underline-offset-4 text-lg font-medium text-gray-900\">\n          <span class=\"hidden sm:inline\">Documentation</span>\n          <span class=\"inline sm:hidden\">Docs</span>\n        </a>\n        <a href=\"https://github.com/kamranahmedse/driver.js\" target=\"_blank\" class=\"hover:underline underline-offset-4 text-lg font-medium text-gray-900\">GitHub</a>\n      </span>\n    </div>\n  </Container>\n</div>\n<div class=\"bg-yellow-300/80 overflow-hidden via-transparent\">\n  <Container>\n    <div class=\"py-10 md:py-14 lg:py-20 flex justify-start items-center gap-4\">\n      <div class=\"flex-grow\" data-hero-text>\n        <h1 data-driver-name class=\"text-7xl md:text-8xl lg:text-9xl mb-2 md:mb-3 lg:mb-4 font-bold\">driver.js</h1>\n        <p data-driver-tagline class=\"text-base md:text-2xl lg:text-3xl !leading-normal\">\n          Lightweight JavaScript library for product tours, highlights, and contextual help to guide users through your\n          product.\n        </p>\n        <div class=\"mt-4 md:mt-8 lg:mt-10 flex flex-col sm:flex-row gap-2 items-stretch\">\n          <button\n            data-demo-tour\n            class=\"bg-black rounded-xl py-2 md:py-3 px-6 font-medium text-white text-lg md:text-xl focus:outline-0 hover:bg-gray-800 focus:bg-gray-800\"\n          >\n            Show Demo\n          </button>\n          <a\n            href=\"/docs/installation\"\n            data-docs-link\n            class=\"bg-white rounded-xl py-2 md:py-3 px-6 font-medium text-black text-lg md:text-xl focus:outline-0 border-2 border-black text-center hover:bg-gray-200 focus:bg-gray-200\"\n          >\n            Get Started\n          </a>\n        </div>\n      </div>\n      <div class=\"flex-shrink-0 hidden sm:flex\">\n        <img src=\"/driver.svg\" alt=\"driver.js image\" class=\"sm:h-48 md:h-60 lg:h-72\" />\n      </div>\n    </div>\n  </Container>\n</div>\n"
  },
  {
    "path": "docs/src/components/OpenSourceLove.astro",
    "content": "---\nimport Container from \"./Container.astro\";\nimport { getFormattedStars } from \"../lib/github\";\n\nconst starCount = getFormattedStars('kamranahmedse/driver.js');\n---\n<div class=\"py-10 md:py-12 lg:py-24 bg-white text-black border-t\">\n  <Container>\n    <div class=\"flex items-center\">\n      <div>\n        <h2 class=\"text-3xl md:text-4xl lg:text-6xl font-bold mb-4\">Loved by Many</h2>\n        <p class=\"md:text-xl lg:text-2xl text-black mb-6 lg:mb-8\">With millions of downloads, Driver.js is an <span class=\"font-bold\">MIT licensed</span>\n          opensource\n          project and is used by\n          thousands of companies around the world.</p>\n\n        <div class=\"flex flex-col sm:flex-row gap-2 md:gap-3\">\n          <a href=\"https://github.com/kamranahmedse/driver.js\"\n             data-github-link\n             target=\"_blank\"\n             class=\"flex justify-center items-center font-medium text-lg md:text-xl lg:text-2xl rounded-lg lg:rounded-xl py-2 lg:py-3 px-5 bg-yellow-300 border-black hover:bg-yellow-400\">\n            <span class=\"mr-3 inline-flex items-center\"><img src=\"/star.svg\" alt=\"Hero Image\" class=\"h-5 md:h-7 mr-1 md:mr-2\" /> { starCount }</span>\n            GitHub Stars\n          </a>\n          <a href=\"/docs/installation\"\n             class=\"bg-black justify-center text-white flex items-center font-medium text-lg md:text-xl lg:text-2xl border-4 border-black rounded-lg lg:rounded-xl py-2 lg:py-3 px-5 hover:bg-gray-800\">\n            Start Using Driver.js\n          </a>\n        </div>\n      </div>\n      <img src=\"/thumbs.svg\" alt=\"Hero Image\" class=\"hidden lg:block h-36 ml-16\" />\n    </div>\n  </Container>\n</div>"
  },
  {
    "path": "docs/src/components/Sidebar.astro",
    "content": "---\nimport { getCollection, getEntry } from \"astro:content\";\nimport { getFormattedStars } from \"../lib/github\";\nimport { getAllGuides } from \"../lib/guide\";\n\nexport interface Props {\n  activePath: string;\n}\n\nconst { activePath, groupedGuides, activeGuideTitle } = Astro.props;\n---\n<div id=\"docs-sidebar\" class=\"hidden md:block w-[200px] lg:w-[350px] border-r border-gray-200 text-right min-h-screen flex-shrink-0\">\n  <div class=\"relative sh:sticky top-0\">\n    <div class=\"justify-end flex pt-10 pb-5 px-5\">\n      <a href=\"/\" class=\"block items-center justify-end mb-2\">\n        <img src=\"/driver-head.svg\" alt=\"Astro\" class=\"w-16 h-16\" />\n      </a>\n    </div>\n\n    {Object.keys(groupedGuides).map(groupTitle => {\n      const guides = groupedGuides[groupTitle];\n\n      return (\n        <>\n          <h2 class=\"text-xl font-bold mb-2 pr-5 relative\">{groupTitle}</h2>\n          <ul class=\"text-gray-400 mb-5\">\n            {guides.map(guide => {\n              const guidePath = `/docs/${guide.slug}`;\n              return (\n                <li class=\"mb-2\">\n                  <a href={guidePath}\n                     class:list={[\"hover:text-black pr-5 py-2\", { \"text-black\": activeGuideTitle === guide.data.title }]}>{guide.data.title}</a>\n                </li>\n              );\n            })}\n          </ul>\n        </>\n      );\n    })}\n  </div>\n</div>"
  },
  {
    "path": "docs/src/components/UsecaseItem.astro",
    "content": "---\nexport interface Props {\n  title: string;\n  description: string;\n}\n\nconst { title, description } = Astro.props;\n---\n\n<div class=\"flex flex-col gap-2 md:gap-2 lg:gap-4 pt-2\">\n  <span class=\"border-b-2 border-b-black block w-[30px] md:w-[40px] lg:w-[50px]\"></span>\n  <h3 class=\"text-xl md:text-2xl lg:text-3xl mt-2 md:mt-3 lg:mt-0 font-bold text-black\">\n    { title }\n  </h3>\n  <p class=\"md:text-lg lg:text-xl text-black\">\n    { description }\n  </p>\n</div>"
  },
  {
    "path": "docs/src/components/UsecaseList.astro",
    "content": "---\nimport UsecaseItem from \"./UsecaseItem.astro\";\n---\n<p class=\"text-base md:text-xl lg:text-2xl text-black\">Due to its extensive API, driver.js can be used for a wide range of use\n  cases.</p>\n<div class=\"grid grid-cols-1 sm:grid-cols-2 gap-4 md:gap-6 lg:gap-12 mt-10\">\n  <UsecaseItem\n    title=\"Onboard Users\"\n    description=\"Onboard your users by explaining how to use your product and answer common questions.\"\n  />\n  <UsecaseItem\n    title=\"Remove Distractions\"\n    description=\"With highlight feature, you can remove distractions and focus your users attention on what matters.\"\n  />\n  <UsecaseItem\n    title=\"Contextual Help\"\n    description=\"Provide contextual help for your users, explain how to use your product and answer common questions.\"\n  />\n  <UsecaseItem\n    title=\"Feature Adoption\"\n    description=\"Highlight new features, explain how to use them and make sure your users don't miss them.\"\n  />\n</div>\n"
  },
  {
    "path": "docs/src/content/config.ts",
    "content": "import { z, defineCollection } from \"astro:content\";\n\nconst guidesCollection = defineCollection({\n  type: \"content\",\n  schema: z.object({\n    groupTitle: z.string(),\n    title: z.string(),\n    sort: z.number(),\n  }),\n});\n\nexport const collections = {\n  guides: guidesCollection,\n};\n"
  },
  {
    "path": "docs/src/content/guides/animated-tour.mdx",
    "content": "---\ntitle: \"Animated Tour\"\ngroupTitle: \"Examples\"\nsort: 2\n---\n\nimport { CodeSample } from \"../../components/CodeSample.tsx\";\n\nThe following example shows how to create a simple tour with a few steps. Click the button below the code sample to see the tour in action.\n\n<CodeSample\n  heading={'Basic Animated Tour'}\n  config={{\n    animate: true,\n    showProgress: true,\n    showButtons: ['next', 'previous'],\n  }}\n  tour={[\n    { element: '#tour-example', popover: { title: 'Animated Tour Example', description: 'Here is the code example showing animated tour. Let\\'s walk you through it.', side: \"left\", align: 'start' }},\n    { element: '.line:nth-child(1)', popover: { title: 'Import the Library', description: 'It works the same in vanilla JavaScript as well as frameworks.', side: \"bottom\", align: 'start' }},\n    { element: '.line:nth-child(2)', popover: { title: 'Importing CSS', description: 'Import the CSS which gives you the default styling for popover and overlay.', side: \"bottom\", align: 'start' }},\n    { element: '.line:nth-child(4) span:nth-child(7)', popover: { title: 'Create Driver', description: 'Simply call the driver function to create a driver.js instance', side: \"left\", align: 'start' }},\n    { element: '.line:nth-child(17)', popover: { title: 'Start Tour', description: 'Call the drive method to start the tour and your tour will be started.', side: \"top\", align: 'start' }},\n    { element: '.line:nth-child(5)', popover: { title: 'Hide Progress', description: 'Progress shown in the bottom left is hidden by default. You can make driver show/hide the progress using this option.', side: \"top\", align: 'start' }},\n    { element: '#docs-sidebar a[href=\"/docs/configuration\"]', popover: { title: 'More Configuration', description: 'Look at this page for all the configuration options you can pass.', side: \"right\", align: 'start' }},\n    { popover: { title: 'Happy Coding', description: 'And that is all, go ahead and start adding tours to your applications.' } }\n  ]}\n  id={\"tour-example\"}\n  client:load\n>\n  ```js\n  import { driver } from \"driver.js\";\n  import \"driver.js/dist/driver.css\";\n\n  const driverObj = driver({\n    showProgress: true,\n    steps: [\n      { element: '#tour-example', popover: { title: 'Animated Tour Example', description: 'Here is the code example showing animated tour. Let\\'s walk you through it.', side: \"left\", align: 'start' }},\n      { element: 'code .line:nth-child(1)', popover: { title: 'Import the Library', description: 'It works the same in vanilla JavaScript as well as frameworks.', side: \"bottom\", align: 'start' }},\n      { element: 'code .line:nth-child(2)', popover: { title: 'Importing CSS', description: 'Import the CSS which gives you the default styling for popover and overlay.', side: \"bottom\", align: 'start' }},\n      { element: 'code .line:nth-child(4) span:nth-child(7)', popover: { title: 'Create Driver', description: 'Simply call the driver function to create a driver.js instance', side: \"left\", align: 'start' }},\n      { element: 'code .line:nth-child(18)', popover: { title: 'Start Tour', description: 'Call the drive method to start the tour and your tour will be started.', side: \"top\", align: 'start' }},\n      { element: 'a[href=\"/docs/configuration\"]', popover: { title: 'More Configuration', description: 'Look at this page for all the configuration options you can pass.', side: \"right\", align: 'start' }},\n      { popover: { title: 'Happy Coding', description: 'And that is all, go ahead and start adding tours to your applications.' } }\n    ]\n  });\n\n  driverObj.drive();\n  ```\n</CodeSample>\n"
  },
  {
    "path": "docs/src/content/guides/api.mdx",
    "content": "---\ntitle: \"API Reference\"\ngroupTitle: \"Introduction\"\nsort: 4\n---\n\nHere is the list of methods provided by `driver` when you initialize it.\n\n> **Note:** We have omitted the configuration options for brevity. Please look at the configuration section for the options. Links are provided in the description below.\n\n```javascript\nimport { driver } from \"driver.js\";\nimport \"driver.js/dist/driver.css\";\n\n// Look at the configuration section for the options\n// https://driverjs.com/docs/configuration#driver-configuration\nconst driverObj = driver({ /* ... */ });\n\n// --------------------------------------------------\n// driverObj is an object with the following methods\n// --------------------------------------------------\n\n// Start the tour using `steps` given in the configuration\ndriverObj.drive();  // Starts at step 0\ndriverObj.drive(4); // Starts at step 4\n\ndriverObj.moveNext(); // Move to the next step\ndriverObj.movePrevious(); // Move to the previous step\ndriverObj.moveTo(4); // Move to the step 4\ndriverObj.hasNextStep(); // Is there a next step\ndriverObj.hasPreviousStep() // Is there a previous step\n\ndriverObj.isFirstStep(); // Is the current step the first step\ndriverObj.isLastStep(); // Is the current step the last step\n\ndriverObj.getActiveIndex(); // Gets the active step index\n\ndriverObj.getActiveStep(); // Gets the active step configuration\ndriverObj.getPreviousStep(); // Gets the previous step configuration\ndriverObj.getActiveElement(); // Gets the active HTML element\ndriverObj.getPreviousElement(); // Gets the previous HTML element\n\n// Is the tour or highlight currently active\ndriverObj.isActive();\n\n// Recalculate and redraw the highlight\ndriverObj.refresh();\n\n// Look at the configuration section for configuration options\n// https://driverjs.com/docs/configuration#driver-configuration\ndriverObj.getConfig();\ndriverObj.setConfig({ /* ... */ });\n\ndriverObj.setSteps([ /* ... */ ]); // Set the steps\n\n// Look at the state section of configuration for format of the state\n// https://driverjs.com/docs/configuration#state\ndriverObj.getState();\n\n// Look at the DriveStep section of configuration for format of the step\n// https://driverjs.com/docs/configuration/#drive-step-configuration\ndriverObj.highlight({ /* ... */ }); // Highlight an element\n\ndriverObj.destroy(); // Destroy the tour\n```"
  },
  {
    "path": "docs/src/content/guides/async-tour.mdx",
    "content": "---\ntitle: \"Async Tour\"\ngroupTitle: \"Examples\"\nsort: 3\n---\n\nimport { CodeSample } from \"../../components/CodeSample.tsx\";\n\nYou can also have async steps in your tour. This is useful when you want to load some data from the server and then show the tour.\n\n<CodeSample\n  heading={'Asynchronous Tour'}\n  tour={[\n    {\n      element: '.line:nth-child(14)',\n      popover: {\n        title: 'First Step',\n        description: 'You can add a function to override the default behavior of the next button i.e. to fetch some data from the server and then call moveNext()',\n      }\n    },\n    {\n      element: '.line:nth-child(17)',\n      popover: {\n        title: 'Manually Handle Next',\n        description: 'Here we are moving to the next step manually since driver.js does not know when the data is loaded dynamically.',\n      }\n    },\n    {\n      popover: {\n        title: 'Next Step is Async',\n        description: 'This is the first step. Next element will be loaded dynamically.',\n      },\n    },\n    { element: '.dynamic-el', popover: { title: 'Async Element', description: 'This element is loaded dynamically and will be removed as soon as we move away from this step' } },\n    { popover: { title: 'Last Step', description: 'This is the last step.' } }\n  ]}\n  id={\"tour-example\"}\n  client:load>\n  ```js\n  import { driver } from \"driver.js\";\n  import \"driver.js/dist/driver.css\";\n\n  const driverObj = driver({\n    showProgress: true,\n    steps: [\n      {\n        popover: {\n          title: 'First Step',\n          description: 'This is the first step. Next element will be loaded dynamically.'\n          // By passing onNextClick, you can override the default behavior of the next button.\n          // This will prevent the driver from moving to the next step automatically.\n          // You can then manually call driverObj.moveNext() to move to the next step.\n          onNextClick: () => {\n            // .. load element dynamically\n            // .. and then call\n            driverObj.moveNext();\n          },\n        },\n      },\n      {\n        element: '.dynamic-el',\n        popover: {\n          title: 'Async Element',\n          description: 'This element is loaded dynamically.'\n        },\n        // onDeselected is called when the element is deselected.\n        // Here we are simply removing the element from the DOM.\n        onDeselected: () => {\n          // .. remove element\n          document.querySelector(\".dynamic-el\")?.remove();\n        }\n      },\n      { popover: { title: 'Last Step', description: 'This is the last step.' } }\n    ]\n\n});\n\ndriverObj.drive();\n\n```\n</CodeSample>\n\n> **Note**: By overriding `onNextClick`, and `onPrevClick` hooks you control the navigation of the driver. This means that user won't be able to navigate using the buttons and you will have to either call `driverObj.moveNext()` or `driverObj.movePrevious()` to navigate to the next/previous step.\n>\n> You can use this to implement custom logic for navigating between steps. This is also useful when you are dealing with dynamic content and want to highlight the next/previous element based on some logic.\n>\n> `onNextClick` and `onPrevClick` hooks can be configured at driver level as well as step level. When configured at the driver level, you control the navigation for all the steps. When configured at the step level, you control the navigation for that particular step only.\n"
  },
  {
    "path": "docs/src/content/guides/basic-usage.mdx",
    "content": "---\ntitle: \"Basic Usage\"\ngroupTitle: \"Introduction\"\nsort: 2\n---\n\nimport { CodeSample } from \"../../components/CodeSample.tsx\";\n\nOnce installed, you can import and start using the library. There are several different configuration options available to customize the library. You can find more details about the options in the [configuration section](/docs/configuration). Given below are the basic steps to get started.\n\nHere is a simple example of how to create a tour with multiple steps.\n\n<CodeSample\n  heading={'Basic Tour Example'}\n  config={{\n    showProgress: true,\n  }}\n  tour={[\n    { element: '#tour-example', popover: { title: 'Highlight Anything', description: 'You can highlight anything on the page.' }},\n    { element: '#tour-example pre', popover: { title: 'Control with Keyboard', description: 'You can use your keyboard to highlight elements.' }},\n    { popover: { title: 'Control with Keyboard', description: 'You can use your keyboard to highlight elements.' }},\n    { element: '#tour-example code .line:first-child', popover: { title: 'Control with Code', description: 'You can use the code to highlight elements.' }},\n    { element: '#tour-example code .line:nth-child(2)', popover: { title: 'Control with Code', description: 'You can use the code to highlight elements.', side: \"bottom\", align: 'start' }},\n  ]}\n  id={\"tour-example\"}\n  client:load\n>\n```js\nimport { driver } from \"driver.js\";\nimport \"driver.js/dist/driver.css\";\n\nconst driverObj = driver({\n  showProgress: true,\n  steps: [\n    { element: '.page-header', popover: { title: 'Title', description: 'Description' } },\n    { element: '.top-nav', popover: { title: 'Title', description: 'Description' } },\n    { element: '.sidebar', popover: { title: 'Title', description: 'Description' } },\n    { element: '.footer', popover: { title: 'Title', description: 'Description' } },\n  ]\n});\n\ndriverObj.drive();\n```\n</CodeSample>\n\nYou can pass a single step configuration to the `highlight` method to highlight a single element. Given below is a simple example of how to highlight a single element.\n\n<CodeSample heading='Highlighting a simple Element' id={\"some-element\"} highlight={{\n  element: '#some-element',\n  popover: {\n    title: 'Title for the Popover',\n    description: 'Description for it',\n  },\n}} client:load>\n```js\nimport { driver } from \"driver.js\";\nimport \"driver.js/dist/driver.css\";\n\nconst driverObj = driver();\ndriverObj.highlight({\n  element: '#some-element',\n  popover: {\n    title: 'Title for the Popover',\n    description: 'Description for it',\n  },\n});\n```\n</CodeSample>\n\nThe same configuration passed to the `highlight` method can be used to create a tour. Given below is a simple example of how to create a tour with a single step.\n\nExamples above show the basic usage of the library. Find more details about the configuration options in the [configuration section](/docs/configuration) and the examples in the [examples section](/docs/examples)."
  },
  {
    "path": "docs/src/content/guides/buttons.mdx",
    "content": "---\ntitle: \"Popover Buttons\"\ngroupTitle: \"Examples\"\nsort: 9\n---\n\nimport { CodeSample } from \"../../components/CodeSample.tsx\";\n\nYou can use the `showButtons` option to choose which buttons to show in the popover. The default value is `['next', 'previous', 'close']`.\n\n<div id=\"driver-note\" className=\"mb-5\">\n  > **Note:** When using the `highlight` method to highlight a single element, the only button shown is the `close`\n  button. However, you can use the `showButtons` option to show other buttons as well. But the buttons won't do\n  anything. You will have to use the `onNextClick` and `onPrevClick` callbacks to implement the functionality.\n</div>\n\n<div className='flex flex-col gap-1'>\n  <CodeSample\n    buttonText={\"Show All Buttons\"}\n    config={{\n      showButtons: [\n        'next',\n        'previous',\n        'close'\n      ],\n    }}\n    tour={[\n      {\n        element: '#driver-note',\n        popover: {\n          title: 'Popover Title',\n          description: 'Popover Description'\n        }\n      },\n      {\n        element: '#driver-note p code:nth-child(4)',\n        popover: {\n          title: 'Popover Title',\n          description: 'Popover Description'\n        }\n      }\n    ]}\n    id={\"code-sample\"}\n    client:load>\n    ```js\n    import { driver } from \"driver.js\";\n    import \"driver.js/dist/driver.css\";\n\n    const driverObj = driver({\n      showButtons: [\n        'next',\n        'previous',\n        'close'\n      ],\n      steps: [\n        {\n          element: '#first-element',\n          popover: {\n            title: 'Popover Title',\n            description: 'Popover Description'\n          }\n        },\n        {\n          element: '#second-element',\n          popover: {\n            title: 'Popover Title',\n            description: 'Popover Description'\n          }\n        }\n      ]\n    });\n\n    driverObj.drive();\n    ```\n  </CodeSample>\n  <CodeSample\n    buttonText=\"No Close Button\"\n    config={{\n      showButtons: [\n        'next',\n        'previous',\n      ],\n    }}\n    tour={[\n      {\n        element: '#driver-note',\n        popover: {\n          title: 'Popover Title',\n          description: 'Popover Description'\n        }\n      },\n      {\n        element: '#driver-note code:nth-child(2)',\n        popover: {\n          title: 'Popover Title',\n          description: 'Popover Description'\n        }\n      }\n    ]}\n    id={\"code-sample\"}\n    client:load />\n  <CodeSample\n    buttonText=\"No Buttons (Use Arrows)\"\n    config={{\n      showButtons: [undefined],\n    }}\n    tour={[\n      {\n        element: '#driver-note',\n        popover: {\n          title: 'Popover Title',\n          description: 'Popover Description'\n        }\n      },\n      {\n        element: '#driver-note code:nth-child(2)',\n        popover: {\n          title: 'Popover Title',\n          description: 'Popover Description',\n          side: 'bottom',\n          align: 'start'\n        }\n      }\n    ]}\n    id={\"code-sample\"}\n    client:load />\n</div>\n\n## Change Button Text\n\nYou can also change the text of buttons using `nextBtnText`, `prevBtnText` and `doneBtnText` options.\n\n<div className='flex flex-col gap-1'>\n  <CodeSample\n    heading=\"Change Button Text\"\n    buttonText={\"Change Button Text\"}\n    config={{\n      showProgress: true,\n      nextBtnText: '—>',\n      prevBtnText: '<--',\n      doneBtnText: 'X',\n    }}\n    tour={[\n      {\n        element: '#code-sample-3',\n        popover: {\n          title: 'Popover Title',\n          description: 'Popover Description'\n        }\n      },\n      {\n        element: '#code-sample-3 code',\n        popover: {\n          title: 'Popover Title',\n          description: 'Popover Description'\n        }\n      }\n    ]}\n    id={\"code-sample-3\"}\n    client:load>\n    ```js\n    import { driver } from \"driver.js\";\n    import \"driver.js/dist/driver.css\";\n\n    const driverObj = driver({\n      nextBtnText: '—›',\n      prevBtnText: '‹—',\n      doneBtnText: '✕',\n      showProgress: true,\n      steps: [\n        // ...\n      ]\n    });\n\n    driverObj.drive();\n    ```\n  </CodeSample>\n</div>\n\n## Event Handlers\n\nYou can use the `onNextClick`, `onPreviousClick` and `onCloseClick` callbacks to implement custom functionality when the user clicks on the next and previous buttons.\n\n> Please note that when you configure these callbacks, the default functionality of the buttons will be disabled. You will have to implement the functionality yourself.\n\n<CodeSample\n  buttonText={\"Show Example\"}\n  config={{}}\n  tour={[\n    {\n      element: '#logger-events',\n      popover: {\n        title: 'Events Logged',\n        description: 'Look at your console for the events logged'\n      }\n    },\n    {\n      element: '#code-sample-4 code',\n      popover: {\n        title: 'Popover Title',\n        description: 'Popover Description'\n      }\n    }\n  ]}\n  id={\"logger-events\"}\n  client:load>\n  ```js\n  import { driver } from \"driver.js\";\n  import \"driver.js/dist/driver.css\";\n\n  const driverObj = driver({\n    onNextClick:() => {\n      console.log('Next Button Clicked');\n      // Implement your own functionality here\n      driverObj.moveNext();\n    },\n    onPrevClick:() => {\n      console.log('Previous Button Clicked');\n      // Implement your own functionality here\n      driverObj.movePrevious();\n    },\n    onCloseClick:() => {\n      console.log('Close Button Clicked');\n      // Implement your own functionality here\n      driverObj.destroy();\n    },\n    steps: [\n      // ...\n    ]\n  });\n\n  driverObj.drive();\n  ```\n</CodeSample>\n\n## Custom Buttons\n\nYou can add custom buttons using `onPopoverRender` callback. This callback is called before the popover is rendered. In the following example, we are adding a custom button that takes the user to the first step.\n\n\n<CodeSample\n  buttonText={\"Run Example\"}\n  config={{\n    prevBtnText: '&larr; Previous',\n    nextBtnText: 'Next &rarr;',\n    doneBtnText: 'Done',\n    showButtons: ['next', 'previous'],\n  }}\n  tour={[\n    {\n      element: '#demo-hook-theme',\n      popover: {\n        align: 'start',\n        side: 'left',\n        title: 'More Control with Hooks',\n        description: 'You can use onPopoverRender hook to modify the popover DOM. Here we are adding a custom button to the popover which takes the user to the first step.'\n      }\n    },\n    {\n      element: 'h1',\n      popover: {\n        align: 'start',\n        side: 'bottom',\n        title: 'Style However You Want',\n        description: 'You can use the default class names and override the styles or you can pass a custom class name to the popoverClass option either globally or per step.'\n      }\n    },\n    {\n      element: 'p a',\n      popover: {\n        align: 'start',\n        side: 'left',\n        title: 'Style However You Want',\n        description: 'You can use the default class names and override the styles or you can pass a custom class name to the popoverClass option either globally or per step.'\n      }\n    }\n  ]}\n  id={\"demo-hook-theme\"}\n  client:load\n>\n  ```js\n  import { driver } from \"driver.js\";\n  import \"driver.js/dist/driver.css\";\n\n  const driverObj = driver({\n    // Get full control over the popover rendering.\n    // Here we are adding a custom button that takes\n    // user to the first step.\n    onPopoverRender: (popover, { config, state }) => {\n      const firstButton = document.createElement(\"button\");\n      firstButton.innerText = \"Go to First\";\n      popover.footerButtons.appendChild(firstButton);\n\n      firstButton.addEventListener(\"click\", () => {\n        driverObj.drive(0);\n      });\n    },\n    steps: [\n      // ..\n    ]\n  });\n\n  driverObj.drive();\n  ```\n</CodeSample>\n"
  },
  {
    "path": "docs/src/content/guides/configuration.mdx",
    "content": "---\ntitle: \"Configuration\"\ngroupTitle: \"Introduction\"\nsort: 3\n---\n\nimport { CodeSample } from \"../../components/CodeSample.tsx\";\n\nDriver.js is built to be highly configurable. You can configure the driver globally, or per step. You can also configure the driver on the fly, while it's running.\n\n> Driver.js is written in TypeScript. Configuration options are mostly self-explanatory. Also, if you're using an IDE like WebStorm or VSCode, you'll get autocomplete and documentation for all the configuration options.\n\n## Driver Configuration\n\nYou can configure the driver globally by passing the configuration object to the `driver` call or by using the `setConfig` method. Given below are some of the available configuration options.\n\n```typescript\ntype Config = {\n  // Array of steps to highlight. You should pass\n  // this when you want to setup a product tour.\n  steps?: DriveStep[];\n\n  // Whether to animate the product tour. (default: true)\n  animate?: boolean;\n  // Overlay color. (default: black)\n  // This is useful when you have a dark background\n  // and want to highlight elements with a light\n  // background color.\n  overlayColor?: string;\n  // Whether to smooth scroll to the highlighted element. (default: false)\n  smoothScroll?: boolean;\n  // Whether to allow closing the popover by clicking on the backdrop. (default: true)\n  allowClose?: boolean;\n  // Opacity of the backdrop. (default: 0.5)\n  overlayOpacity?: number;\n  // What to do when the overlay backdrop is clicked.\n  // Possible options are 'close', 'nextStep', or a custom function. (default: 'close')\n  overlayClickBehavior?: \"close\" | \"nextStep\" | ((element?: Element, step: DriveStep, options: { config: Config; state: State, driver: Driver }) => void),\n  // Distance between the highlighted element and the cutout. (default: 10)\n  stagePadding?: number;\n  // Radius of the cutout around the highlighted element. (default: 5)\n  stageRadius?: number;\n\n  // Whether to allow keyboard navigation. (default: true)\n  allowKeyboardControl?: boolean;\n\n  // Whether to disable interaction with the highlighted element. (default: false)\n  // Can be configured at the step level as well\n  disableActiveInteraction?: boolean;\n\n  // If you want to add custom class to the popover\n  popoverClass?: string;\n  // Distance between the popover and the highlighted element. (default: 10)\n  popoverOffset?: number;\n  // Array of buttons to show in the popover. Defaults to [\"next\", \"previous\", \"close\"]\n  // for product tours and [] for single element highlighting.\n  showButtons?: AllowedButtons[];\n  // Array of buttons to disable. This is useful when you want to show some of the\n  // buttons, but disable some of them.\n  disableButtons?: AllowedButtons[];\n\n  // Whether to show the progress text in popover. (default: false)\n  showProgress?: boolean;\n  // Template for the progress text. You can use the following placeholders in the template:\n  //  - {{current}}: The current step number\n  //  - {{total}}: Total number of steps\n  progressText?: string;\n\n  // Text to show in the buttons. `doneBtnText`\n  // is used on the last step of a tour.\n  nextBtnText?: string;\n  prevBtnText?: string;\n  doneBtnText?: string;\n\n  // Called after the popover is rendered.\n  // PopoverDOM is an object with references to\n  // the popover DOM elements such as buttons\n  // title, descriptions, body, container etc.\n  onPopoverRender?: (popover: PopoverDOM, options: { config: Config; state: State, driver: Driver }) => void;\n\n  // Hooks to run before and after highlighting\n  // each step. Each hook receives the following\n  // parameters:\n  //   - element: The target DOM element of the step\n  //   - step: The step object configured for the step\n  //   - options.config: The current configuration options\n  //   - options.state: The current state of the driver\n  //   - options.driver: Current driver object\n  onHighlightStarted?: (element?: Element, step: DriveStep, options: { config: Config; state: State, driver: Driver }) => void;\n  onHighlighted?: (element?: Element, step: DriveStep, options: { config: Config; state: State, driver: Driver }) => void;\n  onDeselected?: (element?: Element, step: DriveStep, options: { config: Config; state: State, driver: Driver }) => void;\n\n  // Hooks to run before and after the driver\n  // is destroyed. Each hook receives\n  // the following parameters:\n  //   - element: Currently active element\n  //   - step: The step object configured for the currently active\n  //   - options.config: The current configuration options\n  //   - options.state: The current state of the driver\n  //   - options.driver: Current driver object\n  onDestroyStarted?: (element?: Element, step: DriveStep, options: { config: Config; state: State, driver: Driver }) => void;\n  onDestroyed?: (element?: Element, step: DriveStep, options: { config: Config; state: State, driver: Driver }) => void;\n\n  // Hooks to run on button clicks. Each hook receives\n  // the following parameters:\n  //   - element: The current DOM element of the step\n  //   - step: The step object configured for the step\n  //   - options.config: The current configuration options\n  //   - options.state: The current state of the driver\n  //   - options.driver: Current driver object\n  onNextClick?: (element?: Element, step: DriveStep, options: { config: Config; state: State, driver: Driver }) => void;\n  onPrevClick?: (element?: Element, step: DriveStep, options: { config: Config; state: State, driver: Driver }) => void;\n  onCloseClick?: (element?: Element, step: DriveStep, options: { config: Config; state: State, driver: Driver }) => void;\n};\n```\n\n> **Note**: By overriding `onNextClick`, and `onPrevClick` hooks you control the navigation of the driver. This means that user won't be able to navigate using the buttons and you will have to either call `driverObj.moveNext()` or `driverObj.movePrevious()` to navigate to the next/previous step.\n>\n> You can use this to implement custom logic for navigating between steps. This is also useful when you are dealing with dynamic content and want to highlight the next/previous element based on some logic.\n>\n> `onNextClick` and `onPrevClick` hooks can be configured at the step level as well. When configured at the driver level, you control the navigation for all the steps. When configured at the step level, you control the navigation for that particular step only.\n\n## Popover Configuration\n\nThe popover is the main UI element of Driver.js. It's the element that highlights the target element, and shows the step content. You can configure the popover globally, or per step. Given below are some of the available configuration options.\n\n```typescript\ntype Popover = {\n  // Title and descriptions shown in the popover.\n  // You can use HTML in these. Also, you can\n  // omit one of these to show only the other.\n  title?: string;\n  description?: string;\n\n  // The position and alignment of the popover\n  // relative to the target element.\n  side?: \"top\" | \"right\" | \"bottom\" | \"left\";\n  align?: \"start\" | \"center\" | \"end\";\n\n  // Array of buttons to show in the popover.\n  // When highlighting a single element, there\n  // are no buttons by default. When showing\n  // a tour, the default buttons are \"next\",\n  // \"previous\" and \"close\".\n  showButtons?: (\"next\" | \"previous\" | \"close\")[];\n  // An array of buttons to disable. This is\n  // useful when you want to show some of the\n  // buttons, but disable some of them.\n  disableButtons?: (\"next\" | \"previous\" | \"close\")[];\n\n  // Text to show in the buttons. `doneBtnText`\n  // is used on the last step of a tour.\n  nextBtnText?: string;\n  prevBtnText?: string;\n  doneBtnText?: string;\n\n  // Whether to show the progress text in popover.\n  showProgress?: boolean;\n  // Template for the progress text. You can use\n  // the following placeholders in the template:\n  //   - {{current}}: The current step number\n  //   - {{total}}: Total number of steps\n  // Defaults to following if `showProgress` is true:\n  //   - \"{{current}} of {{total}}\"\n  progressText?: string;\n\n  // Custom class to add to the popover element.\n  // This can be used to style the popover.\n  popoverClass?: string;\n\n  // Hook to run after the popover is rendered.\n  // You can modify the popover element here.\n  // Parameter is an object with references to\n  // the popover DOM elements such as buttons\n  // title, descriptions, body, etc.\n  onPopoverRender?: (popover: PopoverDOM, options: { config: Config; state: State, driver: Driver }) => void;\n\n  // Callbacks for button clicks. You can use\n  // these to add custom behavior to the buttons.\n  // Each callback receives the following parameters:\n  //   - element: The current DOM element of the step\n  //   - step: The step object configured for the step\n  //   - options.config: The current configuration options\n  //   - options.state: The current state of the driver\n  //   - options.driver: Current driver object\n  onNextClick?: (element?: Element, step: DriveStep, options: { config: Config; state: State, driver: Driver }) => void\n  onPrevClick?: (element?: Element, step: DriveStep, options: { config: Config; state: State, driver: Driver }) => void\n  onCloseClick?: (element?: Element, step: DriveStep, options: { config: Config; state: State, driver: Driver }) => void\n}\n```\n\n## Drive Step Configuration\n\nDrive step is the configuration object passed to the `highlight` method or the `steps` array of the `drive` method. You can configure the popover and the target element for each step. Given below are some of the available configuration options.\n\n```typescript\ntype DriveStep = {\n  // The target element to highlight.\n  // This can be a DOM element,\n  // a function that returns a DOM Element, or a CSS selector.\n  // If this is a selector, the first matching\n  // element will be highlighted.\n  element?: Element | string | (() => Element);\n\n  // The popover configuration for this step.\n  // Look at the Popover Configuration section\n  popover?: Popover;\n\n  // Whether to disable interaction with the highlighted element. (default: false)\n  disableActiveInteraction?: boolean;\n\n  // Callback when the current step is deselected,\n  // about to be highlighted or highlighted.\n  // Each callback receives the following parameters:\n  //   - element: The current DOM element of the step\n  //   - step: The step object configured for the step\n  //   - options.config: The current configuration options\n  //   - options.state: The current state of the driver\n  //   - options.driver: Current driver object\n  onDeselected?: (element?: Element, step: DriveStep, options: { config: Config; state: State, driver: Driver }) => void;\n  onHighlightStarted?: (element?: Element, step: DriveStep, options: { config: Config; state: State, driver: Driver }) => void;\n  onHighlighted?: (element?: Element, step: DriveStep, options: { config: Config; state: State, driver: Driver }) => void;\n}\n```\n\n## State\n\nYou can access the current state of the driver by calling the `getState` method. It's also passed to the hooks and callbacks.\n\n```typescript\ntype State = {\n  // Whether the driver is currently active or not\n  isInitialized?: boolean;\n\n  // Index of the currently active step if using\n  // as a product tour and have configured the\n  // steps array.\n  activeIndex?: number;\n  // DOM element of the currently active step\n  activeElement?: Element;\n  // Step object of the currently active step\n  activeStep?: DriveStep;\n\n  // DOM element that was previously active\n  previousElement?: Element;\n  // Step object of the previously active step\n  previousStep?: DriveStep;\n\n  // DOM elements for the popover i.e. including\n  // container, title, description, buttons etc.\n  popover?: PopoverDOM;\n}\n```\n"
  },
  {
    "path": "docs/src/content/guides/confirm-on-exit.mdx",
    "content": "---\ntitle: \"Confirm on Exit\"\ngroupTitle: \"Examples\"\nsort: 3\n---\n\nimport { CodeSample } from \"../../components/CodeSample.tsx\";\n\nYou can use the `onDestroyStarted` hook to add a confirmation dialog or some other logic when the user tries to exit the tour. In the example below, upon exit we check if there are any tour steps left and ask for confirmation before we exit.\n\n<CodeSample\n  heading={'Confirm on Exit'}\n  config={{\n    animate: true,\n    showProgress: true,\n    showButtons: ['next', 'previous'],\n  }}\n  tour={[\n    { element: '#confirm-destroy', popover: { title: 'Animated Tour Example', description: 'Here is the code example showing animated tour. Let\\'s walk you through it.', side: \"left\", align: 'start' }},\n    { element: '.line:nth-child(1)', popover: { title: 'Import the Library', description: 'It works the same in vanilla JavaScript as well as frameworks.', side: \"bottom\", align: 'start' }},\n    { element: '.line:nth-child(2)', popover: { title: 'Importing CSS', description: 'Import the CSS which gives you the default styling for popover and overlay.', side: \"bottom\", align: 'start' }},\n    { popover: { title: 'Happy Coding', description: 'And that is all, go ahead and start adding tours to your applications.' } }\n  ]}\n  id={\"confirm-destroy\"}\n  client:load>\n  ```js\n  import { driver } from \"driver.js\";\n  import \"driver.js/dist/driver.css\";\n\n  const driverObj = driver({\n    showProgress: true,\n    steps: [\n      { element: '#confirm-destroy-example', popover: { title: 'Animated Tour Example', description: 'Here is the code example showing animated tour. Let\\'s walk you through it.', side: \"left\", align: 'start' }},\n      { element: 'code .line:nth-child(1)', popover: { title: 'Import the Library', description: 'It works the same in vanilla JavaScript as well as frameworks.', side: \"bottom\", align: 'start' }},\n      { element: 'code .line:nth-child(2)', popover: { title: 'Importing CSS', description: 'Import the CSS which gives you the default styling for popover and overlay.', side: \"bottom\", align: 'start' }},\n      { popover: { title: 'Happy Coding', description: 'And that is all, go ahead and start adding tours to your applications.' } }\n    ],\n    // onDestroyStarted is called when the user tries to exit the tour\n    onDestroyStarted: () => {\n      if (!driverObj.hasNextStep() || confirm(\"Are you sure?\")) {\n        driverObj.destroy();\n      }\n    },\n  });\n\n  driverObj.drive();\n  ```\n</CodeSample>\n\n> **Note:** By overriding the `onDestroyStarted` hook, you are responsible for calling `driverObj.destroy()` to exit the tour."
  },
  {
    "path": "docs/src/content/guides/installation.mdx",
    "content": "---\ntitle: \"Installation\"\ngroupTitle: \"Introduction\"\nsort: 1\n---\n\nRun one of the following commands to install the package:\n\n```bash\n# Using npm\nnpm install driver.js\n\n# Using pnpm\npnpm install driver.js\n\n# Using yarn\nyarn add driver.js\n```\n\nAlternatively, you can use CDN and include the script in your HTML file:\n\n```html\n<script src=\"https://cdn.jsdelivr.net/npm/driver.js@latest/dist/driver.js.iife.js\"></script>\n<link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/driver.js@latest/dist/driver.css\"/>\n```\n\n## Start Using\nOnce installed, you can import the package in your project. The following example shows how to highlight an element:\n\n```js\nimport { driver } from \"driver.js\";\nimport \"driver.js/dist/driver.css\";\n\nconst driverObj = driver();\ndriverObj.highlight({\n  element: \"#some-element\",\n  popover: {\n    title: \"Title\",\n    description: \"Description\"\n  }\n});\n```\n\n### Note on CDN\n\nIf you are using the CDN, you will have to use the package from the `window` object:\n\n```js\nconst driver = window.driver.js.driver;\n\nconst driverObj = driver();\n\ndriverObj.highlight({\n  element: \"#some-element\",\n  popover: {\n    title: \"Title\",\n    description: \"Description\"\n  }\n});\n```\n\nContinue reading the [Getting Started](/docs/basic-usage) guide to learn more about the package."
  },
  {
    "path": "docs/src/content/guides/migrating-from-0x.mdx",
    "content": "---\ntitle: \"Migrate to 1.x\"\ngroupTitle: \"Introduction\"\nsort: 6\n---\n\nDrivers 1.x is a major release that introduces a new API and a new architecture. This page will help you migrate your code from 0.x to 1.x.\n\n> Change in how you import the library\n```diff\n- import Driver from 'driver.js';\n- import 'driver.js/dist/driver.min.css';\n+ import { driver } from 'driver.js';\n+ import \"driver.js/dist/driver.css\";\n```\n\n> Change in how you initialize the library\n```diff\n- const driverObj = new Driver(config);\n- driverObj.setSteps(steps);\n\n+ // Steps can be passed in the constructor\n+ const driverObj = driver({\n+   ...config,\n+   steps\n+ });\n```\n\n> Changes in configuration\n\n```diff\nconst config = {\n-  overlayClickNext: false, // Option has been removed\n-  closeBtnText: 'Close', // Option has been removed (close button is now an icon)\n-  scrollIntoViewOptions: {}, // Option has been renamed\n-  opacity: 0.75,\n+  overlayOpacity: 0.75,\n-  className: 'scoped-class',\n+  popoverClass: 'scoped-class',\n-  padding: 10,\n+  stagePadding: 10,\n-  showButtons: false,\n+  showButtons: ['next', 'prev', 'close'], // pass an array of buttons to show\n-  keyboardControl: true,\n+  allowKeyboardControl: true,\n-  onHighlightStarted: (Element) {},\n+  onHighlightStarted?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;\n-  onHighlighted: (Element) {},\n+  onHighlighted?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;\n-  onDeselected: (Element) {}, // Called when element has been deselected\n+  onDeselected?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;\n\n-  onReset: (Element) {},        // Called when overlay is about to be cleared\n+  onDestroyStarted?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;\n+  onDestroyed?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;\n+  onCloseClick?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;\n\n-  onNext: (Element) => {},      // Called when moving to next step on any step\n-  onPrevious: (Element) => {},  // Called when moving to next step on any step\n+  // By overriding the default onNextClick and onPrevClick, you control the flow of the driver\n+  // Visit for more details: https://driverjs.com/docs/configuration\n+  onNextClick?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;\n+  onPrevClick?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;\n\n+  // New options added\n+  overlayColor?: string;\n+  stageRadius?: number;\n+  popoverOffset?: number;\n+  disableButtons?: [\"next\", \"prev\", \"close\"];\n+  showProgress?: boolean;\n+  progressText?: string;\n+  onPopoverRender?: (popover: PopoverDOM, options: { config: Config; state: State }) => void;\n}\n```\n\n> Changes in step and popover definition\n\n```diff\nconst stepDefinition = {\n  popover: {\n-   closeBtnText: 'Close', // Removed, close button is an icon\n-   element: '.some-element', // Required\n+   element: '.some-element', // Optional, if not provided, step will be shown as modal\n-   className: 'popover-class',\n+   popoverClass: string;\n-   showButtons: false,\n+   showButtons: [\"next\", \"previous\", \"close\"]; // Array of buttons to show\n-   title: '';  // Required\n+   title: '';  // Optional\n-   description: ''; // Required\n+   description: ''; // Optional\n\n-   // position can be left, left-center, left-bottom, top,\n-   // top-center, top-right, right, right-center, right-bottom,\n-   // bottom, bottom-center, bottom-right, mid-center\n-   position: 'left',\n+   // Now you need to specify the side and align separately\n+   side?: \"top\" | \"right\" | \"bottom\" | \"left\";\n+   align?: \"start\" | \"center\" | \"end\";\n\n+   // New options\n+   showProgress?: boolean;\n+   progressText?: string;\n+   onPopoverRender?: (popover: PopoverDOM, options: { config: Config; state: State }) => void;\n+   onNextClick?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void\n+   onPrevClick?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void\n+   onCloseClick?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void\n  }\n\n+ // New hook to control the flow of the driver\n+ onDeselected?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;\n+ onHighlightStarted?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;\n+ onHighlighted?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;\n};\n```\n\n> Changes in API methods.\n\n```diff\n- driverObj.preventMove();  // async support is built-in, no longer need to call this\n- activeElement.getCalculatedPosition();\n- activeElement.hidePopover();\n- activeElement.showPopover();\n- activeElement.getNode();\n\n- const isActivated = driverObj.isActivated;\n+ const isActivated = driverObj.isActive();\n\n- driverObj.start(stepNumber = 0);\n+ driverObj.drive(stepNumber = 0);\n\n- driverObj.highlight(string|stepDefinition);\n+ driverObj.highlight(stepDefinition)\n\n- driverObj.reset();\n+ driverObj.destroy();\n\n- driverObj.hasHighlightedElement();\n+ typeof driverObj.getActiveElement() !== 'undefined';\n\n- driverObj.getHighlightedElement();\n+ driverObj.getActiveElement();\n\n- driverObj.getLastHighlightedElement();\n+ driverObj.getPreviousElement();\n\n+ // New options added\n+ driverObj.moveTo(stepIndex)\n+ driverObj.getActiveStep(); // returns the configured step definition\n+ driverObj.getPreviousStep(); // returns the previous step definition\n+ driverObj.isLastStep();\n+ driverObj.isFirstStep();\n+ driverObj.getState();\n+ driverObj.getConfig();\n+ driverObj.setConfig(config);\n+ driverObj.refresh();\n```\n\nPlease make sure to visit the [documentation](https://driverjs.com/docs/configuration) for more details."
  },
  {
    "path": "docs/src/content/guides/popover-position.mdx",
    "content": "---\ntitle: \"Popover Position\"\ngroupTitle: \"Examples\"\nsort: 7\n---\n\nimport { CodeSample } from \"../../components/CodeSample.tsx\";\n\nYou can control the popover position using the `side` and `align` options. The `side` option controls the side of the element where the popover will be shown and the `align` option controls the alignment of the popover with the element.\n\n> **Note:** Popover is intelligent enough to adjust itself to fit in the viewport. So, if you set `side` to `left` and `align` to `start`, but the popover doesn't fit in the viewport, it will automatically adjust itself to fit in the viewport. Consider highlighting and scrolling the browser to the element below to see this in action.\n\n```js\nimport { driver } from \"driver.js\";\nimport \"driver.js/dist/driver.css\";\n\nconst driverObj = driver();\ndriverObj.highlight({\n  element: '#left-start',\n  popover: {\n    title: 'Animated Tour Example',\n    description: 'Here is the code example showing animated tour. Let\\'s walk you through it.',\n    side: \"left\",\n    align: 'start'\n  }\n});\n```\n\n<div id=\"sample-box\" className='p-12 bg-gray-200 rounded-md flex items-center justify-center'>\n  <p>Use the buttons below to show the popover.</p>\n</div>\n\n<div className=\"flex flex-wrap mt-3 gap-1 justify-start\">\n  <CodeSample\n    buttonText={\"Left Start\"}\n    highlight={{\n      element: '#sample-box',\n      popover: {\n        title: 'Left Start Example',\n        description: 'We have side set to <mark>left</mark> and align set to <mark>start</mark>. PS, we can use HTML in the title and descriptions of popover.',\n        side: \"left\",\n        align: 'start'\n      }\n    }}\n    id={\"left-start\"}\n    client:load\n  />\n\n  <CodeSample\n    buttonText={\"Left Center\"}\n    highlight={{\n      element: '#sample-box',\n      popover: {\n        title: 'Left Center Example',\n        description: 'We have side set to <mark>left</mark> and align set to <mark>center</mark>. PS, we can use HTML in the title and descriptions of popover.',\n        side: \"left\",\n        align: 'center'\n      }\n    }}\n    id={\"left-start\"}\n    client:load\n  />\n\n  <CodeSample\n    buttonText={\"Left End\"}\n    highlight={{\n      element: '#sample-box',\n      popover: {\n        title: 'Left End Example',\n        description: 'We have side set to <mark>left</mark> and align set to <mark>end</mark>. PS, we can use HTML in the title and descriptions of popover.',\n        side: \"left\",\n        align: 'end'\n      }\n    }}\n    id={\"left-start\"}\n    client:load\n  />\n\n  <CodeSample\n    buttonText={\"Top Start\"}\n    highlight={{\n      element: '#sample-box',\n      popover: {\n        title: 'Top Start Example',\n        description: 'We have side set to <mark>top</mark> and align set to <mark>start</mark>. PS, we can use HTML in the title and descriptions of popover.',\n        side: \"top\",\n        align: 'start'\n      }\n    }}\n    id={\"top-start\"}\n    client:load\n  />\n\n  <CodeSample\n    buttonText={\"Top Center\"}\n    highlight={{\n      element: '#sample-box',\n      popover: {\n        title: 'Top Center Example',\n        description: 'We have side set to <mark>top</mark> and align set to <mark>center</mark>. PS, we can use HTML in the title and descriptions of popover.',\n        side: \"top\",\n        align: 'center'\n      }\n    }}\n    id={\"top-start\"}\n    client:load\n  />\n\n  <CodeSample\n    buttonText={\"Top End\"}\n    highlight={{\n      element: '#sample-box',\n      popover: {\n        title: 'Top End Example',\n        description: 'We have side set to <mark>top</mark> and align set to <mark>end</mark>. PS, we can use HTML in the title and descriptions of popover.',\n        side: \"top\",\n        align: 'end'\n      }\n    }}\n    id={\"top-start\"}\n    client:load\n  />\n\n  <CodeSample\n    buttonText={\"Right Start\"}\n    highlight={{\n      element: '#sample-box',\n      popover: {\n        title: 'Right Start Example',\n        description: 'We have side set to <mark>right</mark> and align set to <mark>start</mark>. PS, we can use HTML in the title and descriptions of popover.',\n        side: \"right\",\n        align: 'start'\n      }\n    }}\n    id={\"right-start\"}\n    client:load\n  />\n\n  <CodeSample\n    buttonText={\"Right Center\"}\n    highlight={{\n      element: '#sample-box',\n      popover: {\n        title: 'Right Center Example',\n        description: 'We have side set to <mark>right</mark> and align set to <mark>center</mark>. PS, we can use HTML in the title and descriptions of popover.',\n        side: \"right\",\n        align: 'center'\n      }\n    }}\n    id={\"right-start\"}\n    client:load\n  />\n\n  <CodeSample\n    buttonText={\"Right End\"}\n    highlight={{\n      element: '#sample-box',\n      popover: {\n        title: 'Right End Example',\n        description: 'We have side set to <mark>right</mark> and align set to <mark>end</mark>. PS, we can use HTML in the title and descriptions of popover.',\n        side: \"right\",\n        align: 'end'\n      }\n    }}\n    id={\"right-start\"}\n    client:load\n  />\n\n  <CodeSample\n    buttonText={\"Bottom Start\"}\n    highlight={{\n      element: '#sample-box',\n      popover: {\n        title: 'Bottom Start Example',\n        description: 'We have side set to <mark>bottom</mark> and align set to <mark>start</mark>. PS, we can use HTML in the title and descriptions of popover.',\n        side: \"bottom\",\n        align: 'start'\n      }\n    }}\n    id={\"bottom-start\"}\n    client:load\n  />\n\n  <CodeSample\n    buttonText={\"Bottom Center\"}\n    highlight={{\n      element: '#sample-box',\n      popover: {\n        title: 'Bottom Center Example',\n        description: 'We have side set to <mark>bottom</mark> and align set to <mark>center</mark>. PS, we can use HTML in the title and descriptions of popover.',\n        side: \"bottom\",\n        align: 'center'\n      }\n    }}\n    id={\"bottom-start\"}\n    client:load\n  />\n\n  <CodeSample\n    buttonText={\"Bottom End\"}\n    highlight={{\n      element: '#sample-box',\n      popover: {\n        title: 'Bottom End Example',\n        description: 'We have side set to <mark>bottom</mark> and align set to <mark>end</mark>. PS, we can use HTML in the title and descriptions of popover.',\n        side: \"bottom\",\n        align: 'end'\n      }\n    }}\n    id={\"right-start\"}\n    client:load\n  />\n</div>"
  },
  {
    "path": "docs/src/content/guides/prevent-destroy.mdx",
    "content": "---\ntitle: \"Prevent Tour Exit\"\ngroupTitle: \"Examples\"\nsort: 3\n---\n\nimport { CodeSample } from \"../../components/CodeSample.tsx\";\n\nYou can also prevent the user from exiting the tour using `allowClose` option. This option is useful when you want to force the user to complete the tour before they can exit.\n\nIn the example below, you won't be able to exit the tour until you reach the last step.\n\n<CodeSample\n  heading={'Prevent Exit'}\n  config={{\n    animate: true,\n    showProgress: true,\n    allowClose: false,\n    showButtons: ['next', 'previous'],\n  }}\n  tour={[\n    { element: '#prevent-exit', popover: { title: 'Animated Tour Example', description: 'Here is the code example showing animated tour. Let\\'s walk you through it.', side: \"left\", align: 'start' }},\n    { element: '.line:nth-child(1)', popover: { title: 'Import the Library', description: 'It works the same in vanilla JavaScript as well as frameworks.', side: \"bottom\", align: 'start' }},\n    { element: '.line:nth-child(2)', popover: { title: 'Importing CSS', description: 'Import the CSS which gives you the default styling for popover and overlay.', side: \"bottom\", align: 'start' }},\n    { popover: { title: 'Happy Coding', description: 'And that is all, go ahead and start adding tours to your applications.' } }\n  ]}\n  id={\"prevent-exit\"}\n  client:load>\n  ```js\n  import { driver } from \"driver.js\";\n  import \"driver.js/dist/driver.css\";\n\n  const driverObj = driver({\n    showProgress: true,\n    allowClose: false,\n    steps: [\n      { element: '#prevent-exit', popover: { title: 'Animated Tour Example', description: 'Here is the code example showing animated tour. Let\\'s walk you through it.', side: \"left\", align: 'start' }},\n      { element: 'code .line:nth-child(1)', popover: { title: 'Import the Library', description: 'It works the same in vanilla JavaScript as well as frameworks.', side: \"bottom\", align: 'start' }},\n      { element: 'code .line:nth-child(2)', popover: { title: 'Importing CSS', description: 'Import the CSS which gives you the default styling for popover and overlay.', side: \"bottom\", align: 'start' }},\n      { popover: { title: 'Happy Coding', description: 'And that is all, go ahead and start adding tours to your applications.' } }\n    ],\n  });\n\n  driverObj.drive();\n  ```\n</CodeSample>"
  },
  {
    "path": "docs/src/content/guides/simple-highlight.mdx",
    "content": "---\ntitle: \"Simple Highlight\"\ngroupTitle: \"Examples\"\nsort: 11\n---\n\nimport { FormHelp } from \"../../components/FormHelp.tsx\";\nimport { CodeSample } from \"../../components/CodeSample.tsx\";\n\nProduct tours is not the only usecase for Driver.js. You can use it to highlight any element on the page and show a popover with a description. This is useful for providing contextual help to the user e.g. help the user fill a form or explain a feature.\n\nExample below shows how to highlight an element and simply show a popover.\n\n<CodeSample\n  id={\"highlight-me\"}\n  buttonText={\"Highlight Me\"}\n  config={{\n    popoverClass: \"driverjs-theme\",\n    stagePadding: 4,\n  }}\n  highlight={{\n    element: \"#highlight-me\",\n    popover: {\n      side: \"bottom\",\n      title: \"This is a title\",\n      description: \"This is a description\",\n    },\n  }}\n  client:load\n/>\n\nHere is the code for above example:\n\n```js\nconst driverObj = driver({\n  popoverClass: \"driverjs-theme\",\n  stagePadding: 4,\n});\n\ndriverObj.highlight({\n  element: \"#highlight-me\",\n  popover: {\n    side: \"bottom\",\n    title: \"This is a title\",\n    description: \"This is a description\",\n  }\n})\n```\n\nYou can also use it to show a simple modal without highlighting any element.\n\n<CodeSample\n  id={\"highlight-me\"}\n  buttonText={\"Show Popover\"}\n  highlight={{\n    popover: {\n      side: \"bottom\",\n      description: \"<img src='https://i.imgur.com/EAQhHu5.gif' style='height: 202.5px; width: 270px;' /><span style='font-size: 15px; display: block; margin-top: 10px; text-align: center;'>Yet another highlight example.</span>\",\n    },\n  }}\n  client:load\n/>\n\nHere is the code for above example:\n\n```js\nconst driverObj = driver();\n\ndriverObj.highlight({\n  popover: {\n    description: \"<img src='https://i.imgur.com/EAQhHu5.gif' style='height: 202.5px; width: 270px;' /><span style='font-size: 15px; display: block; margin-top: 10px; text-align: center;'>Yet another highlight example.</span>\",\n  }\n})\n```\n\nFocus on the input below and see how the popover is shown.\n\n<form action=\"#\" className='flex flex-col gap-2'>\n  <input id=\"name\" type=\"text\" placeholder=\"Enter your Name\" className='block w-full border rounded-md py-2 px-3 focus:outline-0' />\n  <input id=\"education\" type=\"text\" placeholder=\"Your Education\" className='block w-full border rounded-md py-2 px-3 focus:outline-0' />\n  <input id=\"age\" type=\"number\" placeholder=\"Your Age\" className='block w-full border rounded-md py-2 px-3 focus:outline-0' />\n  <textarea id=\"address\" placeholder=\"Your Address\" className='block w-full border rounded-md py-2 px-3 focus:outline-0' />\n  <button id=\"submit-btn\" className='w-full rounded-md bg-black p-2 text-white'>Submit</button>\n</form>\n\n<FormHelp client:only />\n\nHere is the code for the above example.\n\n```js\nconst driverObj = driver({\n  popoverClass: \"driverjs-theme\",\n  stagePadding: 0,\n  onDestroyed: () => {\n    document?.activeElement?.blur();\n  }\n});\n\nconst nameEl = document.getElementById(\"name\");\nconst educationEl = document.getElementById(\"education\");\nconst ageEl = document.getElementById(\"age\");\nconst addressEl = document.getElementById(\"address\");\nconst formEl = document.querySelector(\"form\");\n\nnameEl.addEventListener(\"focus\", () => {\n  driverObj.highlight({\n    element: nameEl,\n    popover: {\n      title: \"Name\",\n      description: \"Enter your name here\",\n    },\n  });\n});\n\neducationEl.addEventListener(\"focus\", () => {\n  driverObj.highlight({\n    element: educationEl,\n    popover: {\n      title: \"Education\",\n      description: \"Enter your education here\",\n    },\n  });\n});\n\nageEl.addEventListener(\"focus\", () => {\n  driverObj.highlight({\n    element: ageEl,\n    popover: {\n      title: \"Age\",\n      description: \"Enter your age here\",\n    },\n  });\n});\n\naddressEl.addEventListener(\"focus\", () => {\n  driverObj.highlight({\n    element: addressEl,\n    popover: {\n      title: \"Address\",\n      description: \"Enter your address here\",\n    },\n  });\n});\n\nformEl.addEventListener(\"blur\", () => {\n  driverObj.destroy();\n});\n```"
  },
  {
    "path": "docs/src/content/guides/static-tour.mdx",
    "content": "---\ntitle: \"Static Tour\"\ngroupTitle: \"Examples\"\nsort: 2\n---\n\nimport { CodeSample } from \"../../components/CodeSample.tsx\";\n\nYou can simply set `animate` option to `false` to make the tour static. This will make the tour not animate between steps and will just show the popover.\n\n<CodeSample\n  heading={'Basic Static Tour'}\n  config={{\n    animate: false,\n    showProgress: false,\n    showButtons: ['next', 'previous'],\n  }}\n  tour={[\n    { element: '#tour-example', popover: { title: 'Animated Tour Example', description: 'Here is the code example showing animated tour. Let\\'s walk you through it.', side: \"left\", align: 'start' }},\n    { element: '.line:nth-child(1)', popover: { title: 'Import the Library', description: 'It works the same in vanilla JavaScript as well as frameworks.', side: \"bottom\", align: 'start' }},\n    { element: '.line:nth-child(2)', popover: { title: 'Importing CSS', description: 'Import the CSS which gives you the default styling for popover and overlay.', side: \"bottom\", align: 'start' }},\n    { element: '.line:nth-child(4) span:nth-child(7)', popover: { title: 'Create Driver', description: 'Simply call the driver function to create a driver.js instance', side: \"left\", align: 'start' }},\n    { element: '.line:nth-child(19)', popover: { title: 'Start Tour', description: 'Call the drive method to start the tour and your tour will be started.', side: \"top\", align: 'start' }},\n    { element: '.line:nth-child(6)', popover: { title: 'Hide Progress', description: 'Progress shown in the bottom left is hidden by default. You can make driver show/hide the progress using this option.', side: \"top\", align: 'start' }},\n    { element: '#docs-sidebar a[href=\"/docs/configuration\"]', popover: { title: 'More Configuration', description: 'Look at this page for all the configuration options you can pass.', side: \"right\", align: 'start' }},\n    { popover: { title: 'Happy Coding', description: 'And that is all, go ahead and start adding tours to your applications.' } }\n  ]}\n  id={\"tour-example\"}\n  client:load\n>\n  ```js\n  import { driver } from \"driver.js\";\n  import \"driver.js/dist/driver.css\";\n\n  const driverObj = driver({\n    animate: false,\n    showProgress: false,\n    showButtons: ['next', 'previous', 'close'],\n    steps: [\n      { element: '#tour-example', popover: { title: 'Animated Tour Example', description: 'Here is the code example showing animated tour. Let\\'s walk you through it.', side: \"left\", align: 'start' }},\n      { element: 'code .line:nth-child(1)', popover: { title: 'Import the Library', description: 'It works the same in vanilla JavaScript as well as frameworks.', side: \"bottom\", align: 'start' }},\n      { element: 'code .line:nth-child(2)', popover: { title: 'Importing CSS', description: 'Import the CSS which gives you the default styling for popover and overlay.', side: \"bottom\", align: 'start' }},\n      { element: 'code .line:nth-child(4) span:nth-child(7)', popover: { title: 'Create Driver', description: 'Simply call the driver function to create a driver.js instance', side: \"left\", align: 'start' }},\n      { element: 'code .line:nth-child(18)', popover: { title: 'Start Tour', description: 'Call the drive method to start the tour and your tour will be started.', side: \"top\", align: 'start' }},\n      { element: '#docs-sidebar a[href=\"/docs/configuration\"]', popover: { title: 'More Configuration', description: 'Look at this page for all the configuration options you can pass.', side: \"right\", align: 'start' }},\n      { popover: { title: 'Happy Coding', description: 'And that is all, go ahead and start adding tours to your applications.' } }\n    ]\n  });\n\n  driverObj.drive();\n  ```\n</CodeSample>\n"
  },
  {
    "path": "docs/src/content/guides/styling-overlay.mdx",
    "content": "---\ntitle: \"Styling Overlay\"\ngroupTitle: \"Examples\"\nsort: 5\n---\n\nimport { CodeSample } from \"../../components/CodeSample.tsx\";\n\nYou can customize the overlay opacity and color using `overlayOpacity` and `overlayColor` options to change the look of the overlay.\n\n> **Note:** In the examples below we have used `highlight` method to highlight the elements. The same configuration applies to the tour steps as well.\n\n## Overlay Color\n\nHere are some driver.js examples with different overlay colors.\n\n```js\nimport { driver } from \"driver.js\";\nimport \"driver.js/dist/driver.css\";\n\nconst driverObj = driver({\n  overlayColor: 'red'\n});\n\ndriverObj.highlight({\n  popover: {\n    title: 'Pass any RGB Color',\n    description: 'Here we have set the overlay color to be red. You can pass any RGB color to overlayColor option.'\n  }\n});\n```\n\n<div className='flex flex-col gap-1 -mt-5'>\n  <CodeSample\n    buttonText={\"Red Color\"}\n    config={{\n      overlayColor: 'red',\n      overlayOpacity: 0.3\n    }}\n    highlight={{\n      popover: {\n        title: 'Pass any RGB Color',\n        description: 'Here we have set the overlay color to be red. You can pass any RGB color to overlayColor option.',\n      }\n    }}\n    id={\"left-start\"}\n    client:load\n  />\n\n  <CodeSample\n    buttonText={\"Blue Color\"}\n    config={{\n      overlayColor: 'blue',\n      overlayOpacity: 0.3\n    }}\n    highlight={{\n      popover: {\n        title: 'Pass any RGB Color',\n        description: 'Here we have set the overlay color to be blue. You can pass any RGB color to overlayColor option.',\n      }\n    }}\n    id={\"left-start\"}\n    client:load\n  />\n\n  <CodeSample\n    buttonText={\"Yellow Color\"}\n    config={{\n      overlayColor: 'yellow',\n      overlayOpacity: 0.3\n    }}\n    highlight={{\n      popover: {\n        title: 'Pass any RGB Color',\n        description: 'Here we have set the overlay color to be yellow. You can pass any RGB color to overlayColor option.',\n      }\n    }}\n    id={\"left-start\"}\n    client:load\n  />\n</div>\n"
  },
  {
    "path": "docs/src/content/guides/styling-popover.mdx",
    "content": "---\ntitle: \"Styling Popover\"\ngroupTitle: \"Examples\"\nsort: 2\n---\n\nimport { CodeSample } from \"../../components/CodeSample.tsx\";\n\nYou can either use the default class names and override the styles or you can pass a custom class name to the `popoverClass` option either globally or per step.\n\nAlternatively, if want to modify the Popover DOM, you can use the `onPopoverRender` callback to get the popover DOM element and do whatever you want with it before popover is rendered.\n\nWe have added a few examples below but have a look at the [theming section](/docs/theming#styling-popover) for detailed guide including class names to target etc.\n\n<CodeSample\n  heading=\"Using CSS\"\n  buttonText={\"Driver.js Website Theme\"}\n  config={{\n    prevBtnText: '&larr; Previous',\n    nextBtnText: 'Next &rarr;',\n    doneBtnText: 'Done',\n    showButtons: ['next', 'previous'],\n    popoverClass: 'driverjs-theme'\n  }}\n  tour={[\n    {\n      element: '#demo-theme',\n      popover: {\n        align: 'start',\n        side: 'left',\n        title: 'Style However You Want',\n        description: 'You can use the default class names and override the styles or you can pass a custom class name to the popoverClass option either globally or per step.'\n      }\n    },\n    {\n      element: 'h1',\n      popover: {\n        align: 'start',\n        side: 'bottom',\n        title: 'Style However You Want',\n        description: 'You can use the default class names and override the styles or you can pass a custom class name to the popoverClass option either globally or per step.'\n      }\n    },\n    {\n      element: 'p a',\n      popover: {\n        align: 'start',\n        side: 'left',\n        title: 'Style However You Want',\n        description: 'You can use the default class names and override the styles or you can pass a custom class name to the popoverClass option either globally or per step.'\n      }\n    }\n  ]}\n  id={\"demo-theme\"}\n  client:load\n>\n  ```js\n  import { driver } from \"driver.js\";\n  import \"driver.js/dist/driver.css\";\n\n  const driverObj = driver({\n    popoverClass: 'driverjs-theme'\n  });\n\n  driverObj.highlight({\n    element: '#demo-theme',\n    popover: {\n      title: 'Style However You Want',\n      description: 'You can use the default class names and override the styles or you can pass a custom class name to the popoverClass option either globally or per step.'\n    }\n  });\n  ```\n</CodeSample>\n\nHere is the CSS used for the above example:\n\n```css\n.driver-popover.driverjs-theme {\n  background-color: #fde047;\n  color: #000;\n}\n\n.driver-popover.driverjs-theme .driver-popover-title {\n  font-size: 20px;\n}\n\n.driver-popover.driverjs-theme .driver-popover-title,\n.driver-popover.driverjs-theme .driver-popover-description,\n.driver-popover.driverjs-theme .driver-popover-progress-text {\n  color: #000;\n}\n\n.driver-popover.driverjs-theme button {\n  flex: 1;\n  text-align: center;\n  background-color: #000;\n  color: #ffffff;\n  border: 2px solid #000;\n  text-shadow: none;\n  font-size: 14px;\n  padding: 5px 8px;\n  border-radius: 6px;\n}\n\n.driver-popover.driverjs-theme button:hover {\n  background-color: #000;\n  color: #ffffff;\n}\n\n.driver-popover.driverjs-theme .driver-popover-navigation-btns {\n  justify-content: space-between;\n  gap: 3px;\n}\n\n.driver-popover.driverjs-theme .driver-popover-close-btn {\n  color: #9b9b9b;\n}\n\n.driver-popover.driverjs-theme .driver-popover-close-btn:hover {\n  color: #000;\n}\n\n.driver-popover.driverjs-theme .driver-popover-arrow-side-left.driver-popover-arrow {\n  border-left-color: #fde047;\n}\n\n.driver-popover.driverjs-theme .driver-popover-arrow-side-right.driver-popover-arrow {\n  border-right-color: #fde047;\n}\n\n.driver-popover.driverjs-theme .driver-popover-arrow-side-top.driver-popover-arrow {\n  border-top-color: #fde047;\n}\n\n.driver-popover.driverjs-theme .driver-popover-arrow-side-bottom.driver-popover-arrow {\n  border-bottom-color: #fde047;\n}\n```\n\n<br/>\n\n<CodeSample\n  heading=\"Using Hook to Modify\"\n  buttonText={\"Manipulating Popover DOM\"}\n  config={{\n    prevBtnText: '&larr; Previous',\n    nextBtnText: 'Next &rarr;',\n    doneBtnText: 'Done',\n    showButtons: ['next', 'previous'],\n  }}\n  tour={[\n    {\n      element: '#demo-hook-theme',\n      popover: {\n        align: 'start',\n        side: 'left',\n        title: 'More Control with Hooks',\n        description: 'You can use onPopoverRender hook to modify the popover DOM. Here we are adding a custom button to the popover which takes the user to the first step.'\n      }\n    },\n    {\n      element: 'h1',\n      popover: {\n        align: 'start',\n        side: 'bottom',\n        title: 'Style However You Want',\n        description: 'You can use the default class names and override the styles or you can pass a custom class name to the popoverClass option either globally or per step.'\n      }\n    },\n    {\n      element: 'p a',\n      popover: {\n        align: 'start',\n        side: 'left',\n        title: 'Style However You Want',\n        description: 'You can use the default class names and override the styles or you can pass a custom class name to the popoverClass option either globally or per step.'\n      }\n    }\n  ]}\n  id={\"demo-hook-theme\"}\n  client:load\n>\n  ```js\n  import { driver } from \"driver.js\";\n  import \"driver.js/dist/driver.css\";\n\n  const driverObj = driver({\n    // Get full control over the popover rendering.\n    // Here we are adding a custom button that takes\n    // the user to the first step.\n    onPopoverRender: (popover, { config, state }) => {\n      const firstButton = document.createElement(\"button\");\n      firstButton.innerText = \"Go to First\";\n      popover.footerButtons.appendChild(firstButton);\n\n      firstButton.addEventListener(\"click\", () => {\n        driverObj.drive(0);\n      });\n    },\n    steps: [\n      // ..\n    ]\n  });\n\n  driverObj.drive();\n  ```\n</CodeSample>"
  },
  {
    "path": "docs/src/content/guides/theming.mdx",
    "content": "---\ntitle: \"Theming\"\ngroupTitle: \"Introduction\"\nsort: 5\n---\n\nYou can customize the look and feel of the driver by adding custom class to popover or applying CSS to different classes used by driver.js.\n\n## Styling Popover\n\nYou can set the `popoverClass` option globally in the driver configuration or at the step level to apply custom class to the popover and then use CSS to apply styles.\n\n```js\nconst driverObj = driver({\n  popoverClass: 'my-custom-popover-class'\n});\n\n// or you can also have different classes for different steps\nconst driverObj2 = driver({\n  steps: [\n    {\n      element: '#some-element',\n      popover: {\n        title: 'Title',\n        description: 'Description',\n        popoverClass: 'my-custom-popover-class'\n      }\n    }\n  ],\n})\n```\n\nHere is the list of classes applied to the popover which you can use in conjunction with `popoverClass` option to apply custom styles on the popover.\n\n```css\n/* Class assigned to popover wrapper */\n.driver-popover {}\n\n/* Arrow pointing towards the highlighted element */\n.driver-popover-arrow {}\n\n/* Title and description */\n.driver-popover-title {}\n.driver-popover-description {}\n\n/* Close button displayed on the top right corner */\n.driver-popover-close-btn {}\n\n/* Footer of the popover displaying progress and navigation buttons */\n.driver-popover-footer {}\n.driver-popover-progress-text {}\n.driver-popover-prev-btn {}\n.driver-popover-next-btn {}\n```\n\nVisit the [example page](/docs/styling-popover) for an example that modifies the popover styles.\n\n## Modifying Popover DOM\n\nAlternatively, you can also use the `onPopoverRender` hook to modify the popover DOM before it is displayed. The hook is called with the popover DOM as the first argument.\n\n```typescript\ntype PopoverDOM = {\n  wrapper: HTMLElement;\n  arrow: HTMLElement;\n  title: HTMLElement;\n  description: HTMLElement;\n  footer: HTMLElement;\n  progress: HTMLElement;\n  previousButton: HTMLElement;\n  nextButton: HTMLElement;\n  closeButton: HTMLElement;\n  footerButtons: HTMLElement;\n};\n\nonPopoverRender?: (popover: PopoverDOM, opts: { config: Config; state: State }) => void;\n```\n\n## Styling Page\n\nFollowing classes are applied to the page when the driver is active.\n\n```css\n/* Applied to the `body` when the driver: */\n.driver-active {}  /* is active */\n.driver-fade {}    /* is animated */\n.driver-simple {}  /* is not animated */\n```\n\nFollowing classes are applied to the overlay i.e. the lightbox displayed over the page.\n\n```css\n.driver-overlay {}\n```\n\n## Styling Highlighted Element\n\nWhenever an element is highlighted, the following classes are applied to it.\n\n```css\n.driver-active-element {}\n```"
  },
  {
    "path": "docs/src/content/guides/tour-progress.mdx",
    "content": "---\ntitle: \"Tour Progress\"\ngroupTitle: \"Examples\"\nsort: 2\n---\n\nimport { CodeSample } from \"../../components/CodeSample.tsx\";\n\nYou can use `showProgress` option to show the progress of the tour. It is shown in the bottom left corner of the screen. There is also `progressText` option which can be used to customize the text shown for the progress.\n\nPlease note that `showProgress` is `false` by default. Also the default text for `progressText` is `{{current}} of {{total}}`. You can use `{{current}}` and `{{total}}` in your `progressText` template to show the current and total steps.\n\n<CodeSample\n  config={{\n    showProgress: true,\n    showButtons: ['next', 'previous'],\n  }}\n  tour={[\n    { element: '#tour-example', popover: { title: 'Progress Example', description: 'Notice the text at the bottom left corner showing the progress', side: \"left\", align: 'start' }},\n    { element: '.line:nth-child(1)', popover: { title: 'Import the Library', description: 'It works the same in vanilla JavaScript as well as frameworks.', side: \"bottom\", align: 'start' }},\n    { element: '.line:nth-child(2)', popover: { title: 'Importing CSS', description: 'Import the CSS which gives you the default styling for popover and overlay.', side: \"bottom\", align: 'start' }},\n    { element: '.line:nth-child(4) span:nth-child(7)', popover: { title: 'Create Driver', description: 'Simply call the driver function to create a driver.js instance', side: \"left\", align: 'start' }},\n    { element: '.line:nth-child(16)', popover: { title: 'Start Tour', description: 'Call the drive method to start the tour and your tour will be started.', side: \"top\", align: 'start' }},\n  ]}\n  id={\"tour-example\"}\n  client:load\n>\n  ```js\n  import { driver } from \"driver.js\";\n  import \"driver.js/dist/driver.css\";\n\n  const driverObj = driver({\n    showProgress: true,\n    showButtons: ['next', 'previous'],\n    steps: [\n      { element: '#tour-example', popover: { title: 'Animated Tour Example', description: 'Here is the code example showing animated tour. Let\\'s walk you through it.', side: \"left\", align: 'start' }},\n      { element: 'code .line:nth-child(1)', popover: { title: 'Import the Library', description: 'It works the same in vanilla JavaScript as well as frameworks.', side: \"bottom\", align: 'start' }},\n      { element: 'code .line:nth-child(2)', popover: { title: 'Importing CSS', description: 'Import the CSS which gives you the default styling for popover and overlay.', side: \"bottom\", align: 'start' }},\n      { element: 'code .line:nth-child(4) span:nth-child(7)', popover: { title: 'Create Driver', description: 'Simply call the driver function to create a driver.js instance', side: \"left\", align: 'start' }},\n      { element: 'code .line:nth-child(16)', popover: { title: 'Start Tour', description: 'Call the drive method to start the tour and your tour will be started.', side: \"top\", align: 'start' }},\n    ]\n  });\n\n  driverObj.drive();\n  ```\n</CodeSample>\n\n<div className=\"mb-1.5\"></div>\n\n<CodeSample\n  buttonText={\"Different Progress Text\"}\n  config={{\n    stagePadding: 5,\n    progressText: \"Step {{current}} of {{total}}\",\n    showProgress: true,\n    showButtons: ['next', 'previous'],\n  }}\n  tour={[\n    { element: 'p code:nth-child(2)', popover: { title: 'progressText', description: 'You can use progressText to modify the progress text template.', side: \"bottom\", align: 'start' }},\n    { element: '#tour-example', popover: { title: 'Progress Example', description: 'Notice the text at the bottom left corner showing the progress', side: \"left\", align: 'start' }},\n    { element: '.line:nth-child(1)', popover: { title: 'Import the Library', description: 'It works the same in vanilla JavaScript as well as frameworks.', side: \"bottom\", align: 'start' }},\n    { element: '.line:nth-child(2)', popover: { title: 'Importing CSS', description: 'Import the CSS which gives you the default styling for popover and overlay.', side: \"bottom\", align: 'start' }},\n    { element: '.line:nth-child(4) span:nth-child(7)', popover: { title: 'Create Driver', description: 'Simply call the driver function to create a driver.js instance', side: \"left\", align: 'start' }},\n    { element: '.line:nth-child(16)', popover: { title: 'Start Tour', description: 'Call the drive method to start the tour and your tour will be started.', side: \"top\", align: 'start' }},\n  ]}\n  id={\"tour-example\"}\n  client:load\n/>"
  },
  {
    "path": "docs/src/env.d.ts",
    "content": "/// <reference path=\"../.astro/types.d.ts\" />\n/// <reference types=\"astro/client\" />\n\ninterface Window {\n  driverObj: any;\n}\n"
  },
  {
    "path": "docs/src/layouts/BaseLayout.astro",
    "content": "---\nimport Analytics from \"../components/Analytics/Analytics.astro\";\nexport interface Props {\n  permalink?: string;\n  title?: string;\n  description?: string;\n}\n\nconst {\n  permalink = \"\",\n  title = \"driver.js\",\n  description = \"A light-weight, no-dependency, vanilla JavaScript library to drive user's focus across the page.\",\n} = Astro.props;\n---\n\n<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n\n    <title>{title}</title>\n    <meta name=\"robots\" content=\"index,follow\" />\n    <meta name=\"description\" itemprop=\"description\" content={description} />\n\n    <link href={`https://driverjs.com${permalink}`} rel=\"canonical\" />\n\n    <meta content=\"Kamran Ahmed\" name=\"author\" />\n    <meta content=\"summary_large_image\" name=\"twitter:card\" />\n    <meta content=\"@kamrify\" name=\"twitter:creator\" />\n    <meta content=\"1200\" property=\"og:image:width\" />\n    <meta content=\"630\" property=\"og:image:height\" />\n    <meta content=\"https://driverjs.com/og-img.png\" property=\"og:image\" />\n    <meta content=\"driverjs.com\" property=\"og:image:alt\" />\n    <meta content=\"driverjs.com\" property=\"og:site_name\" />\n    <meta content=\"Driver.js\" property=\"og:title\" />\n    <meta\n      content=\"A light-weight, no-dependency, vanilla JavaScript library to drive user's focus across the page.\"\n      property=\"og:description\"\n    />\n    <meta content=\"website\" property=\"og:type\" />\n    <meta content=\"https://driverjs.com/\" property=\"og:url\" />\n\n    <meta name=\"viewport\" content=\"width=device-width\" />\n    <link rel=\"icon\" type=\"image/svg+xml\" href=\"/favicon.svg\" />\n\n    <style is:global>\n      .driver-popover.driverjs-theme {\n        background-color: #fde047;\n        color: #000;\n      }\n\n      .driver-popover.driverjs-theme .driver-popover-title {\n        font-size: 20px;\n      }\n\n      .driver-popover.driverjs-theme .driver-popover-title,\n      .driver-popover.driverjs-theme .driver-popover-description,\n      .driver-popover.driverjs-theme .driver-popover-progress-text {\n        color: #000;\n      }\n\n      .driver-popover.driverjs-theme button {\n        flex: 1;\n        text-align: center;\n        background-color: #000;\n        color: #ffffff;\n        border: 1px solid #000;\n        text-shadow: none;\n        font-size: 14px;\n        padding: 5px 8px;\n        border-radius: 6px;\n      }\n\n      .driver-popover.driverjs-theme button:focus,\n      .driver-popover.driverjs-theme button:hover {\n        background-color: #000;\n        opacity: 0.8;\n        color: #ffffff;\n      }\n\n      .driver-popover.driverjs-theme .driver-popover-navigation-btns {\n        justify-content: space-between;\n        gap: 3px;\n      }\n\n      .driver-popover.driverjs-theme .driver-popover-close-btn {\n        color: #9b9b9b;\n      }\n\n      .driver-popover.driverjs-theme .driver-popover-close-btn:hover {\n        color: #000;\n      }\n\n      .driver-popover.driverjs-theme .driver-popover-arrow-side-left.driver-popover-arrow {\n        border-left-color: #fde047;\n      }\n\n      .driver-popover.driverjs-theme .driver-popover-arrow-side-right.driver-popover-arrow {\n        border-right-color: #fde047;\n      }\n\n      .driver-popover.driverjs-theme .driver-popover-arrow-side-top.driver-popover-arrow {\n        border-top-color: #fde047;\n      }\n\n      .driver-popover.driverjs-theme .driver-popover-arrow-side-bottom.driver-popover-arrow {\n        border-bottom-color: #fde047;\n      }\n    </style>\n  </head>\n  <body>\n    <slot />\n    <Analytics />\n  </body>\n</html>\n"
  },
  {
    "path": "docs/src/layouts/DocsLayout.astro",
    "content": "---\nimport BaseLayout from \"./BaseLayout.astro\";\nimport { DocsHeader } from \"../components/DocsHeader\";\nimport Container from \"../components/Container.astro\";\nimport { getFormattedStars } from \"../lib/github\";\nimport Sidebar from \"../components/Sidebar.astro\";\nimport type { CollectionEntry } from \"astro:content\";\nimport { getAllGuides } from \"../lib/guide\";\n\ntype GuideType = CollectionEntry<\"guides\">;\n\nexport interface Props {\n  guide: GuideType;\n}\n\nconst groupedGuides = await getAllGuides();\n\nconst { guide } = Astro.props;\nconst { groupTitle, sort, title } = guide.data;\n---\n\n<BaseLayout title={`${title} - Driver.js`} permalink={`/docs/${guide.slug}`}>\n  <div class=\"block md:hidden\">\n    <DocsHeader activeGuideTitle={title} groupedGuides={groupedGuides} client:load />\n  </div>\n  <div class=\"flex\">\n    <Sidebar activeGuideTitle={title} groupedGuides={groupedGuides} />\n    <div\n      class=\"min-w-0 max-w-[800px] py-6 md:py-12 prose px-6 md:px-14 prose-base md:proxe-xl mb-24 prose-blockquote:font-normal prose-blockquote:not-italic prose-blockquote:text-gray-500 prose-p:before:content-['']\">\n      <slot />\n    </div>\n  </div>\n</BaseLayout>\n"
  },
  {
    "path": "docs/src/lib/github.ts",
    "content": "const formatter = Intl.NumberFormat(\"en-US\", {\n  notation: \"compact\",\n});\n\nconst defaultStarCount = 17000;\nlet starCount: number | undefined = undefined;\n\nexport async function countStars(repo = \"kamranahmedse/driver.js\"): Promise<number> {\n  if (starCount) {\n    return starCount;\n  }\n\n  try {\n    const repoData = await fetch(`https://api.github.com/repos/${repo}`);\n    const json = await repoData.json();\n\n    starCount = json.stargazers_count * 1 || defaultStarCount;\n  } catch (e) {\n    console.log(\"Failed to fetch stars\", e);\n    starCount = defaultStarCount;\n  }\n\n  return starCount;\n}\n\nexport async function getFormattedStars(repo = \"kamranahmedse/driver.js\"): Promise<string> {\n  const stars = import.meta.env.DEV ? defaultStarCount : await countStars(repo);\n\n  return formatter.format(stars);\n}\n"
  },
  {
    "path": "docs/src/lib/guide.ts",
    "content": "import { CollectionEntry, getCollection } from \"astro:content\";\n\nexport async function getAllGuides(): Promise<Record<string, CollectionEntry<\"guides\">[]>> {\n  const allGuides: CollectionEntry<\"guides\">[] = await getCollection(\"guides\");\n  const sortedGuides = allGuides.sort((a, b) => a.data.sort - b.data.sort);\n  return sortedGuides.reduce((acc: Record<string, CollectionEntry<\"guides\">[]>, curr: CollectionEntry<\"guides\">) => {\n    const { groupTitle } = curr.data;\n\n    acc[groupTitle] = acc[groupTitle] || [];\n    acc[groupTitle].push(curr);\n\n    return acc;\n  }, {});\n}\n"
  },
  {
    "path": "docs/src/pages/docs/[guideId].astro",
    "content": "---\nimport { CollectionEntry, getCollection } from \"astro:content\";\nimport DocsLayout from \"../../layouts/DocsLayout.astro\";\n\nexport interface Props {\n  guide: CollectionEntry<\"guides\">;\n}\n\nexport async function getStaticPaths() {\n  const guides = await getCollection(\"guides\");\n\n  return guides.map(guide => ({\n    params: { guideId: guide.slug },\n    props: { guide },\n  }));\n}\n\nconst { guideId } = Astro.params;\nconst { guide } = Astro.props;\n\nconst { Content, headings } = await guide.render();\n---\n\n<DocsLayout guide={guide}>\n  <h1 class=\"text-5xl font-bold mb-4\">{guide.data.title}</h1>\n  <Content />\n</DocsLayout>\n"
  },
  {
    "path": "docs/src/pages/index.astro",
    "content": "---\nimport BaseLayout from \"../layouts/BaseLayout.astro\";\nimport { FeatureMarquee } from \"../components/FeatureMarquee\";\nimport Container from \"../components/Container.astro\";\nimport UsecaseItem from \"../components/UsecaseItem.astro\";\nimport { ExampleButton } from \"../components/ExampleButton\";\nimport HeroSection from \"../components/HeroSection.astro\";\nimport Examples from \"../components/Examples.astro\";\nimport UsecaseList from \"../components/UsecaseList.astro\";\nimport OpenSourceLove from \"../components/OpenSourceLove.astro\";\n---\n<BaseLayout title=\"driver.js\">\n  <HeroSection />\n  <div\n    class=\"bg-white overflow-x-hidden overflow-y-hidden relative h-[48px] md:h-[56px] lg:h-[64px] border-b-2 border-b-black\"\n    data-feat-marquee>\n    <FeatureMarquee client:only />\n  </div>\n\n  <div class=\"py-10 md:py-12 lg:py-24 bg-white text-black\">\n    <Container>\n      <Examples />\n      <UsecaseList />\n    </Container>\n  </div>\n\n  <OpenSourceLove />\n\n  <div class=\"py-8 bg-black text-white\">\n    <Container>\n      <p class=\"text-lg text-white text-center\">\n        MIT Licensed &copy; 2024\n        <span class=\"hidden sm:inline\">\n          <span class=\"mx-3\">&middot;</span>\n          <a href=\"/docs/installation\" class=\"\">\n            Docs\n          </a>\n          <a href=\"https://github.com/kamranahmedse/driver.js\" target=\"_blank\" class=\"ml-5\">\n            GitHub\n            <img src=\"/arrow.svg\" class=\"h-3 inline-block ml-2\" alt=\"GitHub\" />\n          </a>\n          <a href=\"https://twitter.com/kamrify\" target=\"_blank\" class=\" ml-5\">\n            Twitter\n            <img src=\"/arrow.svg\" class=\"h-3 inline-block ml-2\" alt=\"GitHub\" />\n          </a>\n        </span>\n      </p>\n    </Container>\n  </div>\n</BaseLayout>\n"
  },
  {
    "path": "docs/tailwind.config.cjs",
    "content": "/** @type {import('tailwindcss').Config} */\nmodule.exports = {\n  content: [\"./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}\"],\n  theme: {\n    screens: {\n      'sh': {\n        'raw': '(min-height: 750px)',\n      },\n      ...require('tailwindcss/defaultConfig').theme.screens,\n    },\n    container: {\n    },\n    extend: {},\n  },\n  plugins: [\n    require('@tailwindcss/typography'),\n  ],\n};\n"
  },
  {
    "path": "docs/tsconfig.json",
    "content": "{\n  \"extends\": \"astro/tsconfigs/strict\",\n  \"compilerOptions\": {\n    \"jsx\": \"react-jsx\",\n    \"jsxImportSource\": \"react\",\n    \"strictNullChecks\": true\n  }\n}"
  },
  {
    "path": "dts-bundle-generator.config.ts",
    "content": "module.exports = {\n  entries: [\n    {\n      filePath: \"./src/driver.ts\",\n      outFile: `./dist/driver.js.d.ts`,\n      noCheck: false,\n    },\n  ],\n};\n"
  },
  {
    "path": "index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <!-- prefetch image -->\n    <link rel=\"preconnect\" href=\"https://i.imgur.com/\" />\n    <title>Vite App</title>\n\n    <style>\n      * {\n        margin: 0;\n        padding: 0;\n      }\n\n      *:focus {\n        outline: 2px solid #1a73e8;\n        outline-offset: 2px;\n      }\n\n      body {\n        font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Oxygen, Ubuntu, Cantarell, \"Open Sans\",\n          \"Helvetica Neue\", sans-serif;\n        font-size: 14px;\n        -webkit-font-smoothing: antialiased;\n        -moz-osx-font-smoothing: grayscale;\n      }\n\n      .driver-popover.custom-driver-popover {\n        min-width: 450px;\n        background: #2d2d2d;\n        color: white;\n      }\n\n      .driver-popover.custom-driver-popover .driver-popover-title {\n        font-size: 26px;\n      }\n\n      .driver-popover.custom-driver-popover .driver-popover-description {\n        font-size: 14px;\n      }\n\n      .driver-popover.custom-driver-popover button {\n        background: #454545;\n        border-color: #454545;\n        text-shadow: none;\n        color: white;\n        font-size: 13px;\n        padding: 7px 10px;\n      }\n\n      .driver-popover.custom-driver-popover button:hover {\n        background: #575757;\n      }\n\n      .gif-popover {\n        display: flex;\n        flex-direction: column;\n        text-align: center;\n      }\n\n      .gif-popover img {\n        width: 100%;\n        height: auto;\n        margin-bottom: 10px;\n      }\n\n      .gif-popover p {\n        font-weight: 500;\n        margin-bottom: 0;\n      }\n\n      p {\n        line-height: 1.5;\n        margin-bottom: 15px;\n      }\n\n      .page-header {\n        text-align: center;\n        margin-bottom: 10px;\n      }\n\n      .container {\n        display: flex;\n        flex-direction: column;\n        max-width: 500px;\n        margin: 0 auto;\n        text-align: left;\n      }\n\n      h1,\n      h2,\n      h3,\n      h4,\n      h5,\n      h6 {\n        margin: 30px 0 10px;\n      }\n\n      h1 {\n        font-size: 48px;\n        font-weight: 600;\n        text-align: center;\n      }\n\n      h1 sup {\n        font-size: 18px;\n        font-weight: 400;\n      }\n\n      ul {\n        list-style: none;\n        padding: 0;\n        margin: 20px 10px 0;\n        line-height: 1.5;\n      }\n\n      ul li:before {\n        content: \"•\";\n        margin-right: 10px;\n      }\n\n      .buttons {\n        display: flex;\n        gap: 10px;\n        max-width: 500px;\n        flex-wrap: wrap;\n      }\n\n      button {\n        all: unset;\n        border: 1px solid #ccc;\n        padding: 5px 15px;\n        border-radius: 5px;\n        display: block;\n        cursor: pointer;\n      }\n\n      pre {\n        margin-bottom: 20px;\n        border: 1px solid #ccc;\n        background: whitesmoke;\n        border-radius: 5px;\n        padding: 10px;\n        line-height: 1.75;\n      }\n\n      #scrollable-area {\n        height: 300px;\n        overflow: auto;\n        border: 1px solid #ccc;\n        padding: 10px;\n        border-radius: 5px;\n        margin: 50px 0;\n      }\n    </style>\n  </head>\n  <body>\n    <div class=\"container\">\n      <div class=\"page-header\">\n        <h1>driver.js <sup>next</sup></h1>\n        <p>Rewritten and enhanced version of driver.js</p>\n      </div>\n\n      <h2>Highlight Feature</h2>\n      <p>given below are the examples of simple `highlight`</p>\n      <div class=\"buttons\">\n        <button id=\"highlight-btn\">Animated Highlight</button>\n        <button id=\"buggy-highlight-btn\">Buggy Highlight</button>\n        <button id=\"off-screen-highlight-btn\">Off Screen Highlight</button>\n        <button id=\"simple-highlight-btn\">Simple Highlight</button>\n        <button id=\"transition-highlight-btn\">Transition Highlight</button>\n        <button id=\"disallow-close\">Disallow Close</button>\n        <button id=\"click-overlay-to-next\">Click Overlay to Next</button>\n        <button id=\"click-overlay-to-handle\">Custom Overlay Click Handler</button>\n        <button id=\"dark-highlight-btn\">Super Dark Highlight</button>\n        <button id=\"dim-highlight-btn\">Super Dim Highlight</button>\n        <button id=\"scrollable-area-btn\">Scrollable Area</button>\n        <button id=\"inner-scroll-area-btn\">Inner Scroll Area</button>\n        <button id=\"without-element-btn\">No Element</button>\n        <button id=\"is-active-btn\">Is Active?</button>\n        <button id=\"activate-check-btn\">Activate and Check</button>\n        <button id=\"backdrop-color-btn\">Backdrop Color</button>\n        <button id=\"hooks\">Hooks</button>\n        <button id=\"destroy-btn\" style=\"border-color: red; background: red; color: white\">Destroy</button>\n      </div>\n      <br />\n      <p>given below are the examples of simple `highlight`</p>\n      <div class=\"buttons\">\n        <button id=\"no-buttons\">No Buttons</button>\n        <button id=\"buttons-from-popover\">Selected Buttons</button>\n        <button id=\"next-button\">Next Button</button>\n        <button id=\"previous-button\">Previous Buttons</button>\n        <button id=\"next-prev-button\">Next Previous Buttons</button>\n        <button id=\"close-button\">Close Buttons</button>\n        <button id=\"button-texts\">Button Texts</button>\n        <button id=\"disabled-buttons\">Disabled Buttons</button>\n        <button id=\"button-config-events\">Button Listeners</button>\n        <button id=\"button-tour-events\">Tour Button Listeners</button>\n        <button id=\"popover-hook-config\">Popover Modified in Hook</button>\n      </div>\n\n      <br />\n      <p>You can modify the popover as well with custom CSS and JS.</p>\n      <div class=\"buttons\">\n        <button id=\"custom-classes\">Custom Classes</button>\n        <button id=\"popover-hook\">Popover Hook</button>\n        <button id=\"padding-change\">Padding Change</button>\n      </div>\n\n      <h2>Tour Feature</h2>\n      <p>Examples below show the tour usage of driver.js.</p>\n      <div class=\"buttons\">\n        <button id=\"basic-tour\">Animated Tour</button>\n        <button id=\"non-animated-tour\">Non-Animated Tour</button>\n        <button id=\"async-tour\">Asynchronous Tour</button>\n        <button id=\"confirm-exit-tour\">Confirm on Exit</button>\n        <button id=\"progress-tour\">Progress Text</button>\n        <button id=\"progress-tour-template\">Progress Text Template</button>\n        <button id=\"api-test\">API Test</button>\n        <button id=\"reconfigure-steps\">Re Configuring Steps</button>\n        <button id=\"disable-keyboard-control\">Disable Keyboard Control</button>\n      </div>\n\n      <ul>\n        <li>Written in TypeScript</li>\n        <li>Lightweight — only 5kb gzipped</li>\n        <li>No dependencies</li>\n        <li>MIT Licensed</li>\n      </ul>\n\n      <ul id=\"hooks-list\">\n        <li><strong>Hooks Button Demo — </strong>List of hooks fired</li>\n      </ul>\n\n      <h2>Yet another Tour Library?</h2>\n      <p>\n        No, it is not. Tours are just one of the many use-cases. Driver.js can be used wherever you need some sort of\n        overlay for the page; some common usecases could be: e.g. dimming the background when user is interacting with\n        some component, using it as a focus shifter to bring user's attention to some component on page, or using it to\n        simulate those \"Turn off the Lights\" widgets that you might have seen on video players online, etc.\n      </p>\n      <p class=\"second-para\">\n        Driver.js is written in Vanilla JS, has zero dependencies and is highly customizable. It has several options\n        allowing you to manipulate how it behaves and also provides you the hooks to manipulate the elements as they are\n        highlighted, about to be highlighted, or deselected.\n      </p>\n\n      <h2 id=\"installation-head\">Installation</h2>\n      <p>You can install it using yarn or npm, whatever you prefer.</p>\n\n      <pre>\nyarn add driver.js\nnpm install driver.js</pre\n      >\n\n      <p>Or include it using CDN — put the version as driver.js@0.5 in the name</p>\n\n      <pre>https://unpkg.com/driver.js/dist/driver.min.js</pre>\n\n      <h2>Usage and Demo</h2>\n\n      <p id=\"large-paragraph-text\">\n        Lorem ipsum dolor sit amet, consectetur adipisicing elit. Animi blanditiis consectetur ea eligendi id in\n        inventore ipsa iure laudantium libero, minus molestias necessitatibus nesciunt non omnis, quasi recusandae\n        tempore voluptates! Lorem ipsum dolor sit amet, consectetur adipisicing elit. Animi blanditiis consectetur ea\n        eligendi id in inventore ipsa iure laudantium libero, minus molestias necessitatibus nesciunt non omnis, quasi\n        recusandae tempore voluptates!\n      </p>\n      <p>\n        Lorem ipsum dolor sit amet, consectetur adipisicing elit. Animi blanditiis consectetur ea eligendi id in\n        inventore ipsa iure laudantium libero, minus molestias necessitatibus nesciunt non omnis, quasi recusandae\n        tempore voluptates!\n      </p>\n      <p>\n        Lorem ipsum dolor sit amet, consectetur adipisicing elit. Animi blanditiis consectetur ea eligendi id in\n        inventore ipsa iure laudantium libero, minus molestias necessitatibus nesciunt non omnis, quasi recusandae\n        tempore voluptates!\n      </p>\n      <div id=\"scrollable-area\">\n        <p>\n          First -> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequuntur dicta ipsum labore quod\n          tempora ullam? Alias consequatur doloremque laborum maxime necessitatibus nostrum odio, officiis quibusdam\n          veniam! Doloribus eos id quaerat.\n        </p>\n        <p>\n          Second -> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequuntur dicta ipsum labore quod\n          tempora ullam? Alias consequatur doloremque laborum maxime necessitatibus nostrum odio, officiis quibusdam\n          veniam! Doloribus eos id quaerat.\n        </p>\n        <p id=\"third-scroll-paragraph\">\n          Third -> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequuntur dicta ipsum labore quod\n          tempora ullam? Alias consequatur doloremque laborum maxime necessitatibus nostrum odio, officiis quibusdam\n          veniam! Doloribus eos id quaerat.\n        </p>\n        <p>\n          Fourth -> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequuntur dicta ipsum labore quod\n          tempora ullam? Alias consequatur doloremque laborum maxime necessitatibus nostrum odio, officiis quibusdam\n          veniam! Doloribus eos id quaerat.\n        </p>\n        <p>\n          Fifth -> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequuntur dicta ipsum labore quod\n          tempora ullam? Alias consequatur doloremque laborum maxime necessitatibus nostrum odio, officiis quibusdam\n          veniam! Doloribus eos id quaerat.\n        </p>\n        <p>\n          Sixth -> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequuntur dicta ipsum labore quod\n          tempora ullam? Alias consequatur doloremque laborum maxime necessitatibus nostrum odio, officiis quibusdam\n          veniam! Doloribus eos id quaerat.\n        </p>\n        <p>\n          Seventh -> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequuntur dicta ipsum labore quod\n          tempora ullam? Alias consequatur doloremque laborum maxime necessitatibus nostrum odio, officiis quibusdam\n          veniam! Doloribus eos id quaerat.\n        </p>\n        <p>\n          Eighth -> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequuntur dicta ipsum labore quod\n          tempora ullam? Alias consequatur doloremque laborum maxime necessitatibus nostrum odio, officiis quibusdam\n          veniam! Doloribus eos id quaerat.\n        </p>\n        <p>\n          Ninth -> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequuntur dicta ipsum labore quod\n          tempora ullam? Alias consequatur doloremque laborum maxime necessitatibus nostrum odio, officiis quibusdam\n          veniam! Doloribus eos id quaerat.\n        </p>\n      </div>\n      <p>\n        Lorem ipsum dolor sit amet, consectetur adipisicing elit. Animi blanditiis consectetur ea eligendi id in\n        inventore ipsa iure laudantium libero, minus molestias necessitatibus nesciunt non omnis, quasi recusandae\n        tempore voluptates!\n      </p>\n      <p>\n        Lorem ipsum dolor sit amet, consectetur adipisicing elit. Animi blanditiis consectetur ea eligendi id in\n        inventore ipsa iure laudantium libero, minus molestias necessitatibus nesciunt non omnis, quasi recusandae\n        tempore voluptates!\n      </p>\n      <p>\n        Lorem ipsum dolor sit amet, consectetur adipisicing elit. Animi blanditiis consectetur ea eligendi id in\n        inventore ipsa iure laudantium libero, minus molestias necessitatibus nesciunt non omnis, quasi recusandae\n        tempore voluptates!\n      </p>\n      <p>\n        Lorem ipsum dolor sit amet, consectetur adipisicing elit. Animi blanditiis consectetur ea eligendi id in\n        inventore ipsa iure laudantium libero, minus molestias necessitatibus nesciunt non omnis, quasi recusandae\n        tempore voluptates!\n      </p>\n      <p>\n        Lorem ipsum dolor sit amet, consectetur adipisicing elit. Animi blanditiis consectetur ea eligendi id in\n        inventore ipsa iure laudantium libero, minus molestias necessitatibus nesciunt non omnis, quasi recusandae\n        tempore voluptates!\n      </p>\n    </div>\n    <script type=\"module\">\n      import { driver } from \"./src/driver.ts\";\n\n      const basicTourSteps = [\n        {\n          element: \".page-header\",\n          popover: {\n            title: \"New and Improved Driver.js\",\n            description:\n              \"Driver.js has been written from the ground up. The new version is more powerful, has less surprises, more customizable and tons of new features.\",\n            side: \"bottom\",\n            align: \"start\",\n          },\n        },\n        {\n          element: \".page-header h1\",\n          popover: {\n            title: \"No Stacking Issues\",\n            description:\n              \"Unlike the older version, new version doesn't work with z-indexes so no more positional issues.\",\n            side: \"left\",\n            align: \"start\",\n          },\n        },\n        {\n          element: \".page-header sup\",\n          popover: {\n            title: \"Improved Hooks\",\n            description:\n              \"Unlike the older version, new version doesn't work with z-indexes so no more positional issues.\",\n            side: \"bottom\",\n            align: \"start\",\n          },\n        },\n        {\n          popover: {\n            title: \"No Element\",\n            description: \"You can now have popovers without elements as well\",\n          },\n        },\n        {\n          element: \".buttons\",\n          popover: {\n            title: \"Buttons\",\n            description: \"Here are some buttons\",\n          },\n        },\n        {\n          element: \"#scrollable-area\",\n          popover: {\n            title: \"Scrollable Areas\",\n            description: \"There are no issues with scrollable element tours as well.\",\n          },\n        },\n        {\n          element: \"#third-scroll-paragraph\",\n          popover: {\n            title: \"Nested Scrolls\",\n            description: \"Even the nested scrollable elements work now.\",\n          },\n        },\n      ];\n\n      document.getElementById(\"non-animated-tour\").addEventListener(\"click\", () => {\n        const driverObj = driver({\n          animate: false,\n          overlayColor: \"blue\",\n          overlayOpacity: 0.3,\n          showProgress: true,\n          steps: basicTourSteps,\n        });\n\n        driverObj.drive();\n      });\n\n      document.getElementById(\"confirm-exit-tour\").addEventListener(\"click\", () => {\n        const driverObj = driver({\n          animate: true,\n          overlayColor: \"green\",\n          overlayOpacity: 0.3,\n          steps: basicTourSteps,\n          onDestroyStarted: () => {\n            if (driverObj.hasNextStep() && confirm(\"Are you sure?\")) {\n              driverObj.destroy();\n            } else {\n              driverObj.destroy();\n            }\n          },\n        });\n\n        driverObj.drive();\n      });\n\n      document.getElementById(\"progress-tour\").addEventListener(\"click\", () => {\n        const driverObj = driver({\n          animate: true,\n          steps: basicTourSteps,\n          showProgress: true,\n        });\n\n        driverObj.drive();\n      });\n\n      document.getElementById(\"progress-tour-template\").addEventListener(\"click\", () => {\n        const driverObj = driver({\n          animate: true,\n          steps: basicTourSteps,\n          showProgress: true,\n          progressText: \"{{current}} of {{total}} done\",\n        });\n\n        driverObj.drive();\n      });\n\n      document.getElementById(\"api-test\").addEventListener(\"click\", () => {\n        const driverObj = driver({\n          animate: true,\n          steps: basicTourSteps,\n          disableActiveInteraction: true,\n          showProgress: true,\n          progressText: \"{{current}} of {{total}} done\",\n          onPopoverRender: popover => {\n            popover.title.innerHTML = `${driverObj.getActiveIndex()} ${driverObj.hasNextStep() ? \"Yes\" : \"No\"} ${\n              driverObj.hasPreviousStep() ? \"Yes\" : \"No\"\n            }`;\n            popover.description.innerHTML = `${driverObj.isFirstStep() ? \"Yes\" : \"No\"} ${\n              driverObj.isLastStep() ? \"Yes\" : \"No\"\n            }`;\n\n            console.log(driverObj.getActiveIndex());\n            console.log(driverObj.getActiveStep());\n          },\n        });\n\n        driverObj.drive(4);\n      });\n\n      document.getElementById(\"reconfigure-steps\").addEventListener(\"click\", () => {\n        const driverObj = driver({\n          animate: true,\n          steps: basicTourSteps,\n          showProgress: true,\n        });\n\n        driverObj.setSteps([\n          {\n            element: \"h1\",\n            popover: {\n              description: \"This is a new description\",\n            },\n          },\n          {\n            element: \"p\",\n            popover: {\n              description: \"This is another new description\",\n            },\n          },\n        ]);\n\n        driverObj.drive();\n      });\n\n      document.getElementById(\"disable-keyboard-control\").addEventListener(\"click\", () => {\n        const driverObj = driver({\n          animate: true,\n          steps: basicTourSteps,\n          showProgress: true,\n          allowKeyboardControl: false,\n        });\n\n        driverObj.setSteps([\n          {\n            element: \"h1\",\n            popover: {\n              description: \"This is a new description\",\n            },\n          },\n          {\n            element: \"p\",\n            popover: {\n              description: \"This is another new description\",\n            },\n          },\n        ]);\n\n        driverObj.drive();\n      });\n\n      document.getElementById(\"async-tour\").addEventListener(\"click\", () => {\n        const driverObj = driver({\n          animate: true,\n          overlayOpacity: 0.3,\n          showProgress: true,\n          progressText: \"{{current}} / {{total}}\",\n          steps: [\n            {\n              element: \".page-header\",\n              popover: {\n                title: \"Async Driver.js\",\n                description:\n                  \"Driver.js has been written from the ground up. The new version is more powerful, has less surprises, more customizable and tons of new features.\",\n                side: \"bottom\",\n                align: \"start\",\n              },\n            },\n            {\n              element: \".page-header h1\",\n              popover: {\n                title: \"Async Test\",\n                description: \"By overriding `onNextClick` you get control over the tour.\",\n                side: \"left\",\n                align: \"start\",\n                onNextClick: () => {\n                  const newDiv = document.querySelector(\".dynamic-el\") || document.createElement(\"div\");\n\n                  newDiv.innerHTML = \"This is a new Element\";\n                  newDiv.style.display = \"block\";\n                  newDiv.style.padding = \"20px\";\n                  newDiv.style.backgroundColor = \"black\";\n                  newDiv.style.color = \"white\";\n                  newDiv.style.fontSize = \"14px\";\n                  newDiv.style.position = \"fixed\";\n                  newDiv.style.top = `${Math.random() * (500 - 30) + 30}px`;\n                  newDiv.style.left = `${Math.random() * (500 - 30) + 30}px`;\n                  newDiv.className = \"dynamic-el\";\n\n                  document.body.appendChild(newDiv);\n\n                  driverObj.moveNext();\n                },\n              },\n            },\n            {\n              element: \".dynamic-el\",\n              onDeselected: element => {\n                element?.parentElement?.removeChild(element);\n              },\n              popover: {\n                title: \"Dynamic Elements\",\n                description: \"This was created before we moved here\",\n              },\n            },\n            {\n              element: \".page-header sup\",\n              popover: {\n                title: \"Improved Hooks\",\n                description:\n                  \"Unlike the older version, new version doesn't work with z-indexes so no more positional issues.\",\n                side: \"bottom\",\n                align: \"start\",\n              },\n            },\n            {\n              popover: {\n                title: \"No Element\",\n                description: \"You can now have popovers without elements as well\",\n              },\n            },\n            {\n              element: \"#scrollable-area\",\n              popover: {\n                title: \"Scrollable Areas\",\n                description: \"There are no issues with scrollable element tours as well.\",\n              },\n            },\n            {\n              element: \"#third-scroll-paragraph\",\n              popover: {\n                title: \"Nested Scrolls\",\n                description: \"Even the nested scrollable elements work now.\",\n              },\n            },\n          ],\n        });\n\n        driverObj.drive();\n      });\n\n      document.getElementById(\"basic-tour\").addEventListener(\"click\", () => {\n        const driverObj = driver({\n          showProgress: true,\n          showButtons: [\"next\", \"previous\", \"close\"],\n          steps: basicTourSteps,\n        });\n\n        driverObj.drive();\n      });\n\n      document.getElementById(\"no-buttons\").addEventListener(\"click\", () => {\n        const driverObj = driver({});\n\n        driverObj.highlight({\n          element: \"#no-buttons\",\n          popover: {\n            title: \"No Buttons\",\n            description:\n              \"No buttons are shown by default for highlight. You can pass in the option to show the buttons you want.\",\n          },\n        });\n      });\n\n      document.getElementById(\"buttons-from-popover\").addEventListener(\"click\", () => {\n        const driverObj = driver();\n\n        driverObj.highlight({\n          element: \"#buttons-from-popover\",\n          popover: {\n            title: \"No Buttons\",\n            showButtons: [\"close\"],\n            description:\n              \"No buttons are shown by default for highlight. You can pass in the option to show the buttons you want.\",\n          },\n        });\n      });\n\n      document.getElementById(\"next-button\").addEventListener(\"click\", () => {\n        const driverObj = driver();\n\n        driverObj.highlight({\n          element: \"#next-button\",\n          popover: {\n            title: \"Next and Close\",\n            showButtons: [\"close\", \"next\"],\n            description: \"This one only has next and close buttons, nothing else.\",\n            onNextClick: (step, element, opts) => {\n              console.log(\"Next Clicked\", step, element, opts);\n              opts.driver.destroy();\n            },\n          },\n        });\n      });\n\n      document.getElementById(\"previous-button\").addEventListener(\"click\", () => {\n        const driverObj = driver();\n\n        driverObj.highlight({\n          element: \"#previous-button\",\n          popover: {\n            title: \"Previous and Close\",\n            showButtons: [\"close\", \"previous\"],\n            description: \"This one only has previous and close buttons, nothing else.\",\n          },\n        });\n      });\n\n      document.getElementById(\"next-prev-button\").addEventListener(\"click\", () => {\n        const driverObj = driver();\n\n        driverObj.highlight({\n          element: \"#next-prev-button\",\n          popover: {\n            title: \"Next and Previous Only\",\n            showButtons: [\"next\", \"previous\"],\n            description: \"This one only has next and previous buttons.\",\n          },\n        });\n      });\n\n      document.getElementById(\"close-button\").addEventListener(\"click\", () => {\n        const driverObj = driver();\n\n        driverObj.highlight({\n          element: \"#close-button\",\n          popover: {\n            title: \"Close Only\",\n            showButtons: [\"close\"],\n            description: \"This one only has close button.\",\n          },\n        });\n      });\n\n      document.getElementById(\"button-texts\").addEventListener(\"click\", () => {\n        const driverObj = driver({\n          prevBtnText: \"<——\",\n          nextBtnText: \"——>\",\n        });\n\n        driverObj.highlight({\n          element: \"#button-texts\",\n          popover: {\n            side: \"left\",\n            title: \"Button from Config\",\n            showButtons: [\"close\", \"next\", \"previous\"],\n            nextBtnText: \"==>\",\n            prevBtnText: \"<==\",\n            description: \"These buttons are configured using driver config.\",\n          },\n        });\n      });\n\n      document.getElementById(\"popover-hook\").addEventListener(\"click\", () => {\n        const driverObj = driver({\n          onPopoverRender: popover => {\n            popover.title.innerText = \"Modified Parent\";\n          },\n        });\n        driverObj.highlight({\n          element: \".page-header\",\n          popover: {\n            title: \"Page Title\",\n            description: \"Body of the popover\",\n            side: \"bottom\",\n            align: \"start\",\n            onPopoverRender: popover => {\n              popover.title.innerText = \"Modified\";\n            },\n          },\n        });\n      });\n\n      document.getElementById(\"padding-change\").addEventListener(\"click\", () => {\n        const driverObj = driver({\n          stagePadding: 0,\n          popoverOffset: 20,\n          stageRadius: 10,\n        });\n\n        driverObj.highlight({\n          element: \"#padding-change\",\n          popover: {\n            title: \"Page Title\",\n            description: \"Body of the popover\",\n            side: \"bottom\",\n            align: \"start\",\n            onPopoverRender: popover => {\n              popover.title.innerText = \"Modified\";\n            },\n          },\n        });\n      });\n\n      document.getElementById(\"custom-classes\").addEventListener(\"click\", () => {\n        const driverObj = driver({\n          popoverClass: \"custom-driver-popover\",\n        });\n\n        driverObj.highlight({\n          popover: {\n            popoverClass: \"custom-driver-popover\",\n            title: \"Custom Classes\",\n            description: \"Popover and buttons have custom classes\",\n            showButtons: [\"close\", \"next\", \"previous\"],\n          },\n        });\n      });\n\n      document.getElementById(\"disabled-buttons\").addEventListener(\"click\", () => {\n        const driverObj = driver();\n        driverObj.highlight({\n          element: \"#disabled-buttons\",\n          popover: {\n            title: \"Disable Buttons\",\n            description: \"You can selectively disable buttons as well\",\n            showButtons: [\"next\", \"previous\", \"close\"],\n            disableButtons: [\"next\", \"previous\"],\n          },\n        });\n      });\n\n      document.getElementById(\"button-config-events\").addEventListener(\"click\", () => {\n        const driverObj = driver({\n          onNextClick: () => {\n            alert(\"Next Clicked\");\n          },\n          onPrevClick: () => {\n            alert(\"Previous Clicked\");\n          },\n          onCloseClick: () => {\n            driverObj.destroy();\n          },\n        });\n\n        driverObj.highlight({\n          popover: {\n            title: \"Global Button Listener\",\n            description: \"You can listen to the button clicks globally.\",\n            showButtons: [\"close\", \"next\", \"previous\"],\n            onPrevClick: () => alert(\"Overriding — Previous Clicked\"),\n          },\n        });\n      });\n\n      document.getElementById(\"button-tour-events\").addEventListener(\"click\", () => {\n        const driverObj = driver({\n          onNextClick: () => {\n            alert(\"Next Clicked\");\n            driverObj.moveNext();\n          },\n          onPrevClick: () => {\n            alert(\"Previous Clicked\");\n            driverObj.movePrevious();\n          },\n          onCloseClick: () => {\n            driverObj.destroy();\n          },\n          steps: [\n            { popover: { title: \"Some title\", description: \"Some description\" } },\n            { popover: { title: \"Another title\", description: \"Some description\" } },\n            { popover: { title: \"Yet another title\", description: \"Some description\" } },\n          ],\n        });\n\n        driverObj.drive();\n      });\n\n      document.getElementById(\"popover-hook-config\").addEventListener(\"click\", () => {\n        const driverObj = driver({\n          onPopoverRender: popover => {\n            const firstButton = document.createElement(\"button\");\n            firstButton.innerText = \"First\";\n            popover.footerButtons.appendChild(firstButton);\n\n            firstButton.addEventListener(\"click\", () => {\n              console.log(\"First Button Clicked\");\n            });\n          },\n          steps: [\n            { popover: { title: \"Some title\", description: \"Some description\" } },\n            { popover: { title: \"Another title\", description: \"Some description\" } },\n            { popover: { title: \"Yet another title\", description: \"Some description\" } },\n          ],\n        });\n\n        driverObj.drive();\n      });\n\n      document.getElementById(\"is-active-btn\").addEventListener(\"click\", () => {\n        alert(driver().isActive());\n      });\n\n      document.getElementById(\"backdrop-color-btn\").addEventListener(\"click\", () => {\n        driver({\n          overlayColor: \"blue\",\n          overlayOpacity: 0.3,\n        }).highlight({\n          element: \"#backdrop-color-btn\",\n        });\n      });\n\n      document.getElementById(\"activate-check-btn\").addEventListener(\"click\", () => {\n        const driverObj = driver({\n          showButtons: false,\n        });\n\n        driverObj.highlight({\n          element: \"#activate-check-btn\",\n          popover: {\n            title: \"Check if driver is active\",\n            description: \"This will alert the status after 2 seconds\",\n            side: \"bottom\",\n            align: \"start\",\n          },\n        });\n\n        setTimeout(() => {\n          alert(`Status: ${driverObj.isActive()}. Destroying driver...`);\n          driverObj.destroy();\n          setTimeout(() => {\n            alert(`Status: ${driverObj.isActive()}`);\n          }, 0);\n        }, 2000);\n      });\n\n      document.getElementById(\"buggy-highlight-btn\").addEventListener(\"click\", () => {\n        driver().highlight({\n          element: \".page-header h1 sup\",\n          popover: {\n            title: \"Buggy Highlight\",\n            description: \"Unlike the older version, new version doesn't work with z-indexes so no more positional issues.\",\n            side: \"bottom\",\n            align: \"start\",\n          },\n        });\n      });\n\n      document.getElementById(\"off-screen-highlight-btn\").addEventListener(\"click\", () => {\n        driver().highlight({\n          element: \".container\",\n          popover: {\n            title: \"Buggy Highlight\",\n            description: \"Unlike the older version, new version doesn't work with z-indexes so no more positional issues.\",\n            side: \"bottom\",\n            align: \"start\",\n          },\n        });\n      });\n\n      document.getElementById(\"highlight-btn\").addEventListener(\"click\", () => {\n        driver({\n          animate: true,\n          popoverOffset: 10,\n          stagePadding: 10,\n          onDeselected: (element, step) => {\n            console.log(\"Deselected element\", element, step);\n          },\n          onHighlightStarted: (element, step) => {\n            console.log(\"Started highlighting element\", element, step);\n          },\n          onHighlighted: (element, step) => {\n            console.log(\"Highlighted element\", element, step);\n          },\n        }).highlight({\n          element: \"h2\",\n          popover: {\n            title: \"MIT License\",\n            description: \"A lightweight, no-dependency JavaScript engine to drive user's focus.\",\n            side: \"bottom\",\n            align: \"start\",\n          },\n        });\n      });\n\n      document.getElementById(\"simple-highlight-btn\").addEventListener(\"click\", () => {\n        driver({ animate: false }).highlight({\n          element: \"#large-paragraph-text\",\n          popover: {\n            title: \"driver.js\",\n            description:\n              \"Highlight anything, anywhere on the page. Yes, literally anything including SVG portions, scrollable items etc.\",\n            align: \"start\",\n            side: \"top\",\n          },\n        });\n      });\n\n      document.getElementById(\"dark-highlight-btn\").addEventListener(\"click\", () => {\n        driver({\n          animate: true,\n          overlayOpacity: 0.9,\n        }).highlight({ element: \"ul\" });\n      });\n\n      document.getElementById(\"dim-highlight-btn\").addEventListener(\"click\", () => {\n        driver({\n          animate: true,\n          overlayOpacity: 0.2,\n        }).highlight({ element: \".buttons\" });\n      });\n\n      document.getElementById(\"transition-highlight-btn\").addEventListener(\"click\", () => {\n        const driverObj = driver({\n          animate: true,\n          onDeselected: (element, step) => {\n            console.log(\"Deselected element\", element, step);\n          },\n          onHighlightStarted: (element, step) => {\n            console.log(\"Started highlighting element\", element, step);\n          },\n          onHighlighted: (element, step) => {\n            console.log(\"Highlighted element\", element, step);\n          },\n        });\n\n        driverObj.highlight({\n          popover: {\n            title: \"driver.js\",\n            description: \"Highlight anything, anywhere on the page\",\n          },\n        });\n\n        window.setTimeout(() => {\n          driverObj.highlight({\n            element: \".buttons button:first-child\",\n            popover: {\n              title: \"driver.js\",\n              description: \"Highlight anything, anywhere on the page\",\n            },\n          });\n        }, 2000);\n\n        window.setTimeout(() => {\n          driverObj.highlight({\n            popover: {\n              title: \"driver.js\",\n              description: \"Highlight anything, anywhere on the page\",\n            },\n          });\n        }, 4000);\n\n        window.setTimeout(() => {\n          driverObj.highlight({\n            element: \"h2\",\n            popover: {\n              description: \"driver.js\",\n            },\n          });\n        }, 6000);\n      });\n\n      document.getElementById(\"hooks\").addEventListener(\"click\", () => {\n        const pageHeader = document.getElementById(\".page-header\");\n\n        const driverObj = driver({\n          animate: true,\n          onDeselected: (element, step) => {\n            const elementText = element?.textContent?.slice(0, 10) || \" - N/A -\";\n            console.log(`Deselected: ${elementText}\\n${JSON.stringify(step)}`);\n          },\n          onHighlightStarted: (element, step) => {\n            const elementText = element?.textContent?.slice(0, 10) || \" - N/A -\";\n            console.log(`Highlight Started: ${elementText}\\n${JSON.stringify(step)}`);\n          },\n          onHighlighted: (element, step) => {\n            const elementText = element?.textContent?.slice(0, 10) || \" - N/A -\";\n            console.log(`Highlighted: ${elementText}\\n${JSON.stringify(step)}`);\n          },\n          onDestroyed: (element, step) => {\n            const elementText = element?.textContent?.slice(0, 10) || \" - N/A -\";\n            console.log(`Destroyed: ${elementText}\\n${JSON.stringify(step)}`);\n          },\n        });\n\n        driverObj.highlight({\n          element: \"#hooks\",\n          popover: {\n            title: \"Hooks\",\n            description: \"Here are all the hooks\",\n          },\n        });\n\n        window.setTimeout(() => {\n          driverObj.highlight({\n            popover: {\n              title: \"Popup Hook\",\n              description: \"There is no element below this popover\",\n            },\n          });\n        }, 1000);\n\n        window.setTimeout(() => {\n          driverObj.highlight({\n            element: \"#hooks-list\",\n            popover: {\n              description: \"Here are all the hooks\",\n            },\n          });\n        }, 2000);\n      });\n\n      document.getElementById(\"scrollable-area-btn\").addEventListener(\"click\", () => {\n        const driverObj = driver({ animate: true });\n        driverObj.highlight({ element: \"#scrollable-area\" });\n      });\n\n      document.getElementById(\"without-element-btn\").addEventListener(\"click\", () => {\n        const driverObj = driver({\n          animate: true,\n          onDestroyed: (element, step) => {\n            console.log(\"Close modal\", element, step);\n          },\n          onDeselected: (element, step) => {\n            console.log(\"Deselected element\", element, step);\n          },\n          onHighlightStarted: (element, step, { config, state }) => {\n            console.log(\"Started highlighting element\", element, step);\n          },\n          onHighlighted: (element, step) => {\n            console.log(\"Highlighted element\", element, step);\n          },\n        });\n        driverObj.highlight({\n          popover: {\n            showButtons: [],\n            description:\n              \"<div class='gif-popover'><img style='max-width: 100%' src='https://i.imgur.com/EAQhHu5.gif' /><p>Go and build something cool!</p></div>\",\n          },\n        });\n      });\n\n      document.getElementById(\"inner-scroll-area-btn\").addEventListener(\"click\", () => {\n        const driverObj = driver({ animate: true });\n        driverObj.highlight({ element: \"#third-scroll-paragraph\" });\n      });\n\n      document.getElementById(\"disallow-close\").addEventListener(\"click\", () => {\n        const driverObj = driver({\n          animate: true,\n          allowClose: false,\n        });\n\n        driverObj.highlight({\n          element: \".buttons\",\n        });\n      });\n\n      document.getElementById(\"click-overlay-to-next\").addEventListener(\"click\", () => {\n        const driverObj = driver({\n          animate: true,\n          overlayClickBehavior: \"nextStep\",\n          steps: basicTourSteps,\n        });\n\n        driverObj.drive();\n      });\n\n      document.getElementById(\"click-overlay-to-handle\").addEventListener(\"click\", () => {\n        const driverObj = driver({\n          animate: true,\n          overlayClickBehavior: (element, step) => {\n            alert(\"Clicking me\");\n          },\n          steps: basicTourSteps,\n        });\n\n        driverObj.drive();\n      });\n\n      document.getElementById(\"destroy-btn\").addEventListener(\"click\", () => {\n        driver().destroy();\n      });\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "license",
    "content": "The MIT License\n\nCopyright (c) Kamran Ahmed\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE."
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"driver.js\",\n  \"license\": \"MIT\",\n  \"private\": false,\n  \"version\": \"1.4.0\",\n  \"main\": \"./dist/driver.js.cjs\",\n  \"module\": \"./dist/driver.js.mjs\",\n  \"types\": \"./dist/driver.js.d.ts\",\n  \"homepage\": \"https://driverjs.com\",\n  \"repository\": \"https://github.com/kamranahmedse/driver.js\",\n  \"author\": \"Kamran Ahmed <kamranahmed.se@gmail.com>\",\n  \"bugs\": {\n    \"url\": \"https://github.com/kamranahmedse/driver.js/issues\"\n  },\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/driver.js.d.ts\",\n      \"require\": \"./dist/driver.js.cjs\",\n      \"import\": \"./dist/driver.js.mjs\"\n    },\n    \"./dist/driver.css\": {\n      \"require\": \"./dist/driver.css\",\n      \"import\": \"./dist/driver.css\",\n      \"default\": \"./dist/driver.css\"\n    }\n  },\n  \"scripts\": {\n    \"dev\": \"vite --host\",\n    \"build\": \"tsc && vite build && dts-bundle-generator --config ./dts-bundle-generator.config.ts\",\n    \"test\": \"vitest\",\n    \"format\": \"prettier . --write\"\n  },\n  \"files\": [\n    \"!tests/**/*\",\n    \"!docs/**/*\",\n    \"dist/**/*\",\n    \"!dist/**/*.js.map\"\n  ],\n  \"devDependencies\": {\n    \"@types/jsdom\": \"^21.1.2\",\n    \"@types/node\": \"^20.5.9\",\n    \"@vitest/coverage-c8\": \"^0.32.0\",\n    \"dts-bundle-generator\": \"^8.0.1\",\n    \"postcss\": \"^8.4.29\",\n    \"postcss-scss\": \"^4.0.7\",\n    \"prettier\": \"^3.0.3\",\n    \"ts-node\": \"^10.9.1\",\n    \"typescript\": \"^5.2.2\",\n    \"vite\": \"^4.4.9\",\n    \"vitest\": \"^0.34.3\"\n  },\n  \"keywords\": [\n    \"driver.js\",\n    \"driver\",\n    \"tour\",\n    \"guide\",\n    \"overlay\",\n    \"tooltip\",\n    \"walkthrough\",\n    \"product tour\",\n    \"product walkthrough\",\n    \"product guide\",\n    \"product tutorial\",\n    \"product demo\",\n    \"modal\",\n    \"lightbox\"\n  ]\n}\n"
  },
  {
    "path": "readme.md",
    "content": "<h1 align=\"center\"><img height=\"150\" src=\"https://driverjs.com/driver.svg\" /><br> Driver.js</h1>\n\n<p align=\"center\">\n  <a href=\"https://github.com/kamranahmedse/driver.js/blob/master/license\">\n    <img src=\"https://img.shields.io/badge/License-MIT-yellow.svg\" />\n  </a>\n  <a href=\"https://www.jsdelivr.com/package/npm/driver.js\">\n    <img src=\"https://data.jsdelivr.com/v1/package/npm/driver.js/badge?style=rounded\" alt=\"jsdelivr hits\" />\n  </a>\n  <a href=\"https://npmjs.org/package/driver.js\">\n    <img src=\"https://img.shields.io/npm/dm/driver.js\" alt=\"downloads\" />\n  </a>\n</p>\n\n<p align=\"center\">\n  <b>Powerful, highly customizable vanilla JavaScript engine to drive user's focus on the page</b></br>\n  <sub>No external dependencies, light-weight, supports all major browsers and highly customizable </sub><br>\n</p>\n\n<br />\n\n- **Simple**: is simple to use and has no external dependency at all\n- **Light-weight**: is just 5kb gzipped as compared to other libraries which are +12kb gzipped\n- **Highly customizable**: has a powerful API and can be used however you want\n- **Highlight anything**: highlight any (literally any) element on page\n- **Feature introductions**: create powerful feature introductions for your web applications\n- **Focus shifters**: add focus shifters for users\n- **User friendly**: Everything is controllable by keyboard\n- **TypeScript**: Written in TypeScript\n- **Consistent behavior**: usable across all browsers\n- **MIT Licensed**: free for personal and commercial use\n\n<br />\n\n## Documentation\n\nFor demos and documentation, visit [driverjs.com](https://driverjs.com)\n\n<br />\n\n## So, yet another tour library?\n\n**No**, it's more than a tour library. **Tours are just one of the many use-cases**. Driver.js can be used wherever you need some sort of overlay for the page; some common usecases could be: [highlighting a page component](https://i.imgur.com/TS0LSK9.png) when user is interacting with some component to keep them focused, providing contextual help e.g. popover with dimmed background when user is filling a form, using it as a focus shifter to bring user's attention to some component on page, using it to simulate those \"Turn off the Lights\" widgets that you might have seen on video players online, usage as a simple modal, and of-course product tours etc.\n\nDriver.js is written in Vanilla TypeScript, has zero dependencies and is highly customizable. It has several options allowing you to change how it behaves and also **provides you the hooks** to manipulate the elements as they are highlighted, about to be highlighted, or deselected.\n\n> Also, comparing the size of Driver.js with other libraries, it's the most light-weight, it is **just ~5kb gzipped** while others are 12kb+.\n\n<br>\n\n## Contributions\n\nFeel free to submit pull requests, create issues or spread the word.\n\n## License\n\nMIT &copy; [Kamran Ahmed](https://twitter.com/kamrify)\n"
  },
  {
    "path": "src/config.ts",
    "content": "import { Driver, DriveStep } from \"./driver\";\nimport { AllowedButtons, PopoverDOM } from \"./popover\";\nimport { State } from \"./state\";\n\nexport type DriverHook = (\n  element: Element | undefined,\n  step: DriveStep,\n  opts: { config: Config; state: State; driver: Driver }\n) => void;\n\nexport type Config = {\n  steps?: DriveStep[];\n\n  animate?: boolean;\n  overlayColor?: string;\n  overlayOpacity?: number;\n  smoothScroll?: boolean;\n  allowClose?: boolean;\n  overlayClickBehavior?: \"close\" | \"nextStep\" | DriverHook;\n  stagePadding?: number;\n  stageRadius?: number;\n\n  disableActiveInteraction?: boolean;\n\n  allowKeyboardControl?: boolean;\n\n  // Popover specific configuration\n  popoverClass?: string;\n  popoverOffset?: number;\n  showButtons?: AllowedButtons[];\n  disableButtons?: AllowedButtons[];\n  showProgress?: boolean;\n\n  // Button texts\n  progressText?: string;\n  nextBtnText?: string;\n  prevBtnText?: string;\n  doneBtnText?: string;\n\n  // Called after the popover is rendered\n  onPopoverRender?: (popover: PopoverDOM, opts: { config: Config; state: State, driver: Driver }) => void;\n\n  // State based callbacks, called upon state changes\n  onHighlightStarted?: DriverHook;\n  onHighlighted?: DriverHook;\n  onDeselected?: DriverHook;\n  onDestroyStarted?: DriverHook;\n  onDestroyed?: DriverHook;\n\n  // Event based callbacks, called upon events\n  onNextClick?: DriverHook;\n  onPrevClick?: DriverHook;\n  onCloseClick?: DriverHook;\n};\n\nlet currentConfig: Config = {};\nlet currentDriver: Driver;\n\nexport function configure(config: Config = {}) {\n  currentConfig = {\n    animate: true,\n    allowClose: true,\n    overlayClickBehavior: \"close\",\n    overlayOpacity: 0.7,\n    smoothScroll: false,\n    disableActiveInteraction: false,\n    showProgress: false,\n    stagePadding: 10,\n    stageRadius: 5,\n    popoverOffset: 10,\n    showButtons: [\"next\", \"previous\", \"close\"],\n    disableButtons: [],\n    overlayColor: \"#000\",\n    ...config,\n  };\n}\n\nexport function getConfig(): Config;\nexport function getConfig<K extends keyof Config>(key: K): Config[K];\nexport function getConfig<K extends keyof Config>(key?: K) {\n  return key ? currentConfig[key] : currentConfig;\n}\n\nexport function setCurrentDriver(driver: Driver) {\n  currentDriver = driver;\n}\n\nexport function getCurrentDriver() {\n  return currentDriver;\n}\n"
  },
  {
    "path": "src/driver.css",
    "content": ".driver-active .driver-overlay {\n  pointer-events: none;\n}\n\n.driver-active * {\n  pointer-events: none;\n}\n\n.driver-active .driver-active-element,\n.driver-active .driver-active-element *,\n.driver-popover,\n.driver-popover * {\n  pointer-events: auto;\n}\n\n@keyframes animate-fade-in {\n  0% {\n    opacity: 0;\n  }\n\n  to {\n    opacity: 1;\n  }\n}\n\n.driver-fade .driver-overlay {\n  animation: animate-fade-in 200ms ease-in-out;\n}\n\n.driver-fade .driver-popover {\n  animation: animate-fade-in 200ms;\n}\n\n/* Popover styles */\n.driver-popover {\n  all: unset;\n  box-sizing: border-box;\n  color: #2d2d2d;\n  margin: 0;\n  padding: 15px;\n  border-radius: 5px;\n  min-width: 250px;\n  max-width: 300px;\n  box-shadow: 0 1px 10px #0006;\n  z-index: 1000000000;\n  position: fixed;\n  top: 0;\n  right: 0;\n  background-color: #fff;\n}\n\n.driver-popover * {\n  font-family: \"Helvetica Neue\", Inter, ui-sans-serif, \"Apple Color Emoji\", Helvetica, Arial, sans-serif;\n}\n\n.driver-popover-title {\n  font: 19px / normal sans-serif;\n  font-weight: 700;\n  display: block;\n  position: relative;\n  line-height: 1.5;\n  zoom: 1;\n  margin: 0;\n}\n\n.driver-popover-close-btn {\n  all: unset;\n  position: absolute;\n  top: 0;\n  right: 0;\n  width: 32px;\n  height: 28px;\n  cursor: pointer;\n  font-size: 18px;\n  font-weight: 500;\n  color: #d2d2d2;\n  z-index: 1;\n  text-align: center;\n  transition: color;\n  transition-duration: 200ms;\n}\n\n.driver-popover-close-btn:hover,\n.driver-popover-close-btn:focus {\n  color: #2d2d2d;\n}\n\n.driver-popover-title[style*=\"block\"] + .driver-popover-description {\n  margin-top: 5px;\n}\n\n.driver-popover-description {\n  margin-bottom: 0;\n  font: 14px / normal sans-serif;\n  line-height: 1.5;\n  font-weight: 400;\n  zoom: 1;\n}\n\n.driver-popover-footer {\n  margin-top: 15px;\n  text-align: right;\n  zoom: 1;\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n}\n\n.driver-popover-progress-text {\n  font-size: 13px;\n  font-weight: 400;\n  color: #727272;\n  zoom: 1;\n}\n\n.driver-popover-footer button {\n  all: unset;\n  display: inline-block;\n  box-sizing: border-box;\n  padding: 3px 7px;\n  text-decoration: none;\n  text-shadow: 1px 1px 0 #fff;\n  background-color: #ffffff;\n  color: #2d2d2d;\n  font: 12px / normal sans-serif;\n  cursor: pointer;\n  outline: 0;\n  zoom: 1;\n  line-height: 1.3;\n  border: 1px solid #ccc;\n  border-radius: 3px;\n}\n\n.driver-popover-footer .driver-popover-btn-disabled {\n  opacity: 0.5;\n  pointer-events: none;\n}\n\n/* Disable the scrolling of parent element if it has an active element*/\n:not(body):has(> .driver-active-element) {\n  overflow: hidden !important;\n}\n\n.driver-no-interaction, .driver-no-interaction * {\n  pointer-events: none !important;\n}\n\n.driver-popover-footer button:hover,\n.driver-popover-footer button:focus {\n  background-color: #f7f7f7;\n}\n\n.driver-popover-navigation-btns {\n  display: flex;\n  flex-grow: 1;\n  justify-content: flex-end;\n}\n\n.driver-popover-navigation-btns button + button {\n  margin-left: 4px;\n}\n\n.driver-popover-arrow {\n  content: \"\";\n  position: absolute;\n  border: 5px solid #fff;\n}\n\n.driver-popover-arrow-side-over {\n  display: none;\n}\n\n/** Popover Arrow Sides **/\n.driver-popover-arrow-side-left {\n  left: 100%;\n  border-right-color: transparent;\n  border-bottom-color: transparent;\n  border-top-color: transparent;\n}\n\n.driver-popover-arrow-side-right {\n  right: 100%;\n  border-left-color: transparent;\n  border-bottom-color: transparent;\n  border-top-color: transparent;\n}\n\n.driver-popover-arrow-side-top {\n  top: 100%;\n  border-right-color: transparent;\n  border-bottom-color: transparent;\n  border-left-color: transparent;\n}\n\n.driver-popover-arrow-side-bottom {\n  bottom: 100%;\n  border-left-color: transparent;\n  border-top-color: transparent;\n  border-right-color: transparent;\n}\n\n.driver-popover-arrow-side-center {\n  display: none;\n}\n\n/* Left/Start + Right/Start */\n.driver-popover-arrow-side-left.driver-popover-arrow-align-start,\n.driver-popover-arrow-side-right.driver-popover-arrow-align-start {\n  top: 15px;\n}\n\n/* Top/Start + Bottom/Start */\n.driver-popover-arrow-side-top.driver-popover-arrow-align-start,\n.driver-popover-arrow-side-bottom.driver-popover-arrow-align-start {\n  left: 15px;\n}\n\n/* End/Left + End/Right */\n.driver-popover-arrow-align-end.driver-popover-arrow-side-left,\n.driver-popover-arrow-align-end.driver-popover-arrow-side-right {\n  bottom: 15px;\n}\n\n/* Top/End + Bottom/End */\n.driver-popover-arrow-side-top.driver-popover-arrow-align-end,\n.driver-popover-arrow-side-bottom.driver-popover-arrow-align-end {\n  right: 15px;\n}\n\n/* Left/Center + Right/Center */\n.driver-popover-arrow-side-left.driver-popover-arrow-align-center,\n.driver-popover-arrow-side-right.driver-popover-arrow-align-center {\n  top: 50%;\n  margin-top: -5px;\n}\n\n/* Top/Center + Bottom/Center */\n.driver-popover-arrow-side-top.driver-popover-arrow-align-center,\n.driver-popover-arrow-side-bottom.driver-popover-arrow-align-center {\n  left: 50%;\n  margin-left: -5px;\n}\n\n/* No arrow */\n.driver-popover-arrow-none {\n  display: none;\n}\n"
  },
  {
    "path": "src/driver.ts",
    "content": "import { AllowedButtons, destroyPopover, Popover } from \"./popover\";\nimport { destroyOverlay } from \"./overlay\";\nimport { destroyEvents, initEvents, requireRefresh } from \"./events\";\nimport { Config, configure, DriverHook, getConfig, getCurrentDriver, setCurrentDriver } from \"./config\";\nimport { destroyHighlight, highlight } from \"./highlight\";\nimport { destroyEmitter, listen } from \"./emitter\";\nimport { getState, resetState, setState } from \"./state\";\nimport \"./driver.css\";\n\nexport type DriveStep = {\n  element?: string | Element | (() => Element);\n  onHighlightStarted?: DriverHook;\n  onHighlighted?: DriverHook;\n  onDeselected?: DriverHook;\n  popover?: Popover;\n  disableActiveInteraction?: boolean;\n};\n\nexport interface Driver {\n  isActive: () => boolean;\n  refresh: () => void;\n  drive: (stepIndex?: number) => void;\n  setConfig: (config: Config) => void;\n  setSteps: (steps: DriveStep[]) => void;\n  getConfig: () => Config;\n  getState: (key?: string) => any;\n  getActiveIndex: () => number | undefined;\n  isFirstStep: () => boolean;\n  isLastStep: () => boolean;\n  getActiveStep: () => DriveStep | undefined;\n  getActiveElement: () => Element | undefined;\n  getPreviousElement: () => Element | undefined;\n  getPreviousStep: () => DriveStep | undefined;\n  moveNext: () => void;\n  movePrevious: () => void;\n  moveTo: (index: number) => void;\n  hasNextStep: () => boolean;\n  hasPreviousStep: () => boolean;\n  highlight: (step: DriveStep) => void;\n  destroy: () => void;\n}\n\nexport function driver(options: Config = {}): Driver {\n  configure(options);\n\n  function handleClose() {\n    if (!getConfig(\"allowClose\")) {\n      return;\n    }\n\n    destroy();\n  }\n\n  function handleOverlayClick() {\n    const overlayClickBehavior = getConfig(\"overlayClickBehavior\");\n\n    if (getConfig(\"allowClose\") && overlayClickBehavior === \"close\") {\n      destroy();\n      return;\n    }\n\n    if (typeof overlayClickBehavior === \"function\") {\n      const activeStep = getState(\"__activeStep\");\n      const activeElement = getState(\"__activeElement\");\n\n      overlayClickBehavior(activeElement, activeStep!, {\n        config: getConfig(),\n        state: getState(),\n        driver: getCurrentDriver(),\n      });\n\n      return;\n    }\n\n    if (overlayClickBehavior === \"nextStep\") {\n      moveNext();\n    }\n  }\n\n  function moveNext() {\n    const activeIndex = getState(\"activeIndex\");\n    const steps = getConfig(\"steps\") || [];\n    if (typeof activeIndex === \"undefined\") {\n      return;\n    }\n\n    const nextStepIndex = activeIndex + 1;\n    if (steps[nextStepIndex]) {\n      drive(nextStepIndex);\n    } else {\n      destroy();\n    }\n  }\n\n  function movePrevious() {\n    const activeIndex = getState(\"activeIndex\");\n    const steps = getConfig(\"steps\") || [];\n    if (typeof activeIndex === \"undefined\") {\n      return;\n    }\n\n    const previousStepIndex = activeIndex - 1;\n    if (steps[previousStepIndex]) {\n      drive(previousStepIndex);\n    } else {\n      destroy();\n    }\n  }\n\n  function moveTo(index: number) {\n    const steps = getConfig(\"steps\") || [];\n\n    if (steps[index]) {\n      drive(index);\n    } else {\n      destroy();\n    }\n  }\n\n  function handleArrowLeft() {\n    const isTransitioning = getState(\"__transitionCallback\");\n    if (isTransitioning) {\n      return;\n    }\n\n    const activeIndex = getState(\"activeIndex\");\n    const activeStep = getState(\"__activeStep\");\n    const activeElement = getState(\"__activeElement\");\n    if (typeof activeIndex === \"undefined\" || typeof activeStep === \"undefined\") {\n      return;\n    }\n\n    const currentStepIndex = getState(\"activeIndex\");\n    if (typeof currentStepIndex === \"undefined\") {\n      return;\n    }\n\n    const onPrevClick = activeStep.popover?.onPrevClick || getConfig(\"onPrevClick\");\n    if (onPrevClick) {\n      return onPrevClick(activeElement, activeStep, {\n        config: getConfig(),\n        state: getState(),\n        driver: getCurrentDriver(),\n      });\n    }\n\n    movePrevious();\n  }\n\n  function handleArrowRight() {\n    const isTransitioning = getState(\"__transitionCallback\");\n    if (isTransitioning) {\n      return;\n    }\n\n    const activeIndex = getState(\"activeIndex\");\n    const activeStep = getState(\"__activeStep\");\n    const activeElement = getState(\"__activeElement\");\n    if (typeof activeIndex === \"undefined\" || typeof activeStep === \"undefined\") {\n      return;\n    }\n\n    const onNextClick = activeStep.popover?.onNextClick || getConfig(\"onNextClick\");\n    if (onNextClick) {\n      return onNextClick(activeElement, activeStep, {\n        config: getConfig(),\n        state: getState(),\n        driver: getCurrentDriver(),\n      });\n    }\n\n    moveNext();\n  }\n\n  function init() {\n    if (getState(\"isInitialized\")) {\n      return;\n    }\n\n    setState(\"isInitialized\", true);\n    document.body.classList.add(\"driver-active\", getConfig(\"animate\") ? \"driver-fade\" : \"driver-simple\");\n\n    initEvents();\n\n    listen(\"overlayClick\", handleOverlayClick);\n    listen(\"escapePress\", handleClose);\n    listen(\"arrowLeftPress\", handleArrowLeft);\n    listen(\"arrowRightPress\", handleArrowRight);\n  }\n\n  function drive(stepIndex: number = 0) {\n    const steps = getConfig(\"steps\");\n    if (!steps) {\n      console.error(\"No steps to drive through\");\n      destroy();\n      return;\n    }\n\n    if (!steps[stepIndex]) {\n      destroy();\n\n      return;\n    }\n\n    setState(\"__activeOnDestroyed\", document.activeElement as HTMLElement);\n    setState(\"activeIndex\", stepIndex);\n\n    const currentStep = steps[stepIndex];\n    const hasNextStep = steps[stepIndex + 1];\n    const hasPreviousStep = steps[stepIndex - 1];\n\n    const doneBtnText = currentStep.popover?.doneBtnText || getConfig(\"doneBtnText\") || \"Done\";\n    const allowsClosing = getConfig(\"allowClose\");\n    const showProgress =\n      typeof currentStep.popover?.showProgress !== \"undefined\"\n        ? currentStep.popover?.showProgress\n        : getConfig(\"showProgress\");\n    const progressText = currentStep.popover?.progressText || getConfig(\"progressText\") || \"{{current}} of {{total}}\";\n    const progressTextReplaced = progressText\n      .replace(\"{{current}}\", `${stepIndex + 1}`)\n      .replace(\"{{total}}\", `${steps.length}`);\n\n    const configuredButtons = currentStep.popover?.showButtons || getConfig(\"showButtons\");\n    const calculatedButtons: AllowedButtons[] = [\n      \"next\",\n      \"previous\",\n      ...(allowsClosing ? [\"close\" as AllowedButtons] : []),\n    ].filter(b => {\n      return !configuredButtons?.length || configuredButtons.includes(b as AllowedButtons);\n    }) as AllowedButtons[];\n\n    const onNextClick = currentStep.popover?.onNextClick || getConfig(\"onNextClick\");\n    const onPrevClick = currentStep.popover?.onPrevClick || getConfig(\"onPrevClick\");\n    const onCloseClick = currentStep.popover?.onCloseClick || getConfig(\"onCloseClick\");\n\n    highlight({\n      ...currentStep,\n      popover: {\n        showButtons: calculatedButtons,\n        nextBtnText: !hasNextStep ? doneBtnText : undefined,\n        disableButtons: [...(!hasPreviousStep ? [\"previous\" as AllowedButtons] : [])],\n        showProgress: showProgress,\n        progressText: progressTextReplaced,\n        onNextClick: onNextClick\n          ? onNextClick\n          : () => {\n              if (!hasNextStep) {\n                destroy();\n              } else {\n                drive(stepIndex + 1);\n              }\n            },\n        onPrevClick: onPrevClick\n          ? onPrevClick\n          : () => {\n              drive(stepIndex - 1);\n            },\n        onCloseClick: onCloseClick\n          ? onCloseClick\n          : () => {\n              destroy();\n            },\n        ...(currentStep?.popover || {}),\n      },\n    });\n  }\n\n  function destroy(withOnDestroyStartedHook = true) {\n    const activeElement = getState(\"__activeElement\");\n    const activeStep = getState(\"__activeStep\");\n\n    const activeOnDestroyed = getState(\"__activeOnDestroyed\");\n\n    const onDestroyStarted = getConfig(\"onDestroyStarted\");\n    // `onDestroyStarted` is used to confirm the exit of tour. If we trigger\n    // the hook for when user calls `destroy`, driver will get into infinite loop\n    // not causing tour to be destroyed.\n    if (withOnDestroyStartedHook && onDestroyStarted) {\n      const isActiveDummyElement = !activeElement || activeElement?.id === \"driver-dummy-element\";\n      onDestroyStarted(isActiveDummyElement ? undefined : activeElement, activeStep!, {\n        config: getConfig(),\n        state: getState(),\n        driver: getCurrentDriver(),\n      });\n      return;\n    }\n\n    const onDeselected = activeStep?.onDeselected || getConfig(\"onDeselected\");\n    const onDestroyed = getConfig(\"onDestroyed\");\n\n    document.body.classList.remove(\"driver-active\", \"driver-fade\", \"driver-simple\");\n\n    destroyEvents();\n    destroyPopover();\n    destroyHighlight();\n    destroyOverlay();\n    destroyEmitter();\n\n    resetState();\n\n    if (activeElement && activeStep) {\n      const isActiveDummyElement = activeElement.id === \"driver-dummy-element\";\n      if (onDeselected) {\n        onDeselected(isActiveDummyElement ? undefined : activeElement, activeStep, {\n          config: getConfig(),\n          state: getState(),\n          driver: getCurrentDriver(),\n        });\n      }\n\n      if (onDestroyed) {\n        onDestroyed(isActiveDummyElement ? undefined : activeElement, activeStep, {\n          config: getConfig(),\n          state: getState(),\n          driver: getCurrentDriver(),\n        });\n      }\n    }\n\n    if (activeOnDestroyed) {\n      (activeOnDestroyed as HTMLElement).focus();\n    }\n  }\n\n  const api: Driver = {\n    isActive: () => getState(\"isInitialized\") || false,\n    refresh: requireRefresh,\n    drive: (stepIndex: number = 0) => {\n      init();\n      drive(stepIndex);\n    },\n    setConfig: configure,\n    setSteps: (steps: DriveStep[]) => {\n      resetState();\n      configure({\n        ...getConfig(),\n        steps,\n      });\n    },\n    getConfig,\n    getState,\n    getActiveIndex: () => getState(\"activeIndex\"),\n    isFirstStep: () => getState(\"activeIndex\") === 0,\n    isLastStep: () => {\n      const steps = getConfig(\"steps\") || [];\n      const activeIndex = getState(\"activeIndex\");\n\n      return activeIndex !== undefined && activeIndex === steps.length - 1;\n    },\n    getActiveStep: () => getState(\"activeStep\"),\n    getActiveElement: () => getState(\"activeElement\"),\n    getPreviousElement: () => getState(\"previousElement\"),\n    getPreviousStep: () => getState(\"previousStep\"),\n    moveNext,\n    movePrevious,\n    moveTo,\n    hasNextStep: () => {\n      const steps = getConfig(\"steps\") || [];\n      const activeIndex = getState(\"activeIndex\");\n\n      return activeIndex !== undefined && !!steps[activeIndex + 1];\n    },\n    hasPreviousStep: () => {\n      const steps = getConfig(\"steps\") || [];\n      const activeIndex = getState(\"activeIndex\");\n\n      return activeIndex !== undefined && !!steps[activeIndex - 1];\n    },\n    highlight: (step: DriveStep) => {\n      init();\n      highlight({\n        ...step,\n        popover: step.popover\n          ? {\n              showButtons: [],\n              showProgress: false,\n              progressText: \"\",\n              ...step.popover!,\n            }\n          : undefined,\n      });\n    },\n    destroy: () => {\n      destroy(false);\n    },\n  };\n\n  setCurrentDriver(api);\n\n  return api;\n}\n"
  },
  {
    "path": "src/emitter.ts",
    "content": "type allowedEvents =\n  | \"overlayClick\"\n  | \"escapePress\"\n  | \"nextClick\"\n  | \"prevClick\"\n  | \"closeClick\"\n  | \"arrowRightPress\"\n  | \"arrowLeftPress\";\n\nlet registeredListeners: Partial<{ [key in allowedEvents]: () => void }> = {};\n\nexport function listen(hook: allowedEvents, callback: () => void) {\n  registeredListeners[hook] = callback;\n}\n\nexport function emit(hook: allowedEvents) {\n  registeredListeners[hook]?.();\n}\n\nexport function destroyEmitter() {\n  registeredListeners = {};\n}\n"
  },
  {
    "path": "src/events.ts",
    "content": "import { refreshActiveHighlight } from \"./highlight\";\nimport { emit } from \"./emitter\";\nimport { getState, setState } from \"./state\";\nimport { getConfig } from \"./config\";\nimport { getFocusableElements } from \"./utils\";\n\nexport function requireRefresh() {\n  const resizeTimeout = getState(\"__resizeTimeout\");\n  if (resizeTimeout) {\n    window.cancelAnimationFrame(resizeTimeout);\n  }\n\n  setState(\"__resizeTimeout\", window.requestAnimationFrame(refreshActiveHighlight));\n}\n\nfunction trapFocus(e: KeyboardEvent) {\n  const isActivated = getState(\"isInitialized\");\n  if (!isActivated) {\n    return;\n  }\n\n  const isTabKey = e.key === \"Tab\" || e.keyCode === 9;\n  if (!isTabKey) {\n    return;\n  }\n\n  const activeElement = getState(\"__activeElement\");\n  const popoverEl = getState(\"popover\")?.wrapper;\n\n  const focusableEls = getFocusableElements([\n    ...(popoverEl ? [popoverEl] : []),\n    ...(activeElement ? [activeElement] : []),\n  ]);\n\n  const firstFocusableEl = focusableEls[0];\n  const lastFocusableEl = focusableEls[focusableEls.length - 1];\n\n  e.preventDefault();\n\n  if (e.shiftKey) {\n    const previousFocusableEl =\n      focusableEls[focusableEls.indexOf(document.activeElement as HTMLElement) - 1] || lastFocusableEl;\n    previousFocusableEl?.focus();\n  } else {\n    const nextFocusableEl =\n      focusableEls[focusableEls.indexOf(document.activeElement as HTMLElement) + 1] || firstFocusableEl;\n    nextFocusableEl?.focus();\n  }\n}\n\nfunction onKeyup(e: KeyboardEvent) {\n  const allowKeyboardControl = getConfig(\"allowKeyboardControl\") ?? true;\n\n  if (!allowKeyboardControl) {\n    return;\n  }\n\n  if (e.key === \"Escape\") {\n    emit(\"escapePress\");\n  } else if (e.key === \"ArrowRight\") {\n    emit(\"arrowRightPress\");\n  } else if (e.key === \"ArrowLeft\") {\n    emit(\"arrowLeftPress\");\n  }\n}\n\n/**\n * Attaches click handler to the elements created by driver.js. It makes\n * sure to give the listener the first chance to handle the event, and\n * prevents all other pointer-events to make sure no external-library\n * ever knows the click happened.\n *\n * @param {Element} element Element to listen for click events\n * @param {(pointer: MouseEvent | PointerEvent) => void} listener Click handler\n * @param {(target: HTMLElement) => boolean} shouldPreventDefault Whether to prevent default action i.e. link clicks etc\n */\nexport function onDriverClick(\n  element: Element,\n  listener: (pointer: MouseEvent | PointerEvent) => void,\n  shouldPreventDefault?: (target: HTMLElement) => boolean\n) {\n  const listenerWrapper = (e: MouseEvent | PointerEvent, listener?: (pointer: MouseEvent | PointerEvent) => void) => {\n    const target = e.target as HTMLElement;\n    if (!element.contains(target)) {\n      return;\n    }\n\n    if (!shouldPreventDefault || shouldPreventDefault(target)) {\n      e.preventDefault();\n      e.stopPropagation();\n      e.stopImmediatePropagation();\n    }\n\n    listener?.(e);\n  };\n\n  // We want to be the absolute first one to hear about the event\n  const useCapture = true;\n\n  // Events to disable\n  document.addEventListener(\"pointerdown\", listenerWrapper, useCapture);\n  document.addEventListener(\"mousedown\", listenerWrapper, useCapture);\n  document.addEventListener(\"pointerup\", listenerWrapper, useCapture);\n  document.addEventListener(\"mouseup\", listenerWrapper, useCapture);\n\n  // Actual click handler\n  document.addEventListener(\n    \"click\",\n    e => {\n      listenerWrapper(e, listener);\n    },\n    useCapture\n  );\n}\n\nexport function initEvents() {\n  window.addEventListener(\"keyup\", onKeyup, false);\n  window.addEventListener(\"keydown\", trapFocus, false);\n  window.addEventListener(\"resize\", requireRefresh);\n  window.addEventListener(\"scroll\", requireRefresh);\n}\n\nexport function destroyEvents() {\n  window.removeEventListener(\"keyup\", onKeyup);\n  window.removeEventListener(\"resize\", requireRefresh);\n  window.removeEventListener(\"scroll\", requireRefresh);\n}\n"
  },
  {
    "path": "src/highlight.ts",
    "content": "import { DriveStep } from \"./driver\";\nimport { refreshOverlay, trackActiveElement, transitionStage } from \"./overlay\";\nimport { getConfig, getCurrentDriver } from \"./config\";\nimport { hidePopover, renderPopover, repositionPopover } from \"./popover\";\nimport { bringInView } from \"./utils\";\nimport { getState, setState } from \"./state\";\n\nfunction mountDummyElement(): Element {\n  const existingDummy = document.getElementById(\"driver-dummy-element\");\n  if (existingDummy) {\n    return existingDummy;\n  }\n\n  let element = document.createElement(\"div\");\n\n  element.id = \"driver-dummy-element\";\n  element.style.width = \"0\";\n  element.style.height = \"0\";\n  element.style.pointerEvents = \"none\";\n  element.style.opacity = \"0\";\n  element.style.position = \"fixed\";\n  element.style.top = \"50%\";\n  element.style.left = \"50%\";\n\n  document.body.appendChild(element);\n\n  return element;\n}\n\nexport function highlight(step: DriveStep) {\n  const { element } = step;\n  let elemObj =\n    typeof element === \"function\" ? element() : typeof element === \"string\" ? document.querySelector(element) : element;\n\n  // If the element is not found, we mount a 1px div\n  // at the center of the screen to highlight and show\n  // the popover on top of that. This is to show a\n  // modal-like highlight.\n  if (!elemObj) {\n    elemObj = mountDummyElement();\n  }\n\n  transferHighlight(elemObj, step);\n}\n\nexport function refreshActiveHighlight() {\n  const activeHighlight = getState(\"__activeElement\");\n  const activeStep = getState(\"__activeStep\")!;\n\n  if (!activeHighlight) {\n    return;\n  }\n\n  trackActiveElement(activeHighlight);\n  refreshOverlay();\n  repositionPopover(activeHighlight, activeStep);\n}\n\nfunction transferHighlight(toElement: Element, toStep: DriveStep) {\n  const duration = 400;\n  const start = Date.now();\n\n  const fromStep = getState(\"__activeStep\");\n  const fromElement = getState(\"__activeElement\") || toElement;\n\n  // If it's the first time we're highlighting an element, we show\n  // the popover immediately. Otherwise, we wait for the animation\n  // to finish before showing the popover.\n  const isFirstHighlight = !fromElement || fromElement === toElement;\n  const isToDummyElement = toElement.id === \"driver-dummy-element\";\n  const isFromDummyElement = fromElement.id === \"driver-dummy-element\";\n\n  const isAnimatedTour = getConfig(\"animate\");\n  const highlightStartedHook = toStep.onHighlightStarted || getConfig(\"onHighlightStarted\");\n  const highlightedHook = toStep?.onHighlighted || getConfig(\"onHighlighted\");\n  const deselectedHook = fromStep?.onDeselected || getConfig(\"onDeselected\");\n\n  const config = getConfig();\n  const state = getState();\n\n  if (!isFirstHighlight && deselectedHook) {\n    deselectedHook(isFromDummyElement ? undefined : fromElement, fromStep!, {\n      config,\n      state,\n      driver: getCurrentDriver(),\n    });\n  }\n\n  if (highlightStartedHook) {\n    highlightStartedHook(isToDummyElement ? undefined : toElement, toStep, {\n      config,\n      state,\n      driver: getCurrentDriver(),\n    });\n  }\n\n  const hasDelayedPopover = !isFirstHighlight && isAnimatedTour;\n  let isPopoverRendered = false;\n\n  hidePopover();\n\n  setState(\"previousStep\", fromStep);\n  setState(\"previousElement\", fromElement);\n  setState(\"activeStep\", toStep);\n  setState(\"activeElement\", toElement);\n\n  const animate = () => {\n    const transitionCallback = getState(\"__transitionCallback\");\n\n    // This makes sure that the repeated calls to transferHighlight\n    // don't interfere with each other. Only the last call will be\n    // executed.\n    if (transitionCallback !== animate) {\n      return;\n    }\n\n    const elapsed = Date.now() - start;\n    const timeRemaining = duration - elapsed;\n    const isHalfwayThrough = timeRemaining <= duration / 2;\n\n    if (toStep.popover && isHalfwayThrough && !isPopoverRendered && hasDelayedPopover) {\n      renderPopover(toElement, toStep);\n      isPopoverRendered = true;\n    }\n\n    if (getConfig(\"animate\") && elapsed < duration) {\n      transitionStage(elapsed, duration, fromElement, toElement);\n    } else {\n      trackActiveElement(toElement);\n\n      if (highlightedHook) {\n        highlightedHook(isToDummyElement ? undefined : toElement, toStep, {\n          config: getConfig(),\n          state: getState(),\n          driver: getCurrentDriver(),\n        });\n      }\n\n      setState(\"__transitionCallback\", undefined);\n      setState(\"__previousStep\", fromStep);\n      setState(\"__previousElement\", fromElement);\n      setState(\"__activeStep\", toStep);\n      setState(\"__activeElement\", toElement);\n    }\n\n    window.requestAnimationFrame(animate);\n  };\n\n  setState(\"__transitionCallback\", animate);\n\n  window.requestAnimationFrame(animate);\n\n  bringInView(toElement);\n  if (!hasDelayedPopover && toStep.popover) {\n    renderPopover(toElement, toStep);\n  }\n\n  fromElement.classList.remove(\"driver-active-element\", \"driver-no-interaction\");\n  fromElement.removeAttribute(\"aria-haspopup\");\n  fromElement.removeAttribute(\"aria-expanded\");\n  fromElement.removeAttribute(\"aria-controls\");\n\n  const disableActiveInteraction = toStep.disableActiveInteraction ?? getConfig(\"disableActiveInteraction\");\n  if (disableActiveInteraction) {\n    toElement.classList.add(\"driver-no-interaction\");\n  }\n\n  toElement.classList.add(\"driver-active-element\");\n  toElement.setAttribute(\"aria-haspopup\", \"dialog\");\n  toElement.setAttribute(\"aria-expanded\", \"true\");\n  toElement.setAttribute(\"aria-controls\", \"driver-popover-content\");\n}\n\nexport function destroyHighlight() {\n  document.getElementById(\"driver-dummy-element\")?.remove();\n  document.querySelectorAll(\".driver-active-element\").forEach(element => {\n    element.classList.remove(\"driver-active-element\", \"driver-no-interaction\");\n    element.removeAttribute(\"aria-haspopup\");\n    element.removeAttribute(\"aria-expanded\");\n    element.removeAttribute(\"aria-controls\");\n  });\n}\n"
  },
  {
    "path": "src/overlay.ts",
    "content": "import { easeInOutQuad } from \"./utils\";\nimport { onDriverClick } from \"./events\";\nimport { emit } from \"./emitter\";\nimport { getConfig } from \"./config\";\nimport { getState, setState } from \"./state\";\n\nexport type StageDefinition = {\n  x: number;\n  y: number;\n  width: number;\n  height: number;\n};\n\n// This method calculates the animated new position of the\n// stage (called for each frame by requestAnimationFrame)\nexport function transitionStage(elapsed: number, duration: number, from: Element, to: Element) {\n  let activeStagePosition = getState(\"__activeStagePosition\");\n\n  const fromDefinition = activeStagePosition ? activeStagePosition : from.getBoundingClientRect();\n  const toDefinition = to.getBoundingClientRect();\n\n  const x = easeInOutQuad(elapsed, fromDefinition.x, toDefinition.x - fromDefinition.x, duration);\n  const y = easeInOutQuad(elapsed, fromDefinition.y, toDefinition.y - fromDefinition.y, duration);\n  const width = easeInOutQuad(elapsed, fromDefinition.width, toDefinition.width - fromDefinition.width, duration);\n  const height = easeInOutQuad(elapsed, fromDefinition.height, toDefinition.height - fromDefinition.height, duration);\n\n  activeStagePosition = {\n    x,\n    y,\n    width,\n    height,\n  };\n\n  renderOverlay(activeStagePosition);\n  setState(\"__activeStagePosition\", activeStagePosition);\n}\n\nexport function trackActiveElement(element: Element) {\n  if (!element) {\n    return;\n  }\n\n  const definition = element.getBoundingClientRect();\n\n  const activeStagePosition: StageDefinition = {\n    x: definition.x,\n    y: definition.y,\n    width: definition.width,\n    height: definition.height,\n  };\n\n  setState(\"__activeStagePosition\", activeStagePosition);\n\n  renderOverlay(activeStagePosition);\n}\n\nexport function refreshOverlay() {\n  const activeStagePosition = getState(\"__activeStagePosition\");\n  const overlaySvg = getState(\"__overlaySvg\");\n\n  if (!activeStagePosition) {\n    return;\n  }\n\n  if (!overlaySvg) {\n    console.warn(\"No stage svg found.\");\n    return;\n  }\n\n  const windowX = window.innerWidth;\n  const windowY = window.innerHeight;\n\n  overlaySvg.setAttribute(\"viewBox\", `0 0 ${windowX} ${windowY}`);\n}\n\nfunction mountOverlay(stagePosition: StageDefinition) {\n  const overlaySvg = createOverlaySvg(stagePosition);\n  document.body.appendChild(overlaySvg);\n\n  onDriverClick(overlaySvg, e => {\n    const target = e.target as SVGElement;\n    if (target.tagName !== \"path\") {\n      return;\n    }\n\n    emit(\"overlayClick\");\n  });\n\n  setState(\"__overlaySvg\", overlaySvg);\n}\n\nfunction renderOverlay(stagePosition: StageDefinition) {\n  const overlaySvg = getState(\"__overlaySvg\");\n\n  // TODO: cancel rendering if element is not visible\n  if (!overlaySvg) {\n    mountOverlay(stagePosition);\n\n    return;\n  }\n\n  const pathElement = overlaySvg.firstElementChild as SVGPathElement | null;\n  if (pathElement?.tagName !== \"path\") {\n    throw new Error(\"no path element found in stage svg\");\n  }\n\n  pathElement.setAttribute(\"d\", generateStageSvgPathString(stagePosition));\n}\n\nfunction createOverlaySvg(stage: StageDefinition): SVGSVGElement {\n  const windowX = window.innerWidth;\n  const windowY = window.innerHeight;\n\n  const svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n  svg.classList.add(\"driver-overlay\", \"driver-overlay-animated\");\n\n  svg.setAttribute(\"viewBox\", `0 0 ${windowX} ${windowY}`);\n  svg.setAttribute(\"xmlSpace\", \"preserve\");\n  svg.setAttribute(\"xmlnsXlink\", \"http://www.w3.org/1999/xlink\");\n  svg.setAttribute(\"version\", \"1.1\");\n  svg.setAttribute(\"preserveAspectRatio\", \"xMinYMin slice\");\n\n  svg.style.fillRule = \"evenodd\";\n  svg.style.clipRule = \"evenodd\";\n  svg.style.strokeLinejoin = \"round\";\n  svg.style.strokeMiterlimit = \"2\";\n  svg.style.zIndex = \"10000\";\n  svg.style.position = \"fixed\";\n  svg.style.top = \"0\";\n  svg.style.left = \"0\";\n  svg.style.width = \"100%\";\n  svg.style.height = \"100%\";\n\n  const stagePath = document.createElementNS(\"http://www.w3.org/2000/svg\", \"path\");\n\n  stagePath.setAttribute(\"d\", generateStageSvgPathString(stage));\n\n  stagePath.style.fill = getConfig(\"overlayColor\") || \"rgb(0,0,0)\";\n  stagePath.style.opacity = `${getConfig(\"overlayOpacity\")}`;\n  stagePath.style.pointerEvents = \"auto\";\n  stagePath.style.cursor = \"auto\";\n\n  svg.appendChild(stagePath);\n\n  return svg;\n}\n\nfunction generateStageSvgPathString(stage: StageDefinition) {\n  const windowX = window.innerWidth;\n  const windowY = window.innerHeight;\n\n  const stagePadding = getConfig(\"stagePadding\") || 0;\n  const stageRadius = getConfig(\"stageRadius\") || 0;\n\n  const stageWidth = stage.width + stagePadding * 2;\n  const stageHeight = stage.height + stagePadding * 2;\n\n  // prevent glitches when stage is too small for radius\n  const limitedRadius = Math.min(stageRadius, stageWidth / 2, stageHeight / 2);\n\n  // no value below 0 allowed + round down\n  const normalizedRadius = Math.floor(Math.max(limitedRadius, 0));\n\n  const highlightBoxX = stage.x - stagePadding + normalizedRadius;\n  const highlightBoxY = stage.y - stagePadding;\n  const highlightBoxWidth = stageWidth - normalizedRadius * 2;\n  const highlightBoxHeight = stageHeight - normalizedRadius * 2;\n\n  return `M${windowX},0L0,0L0,${windowY}L${windowX},${windowY}L${windowX},0Z\n    M${highlightBoxX},${highlightBoxY} h${highlightBoxWidth} a${normalizedRadius},${normalizedRadius} 0 0 1 ${normalizedRadius},${normalizedRadius} v${highlightBoxHeight} a${normalizedRadius},${normalizedRadius} 0 0 1 -${normalizedRadius},${normalizedRadius} h-${highlightBoxWidth} a${normalizedRadius},${normalizedRadius} 0 0 1 -${normalizedRadius},-${normalizedRadius} v-${highlightBoxHeight} a${normalizedRadius},${normalizedRadius} 0 0 1 ${normalizedRadius},-${normalizedRadius} z`;\n}\n\nexport function destroyOverlay() {\n  const overlaySvg = getState(\"__overlaySvg\");\n  if (overlaySvg) {\n    overlaySvg.remove();\n  }\n}\n"
  },
  {
    "path": "src/popover.ts",
    "content": "import { Config, DriverHook, getConfig, getCurrentDriver } from \"./config\";\nimport { Driver, DriveStep } from \"./driver\";\nimport { emit } from \"./emitter\";\nimport { onDriverClick } from \"./events\";\nimport { getState, setState, State } from \"./state\";\nimport { bringInView, getFocusableElements } from \"./utils\";\n\nexport type Side = \"top\" | \"right\" | \"bottom\" | \"left\" | \"over\";\nexport type Alignment = \"start\" | \"center\" | \"end\";\nexport type AllowedButtons = \"next\" | \"previous\" | \"close\";\n\nexport type Popover = {\n  title?: string;\n  description?: string;\n  side?: Side;\n  align?: Alignment;\n\n  showButtons?: AllowedButtons[];\n  showProgress?: boolean;\n  disableButtons?: AllowedButtons[];\n\n  popoverClass?: string;\n\n  // Button texts\n  progressText?: string;\n  doneBtnText?: string;\n  nextBtnText?: string;\n  prevBtnText?: string;\n\n  // Called after the popover is rendered\n  onPopoverRender?: (popover: PopoverDOM, opts: { config: Config; state: State; driver: Driver }) => void;\n\n  // Button callbacks\n  onNextClick?: DriverHook;\n  onPrevClick?: DriverHook;\n  onCloseClick?: DriverHook;\n};\n\nexport type PopoverDOM = {\n  wrapper: HTMLElement;\n  arrow: HTMLElement;\n  title: HTMLElement;\n  description: HTMLElement;\n  footer: HTMLElement;\n  progress: HTMLElement;\n  previousButton: HTMLButtonElement;\n  nextButton: HTMLButtonElement;\n  closeButton: HTMLButtonElement;\n  footerButtons: HTMLElement;\n};\n\nexport function hidePopover() {\n  const popover = getState(\"popover\");\n  if (!popover) {\n    return;\n  }\n\n  popover.wrapper.style.display = \"none\";\n}\n\nexport function renderPopover(element: Element, step: DriveStep) {\n  let popover = getState(\"popover\");\n  if (popover) {\n    document.body.removeChild(popover.wrapper);\n  }\n\n  popover = createPopover();\n  document.body.appendChild(popover.wrapper);\n\n  const {\n    title,\n    description,\n    showButtons,\n    disableButtons,\n    showProgress,\n\n    nextBtnText = getConfig(\"nextBtnText\") || \"Next &rarr;\",\n    prevBtnText = getConfig(\"prevBtnText\") || \"&larr; Previous\",\n    progressText = getConfig(\"progressText\") || \"{current} of {total}\",\n  } = step.popover || {};\n\n  popover.nextButton.innerHTML = nextBtnText;\n  popover.previousButton.innerHTML = prevBtnText;\n  popover.progress.innerHTML = progressText;\n\n  if (title) {\n    popover.title.innerHTML = title;\n    popover.title.style.display = \"block\";\n  } else {\n    popover.title.style.display = \"none\";\n  }\n\n  if (description) {\n    popover.description.innerHTML = description;\n    popover.description.style.display = \"block\";\n  } else {\n    popover.description.style.display = \"none\";\n  }\n\n  const showButtonsConfig: AllowedButtons[] = showButtons || getConfig(\"showButtons\")!;\n  const showProgressConfig = showProgress || getConfig(\"showProgress\") || false;\n  const showFooter =\n    showButtonsConfig?.includes(\"next\") || showButtonsConfig?.includes(\"previous\") || showProgressConfig;\n\n  popover.closeButton.style.display = showButtonsConfig.includes(\"close\") ? \"block\" : \"none\";\n\n  if (showFooter) {\n    popover.footer.style.display = \"flex\";\n\n    popover.progress.style.display = showProgressConfig ? \"block\" : \"none\";\n    popover.nextButton.style.display = showButtonsConfig.includes(\"next\") ? \"block\" : \"none\";\n    popover.previousButton.style.display = showButtonsConfig.includes(\"previous\") ? \"block\" : \"none\";\n  } else {\n    popover.footer.style.display = \"none\";\n  }\n\n  const disabledButtonsConfig: AllowedButtons[] = disableButtons || getConfig(\"disableButtons\")! || [];\n  if (disabledButtonsConfig?.includes(\"next\")) {\n    popover.nextButton.disabled = true;\n    popover.nextButton.classList.add(\"driver-popover-btn-disabled\");\n  }\n\n  if (disabledButtonsConfig?.includes(\"previous\")) {\n    popover.previousButton.disabled = true;\n    popover.previousButton.classList.add(\"driver-popover-btn-disabled\");\n  }\n\n  if (disabledButtonsConfig?.includes(\"close\")) {\n    popover.closeButton.disabled = true;\n    popover.closeButton.classList.add(\"driver-popover-btn-disabled\");\n  }\n\n  // Reset the popover position\n  const popoverWrapper = popover.wrapper;\n  popoverWrapper.style.display = \"block\";\n  popoverWrapper.style.left = \"\";\n  popoverWrapper.style.top = \"\";\n  popoverWrapper.style.bottom = \"\";\n  popoverWrapper.style.right = \"\";\n\n  popoverWrapper.id = \"driver-popover-content\";\n  popoverWrapper.setAttribute(\"role\", \"dialog\");\n  popoverWrapper.setAttribute(\"aria-labelledby\", \"driver-popover-title\");\n  popoverWrapper.setAttribute(\"aria-describedby\", \"driver-popover-description\");\n\n  // Reset the classes responsible for the arrow position\n  const popoverArrow = popover.arrow;\n  popoverArrow.className = \"driver-popover-arrow\";\n\n  // Reset any custom classes on the popover\n  const customPopoverClass = step.popover?.popoverClass || getConfig(\"popoverClass\") || \"\";\n  popoverWrapper.className = `driver-popover ${customPopoverClass}`.trim();\n\n  // Handles the popover button clicks\n  onDriverClick(\n    popover.wrapper,\n    e => {\n      const target = e.target as HTMLElement;\n\n      const onNextClick = step.popover?.onNextClick || getConfig(\"onNextClick\");\n      const onPrevClick = step.popover?.onPrevClick || getConfig(\"onPrevClick\");\n      const onCloseClick = step.popover?.onCloseClick || getConfig(\"onCloseClick\");\n\n      if (!!target.closest(\".driver-popover-next-btn\")) {\n        // If the user has provided a custom callback, call it\n        // otherwise, emit the event.\n        if (onNextClick) {\n          return onNextClick(element, step, {\n            config: getConfig(),\n            state: getState(),\n            driver: getCurrentDriver(),\n          });\n        } else {\n          return emit(\"nextClick\");\n        }\n      }\n\n      if (!!target.closest(\".driver-popover-prev-btn\")) {\n        if (onPrevClick) {\n          return onPrevClick(element, step, {\n            config: getConfig(),\n            state: getState(),\n            driver: getCurrentDriver(),\n          });\n        } else {\n          return emit(\"prevClick\");\n        }\n      }\n\n      if (!!target.closest(\".driver-popover-close-btn\")) {\n        if (onCloseClick) {\n          return onCloseClick(element, step, {\n            config: getConfig(),\n            state: getState(),\n            driver: getCurrentDriver(),\n          });\n        } else {\n          return emit(\"closeClick\");\n        }\n      }\n\n      return undefined;\n    },\n    target => {\n      // Only prevent the default action if we're clicking on a driver button\n      // This allows us to have links inside the popover title and description\n      return (\n        !popover?.description.contains(target) &&\n        !popover?.title.contains(target) &&\n        typeof target.className === \"string\" &&\n        target.className.includes(\"driver-popover\")\n      );\n    }\n  );\n\n  setState(\"popover\", popover);\n\n  const onPopoverRender = step.popover?.onPopoverRender || getConfig(\"onPopoverRender\");\n  if (onPopoverRender) {\n    onPopoverRender(popover, {\n      config: getConfig(),\n      state: getState(),\n      driver: getCurrentDriver(),\n    });\n  }\n\n  repositionPopover(element, step);\n  bringInView(popoverWrapper);\n\n  // Focus on the first focusable element in active element or popover\n  const isToDummyElement = element.classList.contains(\"driver-dummy-element\");\n  const focusableElement = getFocusableElements([popoverWrapper, ...(isToDummyElement ? [] : [element])]);\n  if (focusableElement.length > 0) {\n    focusableElement[0].focus();\n  }\n}\n\ntype PopoverDimensions = {\n  width: number;\n  height: number;\n  realWidth: number;\n  realHeight: number;\n};\n\nfunction getPopoverDimensions(): PopoverDimensions | undefined {\n  const popover = getState(\"popover\");\n  if (!popover?.wrapper) {\n    return;\n  }\n\n  const boundingClientRect = popover.wrapper.getBoundingClientRect();\n\n  const stagePadding = getConfig(\"stagePadding\") || 0;\n  const popoverOffset = getConfig(\"popoverOffset\") || 0;\n\n  return {\n    width: boundingClientRect.width + stagePadding + popoverOffset,\n    height: boundingClientRect.height + stagePadding + popoverOffset,\n\n    realWidth: boundingClientRect.width,\n    realHeight: boundingClientRect.height,\n  };\n}\n\nfunction calculateTopForLeftRight(\n  alignment: Alignment,\n  config: {\n    elementDimensions: DOMRect;\n    popoverDimensions: PopoverDimensions;\n    popoverPadding: number;\n    popoverArrowDimensions: { width: number; height: number };\n  }\n): number {\n  const { elementDimensions, popoverDimensions, popoverPadding, popoverArrowDimensions } = config;\n\n  if (alignment === \"start\") {\n    return Math.max(\n      Math.min(\n        elementDimensions.top - popoverPadding,\n        window.innerHeight - popoverDimensions!.realHeight - popoverArrowDimensions.width\n      ),\n      popoverArrowDimensions.width\n    );\n  }\n\n  if (alignment === \"end\") {\n    return Math.max(\n      Math.min(\n        elementDimensions.top - popoverDimensions?.realHeight + elementDimensions.height + popoverPadding,\n        window.innerHeight - popoverDimensions?.realHeight - popoverArrowDimensions.width\n      ),\n      popoverArrowDimensions.width\n    );\n  }\n\n  if (alignment === \"center\") {\n    return Math.max(\n      Math.min(\n        elementDimensions.top + elementDimensions.height / 2 - popoverDimensions?.realHeight / 2,\n        window.innerHeight - popoverDimensions?.realHeight - popoverArrowDimensions.width\n      ),\n      popoverArrowDimensions.width\n    );\n  }\n\n  return 0;\n}\n\n// Calculate the left placement for top and bottom sides\nfunction calculateLeftForTopBottom(\n  alignment: Alignment,\n  config: {\n    elementDimensions: DOMRect;\n    popoverDimensions: PopoverDimensions;\n    popoverPadding: number;\n    popoverArrowDimensions: { width: number; height: number };\n  }\n): number {\n  const { elementDimensions, popoverDimensions, popoverPadding, popoverArrowDimensions } = config;\n\n  if (alignment === \"start\") {\n    return Math.max(\n      Math.min(\n        elementDimensions.left - popoverPadding,\n        window.innerWidth - popoverDimensions!.realWidth - popoverArrowDimensions.width\n      ),\n      popoverArrowDimensions.width\n    );\n  }\n\n  if (alignment === \"end\") {\n    return Math.max(\n      Math.min(\n        elementDimensions.left - popoverDimensions?.realWidth + elementDimensions.width + popoverPadding,\n        window.innerWidth - popoverDimensions?.realWidth - popoverArrowDimensions.width\n      ),\n      popoverArrowDimensions.width\n    );\n  }\n\n  if (alignment === \"center\") {\n    return Math.max(\n      Math.min(\n        elementDimensions.left + elementDimensions.width / 2 - popoverDimensions?.realWidth / 2,\n        window.innerWidth - popoverDimensions?.realWidth - popoverArrowDimensions.width\n      ),\n      popoverArrowDimensions.width\n    );\n  }\n\n  return 0;\n}\n\nexport function repositionPopover(element: Element, step: DriveStep) {\n  const popover = getState(\"popover\");\n  if (!popover) {\n    return;\n  }\n\n  const { align = \"start\", side = \"left\" } = step?.popover || {};\n\n  // Configure the popover positioning\n  const requiredAlignment: Alignment = align;\n  const requiredSide: Side = element.id === \"driver-dummy-element\" ? \"over\" : side;\n  const popoverPadding = getConfig(\"stagePadding\") || 0;\n\n  const popoverDimensions = getPopoverDimensions()!;\n  const popoverArrowDimensions = popover.arrow.getBoundingClientRect();\n  const elementDimensions = element.getBoundingClientRect();\n\n  const topValue = elementDimensions.top - popoverDimensions!.height;\n  let isTopOptimal = topValue >= 0;\n\n  const bottomValue = window.innerHeight - (elementDimensions.bottom + popoverDimensions!.height);\n  let isBottomOptimal = bottomValue >= 0;\n\n  const leftValue = elementDimensions.left - popoverDimensions!.width;\n  let isLeftOptimal = leftValue >= 0;\n\n  const rightValue = window.innerWidth - (elementDimensions.right + popoverDimensions!.width);\n  let isRightOptimal = rightValue >= 0;\n\n  const noneOptimal = !isTopOptimal && !isBottomOptimal && !isLeftOptimal && !isRightOptimal;\n  let popoverRenderedSide: Side = requiredSide;\n\n  if (requiredSide === \"top\" && isTopOptimal) {\n    isRightOptimal = isLeftOptimal = isBottomOptimal = false;\n  } else if (requiredSide === \"bottom\" && isBottomOptimal) {\n    isRightOptimal = isLeftOptimal = isTopOptimal = false;\n  } else if (requiredSide === \"left\" && isLeftOptimal) {\n    isRightOptimal = isTopOptimal = isBottomOptimal = false;\n  } else if (requiredSide === \"right\" && isRightOptimal) {\n    isLeftOptimal = isTopOptimal = isBottomOptimal = false;\n  }\n\n  if (requiredSide === \"over\") {\n    const leftToSet = window.innerWidth / 2 - popoverDimensions!.realWidth / 2;\n    const topToSet = window.innerHeight / 2 - popoverDimensions!.realHeight / 2;\n\n    popover.wrapper.style.left = `${leftToSet}px`;\n    popover.wrapper.style.right = `auto`;\n    popover.wrapper.style.top = `${topToSet}px`;\n    popover.wrapper.style.bottom = `auto`;\n  } else if (noneOptimal) {\n    const leftValue = window.innerWidth / 2 - popoverDimensions?.realWidth! / 2;\n    const bottomValue = 10;\n\n    popover.wrapper.style.left = `${leftValue}px`;\n    popover.wrapper.style.right = `auto`;\n    popover.wrapper.style.bottom = `${bottomValue}px`;\n    popover.wrapper.style.top = `auto`;\n  } else if (isLeftOptimal) {\n    const leftToSet = Math.min(\n      leftValue,\n      window.innerWidth - popoverDimensions?.realWidth - popoverArrowDimensions.width\n    );\n\n    const topToSet = calculateTopForLeftRight(requiredAlignment, {\n      elementDimensions,\n      popoverDimensions,\n      popoverPadding,\n      popoverArrowDimensions,\n    });\n\n    popover.wrapper.style.left = `${leftToSet}px`;\n    popover.wrapper.style.top = `${topToSet}px`;\n    popover.wrapper.style.bottom = `auto`;\n    popover.wrapper.style.right = \"auto\";\n\n    popoverRenderedSide = \"left\";\n  } else if (isRightOptimal) {\n    const rightToSet = Math.min(\n      rightValue,\n      window.innerWidth - popoverDimensions?.realWidth - popoverArrowDimensions.width\n    );\n    const topToSet = calculateTopForLeftRight(requiredAlignment, {\n      elementDimensions,\n      popoverDimensions,\n      popoverPadding,\n      popoverArrowDimensions,\n    });\n\n    popover.wrapper.style.right = `${rightToSet}px`;\n    popover.wrapper.style.top = `${topToSet}px`;\n    popover.wrapper.style.bottom = `auto`;\n    popover.wrapper.style.left = \"auto\";\n\n    popoverRenderedSide = \"right\";\n  } else if (isTopOptimal) {\n    const topToSet = Math.min(\n      topValue,\n      window.innerHeight - popoverDimensions!.realHeight - popoverArrowDimensions.width\n    );\n    let leftToSet = calculateLeftForTopBottom(requiredAlignment, {\n      elementDimensions,\n      popoverDimensions,\n      popoverPadding,\n      popoverArrowDimensions,\n    });\n\n    popover.wrapper.style.top = `${topToSet}px`;\n    popover.wrapper.style.left = `${leftToSet}px`;\n    popover.wrapper.style.bottom = `auto`;\n    popover.wrapper.style.right = \"auto\";\n\n    popoverRenderedSide = \"top\";\n  } else if (isBottomOptimal) {\n    const bottomToSet = Math.min(\n      bottomValue,\n      window.innerHeight - popoverDimensions?.realHeight - popoverArrowDimensions.width\n    );\n\n    let leftToSet = calculateLeftForTopBottom(requiredAlignment, {\n      elementDimensions,\n      popoverDimensions,\n      popoverPadding,\n      popoverArrowDimensions,\n    });\n\n    popover.wrapper.style.left = `${leftToSet}px`;\n    popover.wrapper.style.bottom = `${bottomToSet}px`;\n    popover.wrapper.style.top = `auto`;\n    popover.wrapper.style.right = \"auto\";\n\n    popoverRenderedSide = \"bottom\";\n  }\n\n  // Popover stays on the screen if the element scrolls out of the visible area.\n  // Render the arrow again to make sure it's in the correct position\n  // e.g. if element scrolled out of the screen to the top, the arrow should be rendered\n  // pointing to the top. If the element scrolled out of the screen to the bottom,\n  // the arrow should be rendered pointing to the bottom.\n  if (!noneOptimal) {\n    renderPopoverArrow(requiredAlignment, popoverRenderedSide, element);\n  } else {\n    popover.arrow.classList.add(\"driver-popover-arrow-none\");\n  }\n}\n\nfunction renderPopoverArrow(alignment: Alignment, side: Side, element: Element) {\n  const popover = getState(\"popover\");\n  if (!popover) {\n    return;\n  }\n\n  const elementDimensions = element.getBoundingClientRect();\n  const popoverDimensions = getPopoverDimensions()!;\n  const popoverArrow = popover.arrow;\n\n  const popoverWidth = popoverDimensions.width;\n  const windowWidth = window.innerWidth;\n  const elementWidth = elementDimensions.width;\n  const elementLeft = elementDimensions.left;\n\n  const popoverHeight = popoverDimensions.height;\n  const windowHeight = window.innerHeight;\n  const elementTop = elementDimensions.top;\n  const elementHeight = elementDimensions.height;\n\n  // Remove all arrow classes\n  popoverArrow.className = \"driver-popover-arrow\";\n\n  let arrowSide = side;\n  let arrowAlignment = alignment;\n\n  if (side === \"top\") {\n    if (elementLeft + elementWidth <= 0) {\n      arrowSide = \"right\";\n      arrowAlignment = \"end\";\n    } else if (elementLeft + elementWidth - popoverWidth <= 0) {\n      arrowSide = \"top\";\n      arrowAlignment = \"start\";\n    }\n    if (elementLeft >= windowWidth) {\n      arrowSide = \"left\";\n      arrowAlignment = \"end\";\n    } else if (elementLeft + popoverWidth >= windowWidth) {\n      arrowSide = \"top\";\n      arrowAlignment = \"end\";\n    }\n  } else if (side === \"bottom\") {\n    if (elementLeft + elementWidth <= 0) {\n      arrowSide = \"right\";\n      arrowAlignment = \"start\";\n    } else if (elementLeft + elementWidth - popoverWidth <= 0) {\n      arrowSide = \"bottom\";\n      arrowAlignment = \"start\";\n    }\n    if (elementLeft >= windowWidth) {\n      arrowSide = \"left\";\n      arrowAlignment = \"start\";\n    } else if (elementLeft + popoverWidth >= windowWidth) {\n      arrowSide = \"bottom\";\n      arrowAlignment = \"end\";\n    }\n  } else if (side === \"left\") {\n    if (elementTop + elementHeight <= 0) {\n      arrowSide = \"bottom\";\n      arrowAlignment = \"end\";\n    } else if (elementTop + elementHeight - popoverHeight <= 0) {\n      arrowSide = \"left\";\n      arrowAlignment = \"start\";\n    }\n\n    if (elementTop >= windowHeight) {\n      arrowSide = \"top\";\n      arrowAlignment = \"end\";\n    } else if (elementTop + popoverHeight >= windowHeight) {\n      arrowSide = \"left\";\n      arrowAlignment = \"end\";\n    }\n  } else if (side === \"right\") {\n    if (elementTop + elementHeight <= 0) {\n      arrowSide = \"bottom\";\n      arrowAlignment = \"start\";\n    } else if (elementTop + elementHeight - popoverHeight <= 0) {\n      arrowSide = \"right\";\n      arrowAlignment = \"start\";\n    }\n\n    if (elementTop >= windowHeight) {\n      arrowSide = \"top\";\n      arrowAlignment = \"start\";\n    } else if (elementTop + popoverHeight >= windowHeight) {\n      arrowSide = \"right\";\n      arrowAlignment = \"end\";\n    }\n  }\n\n  if (!arrowSide) {\n    popoverArrow.classList.add(\"driver-popover-arrow-none\");\n  } else {\n    popoverArrow.classList.add(`driver-popover-arrow-side-${arrowSide}`);\n    popoverArrow.classList.add(`driver-popover-arrow-align-${arrowAlignment}`);\n\n    const elementRect = element.getBoundingClientRect();\n    const arrowRect = popoverArrow.getBoundingClientRect();\n    const stagePadding = getConfig(\"stagePadding\") || 0;\n\n    const isElementPartiallyInViewPort =\n      elementRect.left - stagePadding < window.innerWidth &&\n      elementRect.right + stagePadding > 0 &&\n      elementRect.top - stagePadding < window.innerHeight &&\n      elementRect.bottom + stagePadding > 0;\n\n    if (side === \"bottom\" && isElementPartiallyInViewPort) {\n      const isArrowWithinElementBounds =\n        arrowRect.x > elementRect.x && arrowRect.x + arrowRect.width < elementRect.x + elementRect.width;\n\n      if (!isArrowWithinElementBounds) {\n        popoverArrow.classList.remove(`driver-popover-arrow-align-${arrowAlignment}`);\n        popoverArrow.classList.add(`driver-popover-arrow-none`);\n        // reduce the top position by the padding\n        popover.wrapper.style.transform = `translateY(-${stagePadding / 2}px)`;\n      } else {\n        popover.wrapper.style.transform = `translateY(0)`;\n      }\n\n      // TODO: implement this using either of the following:\n      // 1 - move the arrow to the center of the element and point it towards the popover. This way, scrolling or resizing the window will move the arrow to the correct position.\n      // 2 - calculate the center position of the element and point the arrow towards the popover. However, we will have to re-calculate the position of the arrow when the window is resized or scrolled.\n    }\n  }\n}\n\nfunction createPopover(): PopoverDOM {\n  const wrapper = document.createElement(\"div\");\n  wrapper.classList.add(\"driver-popover\");\n\n  const arrow = document.createElement(\"div\");\n  arrow.classList.add(\"driver-popover-arrow\");\n\n  const title = document.createElement(\"header\");\n  title.id = \"driver-popover-title\";\n  title.classList.add(\"driver-popover-title\");\n  title.style.display = \"none\";\n  title.innerText = \"Popover Title\";\n\n  const description = document.createElement(\"div\");\n  description.id = \"driver-popover-description\";\n  description.classList.add(\"driver-popover-description\");\n  description.style.display = \"none\";\n  description.innerText = \"Popover description is here\";\n\n  const closeButton = document.createElement(\"button\");\n  closeButton.type = \"button\";\n  closeButton.classList.add(\"driver-popover-close-btn\");\n  closeButton.setAttribute(\"aria-label\", \"Close\");\n  closeButton.innerHTML = \"&times;\";\n\n  const footer = document.createElement(\"footer\");\n  footer.classList.add(\"driver-popover-footer\");\n\n  const progress = document.createElement(\"span\");\n  progress.classList.add(\"driver-popover-progress-text\");\n  progress.innerText = \"\";\n\n  const footerButtons = document.createElement(\"span\");\n  footerButtons.classList.add(\"driver-popover-navigation-btns\");\n\n  const previousButton = document.createElement(\"button\");\n  previousButton.type = \"button\";\n  previousButton.classList.add(\"driver-popover-prev-btn\");\n  previousButton.innerHTML = \"&larr; Previous\";\n\n  const nextButton = document.createElement(\"button\");\n  nextButton.type = \"button\";\n  nextButton.classList.add(\"driver-popover-next-btn\");\n  nextButton.innerHTML = \"Next &rarr;\";\n\n  footerButtons.appendChild(previousButton);\n  footerButtons.appendChild(nextButton);\n  footer.appendChild(progress);\n  footer.appendChild(footerButtons);\n\n  wrapper.appendChild(closeButton);\n  wrapper.appendChild(arrow);\n  wrapper.appendChild(title);\n  wrapper.appendChild(description);\n  wrapper.appendChild(footer);\n\n  return {\n    wrapper,\n    arrow,\n    title,\n    description,\n    footer,\n    previousButton,\n    nextButton,\n    closeButton,\n    footerButtons,\n    progress,\n  };\n}\n\nexport function destroyPopover() {\n  const popover = getState(\"popover\");\n  if (!popover) {\n    return;\n  }\n\n  popover.wrapper.parentElement?.removeChild(popover.wrapper);\n}\n"
  },
  {
    "path": "src/state.ts",
    "content": "import { StageDefinition } from \"./overlay\";\nimport { PopoverDOM } from \"./popover\";\nimport { DriveStep } from \"./driver\";\n\nexport type State = {\n  isInitialized?: boolean;\n\n  activeIndex?: number;\n  activeElement?: Element;\n  activeStep?: DriveStep;\n  previousElement?: Element;\n  previousStep?: DriveStep;\n\n  popover?: PopoverDOM;\n\n  // actual values considering the animation\n  // and delays. These are used to determine\n  // the positions etc.\n  __previousElement?: Element;\n  __activeElement?: Element;\n  __previousStep?: DriveStep;\n  __activeStep?: DriveStep;\n\n  __activeOnDestroyed?: Element;\n  __resizeTimeout?: number;\n  __transitionCallback?: () => void;\n  __activeStagePosition?: StageDefinition;\n  __overlaySvg?: SVGSVGElement;\n};\n\nlet currentState: State = {};\n\nexport function setState<K extends keyof State>(key: K, value: State[K]) {\n  currentState[key] = value;\n}\n\nexport function getState(): State;\nexport function getState<K extends keyof State>(key: K): State[K];\nexport function getState<K extends keyof State>(key?: K) {\n  return key ? currentState[key] : currentState;\n}\n\nexport function resetState() {\n  currentState = {};\n}\n"
  },
  {
    "path": "src/utils.ts",
    "content": "import { getConfig } from \"./config\";\n\nexport function easeInOutQuad(elapsed: number, initialValue: number, amountOfChange: number, duration: number): number {\n  if ((elapsed /= duration / 2) < 1) {\n    return (amountOfChange / 2) * elapsed * elapsed + initialValue;\n  }\n  return (-amountOfChange / 2) * (--elapsed * (elapsed - 2) - 1) + initialValue;\n}\n\nexport function getFocusableElements(parentEls: Element[] | HTMLElement[]) {\n  const focusableQuery =\n    'a[href]:not([disabled]), button:not([disabled]), textarea:not([disabled]), input[type=\"text\"]:not([disabled]), input[type=\"radio\"]:not([disabled]), input[type=\"checkbox\"]:not([disabled]), select:not([disabled])';\n\n  return parentEls\n    .flatMap(parentEl => {\n      const isParentFocusable = parentEl.matches(focusableQuery);\n      const focusableEls: HTMLElement[] = Array.from(parentEl.querySelectorAll(focusableQuery));\n\n      return [...(isParentFocusable ? [parentEl as HTMLElement] : []), ...focusableEls];\n    })\n    .filter(el => {\n      return getComputedStyle(el).pointerEvents !== \"none\" && isElementVisible(el);\n    });\n}\n\nexport function bringInView(element: Element) {\n  if (!element || isElementInView(element)) {\n    return;\n  }\n\n  const shouldSmoothScroll = getConfig(\"smoothScroll\");\n\n  const isTallerThanViewport = (element as HTMLElement).offsetHeight > window.innerHeight;\n\n  element.scrollIntoView({\n    // Removing the smooth scrolling for elements which exist inside the scrollable parent\n    // This was causing the highlight to not properly render\n    behavior: !shouldSmoothScroll || hasScrollableParent(element) ? \"auto\" : \"smooth\",\n    inline: \"center\",\n    block: isTallerThanViewport ? \"start\" : \"center\",\n  });\n}\n\nfunction hasScrollableParent(e: Element) {\n  if (!e || !e.parentElement) {\n    return;\n  }\n\n  const parent = e.parentElement as HTMLElement & { scrollTopMax?: number };\n\n  return parent.scrollHeight > parent.clientHeight;\n}\n\nfunction isElementInView(element: Element) {\n  const rect = element.getBoundingClientRect();\n\n  return (\n    rect.top >= 0 &&\n    rect.left >= 0 &&\n    rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&\n    rect.right <= (window.innerWidth || document.documentElement.clientWidth)\n  );\n}\n\nexport function isElementVisible(el: HTMLElement) {\n  return !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length);\n}\n"
  },
  {
    "path": "tests/sum.test.ts",
    "content": "import { describe, expect, it } from \"vitest\";\n\ndescribe(\"add\", () => {\n  it(\"should sum of 2 and 3 equals to 5\", () => {\n    expect(5).toEqual(5);\n  });\n});\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"rootDir\": \"./src\",\n    \"target\": \"ES2019\",\n    \"useDefineForClassFields\": true,\n    \"module\": \"CommonJS\",\n    \"lib\": [\"ES2019\", \"DOM\"],\n    \"moduleResolution\": \"Node\",\n    \"strict\": true,\n    \"sourceMap\": true,\n    \"resolveJsonModule\": true,\n    \"esModuleInterop\": true,\n    \"noEmit\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noImplicitReturns\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"types\": [\"vite/client\", \"node\"]\n  },\n  \"include\": [\"src\"],\n  \"exclude\": [\"**/*.test.ts\", \"node_modules\",\n    \"tests/**\", \".history/**\"]\n}\n"
  },
  {
    "path": "vite.config.ts",
    "content": "/// <reference types=\"vitest\" />\nimport path from \"path\";\nimport { defineConfig } from \"vite\";\n\nconst packageName = \"driver.js\";\n\nconst fileName = {\n  es: `${packageName}.mjs`,\n  cjs: `${packageName}.cjs`,\n  iife: `${packageName}.iife.js`,\n};\n\nconst formats = Object.keys(fileName) as Array<keyof typeof fileName>;\n\nmodule.exports = defineConfig({\n  base: \"./\",\n  build: {\n    target: \"ES2019\",\n    lib: {\n      entry: path.resolve(__dirname, \"src/driver.ts\"),\n      name: packageName,\n      formats,\n      fileName: format => fileName[format],\n    },\n    rollupOptions: {\n      output: {\n        assetFileNames: assetInfo => {\n          return assetInfo.name === \"style.css\" ? `driver.css` : assetInfo.name as string;\n        },\n      },\n    },\n  },\n  test: {},\n});\n"
  }
]