You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lo...@apache.org on 2021/01/21 09:12:31 UTC

[myfaces-tobago] branch master updated (9f0e43b -> c476ad3)

This is an automated email from the ASF dual-hosted git repository.

lofwyr pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/myfaces-tobago.git.


    from 9f0e43b  fix: jasmine tests
     new 13d7743  TOBAGO-2044: Evaluate use of Bootstrap 5
     new f6d21cf  TOBAGO-2044: Evaluate use of Bootstrap 5
     new c990cfb  TOBAGO-2044: Evaluate use of Bootstrap 5
     new c476ad3  chore: optimize/cleanup/simplify

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../internal/renderkit/renderer/ImageRenderer.java |     4 +-
 .../renderkit/renderer/TreeIconRenderer.java       |     2 +-
 .../tobago/internal/util/HtmlRendererUtils.java    |     2 +-
 .../apache/myfaces/tobago/renderkit/css/Icons.java |    11 +-
 .../tobago-example-demo/npm/package-lock.json      |   138 +-
 .../tobago-example-demo/npm/package.json           |     5 +-
 .../tobago-example-demo/npm/rollup.config.js       |     2 +-
 .../npm/package-lock.json                          |     6 +-
 .../tobago-theme-charlotteville/npm/package.json   |     2 +-
 .../tobago-theme-roxborough/npm/package-lock.json  |     6 +-
 .../tobago-theme-roxborough/npm/package.json       |     2 +-
 .../tobago-theme-scarborough/npm/package-lock.json |     6 +-
 .../tobago-theme-scarborough/npm/package.json      |     2 +-
 .../tobago-theme-speyside/npm/package-lock.json    |     6 +-
 .../tobago-theme-speyside/npm/package.json         |     2 +-
 .../npm/dist/js/tobago-dropdown.js                 |     6 +-
 .../npm/dist/js/tobago-dropdown.js.map             |     2 +-
 .../npm/dist/js/tobago-popover.js                  |    12 +-
 .../npm/dist/js/tobago-popover.js.map              |     2 +-
 .../npm/dist/js/tobago-popup.js                    |     5 +-
 .../npm/dist/js/tobago-popup.js.map                |     2 +-
 .../npm/dist/js/tobago-range.js                    |     4 +-
 .../npm/dist/js/tobago-range.js.map                |     2 +-
 .../tobago-theme-standard/npm/dist/js/tobago.js    | 10134 ++++++++++++-------
 .../npm/dist/js/tobago.js.map                      |     2 +-
 .../tobago-theme-standard/npm/package-lock.json    |   121 +-
 .../tobago-theme-standard/npm/package.json         |     9 +-
 .../tobago-theme-standard/npm/rollup.config.js     |    10 +-
 .../npm/ts/tobago-dropdown.ts                      |     3 +-
 .../tobago-theme-standard/npm/ts/tobago-popover.ts |    12 +-
 .../tobago-theme-standard/npm/ts/tobago-popup.ts   |     5 +-
 .../tobago-theme-standard/npm/ts/tobago-range.ts   |     5 +-
 .../src/main/resources/META-INF/tobago-config.xml  |     4 -
 33 files changed, 6553 insertions(+), 3983 deletions(-)


[myfaces-tobago] 02/04: TOBAGO-2044: Evaluate use of Bootstrap 5

Posted by lo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

lofwyr pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/myfaces-tobago.git

commit f6d21cfd373e4c65fb6e434afd3adbadbbe11da6
Author: Udo Schnurpfeil <ud...@irian.eu>
AuthorDate: Wed Jan 20 17:47:57 2021 +0100

    TOBAGO-2044: Evaluate use of Bootstrap 5
    
    * Nicer way to import JS (popper, bootstrap) - working now!
---
 .../tobago-example-demo/npm/package-lock.json      |  138 +-
 .../tobago-example-demo/npm/package.json           |    5 +-
 .../tobago-example-demo/npm/rollup.config.js       |    2 +-
 .../npm/package-lock.json                          |    6 +-
 .../tobago-theme-charlotteville/npm/package.json   |    2 +-
 .../tobago-theme-roxborough/npm/package-lock.json  |    6 +-
 .../tobago-theme-roxborough/npm/package.json       |    2 +-
 .../tobago-theme-scarborough/npm/package-lock.json |    6 +-
 .../tobago-theme-scarborough/npm/package.json      |    2 +-
 .../tobago-theme-speyside/npm/package-lock.json    |    6 +-
 .../tobago-theme-speyside/npm/package.json         |    2 +-
 .../npm/dist/js/tobago-dropdown.js                 |    3 +
 .../npm/dist/js/tobago-dropdown.js.map             |    2 +-
 .../tobago-theme-standard/npm/dist/js/tobago.js    | 2722 +-------------------
 .../npm/dist/js/tobago.js.map                      |    2 +-
 .../tobago-theme-standard/npm/package-lock.json    |  118 +-
 .../tobago-theme-standard/npm/package.json         |    5 +-
 .../tobago-theme-standard/npm/rollup.config.js     |   10 +-
 18 files changed, 217 insertions(+), 2822 deletions(-)

diff --git a/tobago-example/tobago-example-demo/npm/package-lock.json b/tobago-example/tobago-example-demo/npm/package-lock.json
index 383740f..8351acc 100644
--- a/tobago-example/tobago-example-demo/npm/package-lock.json
+++ b/tobago-example/tobago-example-demo/npm/package-lock.json
@@ -56,6 +56,72 @@
         "fastq": "^1.6.0"
       }
     },
+    "@rollup/plugin-node-resolve": {
+      "version": "11.1.0",
+      "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.1.0.tgz",
+      "integrity": "sha512-ouBBppRdWJKCllDXGzJ7ZIkYbaq+5TmyP0smt1vdJCFfoZhLi31vhpmjLhyo8lreHf4RoeSNllaWrvSqHpHRog==",
+      "dev": true,
+      "requires": {
+        "@rollup/pluginutils": "^3.1.0",
+        "@types/resolve": "1.17.1",
+        "builtin-modules": "^3.1.0",
+        "deepmerge": "^4.2.2",
+        "is-module": "^1.0.0",
+        "resolve": "^1.19.0"
+      },
+      "dependencies": {
+        "@types/resolve": {
+          "version": "1.17.1",
+          "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz",
+          "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==",
+          "dev": true,
+          "requires": {
+            "@types/node": "*"
+          }
+        },
+        "builtin-modules": {
+          "version": "3.2.0",
+          "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz",
+          "integrity": "sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==",
+          "dev": true
+        }
+      }
+    },
+    "@rollup/plugin-replace": {
+      "version": "2.3.4",
+      "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.3.4.tgz",
+      "integrity": "sha512-waBhMzyAtjCL1GwZes2jaE9MjuQ/DQF2BatH3fRivUF3z0JBFrU0U6iBNC/4WR+2rLKhaAhPWDNPYp4mI6RqdQ==",
+      "dev": true,
+      "requires": {
+        "@rollup/pluginutils": "^3.1.0",
+        "magic-string": "^0.25.7"
+      }
+    },
+    "@rollup/pluginutils": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz",
+      "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==",
+      "dev": true,
+      "requires": {
+        "@types/estree": "0.0.39",
+        "estree-walker": "^1.0.1",
+        "picomatch": "^2.2.2"
+      },
+      "dependencies": {
+        "estree-walker": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz",
+          "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==",
+          "dev": true
+        }
+      }
+    },
+    "@types/estree": {
+      "version": "0.0.39",
+      "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
+      "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
+      "dev": true
+    },
     "@types/node": {
       "version": "14.14.7",
       "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.7.tgz",
@@ -68,15 +134,6 @@
       "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==",
       "dev": true
     },
-    "@types/resolve": {
-      "version": "0.0.8",
-      "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz",
-      "integrity": "sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==",
-      "dev": true,
-      "requires": {
-        "@types/node": "*"
-      }
-    },
     "abbrev": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
@@ -573,6 +630,12 @@
       "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
       "dev": true
     },
+    "deepmerge": {
+      "version": "4.2.2",
+      "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
+      "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==",
+      "dev": true
+    },
     "define-properties": {
       "version": "1.1.3",
       "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
@@ -715,12 +778,6 @@
       "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
       "dev": true
     },
-    "estree-walker": {
-      "version": "0.6.1",
-      "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz",
-      "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==",
-      "dev": true
-    },
     "extend": {
       "version": "3.0.2",
       "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
@@ -1463,6 +1520,15 @@
         "signal-exit": "^3.0.0"
       }
     },
+    "magic-string": {
+      "version": "0.25.7",
+      "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz",
+      "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==",
+      "dev": true,
+      "requires": {
+        "sourcemap-codec": "^1.4.4"
+      }
+    },
     "map-obj": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
@@ -2397,44 +2463,14 @@
       }
     },
     "rollup": {
-      "version": "2.33.1",
-      "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.33.1.tgz",
-      "integrity": "sha512-uY4O/IoL9oNW8MMcbA5hcOaz6tZTMIh7qJHx/tzIJm+n1wLoY38BLn6fuy7DhR57oNFLMbDQtDeJoFURt5933w==",
+      "version": "2.37.1",
+      "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.37.1.tgz",
+      "integrity": "sha512-V3ojEeyGeSdrMSuhP3diBb06P+qV4gKQeanbDv+Qh/BZbhdZ7kHV0xAt8Yjk4GFshq/WjO7R4c7DFM20AwTFVQ==",
       "dev": true,
       "requires": {
         "fsevents": "~2.1.2"
       }
     },
-    "rollup-plugin-node-resolve": {
-      "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz",
-      "integrity": "sha512-jUlyaDXts7TW2CqQ4GaO5VJ4PwwaV8VUGA7+km3n6k6xtOEacf61u0VXwN80phY/evMcaS+9eIeJ9MOyDxt5Zw==",
-      "dev": true,
-      "requires": {
-        "@types/resolve": "0.0.8",
-        "builtin-modules": "^3.1.0",
-        "is-module": "^1.0.0",
-        "resolve": "^1.11.1",
-        "rollup-pluginutils": "^2.8.1"
-      },
-      "dependencies": {
-        "builtin-modules": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz",
-          "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==",
-          "dev": true
-        }
-      }
-    },
-    "rollup-pluginutils": {
-      "version": "2.8.2",
-      "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz",
-      "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==",
-      "dev": true,
-      "requires": {
-        "estree-walker": "^0.6.1"
-      }
-    },
     "run-parallel": {
       "version": "1.1.10",
       "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz",
@@ -2536,6 +2572,12 @@
         "amdefine": ">=0.0.4"
       }
     },
+    "sourcemap-codec": {
+      "version": "1.4.8",
+      "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
+      "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
+      "dev": true
+    },
     "spdx-correct": {
       "version": "3.1.1",
       "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz",
diff --git a/tobago-example/tobago-example-demo/npm/package.json b/tobago-example/tobago-example-demo/npm/package.json
index b19635f..aa02780 100644
--- a/tobago-example/tobago-example-demo/npm/package.json
+++ b/tobago-example/tobago-example-demo/npm/package.json
@@ -34,8 +34,9 @@
     "npm-run-all": "^4.1.5",
     "postcss-cli": "^8.2.0",
     "prismjs": "^1.22.0",
-    "rollup": "^2.33.1",
-    "rollup-plugin-node-resolve": "^5.2.0",
+    "rollup": "^2.37.1",
+    "@rollup/plugin-node-resolve": "^11.1.0",
+    "@rollup/plugin-replace": "^2.3.4",
     "tslint": "^6.1.3",
     "typescript": "^4.0.5"
   }
diff --git a/tobago-example/tobago-example-demo/npm/rollup.config.js b/tobago-example/tobago-example-demo/npm/rollup.config.js
index e5a92f9..f32a54c 100644
--- a/tobago-example/tobago-example-demo/npm/rollup.config.js
+++ b/tobago-example/tobago-example-demo/npm/rollup.config.js
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-import resolve from "rollup-plugin-node-resolve"
+import resolve from "@rollup/plugin-node-resolve"
 
 export default {
   input: '../src/main/webapp/js/demo-all.js',
diff --git a/tobago-theme/tobago-theme-charlotteville/npm/package-lock.json b/tobago-theme/tobago-theme-charlotteville/npm/package-lock.json
index f02357c..fcbf28e 100644
--- a/tobago-theme/tobago-theme-charlotteville/npm/package-lock.json
+++ b/tobago-theme/tobago-theme-charlotteville/npm/package-lock.json
@@ -1889,9 +1889,9 @@
       }
     },
     "rollup": {
-      "version": "2.36.1",
-      "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.36.1.tgz",
-      "integrity": "sha512-eAfqho8dyzuVvrGqpR0ITgEdq0zG2QJeWYh+HeuTbpcaXk8vNFc48B7bJa1xYosTCKx0CuW+447oQOW8HgBIZQ==",
+      "version": "2.37.1",
+      "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.37.1.tgz",
+      "integrity": "sha512-V3ojEeyGeSdrMSuhP3diBb06P+qV4gKQeanbDv+Qh/BZbhdZ7kHV0xAt8Yjk4GFshq/WjO7R4c7DFM20AwTFVQ==",
       "dev": true,
       "requires": {
         "fsevents": "~2.1.2"
diff --git a/tobago-theme/tobago-theme-charlotteville/npm/package.json b/tobago-theme/tobago-theme-charlotteville/npm/package.json
index a5c5816..f08b4b6 100644
--- a/tobago-theme/tobago-theme-charlotteville/npm/package.json
+++ b/tobago-theme/tobago-theme-charlotteville/npm/package.json
@@ -60,7 +60,7 @@
     "eslint-plugin-compat": "^3.8.0",
     "npm-run-all": "^4.1.5",
     "postcss-cli": "^7.1.2",
-    "rollup": "^2.33.1",
+    "rollup": "^2.37.1",
     "sass": "^1.29.0",
     "tslint": "^6.1.3",
     "typescript": "^4.0.5"
diff --git a/tobago-theme/tobago-theme-roxborough/npm/package-lock.json b/tobago-theme/tobago-theme-roxborough/npm/package-lock.json
index 67d1001..0b53001 100644
--- a/tobago-theme/tobago-theme-roxborough/npm/package-lock.json
+++ b/tobago-theme/tobago-theme-roxborough/npm/package-lock.json
@@ -1889,9 +1889,9 @@
       }
     },
     "rollup": {
-      "version": "2.36.1",
-      "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.36.1.tgz",
-      "integrity": "sha512-eAfqho8dyzuVvrGqpR0ITgEdq0zG2QJeWYh+HeuTbpcaXk8vNFc48B7bJa1xYosTCKx0CuW+447oQOW8HgBIZQ==",
+      "version": "2.37.1",
+      "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.37.1.tgz",
+      "integrity": "sha512-V3ojEeyGeSdrMSuhP3diBb06P+qV4gKQeanbDv+Qh/BZbhdZ7kHV0xAt8Yjk4GFshq/WjO7R4c7DFM20AwTFVQ==",
       "dev": true,
       "requires": {
         "fsevents": "~2.1.2"
diff --git a/tobago-theme/tobago-theme-roxborough/npm/package.json b/tobago-theme/tobago-theme-roxborough/npm/package.json
index a144de9..b08d575 100644
--- a/tobago-theme/tobago-theme-roxborough/npm/package.json
+++ b/tobago-theme/tobago-theme-roxborough/npm/package.json
@@ -60,7 +60,7 @@
     "eslint-plugin-compat": "^3.8.0",
     "npm-run-all": "^4.1.5",
     "postcss-cli": "^7.1.2",
-    "rollup": "^2.33.1",
+    "rollup": "^2.37.1",
     "sass": "^1.29.0",
     "tslint": "^6.1.3",
     "typescript": "^4.0.5"
diff --git a/tobago-theme/tobago-theme-scarborough/npm/package-lock.json b/tobago-theme/tobago-theme-scarborough/npm/package-lock.json
index 6ba7bb2..5b8e988 100644
--- a/tobago-theme/tobago-theme-scarborough/npm/package-lock.json
+++ b/tobago-theme/tobago-theme-scarborough/npm/package-lock.json
@@ -1889,9 +1889,9 @@
       }
     },
     "rollup": {
-      "version": "2.36.1",
-      "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.36.1.tgz",
-      "integrity": "sha512-eAfqho8dyzuVvrGqpR0ITgEdq0zG2QJeWYh+HeuTbpcaXk8vNFc48B7bJa1xYosTCKx0CuW+447oQOW8HgBIZQ==",
+      "version": "2.37.1",
+      "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.37.1.tgz",
+      "integrity": "sha512-V3ojEeyGeSdrMSuhP3diBb06P+qV4gKQeanbDv+Qh/BZbhdZ7kHV0xAt8Yjk4GFshq/WjO7R4c7DFM20AwTFVQ==",
       "dev": true,
       "requires": {
         "fsevents": "~2.1.2"
diff --git a/tobago-theme/tobago-theme-scarborough/npm/package.json b/tobago-theme/tobago-theme-scarborough/npm/package.json
index 450c077..714be1d 100644
--- a/tobago-theme/tobago-theme-scarborough/npm/package.json
+++ b/tobago-theme/tobago-theme-scarborough/npm/package.json
@@ -60,7 +60,7 @@
     "eslint-plugin-compat": "^3.8.0",
     "npm-run-all": "^4.1.5",
     "postcss-cli": "^7.1.2",
-    "rollup": "^2.33.1",
+    "rollup": "^2.37.1",
     "sass": "^1.29.0",
     "tslint": "^6.1.3",
     "typescript": "^4.0.5"
diff --git a/tobago-theme/tobago-theme-speyside/npm/package-lock.json b/tobago-theme/tobago-theme-speyside/npm/package-lock.json
index 1a731cb..529ebe1 100644
--- a/tobago-theme/tobago-theme-speyside/npm/package-lock.json
+++ b/tobago-theme/tobago-theme-speyside/npm/package-lock.json
@@ -1889,9 +1889,9 @@
       }
     },
     "rollup": {
-      "version": "2.36.1",
-      "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.36.1.tgz",
-      "integrity": "sha512-eAfqho8dyzuVvrGqpR0ITgEdq0zG2QJeWYh+HeuTbpcaXk8vNFc48B7bJa1xYosTCKx0CuW+447oQOW8HgBIZQ==",
+      "version": "2.37.1",
+      "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.37.1.tgz",
+      "integrity": "sha512-V3ojEeyGeSdrMSuhP3diBb06P+qV4gKQeanbDv+Qh/BZbhdZ7kHV0xAt8Yjk4GFshq/WjO7R4c7DFM20AwTFVQ==",
       "dev": true,
       "requires": {
         "fsevents": "~2.1.2"
diff --git a/tobago-theme/tobago-theme-speyside/npm/package.json b/tobago-theme/tobago-theme-speyside/npm/package.json
index 2ae88a3..104574b 100644
--- a/tobago-theme/tobago-theme-speyside/npm/package.json
+++ b/tobago-theme/tobago-theme-speyside/npm/package.json
@@ -60,7 +60,7 @@
     "eslint-plugin-compat": "^3.8.0",
     "npm-run-all": "^4.1.5",
     "postcss-cli": "^7.1.2",
-    "rollup": "^2.33.1",
+    "rollup": "^2.37.1",
     "sass": "^1.29.0",
     "tslint": "^6.1.3",
     "typescript": "^4.0.5"
diff --git a/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-dropdown.js b/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-dropdown.js
index 5d899fb..6f4fb1c 100644
--- a/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-dropdown.js
+++ b/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-dropdown.js
@@ -22,6 +22,9 @@ const Event = {
     SHOW: "tobago.dropdown.show",
     SHOWN: "tobago.dropdown.shown"
 };
+/**
+ * The dropdown implementation of Bootstrap does not support submenus. Therefore we need an own dropdown implementation.
+ */
 class Dropdown extends HTMLElement {
     constructor() {
         super();
diff --git a/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-dropdown.js.map b/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-dropdown.js.map
index 90eec22..6b806d9 100644
--- a/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-dropdown.js.map
+++ b/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-dropdown.js.map
@@ -1 +1 @@
-{"version":3,"file":"tobago-dropdown.js","sourceRoot":"","sources":["../../ts/tobago-dropdown.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAC;AAC5C,+DAA+D;AAE/D,MAAM,KAAK,GAAG;IACZ,IAAI,EAAE,sBAAsB;IAC5B,MAAM,EAAE,wBAAwB;IAChC,IAAI,EAAE,sBAAsB;IAC5B,KAAK,EAAE,uBAAuB;CAC/B,CAAC;AAEF,MAAM,QAAS,SAAQ,WAAW;IAIhC;QACE,KAAK,EAAE,CAAC;QAHF,oBAAe,GAAoB,EAAE,CAAC;QAI5C,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,yBAAyB,CAAC,EAAE,EAAE,kBAAkB;YAC3E,MAAM,IAAI [...]
\ No newline at end of file
+{"version":3,"file":"tobago-dropdown.js","sourceRoot":"","sources":["../../ts/tobago-dropdown.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAC;AAC5C,+DAA+D;AAE/D,MAAM,KAAK,GAAG;IACZ,IAAI,EAAE,sBAAsB;IAC5B,MAAM,EAAE,wBAAwB;IAChC,IAAI,EAAE,sBAAsB;IAC5B,KAAK,EAAE,uBAAuB;CAC/B,CAAC;AAEF;;GAEG;AACH,MAAM,QAAS,SAAQ,WAAW;IAIhC;QACE,KAAK,EAAE,CAAC;QAHF,oBAAe,GAAoB,EAAE,CAAC;QAI5C,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,yBAAyB,CAAC,EAAE,EAAE,kBAAkB;YAC3 [...]
\ No newline at end of file
diff --git a/tobago-theme/tobago-theme-standard/npm/dist/js/tobago.js b/tobago-theme/tobago-theme-standard/npm/dist/js/tobago.js
index bee44c4..ac56f7c 100644
--- a/tobago-theme/tobago-theme-standard/npm/dist/js/tobago.js
+++ b/tobago-theme/tobago-theme-standard/npm/dist/js/tobago.js
@@ -1,7 +1,12 @@
-(function (factory) {
-    typeof define === 'function' && define.amd ? define(factory) :
-    factory();
-}((function () { 'use strict';
+(function (global, factory) {
+    typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('vanillajs-datepicker/js/Datepicker.js')) :
+    typeof define === 'function' && define.amd ? define(['vanillajs-datepicker/js/Datepicker.js'], factory) :
+    (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Datepicker));
+}(this, (function (Datepicker) { 'use strict';
+
+    function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
+
+    var Datepicker__default = /*#__PURE__*/_interopDefaultLegacy(Datepicker);
 
     /*
      * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -619,16 +624,7 @@
         }
       }
 
-      if (process.env.NODE_ENV !== "production") {
-        if (!isHTMLElement(arrowElement)) {
-          console.error(['Popper: "arrow" element must be an HTMLElement (not an SVGElement).', 'To use an SVG arrow, wrap it in an HTMLElement that will be used as', 'the arrow.'].join(' '));
-        }
-      }
-
       if (!contains(state.elements.popper, arrowElement)) {
-        if (process.env.NODE_ENV !== "production") {
-          console.error(['Popper: "arrow" modifier\'s `element` must be a child of the popper', 'element.'].join(' '));
-        }
 
         return;
       }
@@ -740,16 +736,6 @@
           _options$roundOffsets = options.roundOffsets,
           roundOffsets = _options$roundOffsets === void 0 ? true : _options$roundOffsets;
 
-      if (process.env.NODE_ENV !== "production") {
-        var transitionProperty = getComputedStyle$1(state.elements.popper).transitionProperty || '';
-
-        if (adaptive && ['transform', 'top', 'right', 'bottom', 'left'].some(function (property) {
-          return transitionProperty.indexOf(property) >= 0;
-        })) {
-          console.warn(['Popper: Detected CSS transitions on at least one of the following', 'CSS properties: "transform", "top", "right", "bottom", "left".', '\n\n', 'Disable the "computeStyles" modifier\'s `adaptive` option to allow', 'for smooth transitions, or remove these properties from the CSS', 'transition declaration on the popper element if only transitioning', 'opacity or background-color for example.', '\n\n', 'We recommend using the popper element as a wrapper around an inne [...]
-        }
-      }
-
       var commonStyles = {
         placement: getBasePlacement(state.placement),
         popper: state.elements.popper,
@@ -1214,10 +1200,6 @@
 
       if (allowedPlacements.length === 0) {
         allowedPlacements = placements$1;
-
-        if (process.env.NODE_ENV !== "production") {
-          console.error(['Popper: The `allowedAutoPlacements` option did not allow any', 'placements. Ensure the `placement` option matches the variation', 'of the allowed placements.', 'For example, "auto" cannot be used to allow "bottom-start".', 'Use "auto-start" instead.'].join(' '));
-        }
       } // $FlowFixMe[incompatible-type]: Flow seems to have problems with two array unions...
 
 
@@ -1739,103 +1721,6 @@
       };
     }
 
-    function format(str) {
-      for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
-        args[_key - 1] = arguments[_key];
-      }
-
-      return [].concat(args).reduce(function (p, c) {
-        return p.replace(/%s/, c);
-      }, str);
-    }
-
-    var INVALID_MODIFIER_ERROR = 'Popper: modifier "%s" provided an invalid %s property, expected %s but got %s';
-    var MISSING_DEPENDENCY_ERROR = 'Popper: modifier "%s" requires "%s", but "%s" modifier is not available';
-    var VALID_PROPERTIES = ['name', 'enabled', 'phase', 'fn', 'effect', 'requires', 'options'];
-    function validateModifiers(modifiers) {
-      modifiers.forEach(function (modifier) {
-        Object.keys(modifier).forEach(function (key) {
-          switch (key) {
-            case 'name':
-              if (typeof modifier.name !== 'string') {
-                console.error(format(INVALID_MODIFIER_ERROR, String(modifier.name), '"name"', '"string"', "\"" + String(modifier.name) + "\""));
-              }
-
-              break;
-
-            case 'enabled':
-              if (typeof modifier.enabled !== 'boolean') {
-                console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"enabled"', '"boolean"', "\"" + String(modifier.enabled) + "\""));
-              }
-
-            case 'phase':
-              if (modifierPhases.indexOf(modifier.phase) < 0) {
-                console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"phase"', "either " + modifierPhases.join(', '), "\"" + String(modifier.phase) + "\""));
-              }
-
-              break;
-
-            case 'fn':
-              if (typeof modifier.fn !== 'function') {
-                console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"fn"', '"function"', "\"" + String(modifier.fn) + "\""));
-              }
-
-              break;
-
-            case 'effect':
-              if (typeof modifier.effect !== 'function') {
-                console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"effect"', '"function"', "\"" + String(modifier.fn) + "\""));
-              }
-
-              break;
-
-            case 'requires':
-              if (!Array.isArray(modifier.requires)) {
-                console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"requires"', '"array"', "\"" + String(modifier.requires) + "\""));
-              }
-
-              break;
-
-            case 'requiresIfExists':
-              if (!Array.isArray(modifier.requiresIfExists)) {
-                console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"requiresIfExists"', '"array"', "\"" + String(modifier.requiresIfExists) + "\""));
-              }
-
-              break;
-
-            case 'options':
-            case 'data':
-              break;
-
-            default:
-              console.error("PopperJS: an invalid property has been provided to the \"" + modifier.name + "\" modifier, valid properties are " + VALID_PROPERTIES.map(function (s) {
-                return "\"" + s + "\"";
-              }).join(', ') + "; but \"" + key + "\" was provided.");
-          }
-
-          modifier.requires && modifier.requires.forEach(function (requirement) {
-            if (modifiers.find(function (mod) {
-              return mod.name === requirement;
-            }) == null) {
-              console.error(format(MISSING_DEPENDENCY_ERROR, String(modifier.name), requirement, requirement));
-            }
-          });
-        });
-      });
-    }
-
-    function uniqueBy(arr, fn) {
-      var identifiers = new Set();
-      return arr.filter(function (item) {
-        var identifier = fn(item);
-
-        if (!identifiers.has(identifier)) {
-          identifiers.add(identifier);
-          return true;
-        }
-      });
-    }
-
     function mergeByName(modifiers) {
       var merged = modifiers.reduce(function (merged, current) {
         var existing = merged[current.name];
@@ -1851,8 +1736,6 @@
       });
     }
 
-    var INVALID_ELEMENT_ERROR = 'Popper: Invalid reference or popper argument provided. They must be either a DOM element or virtual element.';
-    var INFINITE_LOOP_ERROR = 'Popper: An infinite loop in the modifiers cycle has been detected! The cycle has been interrupted to prevent a browser crash.';
     var DEFAULT_OPTIONS = {
       placement: 'bottom',
       modifiers: [],
@@ -1914,40 +1797,6 @@
             state.orderedModifiers = orderedModifiers.filter(function (m) {
               return m.enabled;
             }); // Validate the provided modifiers so that the consumer will get warned
-            // if one of the modifiers is invalid for any reason
-
-            if (process.env.NODE_ENV !== "production") {
-              var modifiers = uniqueBy([].concat(orderedModifiers, state.options.modifiers), function (_ref) {
-                var name = _ref.name;
-                return name;
-              });
-              validateModifiers(modifiers);
-
-              if (getBasePlacement(state.options.placement) === auto) {
-                var flipModifier = state.orderedModifiers.find(function (_ref2) {
-                  var name = _ref2.name;
-                  return name === 'flip';
-                });
-
-                if (!flipModifier) {
-                  console.error(['Popper: "auto" placements require the "flip" modifier be', 'present and enabled to work.'].join(' '));
-                }
-              }
-
-              var _getComputedStyle = getComputedStyle$1(popper),
-                  marginTop = _getComputedStyle.marginTop,
-                  marginRight = _getComputedStyle.marginRight,
-                  marginBottom = _getComputedStyle.marginBottom,
-                  marginLeft = _getComputedStyle.marginLeft; // We no longer take into account `margins` on the popper, and it can
-              // cause bugs with positioning, so we'll warn the consumer
-
-
-              if ([marginTop, marginRight, marginBottom, marginLeft].some(function (margin) {
-                return parseFloat(margin);
-              })) {
-                console.warn(['Popper: CSS "margin" styles cannot be used to apply padding', 'between the popper and its reference element or boundary.', 'To replicate margin, use the `offset` modifier, as well as', 'the `padding` option in the `preventOverflow` and `flip`', 'modifiers.'].join(' '));
-              }
-            }
 
             runModifierEffects();
             return instance.update();
@@ -1968,9 +1817,6 @@
             // anymore
 
             if (!areValidElements(reference, popper)) {
-              if (process.env.NODE_ENV !== "production") {
-                console.error(INVALID_ELEMENT_ERROR);
-              }
 
               return;
             } // Store the reference and popper rects to be read by modifiers
@@ -1994,17 +1840,8 @@
             state.orderedModifiers.forEach(function (modifier) {
               return state.modifiersData[modifier.name] = Object.assign({}, modifier.data);
             });
-            var __debug_loops__ = 0;
 
             for (var index = 0; index < state.orderedModifiers.length; index++) {
-              if (process.env.NODE_ENV !== "production") {
-                __debug_loops__ += 1;
-
-                if (__debug_loops__ > 100) {
-                  console.error(INFINITE_LOOP_ERROR);
-                  break;
-                }
-              }
 
               if (state.reset === true) {
                 state.reset = false;
@@ -2043,9 +1880,6 @@
         };
 
         if (!areValidElements(reference, popper)) {
-          if (process.env.NODE_ENV !== "production") {
-            console.error(INVALID_ELEMENT_ERROR);
-          }
 
           return instance;
         }
@@ -2169,6 +2003,9 @@
         SHOW: "tobago.dropdown.show",
         SHOWN: "tobago.dropdown.shown"
     };
+    /**
+     * The dropdown implementation of Bootstrap does not support submenus. Therefore we need an own dropdown implementation.
+     */
     class Dropdown extends HTMLElement {
         constructor() {
             super();
@@ -2437,2537 +2274,6 @@
         }
     });
 
-    function hasProperty(obj, prop) {
-      return Object.prototype.hasOwnProperty.call(obj, prop);
-    }
-
-    function lastItemOf(arr) {
-      return arr[arr.length - 1];
-    }
-
-    // push only the items not included in the array
-    function pushUnique(arr, ...items) {
-      items.forEach((item) => {
-        if (arr.includes(item)) {
-          return;
-        }
-        arr.push(item);
-      });
-      return arr;
-    }
-
-    function stringToArray(str, separator) {
-      // convert empty string to an empty array
-      return str ? str.split(separator) : [];
-    }
-
-    function isInRange(testVal, min, max) {
-      const minOK = min === undefined || testVal >= min;
-      const maxOK = max === undefined || testVal <= max;
-      return minOK && maxOK;
-    }
-
-    function limitToRange(val, min, max) {
-      if (val < min) {
-        return min;
-      }
-      if (val > max) {
-        return max;
-      }
-      return val;
-    }
-
-    function createTagRepeat(tagName, repeat, attributes = {}, index = 0, html = '') {
-      const openTagSrc = Object.keys(attributes).reduce((src, attr) => {
-        let val = attributes[attr];
-        if (typeof val === 'function') {
-          val = val(index);
-        }
-        return `${src} ${attr}="${val}"`;
-      }, tagName);
-      html += `<${openTagSrc}></${tagName}>`;
-
-      const next = index + 1;
-      return next < repeat
-        ? createTagRepeat(tagName, repeat, attributes, next, html)
-        : html;
-    }
-
-    // Remove the spacing surrounding tags for HTML parser not to create text nodes
-    // before/after elements
-    function optimizeTemplateHTML(html) {
-      return html.replace(/>\s+/g, '>').replace(/\s+</, '<');
-    }
-
-    function stripTime(timeValue) {
-      return new Date(timeValue).setHours(0, 0, 0, 0);
-    }
-
-    function today() {
-      return new Date().setHours(0, 0, 0, 0);
-    }
-
-    // Get the time value of the start of given date or year, month and day
-    function dateValue(...args) {
-      switch (args.length) {
-        case 0:
-          return today();
-        case 1:
-          return stripTime(args[0]);
-      }
-
-      // use setFullYear() to keep 2-digit year from being mapped to 1900-1999
-      const newDate = new Date(0);
-      newDate.setFullYear(...args);
-      return newDate.setHours(0, 0, 0, 0);
-    }
-
-    function addDays(date, amount) {
-      const newDate = new Date(date);
-      return newDate.setDate(newDate.getDate() + amount);
-    }
-
-    function addWeeks(date, amount) {
-      return addDays(date, amount * 7);
-    }
-
-    function addMonths(date, amount) {
-      // If the day of the date is not in the new month, the last day of the new
-      // month will be returned. e.g. Jan 31 + 1 month → Feb 28 (not Mar 03)
-      const newDate = new Date(date);
-      const monthsToSet = newDate.getMonth() + amount;
-      let expectedMonth = monthsToSet % 12;
-      if (expectedMonth < 0) {
-        expectedMonth += 12;
-      }
-
-      const time = newDate.setMonth(monthsToSet);
-      return newDate.getMonth() !== expectedMonth ? newDate.setDate(0) : time;
-    }
-
-    function addYears(date, amount) {
-      // If the date is Feb 29 and the new year is not a leap year, Feb 28 of the
-      // new year will be returned.
-      const newDate = new Date(date);
-      const expectedMonth = newDate.getMonth();
-      const time = newDate.setFullYear(newDate.getFullYear() + amount);
-      return expectedMonth === 1 && newDate.getMonth() === 2 ? newDate.setDate(0) : time;
-    }
-
-    // Calculate the distance bettwen 2 days of the week
-    function dayDiff(day, from) {
-      return (day - from + 7) % 7;
-    }
-
-    // Get the date of the specified day of the week of given base date
-    function dayOfTheWeekOf(baseDate, dayOfWeek, weekStart = 0) {
-      const baseDay = new Date(baseDate).getDay();
-      return addDays(baseDate, dayDiff(dayOfWeek, weekStart) - dayDiff(baseDay, weekStart));
-    }
-
-    // Get the ISO week of a date
-    function getWeek(date) {
-      // start of ISO week is Monday
-      const thuOfTheWeek = dayOfTheWeekOf(date, 4, 1);
-      // 1st week == the week where the 4th of January is in
-      const firstThu = dayOfTheWeekOf(new Date(thuOfTheWeek).setMonth(0, 4), 4, 1);
-      return Math.round((thuOfTheWeek - firstThu) / 604800000) + 1;
-    }
-
-    // Get the start year of the period of years that includes given date
-    // years: length of the year period
-    function startOfYearPeriod(date, years) {
-      /* @see https://en.wikipedia.org/wiki/Year_zero#ISO_8601 */
-      const year = new Date(date).getFullYear();
-      return Math.floor(year / years) * years;
-    }
-
-    // pattern for format parts
-    const reFormatTokens = /dd?|DD?|mm?|MM?|yy?(?:yy)?/;
-    // pattern for non date parts
-    const reNonDateParts = /[\s!-/:-@[-`{-~年月日]+/;
-    // cache for persed formats
-    let knownFormats = {};
-    // parse funtions for date parts
-    const parseFns = {
-      y(date, year) {
-        return new Date(date).setFullYear(parseInt(year, 10));
-      },
-      M: undefined,  // placeholder to maintain the key order
-      m(date, month, locale) {
-        const newDate = new Date(date);
-        let monthIndex = parseInt(month, 10) - 1;
-
-        if (isNaN(monthIndex)) {
-          if (!month) {
-            return NaN;
-          }
-
-          const monthName = month.toLowerCase();
-          const compareNames = name => name.toLowerCase().startsWith(monthName);
-          // compare with both short and full names because some locales have periods
-          // in the short names (not equal to the first X letters of the full names)
-          monthIndex = locale.monthsShort.findIndex(compareNames);
-          if (monthIndex < 0) {
-            monthIndex = locale.months.findIndex(compareNames);
-          }
-          return monthIndex < 0 ? NaN : newDate.setMonth(monthIndex);
-        }
-
-        newDate.setMonth(monthIndex);
-        return newDate.getMonth() !== normalizeMonth(monthIndex)
-          ? newDate.setDate(0)
-          : newDate.getTime();
-      },
-      d(date, day) {
-        return new Date(date).setDate(parseInt(day, 10));
-      },
-    };
-    parseFns.M = parseFns.m;  // make "M" an alias of "m"
-    // format functions for date parts
-    const formatFns = {
-      d(date) {
-        return date.getDate();
-      },
-      dd(date) {
-        return padZero(date.getDate(), 2);
-      },
-      D(date, locale) {
-        return locale.daysShort[date.getDay()];
-      },
-      DD(date, locale) {
-        return locale.days[date.getDay()];
-      },
-      m(date) {
-        return date.getMonth() + 1;
-      },
-      mm(date) {
-        return padZero(date.getMonth() + 1, 2);
-      },
-      M(date, locale) {
-        return locale.monthsShort[date.getMonth()];
-      },
-      MM(date, locale) {
-        return locale.months[date.getMonth()];
-      },
-      y(date) {
-        return date.getFullYear();
-      },
-      yy(date) {
-        return padZero(date.getFullYear(), 2).slice(-2);
-      },
-      yyyy(date) {
-        return padZero(date.getFullYear(), 4);
-      },
-    };
-
-    // get month index in normal range (0 - 11) from any number
-    function normalizeMonth(monthIndex) {
-      return monthIndex > -1 ? monthIndex % 12 : normalizeMonth(monthIndex + 12);
-    }
-
-    function padZero(num, length) {
-      return num.toString().padStart(length, '0');
-    }
-
-    function parseFormatString(format) {
-      if (typeof format !== 'string') {
-        throw new Error("Invalid date format.");
-      }
-      if (format in knownFormats) {
-        return knownFormats[format];
-      }
-
-      // sprit the format string into parts and seprators
-      const separators = format.split(reFormatTokens);
-      const parts = format.match(new RegExp(reFormatTokens, 'g'));
-      if (separators.length === 0 || !parts) {
-        throw new Error("Invalid date format.");
-      }
-
-      // collect format functions used in the format
-      const partFormatters = parts.map(token => formatFns[token]);
-
-      // collect parse functions used in the format
-      // iterate over parseFns' keys in order to keep the order of the keys.
-      const partParsers = Object.keys(parseFns).reduce((parsers, key) => {
-        const token = parts.find(part => part[0] === key);
-        if (!token) {
-          return parsers;
-        }
-        parsers[key] = parseFns[key];
-        return parsers;
-      }, {});
-      const partParserKeys = Object.keys(partParsers);
-
-      return knownFormats[format] = {
-        parser(dateStr, locale) {
-          const dateParts = dateStr.split(reNonDateParts).reduce((dtParts, part, index) => {
-            if (part.length > 0 && parts[index]) {
-              const token = parts[index][0];
-              if (parseFns[token] !== undefined) {
-                dtParts[token] = part;
-              }
-            }
-            return dtParts;
-          }, {});
-
-          // iterate over partParsers' keys so that the parsing is made in the oder
-          // of year, month and day to prevent the day parser from correcting last
-          // day of month wrongly
-          return partParserKeys.reduce((origDate, key) => {
-            const newDate = partParsers[key](origDate, dateParts[key], locale);
-            // ingnore the part failed to parse
-            return isNaN(newDate) ? origDate : newDate;
-          }, today());
-        },
-        formatter(date, locale) {
-          let dateStr = partFormatters.reduce((str, fn, index) => {
-            return str += `${separators[index]}${fn(date, locale)}`;
-          }, '');
-          // separators' length is always parts' length + 1,
-          return dateStr += lastItemOf(separators);
-        },
-      };
-    }
-
-    function parseDate(dateStr, format, locale) {
-      if (dateStr instanceof Date || typeof dateStr === 'number') {
-        const date = stripTime(dateStr);
-        return isNaN(date) ? undefined : date;
-      }
-      if (!dateStr) {
-        return undefined;
-      }
-      if (dateStr === 'today') {
-        return today();
-      }
-
-      if (format && format.toValue) {
-        const date = format.toValue(dateStr, format, locale);
-        return isNaN(date) ? undefined : stripTime(date);
-      }
-
-      return parseFormatString(format).parser(dateStr, locale);
-    }
-
-    function formatDate(date, format, locale) {
-      if (isNaN(date) || (!date && date !== 0)) {
-        return '';
-      }
-
-      const dateObj = typeof date === 'number' ? new Date(date) : date;
-
-      if (format.toDisplay) {
-        return format.toDisplay(dateObj, format, locale);
-      }
-
-      return parseFormatString(format).formatter(dateObj, locale);
-    }
-
-    const listenerRegistry = new WeakMap();
-    const {addEventListener, removeEventListener} = EventTarget.prototype;
-
-    // Register event listeners to a key object
-    // listeners: array of listener definitions;
-    //   - each definition must be a flat array of event target and the arguments
-    //     used to call addEventListener() on the target
-    function registerListeners(keyObj, listeners) {
-      let registered = listenerRegistry.get(keyObj);
-      if (!registered) {
-        registered = [];
-        listenerRegistry.set(keyObj, registered);
-      }
-      listeners.forEach((listener) => {
-        addEventListener.call(...listener);
-        registered.push(listener);
-      });
-    }
-
-    function unregisterListeners(keyObj) {
-      let listeners = listenerRegistry.get(keyObj);
-      if (!listeners) {
-        return;
-      }
-      listeners.forEach((listener) => {
-        removeEventListener.call(...listener);
-      });
-      listenerRegistry.delete(keyObj);
-    }
-
-    // Event.composedPath() polyfill for Edge
-    // based on https://gist.github.com/kleinfreund/e9787d73776c0e3750dcfcdc89f100ec
-    if (!Event.prototype.composedPath) {
-      const getComposedPath = (node, path = []) => {
-        path.push(node);
-
-        let parent;
-        if (node.parentNode) {
-          parent = node.parentNode;
-        } else if (node.host) { // ShadowRoot
-          parent = node.host;
-        } else if (node.defaultView) {  // Document
-          parent = node.defaultView;
-        }
-        return parent ? getComposedPath(parent, path) : path;
-      };
-
-      Event.prototype.composedPath = function () {
-        return getComposedPath(this.target);
-      };
-    }
-
-    function findFromPath(path, criteria, currentTarget, index = 0) {
-      const el = path[index];
-      if (criteria(el)) {
-        return el;
-      } else if (el === currentTarget || !el.parentElement) {
-        // stop when reaching currentTarget or <html>
-        return;
-      }
-      return findFromPath(path, criteria, currentTarget, index + 1);
-    }
-
-    // Search for the actual target of a delegated event
-    function findElementInEventPath(ev, selector) {
-      const criteria = typeof selector === 'function' ? selector : el => el.matches(selector);
-      return findFromPath(ev.composedPath(), criteria, ev.currentTarget);
-    }
-
-    // default locales
-    const locales = {
-      en: {
-        days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
-        daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
-        daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"],
-        months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
-        monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
-        today: "Today",
-        clear: "Clear",
-        titleFormat: "MM y"
-      }
-    };
-
-    // config options updatable by setOptions() and their default values
-    const defaultOptions = {
-      autohide: false,
-      beforeShowDay: null,
-      beforeShowDecade: null,
-      beforeShowMonth: null,
-      beforeShowYear: null,
-      calendarWeeks: false,
-      clearBtn: false,
-      dateDelimiter: ',',
-      datesDisabled: [],
-      daysOfWeekDisabled: [],
-      daysOfWeekHighlighted: [],
-      defaultViewDate: undefined, // placeholder, defaults to today() by the program
-      disableTouchKeyboard: false,
-      format: 'mm/dd/yyyy',
-      language: 'en',
-      maxDate: null,
-      maxNumberOfDates: 1,
-      maxView: 3,
-      minDate: null,
-      nextArrow: '»',
-      orientation: 'auto',
-      pickLevel: 0,
-      prevArrow: '«',
-      showDaysOfWeek: true,
-      showOnClick: true,
-      showOnFocus: true,
-      startView: 0,
-      title: '',
-      todayBtn: false,
-      todayBtnMode: 0,
-      todayHighlight: false,
-      updateOnBlur: true,
-      weekStart: 0,
-    };
-
-    const range = document.createRange();
-
-    function parseHTML(html) {
-      return range.createContextualFragment(html);
-    }
-
-    function hideElement(el) {
-      if (el.style.display === 'none') {
-        return;
-      }
-      // back up the existing display setting in data-style-display
-      if (el.style.display) {
-        el.dataset.styleDisplay = el.style.display;
-      }
-      el.style.display = 'none';
-    }
-
-    function showElement(el) {
-      if (el.style.display !== 'none') {
-        return;
-      }
-      if (el.dataset.styleDisplay) {
-        // restore backed-up dispay property
-        el.style.display = el.dataset.styleDisplay;
-        delete el.dataset.styleDisplay;
-      } else {
-        el.style.display = '';
-      }
-    }
-
-    function emptyChildNodes(el) {
-      if (el.firstChild) {
-        el.removeChild(el.firstChild);
-        emptyChildNodes(el);
-      }
-    }
-
-    function replaceChildNodes(el, newChildNodes) {
-      emptyChildNodes(el);
-      if (newChildNodes instanceof DocumentFragment) {
-        el.appendChild(newChildNodes);
-      } else if (typeof newChildNodes === 'string') {
-        el.appendChild(parseHTML(newChildNodes));
-      } else if (typeof newChildNodes.forEach === 'function') {
-        newChildNodes.forEach((node) => {
-          el.appendChild(node);
-        });
-      }
-    }
-
-    const {
-      language: defaultLang,
-      format: defaultFormat,
-      weekStart: defaultWeekStart,
-    } = defaultOptions;
-
-    // Reducer function to filter out invalid day-of-week from the input
-    function sanitizeDOW(dow, day) {
-      return dow.length < 6 && day >= 0 && day < 7
-        ? pushUnique(dow, day)
-        : dow;
-    }
-
-    function calcEndOfWeek(startOfWeek) {
-      return (startOfWeek + 6) % 7;
-    }
-
-    // validate input date. if invalid, fallback to the original value
-    function validateDate(value, format, locale, origValue) {
-      const date = parseDate(value, format, locale);
-      return date !== undefined ? date : origValue;
-    }
-
-    // Validate viewId. if invalid, fallback to the original value
-    function validateViewId(value, origValue, max = 3) {
-      const viewId = parseInt(value, 10);
-      return viewId >= 0 && viewId <= max ? viewId : origValue;
-    }
-
-    // Create Datepicker configuration to set
-    function processOptions(options, datepicker) {
-      const inOpts = Object.assign({}, options);
-      const config = {};
-      const locales = datepicker.constructor.locales;
-      let {
-        format,
-        language,
-        locale,
-        maxDate,
-        maxView,
-        minDate,
-        pickLevel,
-        startView,
-        weekStart,
-      } = datepicker.config || {};
-
-      if (inOpts.language) {
-        let lang;
-        if (inOpts.language !== language) {
-          if (locales[inOpts.language]) {
-            lang = inOpts.language;
-          } else {
-            // Check if langauge + region tag can fallback to the one without
-            // region (e.g. fr-CA → fr)
-            lang = inOpts.language.split('-')[0];
-            if (locales[lang] === undefined) {
-              lang = false;
-            }
-          }
-        }
-        delete inOpts.language;
-        if (lang) {
-          language = config.language = lang;
-
-          // update locale as well when updating language
-          const origLocale = locale || locales[defaultLang];
-          // use default language's properties for the fallback
-          locale = Object.assign({
-            format: defaultFormat,
-            weekStart: defaultWeekStart
-          }, locales[defaultLang]);
-          if (language !== defaultLang) {
-            Object.assign(locale, locales[language]);
-          }
-          config.locale = locale;
-          // if format and/or weekStart are the same as old locale's defaults,
-          // update them to new locale's defaults
-          if (format === origLocale.format) {
-            format = config.format = locale.format;
-          }
-          if (weekStart === origLocale.weekStart) {
-            weekStart = config.weekStart = locale.weekStart;
-            config.weekEnd = calcEndOfWeek(locale.weekStart);
-          }
-        }
-      }
-
-      if (inOpts.format) {
-        const hasToDisplay = typeof inOpts.format.toDisplay === 'function';
-        const hasToValue = typeof inOpts.format.toValue === 'function';
-        const validFormatString = reFormatTokens.test(inOpts.format);
-        if ((hasToDisplay && hasToValue) || validFormatString) {
-          format = config.format = inOpts.format;
-        }
-        delete inOpts.format;
-      }
-
-      //*** dates ***//
-      // while min and maxDate for "no limit" in the options are better to be null
-      // (especially when updating), the ones in the config have to be undefined
-      // because null is treated as 0 (= unix epoch) when comparing with time value
-      let minDt = minDate;
-      let maxDt = maxDate;
-      if (inOpts.minDate !== undefined) {
-        minDt = inOpts.minDate === null
-          ? dateValue(0, 0, 1)  // set 0000-01-01 to prevent negative values for year
-          : validateDate(inOpts.minDate, format, locale, minDt);
-        delete inOpts.minDate;
-      }
-      if (inOpts.maxDate !== undefined) {
-        maxDt = inOpts.maxDate === null
-          ? undefined
-          : validateDate(inOpts.maxDate, format, locale, maxDt);
-        delete inOpts.maxDate;
-      }
-      if (maxDt < minDt) {
-        minDate = config.minDate = maxDt;
-        maxDate = config.maxDate = minDt;
-      } else {
-        if (minDate !== minDt) {
-          minDate = config.minDate = minDt;
-        }
-        if (maxDate !== maxDt) {
-          maxDate = config.maxDate = maxDt;
-        }
-      }
-
-      if (inOpts.datesDisabled) {
-        config.datesDisabled = inOpts.datesDisabled.reduce((dates, dt) => {
-          const date = parseDate(dt, format, locale);
-          return date !== undefined ? pushUnique(dates, date) : dates;
-        }, []);
-        delete inOpts.datesDisabled;
-      }
-      if (inOpts.defaultViewDate !== undefined) {
-        const viewDate = parseDate(inOpts.defaultViewDate, format, locale);
-        if (viewDate !== undefined) {
-          config.defaultViewDate = viewDate;
-        }
-        delete inOpts.defaultViewDate;
-      }
-
-      //*** days of week ***//
-      if (inOpts.weekStart !== undefined) {
-        const wkStart = Number(inOpts.weekStart) % 7;
-        if (!isNaN(wkStart)) {
-          weekStart = config.weekStart = wkStart;
-          config.weekEnd = calcEndOfWeek(wkStart);
-        }
-        delete inOpts.weekStart;
-      }
-      if (inOpts.daysOfWeekDisabled) {
-        config.daysOfWeekDisabled = inOpts.daysOfWeekDisabled.reduce(sanitizeDOW, []);
-        delete inOpts.daysOfWeekDisabled;
-      }
-      if (inOpts.daysOfWeekHighlighted) {
-        config.daysOfWeekHighlighted = inOpts.daysOfWeekHighlighted.reduce(sanitizeDOW, []);
-        delete inOpts.daysOfWeekHighlighted;
-      }
-
-      //*** multi date ***//
-      if (inOpts.maxNumberOfDates !== undefined) {
-        const maxNumberOfDates = parseInt(inOpts.maxNumberOfDates, 10);
-        if (maxNumberOfDates >= 0) {
-          config.maxNumberOfDates = maxNumberOfDates;
-          config.multidate = maxNumberOfDates !== 1;
-        }
-        delete inOpts.maxNumberOfDates;
-      }
-      if (inOpts.dateDelimiter) {
-        config.dateDelimiter = String(inOpts.dateDelimiter);
-        delete inOpts.dateDelimiter;
-      }
-
-      //*** pick level & view ***//
-      let newPickLevel = pickLevel;
-      if (inOpts.pickLevel !== undefined) {
-        newPickLevel = validateViewId(inOpts.pickLevel, 2);
-        delete inOpts.pickLevel;
-      }
-      if (newPickLevel !== pickLevel) {
-        pickLevel = config.pickLevel = newPickLevel;
-      }
-
-      let newMaxView = maxView;
-      if (inOpts.maxView !== undefined) {
-        newMaxView = validateViewId(inOpts.maxView, maxView);
-        delete inOpts.maxView;
-      }
-      // ensure max view >= pick level
-      newMaxView = pickLevel > newMaxView ? pickLevel : newMaxView;
-      if (newMaxView !== maxView) {
-        maxView = config.maxView = newMaxView;
-      }
-
-      let newStartView = startView;
-      if (inOpts.startView !== undefined) {
-        newStartView = validateViewId(inOpts.startView, newStartView);
-        delete inOpts.startView;
-      }
-      // ensure pick level <= start view <= max view
-      if (newStartView < pickLevel) {
-        newStartView = pickLevel;
-      } else if (newStartView > maxView) {
-        newStartView = maxView;
-      }
-      if (newStartView !== startView) {
-        config.startView = newStartView;
-      }
-
-      //*** template ***//
-      if (inOpts.prevArrow) {
-        const prevArrow = parseHTML(inOpts.prevArrow);
-        if (prevArrow.childNodes.length > 0) {
-          config.prevArrow = prevArrow.childNodes;
-        }
-        delete inOpts.prevArrow;
-      }
-      if (inOpts.nextArrow) {
-        const nextArrow = parseHTML(inOpts.nextArrow);
-        if (nextArrow.childNodes.length > 0) {
-          config.nextArrow = nextArrow.childNodes;
-        }
-        delete inOpts.nextArrow;
-      }
-
-      //*** misc ***//
-      if (inOpts.disableTouchKeyboard !== undefined) {
-        config.disableTouchKeyboard = 'ontouchstart' in document && !!inOpts.disableTouchKeyboard;
-        delete inOpts.disableTouchKeyboard;
-      }
-      if (inOpts.orientation) {
-        const orientation = inOpts.orientation.toLowerCase().split(/\s+/g);
-        config.orientation = {
-          x: orientation.find(x => (x === 'left' || x === 'right')) || 'auto',
-          y: orientation.find(y => (y === 'top' || y === 'bottom')) || 'auto',
-        };
-        delete inOpts.orientation;
-      }
-      if (inOpts.todayBtnMode !== undefined) {
-        switch(inOpts.todayBtnMode) {
-          case 0:
-          case 1:
-            config.todayBtnMode = inOpts.todayBtnMode;
-        }
-        delete inOpts.todayBtnMode;
-      }
-
-      //*** copy the rest ***//
-      Object.keys(inOpts).forEach((key) => {
-        if (inOpts[key] !== undefined && hasProperty(defaultOptions, key)) {
-          config[key] = inOpts[key];
-        }
-      });
-
-      return config;
-    }
-
-    const pickerTemplate = optimizeTemplateHTML(`<div class="datepicker">
-  <div class="datepicker-picker">
-    <div class="datepicker-header">
-      <div class="datepicker-title"></div>
-      <div class="datepicker-controls">
-        <button class="%buttonClass% prev-btn"></button>
-        <button class="%buttonClass% view-switch"></button>
-        <button class="%buttonClass% next-btn"></button>
-      </div>
-    </div>
-    <div class="datepicker-main"></div>
-    <div class="datepicker-footer">
-      <div class="datepicker-controls">
-        <button class="%buttonClass% today-btn"></button>
-        <button class="%buttonClass% clear-btn"></button>
-      </div>
-    </div>
-  </div>
-</div>`);
-
-    const daysTemplate = optimizeTemplateHTML(`<div class="days">
-  <div class="days-of-week">${createTagRepeat('span', 7, {class: 'dow'})}</div>
-  <div class="datepicker-grid">${createTagRepeat('span', 42)}</div>
-</div>`);
-
-    const calendarWeeksTemplate = optimizeTemplateHTML(`<div class="calendar-weeks">
-  <div class="days-of-week"><span class="dow"></span></div>
-  <div class="weeks">${createTagRepeat('span', 6, {class: 'week'})}</div>
-</div>`);
-
-    // Base class of the view classes
-    class View {
-      constructor(picker, config) {
-        Object.assign(this, config, {
-          picker,
-          element: parseHTML(`<div class="datepicker-view"></div>`).firstChild,
-          selected: [],
-        });
-        this.init(this.picker.datepicker.config);
-      }
-
-      init(options) {
-        if (options.pickLevel !== undefined) {
-          this.isMinView = this.id === options.pickLevel;
-        }
-        this.setOptions(options);
-        this.updateFocus();
-        this.updateSelection();
-      }
-
-      // Execute beforeShow() callback and apply the result to the element
-      // args:
-      // - current - current value on the iteration on view rendering
-      // - timeValue - time value of the date to pass to beforeShow()
-      performBeforeHook(el, current, timeValue) {
-        let result = this.beforeShow(new Date(timeValue));
-        switch (typeof result) {
-          case 'boolean':
-            result = {enabled: result};
-            break;
-          case 'string':
-            result = {classes: result};
-        }
-
-        if (result) {
-          if (result.enabled === false) {
-            el.classList.add('disabled');
-            pushUnique(this.disabled, current);
-          }
-          if (result.classes) {
-            const extraClasses = result.classes.split(/\s+/);
-            el.classList.add(...extraClasses);
-            if (extraClasses.includes('disabled')) {
-              pushUnique(this.disabled, current);
-            }
-          }
-          if (result.content) {
-            replaceChildNodes(el, result.content);
-          }
-        }
-      }
-    }
-
-    class DaysView extends View {
-      constructor(picker) {
-        super(picker, {
-          id: 0,
-          name: 'days',
-          cellClass: 'day',
-        });
-      }
-
-      init(options, onConstruction = true) {
-        if (onConstruction) {
-          const inner = parseHTML(daysTemplate).firstChild;
-          this.dow = inner.firstChild;
-          this.grid = inner.lastChild;
-          this.element.appendChild(inner);
-        }
-        super.init(options);
-      }
-
-      setOptions(options) {
-        let updateDOW;
-
-        if (hasProperty(options, 'minDate')) {
-          this.minDate = options.minDate;
-        }
-        if (hasProperty(options, 'maxDate')) {
-          this.maxDate = options.maxDate;
-        }
-        if (options.datesDisabled) {
-          this.datesDisabled = options.datesDisabled;
-        }
-        if (options.daysOfWeekDisabled) {
-          this.daysOfWeekDisabled = options.daysOfWeekDisabled;
-          updateDOW = true;
-        }
-        if (options.daysOfWeekHighlighted) {
-          this.daysOfWeekHighlighted = options.daysOfWeekHighlighted;
-        }
-        if (options.todayHighlight !== undefined) {
-          this.todayHighlight = options.todayHighlight;
-        }
-        if (options.weekStart !== undefined) {
-          this.weekStart = options.weekStart;
-          this.weekEnd = options.weekEnd;
-          updateDOW = true;
-        }
-        if (options.locale) {
-          const locale = this.locale = options.locale;
-          this.dayNames = locale.daysMin;
-          this.switchLabelFormat = locale.titleFormat;
-          updateDOW = true;
-        }
-        if (options.beforeShowDay !== undefined) {
-          this.beforeShow = typeof options.beforeShowDay === 'function'
-            ? options.beforeShowDay
-            : undefined;
-        }
-
-        if (options.calendarWeeks !== undefined) {
-          if (options.calendarWeeks && !this.calendarWeeks) {
-            const weeksElem = parseHTML(calendarWeeksTemplate).firstChild;
-            this.calendarWeeks = {
-              element: weeksElem,
-              dow: weeksElem.firstChild,
-              weeks: weeksElem.lastChild,
-            };
-            this.element.insertBefore(weeksElem, this.element.firstChild);
-          } else if (this.calendarWeeks && !options.calendarWeeks) {
-            this.element.removeChild(this.calendarWeeks.element);
-            this.calendarWeeks = null;
-          }
-        }
-        if (options.showDaysOfWeek !== undefined) {
-          if (options.showDaysOfWeek) {
-            showElement(this.dow);
-            if (this.calendarWeeks) {
-              showElement(this.calendarWeeks.dow);
-            }
-          } else {
-            hideElement(this.dow);
-            if (this.calendarWeeks) {
-              hideElement(this.calendarWeeks.dow);
-            }
-          }
-        }
-
-        // update days-of-week when locale, daysOfweekDisabled or weekStart is changed
-        if (updateDOW) {
-          Array.from(this.dow.children).forEach((el, index) => {
-            const dow = (this.weekStart + index) % 7;
-            el.textContent = this.dayNames[dow];
-            el.className = this.daysOfWeekDisabled.includes(dow) ? 'dow disabled' : 'dow';
-          });
-        }
-      }
-
-      // Apply update on the focused date to view's settings
-      updateFocus() {
-        const viewDate = new Date(this.picker.viewDate);
-        const viewYear = viewDate.getFullYear();
-        const viewMonth = viewDate.getMonth();
-        const firstOfMonth = dateValue(viewYear, viewMonth, 1);
-        const start = dayOfTheWeekOf(firstOfMonth, this.weekStart, this.weekStart);
-
-        this.first = firstOfMonth;
-        this.last = dateValue(viewYear, viewMonth + 1, 0);
-        this.start = start;
-        this.focused = this.picker.viewDate;
-      }
-
-      // Apply update on the selected dates to view's settings
-      updateSelection() {
-        const {dates, rangepicker} = this.picker.datepicker;
-        this.selected = dates;
-        if (rangepicker) {
-          this.range = rangepicker.dates;
-        }
-      }
-
-       // Update the entire view UI
-      render() {
-        // update today marker on ever render
-        this.today = this.todayHighlight ? today() : undefined;
-        // refresh disabled dates on every render in order to clear the ones added
-        // by beforeShow hook at previous render
-        this.disabled = [...this.datesDisabled];
-
-        const switchLabel = formatDate(this.focused, this.switchLabelFormat, this.locale);
-        this.picker.setViewSwitchLabel(switchLabel);
-        this.picker.setPrevBtnDisabled(this.first <= this.minDate);
-        this.picker.setNextBtnDisabled(this.last >= this.maxDate);
-
-        if (this.calendarWeeks) {
-          // start of the UTC week (Monday) of the 1st of the month
-          const startOfWeek = dayOfTheWeekOf(this.first, 1, 1);
-          Array.from(this.calendarWeeks.weeks.children).forEach((el, index) => {
-            el.textContent = getWeek(addWeeks(startOfWeek, index));
-          });
-        }
-        Array.from(this.grid.children).forEach((el, index) => {
-          const classList = el.classList;
-          const current = addDays(this.start, index);
-          const date = new Date(current);
-          const day = date.getDay();
-
-          el.className = `datepicker-cell ${this.cellClass}`;
-          el.dataset.date = current;
-          el.textContent = date.getDate();
-
-          if (current < this.first) {
-            classList.add('prev');
-          } else if (current > this.last) {
-            classList.add('next');
-          }
-          if (this.today === current) {
-            classList.add('today');
-          }
-          if (current < this.minDate || current > this.maxDate || this.disabled.includes(current)) {
-            classList.add('disabled');
-          }
-          if (this.daysOfWeekDisabled.includes(day)) {
-            classList.add('disabled');
-            pushUnique(this.disabled, current);
-          }
-          if (this.daysOfWeekHighlighted.includes(day)) {
-            classList.add('highlighted');
-          }
-          if (this.range) {
-            const [rangeStart, rangeEnd] = this.range;
-            if (current > rangeStart && current < rangeEnd) {
-              classList.add('range');
-            }
-            if (current === rangeStart) {
-              classList.add('range-start');
-            }
-            if (current === rangeEnd) {
-              classList.add('range-end');
-            }
-          }
-          if (this.selected.includes(current)) {
-            classList.add('selected');
-          }
-          if (current === this.focused) {
-            classList.add('focused');
-          }
-
-          if (this.beforeShow) {
-            this.performBeforeHook(el, current, current);
-          }
-        });
-      }
-
-      // Update the view UI by applying the changes of selected and focused items
-      refresh() {
-        const [rangeStart, rangeEnd] = this.range || [];
-        this.grid
-          .querySelectorAll('.range, .range-start, .range-end, .selected, .focused')
-          .forEach((el) => {
-            el.classList.remove('range', 'range-start', 'range-end', 'selected', 'focused');
-          });
-        Array.from(this.grid.children).forEach((el) => {
-          const current = Number(el.dataset.date);
-          const classList = el.classList;
-          if (current > rangeStart && current < rangeEnd) {
-            classList.add('range');
-          }
-          if (current === rangeStart) {
-            classList.add('range-start');
-          }
-          if (current === rangeEnd) {
-            classList.add('range-end');
-          }
-          if (this.selected.includes(current)) {
-            classList.add('selected');
-          }
-          if (current === this.focused) {
-            classList.add('focused');
-          }
-        });
-      }
-
-      // Update the view UI by applying the change of focused item
-      refreshFocus() {
-        const index = Math.round((this.focused - this.start) / 86400000);
-        this.grid.querySelectorAll('.focused').forEach((el) => {
-          el.classList.remove('focused');
-        });
-        this.grid.children[index].classList.add('focused');
-      }
-    }
-
-    function computeMonthRange(range, thisYear) {
-      if (!range || !range[0] || !range[1]) {
-        return;
-      }
-
-      const [[startY, startM], [endY, endM]] = range;
-      if (startY > thisYear || endY < thisYear) {
-        return;
-      }
-      return [
-        startY === thisYear ? startM : -1,
-        endY === thisYear ? endM : 12,
-      ];
-    }
-
-    class MonthsView extends View {
-      constructor(picker) {
-        super(picker, {
-          id: 1,
-          name: 'months',
-          cellClass: 'month',
-        });
-      }
-
-      init(options, onConstruction = true) {
-        if (onConstruction) {
-          this.grid = this.element;
-          this.element.classList.add('months', 'datepicker-grid');
-          this.grid.appendChild(parseHTML(createTagRepeat('span', 12, {'data-month': ix => ix})));
-        }
-        super.init(options);
-      }
-
-      setOptions(options) {
-        if (options.locale) {
-          this.monthNames = options.locale.monthsShort;
-        }
-        if (hasProperty(options, 'minDate')) {
-          if (options.minDate === undefined) {
-            this.minYear = this.minMonth = this.minDate = undefined;
-          } else {
-            const minDateObj = new Date(options.minDate);
-            this.minYear = minDateObj.getFullYear();
-            this.minMonth = minDateObj.getMonth();
-            this.minDate = minDateObj.setDate(1);
-          }
-        }
-        if (hasProperty(options, 'maxDate')) {
-          if (options.maxDate === undefined) {
-            this.maxYear = this.maxMonth = this.maxDate = undefined;
-          } else {
-            const maxDateObj = new Date(options.maxDate);
-            this.maxYear = maxDateObj.getFullYear();
-            this.maxMonth = maxDateObj.getMonth();
-            this.maxDate = dateValue(this.maxYear, this.maxMonth + 1, 0);
-          }
-        }
-        if (options.beforeShowMonth !== undefined) {
-          this.beforeShow = typeof options.beforeShowMonth === 'function'
-            ? options.beforeShowMonth
-            : undefined;
-        }
-      }
-
-      // Update view's settings to reflect the viewDate set on the picker
-      updateFocus() {
-        const viewDate = new Date(this.picker.viewDate);
-        this.year = viewDate.getFullYear();
-        this.focused = viewDate.getMonth();
-      }
-
-      // Update view's settings to reflect the selected dates
-      updateSelection() {
-        const {dates, rangepicker} = this.picker.datepicker;
-        this.selected = dates.reduce((selected, timeValue) => {
-          const date = new Date(timeValue);
-          const year = date.getFullYear();
-          const month = date.getMonth();
-          if (selected[year] === undefined) {
-            selected[year] = [month];
-          } else {
-            pushUnique(selected[year], month);
-          }
-          return selected;
-        }, {});
-        if (rangepicker && rangepicker.dates) {
-          this.range = rangepicker.dates.map(timeValue => {
-            const date = new Date(timeValue);
-            return isNaN(date) ? undefined : [date.getFullYear(), date.getMonth()];
-          });
-        }
-      }
-
-      // Update the entire view UI
-      render() {
-        // refresh disabled months on every render in order to clear the ones added
-        // by beforeShow hook at previous render
-        this.disabled = [];
-
-        this.picker.setViewSwitchLabel(this.year);
-        this.picker.setPrevBtnDisabled(this.year <= this.minYear);
-        this.picker.setNextBtnDisabled(this.year >= this.maxYear);
-
-        const selected = this.selected[this.year] || [];
-        const yrOutOfRange = this.year < this.minYear || this.year > this.maxYear;
-        const isMinYear = this.year === this.minYear;
-        const isMaxYear = this.year === this.maxYear;
-        const range = computeMonthRange(this.range, this.year);
-
-        Array.from(this.grid.children).forEach((el, index) => {
-          const classList = el.classList;
-          const date = dateValue(this.year, index, 1);
-
-          el.className = `datepicker-cell ${this.cellClass}`;
-          if (this.isMinView) {
-            el.dataset.date = date;
-          }
-          // reset text on every render to clear the custom content set
-          // by beforeShow hook at previous render
-          el.textContent = this.monthNames[index];
-
-          if (
-            yrOutOfRange
-            || isMinYear && index < this.minMonth
-            || isMaxYear && index > this.maxMonth
-          ) {
-            classList.add('disabled');
-          }
-          if (range) {
-            const [rangeStart, rangeEnd] = range;
-            if (index > rangeStart && index < rangeEnd) {
-              classList.add('range');
-            }
-            if (index === rangeStart) {
-              classList.add('range-start');
-            }
-            if (index === rangeEnd) {
-              classList.add('range-end');
-            }
-          }
-          if (selected.includes(index)) {
-            classList.add('selected');
-          }
-          if (index === this.focused) {
-            classList.add('focused');
-          }
-
-          if (this.beforeShow) {
-            this.performBeforeHook(el, index, date);
-          }
-        });
-      }
-
-      // Update the view UI by applying the changes of selected and focused items
-      refresh() {
-        const selected = this.selected[this.year] || [];
-        const [rangeStart, rangeEnd] = computeMonthRange(this.range, this.year) || [];
-        this.grid
-          .querySelectorAll('.range, .range-start, .range-end, .selected, .focused')
-          .forEach((el) => {
-            el.classList.remove('range', 'range-start', 'range-end', 'selected', 'focused');
-          });
-        Array.from(this.grid.children).forEach((el, index) => {
-          const classList = el.classList;
-          if (index > rangeStart && index < rangeEnd) {
-            classList.add('range');
-          }
-          if (index === rangeStart) {
-            classList.add('range-start');
-          }
-          if (index === rangeEnd) {
-            classList.add('range-end');
-          }
-          if (selected.includes(index)) {
-            classList.add('selected');
-          }
-          if (index === this.focused) {
-            classList.add('focused');
-          }
-        });
-      }
-
-      // Update the view UI by applying the change of focused item
-      refreshFocus() {
-        this.grid.querySelectorAll('.focused').forEach((el) => {
-          el.classList.remove('focused');
-        });
-        this.grid.children[this.focused].classList.add('focused');
-      }
-    }
-
-    function toTitleCase(word) {
-      return [...word].reduce((str, ch, ix) => str += ix ? ch : ch.toUpperCase(), '');
-    }
-
-    // Class representing the years and decades view elements
-    class YearsView extends View {
-      constructor(picker, config) {
-        super(picker, config);
-      }
-
-      init(options, onConstruction = true) {
-        if (onConstruction) {
-          this.navStep = this.step * 10;
-          this.beforeShowOption = `beforeShow${toTitleCase(this.cellClass)}`;
-          this.grid = this.element;
-          this.element.classList.add(this.name, 'datepicker-grid');
-          this.grid.appendChild(parseHTML(createTagRepeat('span', 12)));
-        }
-        super.init(options);
-      }
-
-      setOptions(options) {
-        if (hasProperty(options, 'minDate')) {
-          if (options.minDate === undefined) {
-            this.minYear = this.minDate = undefined;
-          } else {
-            this.minYear = startOfYearPeriod(options.minDate, this.step);
-            this.minDate = dateValue(this.minYear, 0, 1);
-          }
-        }
-        if (hasProperty(options, 'maxDate')) {
-          if (options.maxDate === undefined) {
-            this.maxYear = this.maxDate = undefined;
-          } else {
-            this.maxYear = startOfYearPeriod(options.maxDate, this.step);
-            this.maxDate = dateValue(this.maxYear, 11, 31);
-          }
-        }
-        if (options[this.beforeShowOption] !== undefined) {
-          const beforeShow = options[this.beforeShowOption];
-          this.beforeShow = typeof beforeShow === 'function' ? beforeShow : undefined;
-        }
-      }
-
-      // Update view's settings to reflect the viewDate set on the picker
-      updateFocus() {
-        const viewDate = new Date(this.picker.viewDate);
-        const first = startOfYearPeriod(viewDate, this.navStep);
-        const last = first + 9 * this.step;
-
-        this.first = first;
-        this.last = last;
-        this.start = first - this.step;
-        this.focused = startOfYearPeriod(viewDate, this.step);
-      }
-
-      // Update view's settings to reflect the selected dates
-      updateSelection() {
-        const {dates, rangepicker} = this.picker.datepicker;
-        this.selected = dates.reduce((years, timeValue) => {
-          return pushUnique(years, startOfYearPeriod(timeValue, this.step));
-        }, []);
-        if (rangepicker && rangepicker.dates) {
-          this.range = rangepicker.dates.map(timeValue => {
-            if (timeValue !== undefined) {
-              return startOfYearPeriod(timeValue, this.step);
-            }
-          });
-        }
-      }
-
-      // Update the entire view UI
-      render() {
-        // refresh disabled years on every render in order to clear the ones added
-        // by beforeShow hook at previous render
-        this.disabled = [];
-
-        this.picker.setViewSwitchLabel(`${this.first}-${this.last}`);
-        this.picker.setPrevBtnDisabled(this.first <= this.minYear);
-        this.picker.setNextBtnDisabled(this.last >= this.maxYear);
-
-        Array.from(this.grid.children).forEach((el, index) => {
-          const classList = el.classList;
-          const current = this.start + (index * this.step);
-          const date = dateValue(current, 0, 1);
-
-          el.className = `datepicker-cell ${this.cellClass}`;
-          if (this.isMinView) {
-            el.dataset.date = date;
-          }
-          el.textContent = el.dataset.year = current;
-
-          if (index === 0) {
-            classList.add('prev');
-          } else if (index === 11) {
-            classList.add('next');
-          }
-          if (current < this.minYear || current > this.maxYear) {
-            classList.add('disabled');
-          }
-          if (this.range) {
-            const [rangeStart, rangeEnd] = this.range;
-            if (current > rangeStart && current < rangeEnd) {
-              classList.add('range');
-            }
-            if (current === rangeStart) {
-              classList.add('range-start');
-            }
-            if (current === rangeEnd) {
-              classList.add('range-end');
-            }
-          }
-          if (this.selected.includes(current)) {
-            classList.add('selected');
-          }
-          if (current === this.focused) {
-            classList.add('focused');
-          }
-
-          if (this.beforeShow) {
-            this.performBeforeHook(el, current, date);
-          }
-        });
-      }
-
-      // Update the view UI by applying the changes of selected and focused items
-      refresh() {
-        const [rangeStart, rangeEnd] = this.range || [];
-        this.grid
-          .querySelectorAll('.range, .range-start, .range-end, .selected, .focused')
-          .forEach((el) => {
-            el.classList.remove('range', 'range-start', 'range-end', 'selected', 'focused');
-          });
-        Array.from(this.grid.children).forEach((el) => {
-          const current = Number(el.textContent);
-          const classList = el.classList;
-          if (current > rangeStart && current < rangeEnd) {
-            classList.add('range');
-          }
-          if (current === rangeStart) {
-            classList.add('range-start');
-          }
-          if (current === rangeEnd) {
-            classList.add('range-end');
-          }
-          if (this.selected.includes(current)) {
-            classList.add('selected');
-          }
-          if (current === this.focused) {
-            classList.add('focused');
-          }
-        });
-      }
-
-      // Update the view UI by applying the change of focused item
-      refreshFocus() {
-        const index = Math.round((this.focused - this.start) / this.step);
-        this.grid.querySelectorAll('.focused').forEach((el) => {
-          el.classList.remove('focused');
-        });
-        this.grid.children[index].classList.add('focused');
-      }
-    }
-
-    function triggerDatepickerEvent(datepicker, type) {
-      const detail = {
-        date: datepicker.getDate(),
-        viewDate: new Date(datepicker.picker.viewDate),
-        viewId: datepicker.picker.currentView.id,
-        datepicker,
-      };
-      datepicker.element.dispatchEvent(new CustomEvent(type, {detail}));
-    }
-
-    // direction: -1 (to previous), 1 (to next)
-    function goToPrevOrNext(datepicker, direction) {
-      const {minDate, maxDate} = datepicker.config;
-      const {currentView, viewDate} = datepicker.picker;
-      let newViewDate;
-      switch (currentView.id) {
-        case 0:
-          newViewDate = addMonths(viewDate, direction);
-          break;
-        case 1:
-          newViewDate = addYears(viewDate, direction);
-          break;
-        default:
-          newViewDate = addYears(viewDate, direction * currentView.navStep);
-      }
-      newViewDate = limitToRange(newViewDate, minDate, maxDate);
-      datepicker.picker.changeFocus(newViewDate).render();
-    }
-
-    function switchView(datepicker) {
-      const viewId = datepicker.picker.currentView.id;
-      if (viewId === datepicker.config.maxView) {
-        return;
-      }
-      datepicker.picker.changeView(viewId + 1).render();
-    }
-
-    function unfocus(datepicker) {
-      if (datepicker.config.updateOnBlur) {
-        datepicker.update({autohide: true});
-      } else {
-        datepicker.refresh('input');
-        datepicker.hide();
-      }
-    }
-
-    function goToSelectedMonthOrYear(datepicker, selection) {
-      const picker = datepicker.picker;
-      const viewDate = new Date(picker.viewDate);
-      const viewId = picker.currentView.id;
-      const newDate = viewId === 1
-        ? addMonths(viewDate, selection - viewDate.getMonth())
-        : addYears(viewDate, selection - viewDate.getFullYear());
-
-      picker.changeFocus(newDate).changeView(viewId - 1).render();
-    }
-
-    function onClickTodayBtn(datepicker) {
-      const picker = datepicker.picker;
-      const currentDate = today();
-      if (datepicker.config.todayBtnMode === 1) {
-        if (datepicker.config.autohide) {
-          datepicker.setDate(currentDate);
-          return;
-        }
-        datepicker.setDate(currentDate, {render: false});
-        picker.update();
-      }
-      if (picker.viewDate !== currentDate) {
-        picker.changeFocus(currentDate);
-      }
-      picker.changeView(0).render();
-    }
-
-    function onClickClearBtn(datepicker) {
-      datepicker.setDate({clear: true});
-    }
-
-    function onClickViewSwitch(datepicker) {
-      switchView(datepicker);
-    }
-
-    function onClickPrevBtn(datepicker) {
-      goToPrevOrNext(datepicker, -1);
-    }
-
-    function onClickNextBtn(datepicker) {
-      goToPrevOrNext(datepicker, 1);
-    }
-
-    // For the picker's main block to delegete the events from `datepicker-cell`s
-    function onClickView(datepicker, ev) {
-      const target = findElementInEventPath(ev, '.datepicker-cell');
-      if (!target || target.classList.contains('disabled')) {
-        return;
-      }
-
-      const {id, isMinView} = datepicker.picker.currentView;
-      if (isMinView) {
-        datepicker.setDate(Number(target.dataset.date));
-      } else if (id === 1) {
-        goToSelectedMonthOrYear(datepicker, Number(target.dataset.month));
-      } else {
-        goToSelectedMonthOrYear(datepicker, Number(target.dataset.year));
-      }
-    }
-
-    function onClickPicker(datepicker) {
-      if (!datepicker.inline && !datepicker.config.disableTouchKeyboard) {
-        datepicker.inputField.focus();
-      }
-    }
-
-    function processPickerOptions(picker, options) {
-      if (options.title !== undefined) {
-        if (options.title) {
-          picker.controls.title.textContent = options.title;
-          showElement(picker.controls.title);
-        } else {
-          picker.controls.title.textContent = '';
-          hideElement(picker.controls.title);
-        }
-      }
-      if (options.prevArrow) {
-        const prevBtn = picker.controls.prevBtn;
-        emptyChildNodes(prevBtn);
-        options.prevArrow.forEach((node) => {
-          prevBtn.appendChild(node.cloneNode(true));
-        });
-      }
-      if (options.nextArrow) {
-        const nextBtn = picker.controls.nextBtn;
-        emptyChildNodes(nextBtn);
-        options.nextArrow.forEach((node) => {
-          nextBtn.appendChild(node.cloneNode(true));
-        });
-      }
-      if (options.locale) {
-        picker.controls.todayBtn.textContent = options.locale.today;
-        picker.controls.clearBtn.textContent = options.locale.clear;
-      }
-      if (options.todayBtn !== undefined) {
-        if (options.todayBtn) {
-          showElement(picker.controls.todayBtn);
-        } else {
-          hideElement(picker.controls.todayBtn);
-        }
-      }
-      if (hasProperty(options, 'minDate') || hasProperty(options, 'maxDate')) {
-        const {minDate, maxDate} = picker.datepicker.config;
-        picker.controls.todayBtn.disabled = !isInRange(today(), minDate, maxDate);
-      }
-      if (options.clearBtn !== undefined) {
-        if (options.clearBtn) {
-          showElement(picker.controls.clearBtn);
-        } else {
-          hideElement(picker.controls.clearBtn);
-        }
-      }
-    }
-
-    // Compute view date to reset, which will be...
-    // - the last item of the selected dates or defaultViewDate if no selection
-    // - limitted to minDate or maxDate if it exceeds the range
-    function computeResetViewDate(datepicker) {
-      const {dates, config} = datepicker;
-      const viewDate = dates.length > 0 ? lastItemOf(dates) : config.defaultViewDate;
-      return limitToRange(viewDate, config.minDate, config.maxDate);
-    }
-
-    // Change current view's view date
-    function setViewDate(picker, newDate) {
-      const oldViewDate = new Date(picker.viewDate);
-      const newViewDate = new Date(newDate);
-      const {id, year, first, last} = picker.currentView;
-      const viewYear = newViewDate.getFullYear();
-
-      picker.viewDate = newDate;
-      if (viewYear !== oldViewDate.getFullYear()) {
-        triggerDatepickerEvent(picker.datepicker, 'changeYear');
-      }
-      if (newViewDate.getMonth() !== oldViewDate.getMonth()) {
-        triggerDatepickerEvent(picker.datepicker, 'changeMonth');
-      }
-
-      // return whether the new date is in different period on time from the one
-      // displayed in the current view
-      // when true, the view needs to be re-rendered on the next UI refresh.
-      switch (id) {
-        case 0:
-          return newDate < first || newDate > last;
-        case 1:
-          return viewYear !== year;
-        default:
-          return viewYear < first || viewYear > last;
-      }
-    }
-
-    function getTextDirection(el) {
-      return window.getComputedStyle(el).direction;
-    }
-
-    // Class representing the picker UI
-    class Picker {
-      constructor(datepicker) {
-        this.datepicker = datepicker;
-
-        const template = pickerTemplate.replace(/%buttonClass%/g, datepicker.config.buttonClass);
-        const element = this.element = parseHTML(template).firstChild;
-        const [header, main, footer] = element.firstChild.children;
-        const title = header.firstElementChild;
-        const [prevBtn, viewSwitch, nextBtn] = header.lastElementChild.children;
-        const [todayBtn, clearBtn] = footer.firstChild.children;
-        const controls = {
-          title,
-          prevBtn,
-          viewSwitch,
-          nextBtn,
-          todayBtn,
-          clearBtn,
-        };
-        this.main = main;
-        this.controls = controls;
-
-        const elementClass = datepicker.inline ? 'inline' : 'dropdown';
-        element.classList.add(`datepicker-${elementClass}`);
-
-        processPickerOptions(this, datepicker.config);
-        this.viewDate = computeResetViewDate(datepicker);
-
-        // set up event listeners
-        registerListeners(datepicker, [
-          [element, 'click', onClickPicker.bind(null, datepicker), {capture: true}],
-          [main, 'click', onClickView.bind(null, datepicker)],
-          [controls.viewSwitch, 'click', onClickViewSwitch.bind(null, datepicker)],
-          [controls.prevBtn, 'click', onClickPrevBtn.bind(null, datepicker)],
-          [controls.nextBtn, 'click', onClickNextBtn.bind(null, datepicker)],
-          [controls.todayBtn, 'click', onClickTodayBtn.bind(null, datepicker)],
-          [controls.clearBtn, 'click', onClickClearBtn.bind(null, datepicker)],
-        ]);
-
-        // set up views
-        this.views = [
-          new DaysView(this),
-          new MonthsView(this),
-          new YearsView(this, {id: 2, name: 'years', cellClass: 'year', step: 1}),
-          new YearsView(this, {id: 3, name: 'decades', cellClass: 'decade', step: 10}),
-        ];
-        this.currentView = this.views[datepicker.config.startView];
-
-        this.currentView.render();
-        this.main.appendChild(this.currentView.element);
-        datepicker.config.container.appendChild(this.element);
-      }
-
-      setOptions(options) {
-        processPickerOptions(this, options);
-        this.views.forEach((view) => {
-          view.init(options, false);
-        });
-        this.currentView.render();
-      }
-
-      detach() {
-        this.datepicker.config.container.removeChild(this.element);
-      }
-
-      show() {
-        if (this.active) {
-          return;
-        }
-        this.element.classList.add('active');
-        this.active = true;
-
-        const datepicker = this.datepicker;
-        if (!datepicker.inline) {
-          // ensure picker's direction matches input's
-          const inputDirection = getTextDirection(datepicker.inputField);
-          if (inputDirection !== getTextDirection(datepicker.config.container)) {
-            this.element.dir = inputDirection;
-          } else if (this.element.dir) {
-            this.element.removeAttribute('dir');
-          }
-
-          this.place();
-          if (datepicker.config.disableTouchKeyboard) {
-            datepicker.inputField.blur();
-          }
-        }
-        triggerDatepickerEvent(datepicker, 'show');
-      }
-
-      hide() {
-        if (!this.active) {
-          return;
-        }
-        this.datepicker.exitEditMode();
-        this.element.classList.remove('active');
-        this.active = false;
-        triggerDatepickerEvent(this.datepicker, 'hide');
-      }
-
-      place() {
-        const {classList, style} = this.element;
-        const {config, inputField} = this.datepicker;
-        const container = config.container;
-        const {
-          width: calendarWidth,
-          height: calendarHeight,
-        } = this.element.getBoundingClientRect();
-        const {
-          left: containerLeft,
-          top: containerTop,
-          width: containerWidth,
-        } = container.getBoundingClientRect();
-        const {
-          left: inputLeft,
-          top: inputTop,
-          width: inputWidth,
-          height: inputHeight
-        } = inputField.getBoundingClientRect();
-        let {x: orientX, y: orientY} = config.orientation;
-        let scrollTop;
-        let left;
-        let top;
-
-        if (container === document.body) {
-          scrollTop = window.scrollY;
-          left = inputLeft + window.scrollX;
-          top = inputTop + scrollTop;
-        } else {
-          scrollTop = container.scrollTop;
-          left = inputLeft - containerLeft;
-          top = inputTop - containerTop + scrollTop;
-        }
-
-        if (orientX === 'auto') {
-          if (left < 0) {
-            // align to the left and move into visible area if input's left edge < window's
-            orientX = 'left';
-            left = 10;
-          } else if (left + calendarWidth > containerWidth) {
-            // align to the right if canlendar's right edge > container's
-            orientX = 'right';
-          } else {
-            orientX = getTextDirection(inputField) === 'rtl' ? 'right' : 'left';
-          }
-        }
-        if (orientX === 'right') {
-          left -= calendarWidth - inputWidth;
-        }
-
-        if (orientY === 'auto') {
-          orientY = top - calendarHeight < scrollTop ? 'bottom' : 'top';
-        }
-        if (orientY === 'top') {
-          top -= calendarHeight;
-        } else {
-          top += inputHeight;
-        }
-
-        classList.remove(
-          'datepicker-orient-top',
-          'datepicker-orient-bottom',
-          'datepicker-orient-right',
-          'datepicker-orient-left'
-        );
-        classList.add(`datepicker-orient-${orientY}`, `datepicker-orient-${orientX}`);
-
-        style.top = top ? `${top}px` : top;
-        style.left = left ? `${left}px` : left;
-      }
-
-      setViewSwitchLabel(labelText) {
-        this.controls.viewSwitch.textContent = labelText;
-      }
-
-      setPrevBtnDisabled(disabled) {
-        this.controls.prevBtn.disabled = disabled;
-      }
-
-      setNextBtnDisabled(disabled) {
-        this.controls.nextBtn.disabled = disabled;
-      }
-
-      changeView(viewId) {
-        const oldView = this.currentView;
-        const newView =  this.views[viewId];
-        if (newView.id !== oldView.id) {
-          this.currentView = newView;
-          this._renderMethod = 'render';
-          triggerDatepickerEvent(this.datepicker, 'changeView');
-          this.main.replaceChild(newView.element, oldView.element);
-        }
-        return this;
-      }
-
-      // Change the focused date (view date)
-      changeFocus(newViewDate) {
-        this._renderMethod = setViewDate(this, newViewDate) ? 'render' : 'refreshFocus';
-        this.views.forEach((view) => {
-          view.updateFocus();
-        });
-        return this;
-      }
-
-      // Apply the change of the selected dates
-      update() {
-        const newViewDate = computeResetViewDate(this.datepicker);
-        this._renderMethod = setViewDate(this, newViewDate) ? 'render' : 'refresh';
-        this.views.forEach((view) => {
-          view.updateFocus();
-          view.updateSelection();
-        });
-        return this;
-      }
-
-      // Refresh the picker UI
-      render(quickRender = true) {
-        const renderMethod = (quickRender && this._renderMethod) || 'render';
-        delete this._renderMethod;
-
-        this.currentView[renderMethod]();
-      }
-    }
-
-    // Find the closest date that doesn't meet the condition for unavailable date
-    // Returns undefined if no available date is found
-    // addFn: function to calculate the next date
-    //   - args: time value, amount
-    // increase: amount to pass to addFn
-    // testFn: function to test the unavailablity of the date
-    //   - args: time value; retun: true if unavailable
-    function findNextAvailableOne(date, addFn, increase, testFn, min, max) {
-      if (!isInRange(date, min, max)) {
-        return;
-      }
-      if (testFn(date)) {
-        const newDate = addFn(date, increase);
-        return findNextAvailableOne(newDate, addFn, increase, testFn, min, max);
-      }
-      return date;
-    }
-
-    // direction: -1 (left/up), 1 (right/down)
-    // vertical: true for up/down, false for left/right
-    function moveByArrowKey(datepicker, ev, direction, vertical) {
-      const picker = datepicker.picker;
-      const currentView = picker.currentView;
-      const step = currentView.step || 1;
-      let viewDate = picker.viewDate;
-      let addFn;
-      let testFn;
-      switch (currentView.id) {
-        case 0:
-          if (vertical) {
-            viewDate = addDays(viewDate, direction * 7);
-          } else if (ev.ctrlKey || ev.metaKey) {
-            viewDate = addYears(viewDate, direction);
-          } else {
-            viewDate = addDays(viewDate, direction);
-          }
-          addFn = addDays;
-          testFn = (date) => currentView.disabled.includes(date);
-          break;
-        case 1:
-          viewDate = addMonths(viewDate, vertical ? direction * 4 : direction);
-          addFn = addMonths;
-          testFn = (date) => {
-            const dt = new Date(date);
-            const {year, disabled} = currentView;
-            return dt.getFullYear() === year && disabled.includes(dt.getMonth());
-          };
-          break;
-        default:
-          viewDate = addYears(viewDate, direction * (vertical ? 4 : 1) * step);
-          addFn = addYears;
-          testFn = date => currentView.disabled.includes(startOfYearPeriod(date, step));
-      }
-      viewDate = findNextAvailableOne(
-        viewDate,
-        addFn,
-        direction < 0 ? -step : step,
-        testFn,
-        currentView.minDate,
-        currentView.maxDate
-      );
-      if (viewDate !== undefined) {
-        picker.changeFocus(viewDate).render();
-      }
-    }
-
-    function onKeydown(datepicker, ev) {
-      if (ev.key === 'Tab') {
-        unfocus(datepicker);
-        return;
-      }
-
-      const picker = datepicker.picker;
-      const {id, isMinView} = picker.currentView;
-      if (!picker.active) {
-        switch (ev.key) {
-          case 'ArrowDown':
-          case 'Escape':
-            picker.show();
-            break;
-          case 'Enter':
-            datepicker.update();
-            break;
-          default:
-            return;
-        }
-      } else if (datepicker.editMode) {
-        switch (ev.key) {
-          case 'Escape':
-            picker.hide();
-            break;
-          case 'Enter':
-            datepicker.exitEditMode({update: true, autohide: datepicker.config.autohide});
-            break;
-          default:
-            return;
-        }
-      } else {
-        switch (ev.key) {
-          case 'Escape':
-            picker.hide();
-            break;
-          case 'ArrowLeft':
-            if (ev.ctrlKey || ev.metaKey) {
-              goToPrevOrNext(datepicker, -1);
-            } else if (ev.shiftKey) {
-              datepicker.enterEditMode();
-              return;
-            } else {
-              moveByArrowKey(datepicker, ev, -1, false);
-            }
-            break;
-          case 'ArrowRight':
-            if (ev.ctrlKey || ev.metaKey) {
-              goToPrevOrNext(datepicker, 1);
-            } else if (ev.shiftKey) {
-              datepicker.enterEditMode();
-              return;
-            } else {
-              moveByArrowKey(datepicker, ev, 1, false);
-            }
-            break;
-          case 'ArrowUp':
-            if (ev.ctrlKey || ev.metaKey) {
-              switchView(datepicker);
-            } else if (ev.shiftKey) {
-              datepicker.enterEditMode();
-              return;
-            } else {
-              moveByArrowKey(datepicker, ev, -1, true);
-            }
-            break;
-          case 'ArrowDown':
-            if (ev.shiftKey && !ev.ctrlKey && !ev.metaKey) {
-              datepicker.enterEditMode();
-              return;
-            }
-            moveByArrowKey(datepicker, ev, 1, true);
-            break;
-          case 'Enter':
-            if (isMinView) {
-              datepicker.setDate(picker.viewDate);
-            } else {
-              picker.changeView(id - 1).render();
-            }
-            break;
-          case 'Backspace':
-          case 'Delete':
-            datepicker.enterEditMode();
-            return;
-          default:
-            if (ev.key.length === 1 && !ev.ctrlKey && !ev.metaKey) {
-              datepicker.enterEditMode();
-            }
-            return;
-        }
-      }
-      ev.preventDefault();
-      ev.stopPropagation();
-    }
-
-    function onFocus(datepicker) {
-      if (datepicker.config.showOnFocus) {
-        datepicker.show();
-      }
-    }
-
-    // for the prevention for entering edit mode while getting focus on click
-    function onMousedown(datepicker, ev) {
-      const el = ev.target;
-      if (datepicker.picker.active || datepicker.config.showOnClick) {
-        el._active = el === document.activeElement;
-        el._clicking = setTimeout(() => {
-          delete el._active;
-          delete el._clicking;
-        }, 2000);
-      }
-    }
-
-    function onClickInput(datepicker, ev) {
-      const el = ev.target;
-      if (!el._clicking) {
-        return;
-      }
-      clearTimeout(el._clicking);
-      delete el._clicking;
-
-      if (el._active) {
-        datepicker.enterEditMode();
-      }
-      delete el._active;
-
-      if (datepicker.config.showOnClick) {
-        datepicker.show();
-      }
-    }
-
-    function onPaste(datepicker, ev) {
-      if (ev.clipboardData.types.includes('text/plain')) {
-        datepicker.enterEditMode();
-      }
-    }
-
-    // for the `document` to delegate the events from outside the picker/input field
-    function onClickOutside(datepicker, ev) {
-      const element = datepicker.element;
-      if (element !== document.activeElement) {
-        return;
-      }
-      const pickerElem = datepicker.picker.element;
-      if (findElementInEventPath(ev, el => el === element || el === pickerElem)) {
-        return;
-      }
-      unfocus(datepicker);
-    }
-
-    function stringifyDates(dates, config) {
-      return dates
-        .map(dt => formatDate(dt, config.format, config.locale))
-        .join(config.dateDelimiter);
-    }
-
-    // parse input dates and create an array of time values for selection
-    // returns undefined if there are no valid dates in inputDates
-    // when origDates (current selection) is passed, the function works to mix
-    // the input dates into the current selection
-    function processInputDates(datepicker, inputDates, clear = false) {
-      const {config, dates: origDates, rangepicker} = datepicker;
-        if (inputDates.length === 0) {
-        // empty input is considered valid unless origiDates is passed
-        return clear ? [] : undefined;
-      }
-
-      const rangeEnd = rangepicker && datepicker === rangepicker.datepickers[1];
-      let newDates = inputDates.reduce((dates, dt) => {
-        let date = parseDate(dt, config.format, config.locale);
-        if (date === undefined) {
-          return dates;
-        }
-        if (config.pickLevel > 0) {
-          // adjust to 1st of the month/Jan 1st of the year
-          // or to the last day of the monh/Dec 31st of the year if the datepicker
-          // is the range-end picker of a rangepicker
-          const dt = new Date(date);
-          if (config.pickLevel === 1) {
-            date = rangeEnd
-              ? dt.setMonth(dt.getMonth() + 1, 0)
-              : dt.setDate(1);
-          } else {
-            date = rangeEnd
-              ? dt.setFullYear(dt.getFullYear() + 1, 0, 0)
-              : dt.setMonth(0, 1);
-          }
-        }
-        if (
-          isInRange(date, config.minDate, config.maxDate)
-          && !dates.includes(date)
-          && !config.datesDisabled.includes(date)
-          && !config.daysOfWeekDisabled.includes(new Date(date).getDay())
-        ) {
-          dates.push(date);
-        }
-        return dates;
-      }, []);
-      if (newDates.length === 0) {
-        return;
-      }
-      if (config.multidate && !clear) {
-        // get the synmetric difference between origDates and newDates
-        newDates = newDates.reduce((dates, date) => {
-          if (!origDates.includes(date)) {
-            dates.push(date);
-          }
-          return dates;
-        }, origDates.filter(date => !newDates.includes(date)));
-      }
-      // do length check always because user can input multiple dates regardless of the mode
-      return config.maxNumberOfDates && newDates.length > config.maxNumberOfDates
-        ? newDates.slice(config.maxNumberOfDates * -1)
-        : newDates;
-    }
-
-    // refresh the UI elements
-    // modes: 1: input only, 2, picker only, 3 both
-    function refreshUI(datepicker, mode = 3, quickRender = true) {
-      const {config, picker, inputField} = datepicker;
-      if (mode & 2) {
-        const newView = picker.active ? config.pickLevel : config.startView;
-        picker.update().changeView(newView).render(quickRender);
-      }
-      if (mode & 1 && inputField) {
-        inputField.value = stringifyDates(datepicker.dates, config);
-      }
-    }
-
-    function setDate(datepicker, inputDates, options) {
-      let {clear, render, autohide} = options;
-      if (render === undefined) {
-        render = true;
-      }
-      if (!render) {
-        autohide = false;
-      } else if (autohide === undefined) {
-        autohide = datepicker.config.autohide;
-      }
-
-      const newDates = processInputDates(datepicker, inputDates, clear);
-      if (!newDates) {
-        return;
-      }
-      if (newDates.toString() !== datepicker.dates.toString()) {
-        datepicker.dates = newDates;
-        refreshUI(datepicker, render ? 3 : 1);
-        triggerDatepickerEvent(datepicker, 'changeDate');
-      } else {
-        refreshUI(datepicker, 1);
-      }
-      if (autohide) {
-        datepicker.hide();
-      }
-    }
-
-    /**
-     * Class representing a date picker
-     */
-    class Datepicker {
-      /**
-       * Create a date picker
-       * @param  {Element} element - element to bind a date picker
-       * @param  {Object} [options] - config options
-       * @param  {DateRangePicker} [rangepicker] - DateRangePicker instance the
-       * date picker belongs to. Use this only when creating date picker as a part
-       * of date range picker
-       */
-      constructor(element, options = {}, rangepicker = undefined) {
-        element.datepicker = this;
-        this.element = element;
-
-        // set up config
-        const config = this.config = Object.assign({
-          buttonClass: (options.buttonClass && String(options.buttonClass)) || 'button',
-          container: document.body,
-          defaultViewDate: today(),
-          maxDate: undefined,
-          minDate: undefined,
-        }, processOptions(defaultOptions, this));
-        this._options = options;
-        Object.assign(config, processOptions(options, this));
-
-        // configure by type
-        const inline = this.inline = element.tagName !== 'INPUT';
-        let inputField;
-        let initialDates;
-
-        if (inline) {
-          config.container = element;
-          initialDates = stringToArray(element.dataset.date, config.dateDelimiter);
-          delete element.dataset.date;
-        } else {
-          const container = options.container ? document.querySelector(options.container) : null;
-          if (container) {
-            config.container = container;
-          }
-          inputField = this.inputField = element;
-          inputField.classList.add('datepicker-input');
-          initialDates = stringToArray(inputField.value, config.dateDelimiter);
-        }
-        if (rangepicker) {
-          // check validiry
-          const index = rangepicker.inputs.indexOf(inputField);
-          const datepickers = rangepicker.datepickers;
-          if (index < 0 || index > 1 || !Array.isArray(datepickers)) {
-            throw Error('Invalid rangepicker object.');
-          }
-          // attach itaelf to the rangepicker here so that processInputDates() can
-          // determine if this is the range-end picker of the rangepicker while
-          // setting inital values when pickLevel > 0
-          datepickers[index] = this;
-          // add getter for rangepicker
-          Object.defineProperty(this, 'rangepicker', {
-            get() {
-              return rangepicker;
-            },
-          });
-        }
-
-        // set initial value
-        this.dates = processInputDates(this, initialDates) || [];
-        if (inputField) {
-          inputField.value = stringifyDates(this.dates, config);
-        }
-
-        const picker = this.picker = new Picker(this);
-
-        if (inline) {
-          this.show();
-        } else {
-          // set up event listeners in other modes
-          const onMousedownDocument = onClickOutside.bind(null, this);
-          const listeners = [
-            [inputField, 'keydown', onKeydown.bind(null, this)],
-            [inputField, 'focus', onFocus.bind(null, this)],
-            [inputField, 'mousedown', onMousedown.bind(null, this)],
-            [inputField, 'click', onClickInput.bind(null, this)],
-            [inputField, 'paste', onPaste.bind(null, this)],
-            [document, 'mousedown', onMousedownDocument],
-            [document, 'touchstart', onMousedownDocument],
-            [window, 'resize', picker.place.bind(picker)]
-          ];
-          registerListeners(this, listeners);
-        }
-      }
-
-      /**
-       * Format Date object or time value in given format and language
-       * @param  {Date|Number} date - date or time value to format
-       * @param  {String|Object} format - format string or object that contains
-       * toDisplay() custom formatter, whose signature is
-       * - args:
-       *   - date: {Date} - Date instance of the date passed to the method
-       *   - format: {Object} - the format object passed to the method
-       *   - locale: {Object} - locale for the language specified by `lang`
-       * - return:
-       *     {String} formatted date
-       * @param  {String} [lang=en] - language code for the locale to use
-       * @return {String} formatted date
-       */
-      static formatDate(date, format, lang) {
-        return formatDate(date, format, lang && locales[lang] || locales.en);
-      }
-
-      /**
-       * Parse date string
-       * @param  {String|Date|Number} dateStr - date string, Date object or time
-       * value to parse
-       * @param  {String|Object} format - format string or object that contains
-       * toValue() custom parser, whose signature is
-       * - args:
-       *   - dateStr: {String|Date|Number} - the dateStr passed to the method
-       *   - format: {Object} - the format object passed to the method
-       *   - locale: {Object} - locale for the language specified by `lang`
-       * - return:
-       *     {Date|Number} parsed date or its time value
-       * @param  {String} [lang=en] - language code for the locale to use
-       * @return {Number} time value of parsed date
-       */
-      static parseDate(dateStr, format, lang) {
-        return parseDate(dateStr, format, lang && locales[lang] || locales.en);
-      }
-
-      /**
-       * @type {Object} - Installed locales in `[languageCode]: localeObject` format
-       * en`:_English (US)_ is pre-installed.
-       */
-      static get locales() {
-        return locales;
-      }
-
-      /**
-       * @type {Boolean} - Whether the picker element is shown. `true` whne shown
-       */
-      get active() {
-        return !!(this.picker && this.picker.active);
-      }
-
-      /**
-       * @type {HTMLDivElement} - DOM object of picker element
-       */
-      get pickerElement() {
-        return this.picker ? this.picker.element : undefined;
-      }
-
-      /**
-       * Set new values to the config options
-       * @param {Object} options - config options to update
-       */
-      setOptions(options) {
-        const picker = this.picker;
-        const newOptions = processOptions(options, this);
-        Object.assign(this._options, options);
-        Object.assign(this.config, newOptions);
-        picker.setOptions(newOptions);
-
-        refreshUI(this, 3);
-      }
-
-      /**
-       * Show the picker element
-       */
-      show() {
-        if (this.inputField && this.inputField.disabled) {
-          return;
-        }
-        this.picker.show();
-      }
-
-      /**
-       * Hide the picker element
-       * Not available on inline picker
-       */
-      hide() {
-        if (this.inline) {
-          return;
-        }
-        this.picker.hide();
-        this.picker.update().changeView(this.config.startView).render();
-      }
-
-      /**
-       * Destroy the Datepicker instance
-       * @return {Detepicker} - the instance destroyed
-       */
-      destroy() {
-        this.hide();
-        unregisterListeners(this);
-        this.picker.detach();
-        if (!this.inline) {
-          this.inputField.classList.remove('datepicker-input');
-        }
-        delete this.element.datepicker;
-        return this;
-      }
-
-      /**
-       * Get the selected date(s)
-       *
-       * The method returns a Date object of selected date by default, and returns
-       * an array of selected dates in multidate mode. If format string is passed,
-       * it returns date string(s) formatted in given format.
-       *
-       * @param  {String} [format] - Format string to stringify the date(s)
-       * @return {Date|String|Date[]|String[]} - selected date(s), or if none is
-       * selected, empty array in multidate mode and untitled in sigledate mode
-       */
-      getDate(format = undefined) {
-        const callback = format
-          ? date => formatDate(date, format, this.config.locale)
-          : date => new Date(date);
-
-        if (this.config.multidate) {
-          return this.dates.map(callback);
-        }
-        if (this.dates.length > 0) {
-          return callback(this.dates[0]);
-        }
-      }
-
-      /**
-       * Set selected date(s)
-       *
-       * In multidate mode, you can pass multiple dates as a series of arguments
-       * or an array. (Since each date is parsed individually, the type of the
-       * dates doesn't have to be the same.)
-       * The given dates are used to toggle the select status of each date. The
-       * number of selected dates is kept from exceeding the length set to
-       * maxNumberOfDates.
-       *
-       * With clear: true option, the method can be used to clear the selection
-       * and to replace the selection instead of toggling in multidate mode.
-       * If the option is passed with no date arguments or an empty dates array,
-       * it works as "clear" (clear the selection then set nothing), and if the
-       * option is passed with new dates to select, it works as "replace" (clear
-       * the selection then set the given dates)
-       *
-       * When render: false option is used, the method omits re-rendering the
-       * picker element. In this case, you need to call refresh() method later in
-       * order for the picker element to reflect the changes. The input field is
-       * refreshed always regardless of this option.
-       *
-       * When invalid (unparsable, repeated, disabled or out-of-range) dates are
-       * passed, the method ignores them and applies only valid ones. In the case
-       * that all the given dates are invalid, which is distinguished from passing
-       * no dates, the method considers it as an error and leaves the selection
-       * untouched.
-       *
-       * @param {...(Date|Number|String)|Array} [dates] - Date strings, Date
-       * objects, time values or mix of those for new selection
-       * @param {Object} [options] - function options
-       * - clear: {boolean} - Whether to clear the existing selection
-       *     defualt: false
-       * - render: {boolean} - Whether to re-render the picker element
-       *     default: true
-       * - autohide: {boolean} - Whether to hide the picker element after re-render
-       *     Ignored when used with render: false
-       *     default: config.autohide
-       */
-      setDate(...args) {
-        const dates = [...args];
-        const opts = {};
-        const lastArg = lastItemOf(args);
-        if (
-          typeof lastArg === 'object'
-          && !Array.isArray(lastArg)
-          && !(lastArg instanceof Date)
-          && lastArg
-        ) {
-          Object.assign(opts, dates.pop());
-        }
-
-        const inputDates = Array.isArray(dates[0]) ? dates[0] : dates;
-        setDate(this, inputDates, opts);
-      }
-
-      /**
-       * Update the selected date(s) with input field's value
-       * Not available on inline picker
-       *
-       * The input field will be refreshed with properly formatted date string.
-       *
-       * @param  {Object} [options] - function options
-       * - autohide: {boolean} - whether to hide the picker element after refresh
-       *     default: false
-       */
-      update(options = undefined) {
-        if (this.inline) {
-          return;
-        }
-
-        const opts = {clear: true, autohide: !!(options && options.autohide)};
-        const inputDates = stringToArray(this.inputField.value, this.config.dateDelimiter);
-        setDate(this, inputDates, opts);
-      }
-
-      /**
-       * Refresh the picker element and the associated input field
-       * @param {String} [target] - target item when refreshing one item only
-       * 'picker' or 'input'
-       * @param {Boolean} [forceRender] - whether to re-render the picker element
-       * regardless of its state instead of optimized refresh
-       */
-      refresh(target = undefined, forceRender = false) {
-        if (target && typeof target !== 'string') {
-          forceRender = target;
-          target = undefined;
-        }
-
-        let mode;
-        if (target === 'picker') {
-          mode = 2;
-        } else if (target === 'input') {
-          mode = 1;
-        } else {
-          mode = 3;
-        }
-        refreshUI(this, mode, !forceRender);
-      }
-
-      /**
-       * Enter edit mode
-       * Not available on inline picker or when the picker element is hidden
-       */
-      enterEditMode() {
-        if (this.inline || !this.picker.active || this.editMode) {
-          return;
-        }
-        this.editMode = true;
-        this.inputField.classList.add('in-edit');
-      }
-
-      /**
-       * Exit from edit mode
-       * Not available on inline picker
-       * @param  {Object} [options] - function options
-       * - update: {boolean} - whether to call update() after exiting
-       *     If false, input field is revert to the existing selection
-       *     default: false
-       */
-      exitEditMode(options = undefined) {
-        if (this.inline || !this.editMode) {
-          return;
-        }
-        const opts = Object.assign({update: false}, options);
-        delete this.editMode;
-        this.inputField.classList.remove('in-edit');
-        if (opts.update) {
-          this.update(opts);
-        }
-      }
-    }
-
     /*
      * Licensed to the Apache Software Foundation (ASF) under one or more
      * contributor license agreements.  See the NOTICE file distributed with
@@ -10838,7 +8144,7 @@
             const i18n = this.i18n;
             i18n.titleFormat = "MM y"; // todo i18n
             i18n.format = this.pattern;
-            Datepicker.locales[locale] = i18n;
+            Datepicker__default['default'].locales[locale] = i18n;
             const options = {
                 buttonClass: "btn",
                 orientation: "bottom top auto",
@@ -10849,7 +8155,7 @@
                 // todo readonly
                 // todo show week numbers
             };
-            const datepicker = new Datepicker(field, options);
+            const datepicker = new Datepicker__default['default'](field, options);
             // XXX these listeners are needed as long as we have a solution for:
             // XXX https://github.com/mymth/vanillajs-datepicker/issues/13
             // XXX the 2nd point is missing the "normal" change event on the input element
diff --git a/tobago-theme/tobago-theme-standard/npm/dist/js/tobago.js.map b/tobago-theme/tobago-theme-standard/npm/dist/js/tobago.js.map
index 11d099f..0f7ed14 100644
--- a/tobago-theme/tobago-theme-standard/npm/dist/js/tobago.js.map
+++ b/tobago-theme/tobago-theme-standard/npm/dist/js/tobago.js.map
@@ -1 +1 @@
-{"version":3,"file":"tobago.js","sources":["tobago-listener.js","tobago-utils.js","tobago-bar.js","../../node_modules/@popperjs/core/lib/enums.js","../../node_modules/@popperjs/core/lib/dom-utils/getNodeName.js","../../node_modules/@popperjs/core/lib/dom-utils/getWindow.js","../../node_modules/@popperjs/core/lib/dom-utils/instanceOf.js","../../node_modules/@popperjs/core/lib/modifiers/applyStyles.js","../../node_modules/@popperjs/core/lib/utils/getBasePlacement.js","../../node_modules/@p [...]
\ No newline at end of file
+{"version":3,"file":"tobago.js","sources":["tobago-listener.js","tobago-utils.js","tobago-bar.js","../../node_modules/@popperjs/core/lib/enums.js","../../node_modules/@popperjs/core/lib/dom-utils/getNodeName.js","../../node_modules/@popperjs/core/lib/dom-utils/getWindow.js","../../node_modules/@popperjs/core/lib/dom-utils/instanceOf.js","../../node_modules/@popperjs/core/lib/modifiers/applyStyles.js","../../node_modules/@popperjs/core/lib/utils/getBasePlacement.js","../../node_modules/@p [...]
\ No newline at end of file
diff --git a/tobago-theme/tobago-theme-standard/npm/package-lock.json b/tobago-theme/tobago-theme-standard/npm/package-lock.json
index bc5d0b0..e5dc2cf 100644
--- a/tobago-theme/tobago-theme-standard/npm/package-lock.json
+++ b/tobago-theme/tobago-theme-standard/npm/package-lock.json
@@ -704,6 +704,60 @@
       "integrity": "sha512-cPqjjzuFWNK3BSKLm0abspP0sp/IGOli4p5I5fKFAzdS8fvjdOwDCfZqAaIiXd9lPkOWi3SUUfZof3hEb7J/uw==",
       "dev": true
     },
+    "@rollup/plugin-node-resolve": {
+      "version": "11.1.0",
+      "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.1.0.tgz",
+      "integrity": "sha512-ouBBppRdWJKCllDXGzJ7ZIkYbaq+5TmyP0smt1vdJCFfoZhLi31vhpmjLhyo8lreHf4RoeSNllaWrvSqHpHRog==",
+      "dev": true,
+      "requires": {
+        "@rollup/pluginutils": "^3.1.0",
+        "@types/resolve": "1.17.1",
+        "builtin-modules": "^3.1.0",
+        "deepmerge": "^4.2.2",
+        "is-module": "^1.0.0",
+        "resolve": "^1.19.0"
+      },
+      "dependencies": {
+        "@types/resolve": {
+          "version": "1.17.1",
+          "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz",
+          "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==",
+          "dev": true,
+          "requires": {
+            "@types/node": "*"
+          }
+        }
+      }
+    },
+    "@rollup/plugin-replace": {
+      "version": "2.3.4",
+      "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.3.4.tgz",
+      "integrity": "sha512-waBhMzyAtjCL1GwZes2jaE9MjuQ/DQF2BatH3fRivUF3z0JBFrU0U6iBNC/4WR+2rLKhaAhPWDNPYp4mI6RqdQ==",
+      "dev": true,
+      "requires": {
+        "@rollup/pluginutils": "^3.1.0",
+        "magic-string": "^0.25.7"
+      }
+    },
+    "@rollup/pluginutils": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz",
+      "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==",
+      "dev": true,
+      "requires": {
+        "@types/estree": "0.0.39",
+        "estree-walker": "^1.0.1",
+        "picomatch": "^2.2.2"
+      },
+      "dependencies": {
+        "estree-walker": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz",
+          "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==",
+          "dev": true
+        }
+      }
+    },
     "@sinonjs/commons": {
       "version": "1.8.2",
       "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.2.tgz",
@@ -773,6 +827,12 @@
         "@babel/types": "^7.3.0"
       }
     },
+    "@types/estree": {
+      "version": "0.0.39",
+      "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
+      "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
+      "dev": true
+    },
     "@types/graceful-fs": {
       "version": "4.1.4",
       "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.4.tgz",
@@ -834,15 +894,6 @@
       "integrity": "sha512-6gOkRe7OIioWAXfnO/2lFiv+SJichKVSys1mSsgyrYHSEjk8Ctv4tSR/Odvnu+HWlH2C8j53dahU03XmQdd5fA==",
       "dev": true
     },
-    "@types/resolve": {
-      "version": "0.0.8",
-      "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz",
-      "integrity": "sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==",
-      "dev": true,
-      "requires": {
-        "@types/node": "*"
-      }
-    },
     "@types/stack-utils": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.0.tgz",
@@ -2158,12 +2209,6 @@
       "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
       "dev": true
     },
-    "estree-walker": {
-      "version": "0.6.1",
-      "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz",
-      "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==",
-      "dev": true
-    },
     "esutils": {
       "version": "2.0.3",
       "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
@@ -4008,6 +4053,15 @@
         "yallist": "^4.0.0"
       }
     },
+    "magic-string": {
+      "version": "0.25.7",
+      "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz",
+      "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==",
+      "dev": true,
+      "requires": {
+        "sourcemap-codec": "^1.4.4"
+      }
+    },
     "make-dir": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
@@ -5163,9 +5217,9 @@
       }
     },
     "rollup": {
-      "version": "2.36.1",
-      "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.36.1.tgz",
-      "integrity": "sha512-eAfqho8dyzuVvrGqpR0ITgEdq0zG2QJeWYh+HeuTbpcaXk8vNFc48B7bJa1xYosTCKx0CuW+447oQOW8HgBIZQ==",
+      "version": "2.37.1",
+      "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.37.1.tgz",
+      "integrity": "sha512-V3ojEeyGeSdrMSuhP3diBb06P+qV4gKQeanbDv+Qh/BZbhdZ7kHV0xAt8Yjk4GFshq/WjO7R4c7DFM20AwTFVQ==",
       "dev": true,
       "requires": {
         "fsevents": "~2.1.2"
@@ -5180,28 +5234,6 @@
         }
       }
     },
-    "rollup-plugin-node-resolve": {
-      "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz",
-      "integrity": "sha512-jUlyaDXts7TW2CqQ4GaO5VJ4PwwaV8VUGA7+km3n6k6xtOEacf61u0VXwN80phY/evMcaS+9eIeJ9MOyDxt5Zw==",
-      "dev": true,
-      "requires": {
-        "@types/resolve": "0.0.8",
-        "builtin-modules": "^3.1.0",
-        "is-module": "^1.0.0",
-        "resolve": "^1.11.1",
-        "rollup-pluginutils": "^2.8.1"
-      }
-    },
-    "rollup-pluginutils": {
-      "version": "2.8.2",
-      "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz",
-      "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==",
-      "dev": true,
-      "requires": {
-        "estree-walker": "^0.6.1"
-      }
-    },
     "rsvp": {
       "version": "4.8.5",
       "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz",
@@ -5652,6 +5684,12 @@
       "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=",
       "dev": true
     },
+    "sourcemap-codec": {
+      "version": "1.4.8",
+      "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
+      "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
+      "dev": true
+    },
     "spdx-correct": {
       "version": "3.1.1",
       "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz",
diff --git a/tobago-theme/tobago-theme-standard/npm/package.json b/tobago-theme/tobago-theme-standard/npm/package.json
index f69b5e7..c6bb745 100644
--- a/tobago-theme/tobago-theme-standard/npm/package.json
+++ b/tobago-theme/tobago-theme-standard/npm/package.json
@@ -66,8 +66,9 @@
     "jest": "^26.6.3",
     "npm-run-all": "^4.1.5",
     "postcss-cli": "^7.1.2",
-    "rollup": "^2.33.1",
-    "rollup-plugin-node-resolve": "^5.2.0",
+    "rollup": "^2.37.1",
+    "@rollup/plugin-node-resolve": "^11.1.0",
+    "@rollup/plugin-replace": "^2.3.4",
     "sass": "^1.29.0",
     "ts-jest": "^26.4.4",
     "tslint": "^6.1.3",
diff --git a/tobago-theme/tobago-theme-standard/npm/rollup.config.js b/tobago-theme/tobago-theme-standard/npm/rollup.config.js
index e4615db..b8407bd 100644
--- a/tobago-theme/tobago-theme-standard/npm/rollup.config.js
+++ b/tobago-theme/tobago-theme-standard/npm/rollup.config.js
@@ -15,7 +15,8 @@
  * limitations under the License.
  */
 
-import resolve from "rollup-plugin-node-resolve"
+import resolve from "@rollup/plugin-node-resolve"
+import replace from '@rollup/plugin-replace';
 
 export default {
   input: 'dist/js/tobago-all.js',
@@ -26,6 +27,9 @@ export default {
     name: 'tobago'
   },
   plugins: [
-    resolve()
-  ]
+    resolve(),
+    replace({
+      // XXX workaround for popper2 included by bootstrap, otherwise be get an error: process is not defined at runtime
+      'process.env.NODE_ENV': JSON.stringify('production')
+    }),  ]
 };


[myfaces-tobago] 04/04: chore: optimize/cleanup/simplify

Posted by lo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

lofwyr pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/myfaces-tobago.git

commit c476ad3284cce8723f573a9049af32b653096bd5
Author: Udo Schnurpfeil <ud...@irian.eu>
AuthorDate: Thu Jan 21 10:10:09 2021 +0100

    chore: optimize/cleanup/simplify
---
 .../tobago/internal/renderkit/renderer/ImageRenderer.java     |  4 ++--
 .../tobago/internal/renderkit/renderer/TreeIconRenderer.java  |  2 +-
 .../myfaces/tobago/internal/util/HtmlRendererUtils.java       |  2 +-
 .../java/org/apache/myfaces/tobago/renderkit/css/Icons.java   | 11 ++++++++---
 4 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ImageRenderer.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ImageRenderer.java
index 948c291..f65e059 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ImageRenderer.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ImageRenderer.java
@@ -42,13 +42,13 @@ public class ImageRenderer<T extends AbstractUIImage> extends RendererBase<T> {
     final TobagoResponseWriter writer = getResponseWriter(facesContext);
 
     final String value = component.getUrl();
-    final boolean fontAwesome = value != null && value.startsWith("fa-");
+    final boolean isIcon = Icons.matches(value);
     final boolean disabled = component.isDisabled()
         || (component.getParent() instanceof AbstractUICommandBase
         && ((AbstractUICommandBase) component.getParent()).isDisabled());
     final String title = HtmlRendererUtils.getTitleFromTipAndMessages(facesContext, component);
     final Markup markup = component.getMarkup();
-    if (fontAwesome) {
+    if (isIcon) {
       writer.startElement(HtmlElements.I);
       writer.writeIdAttribute(component.getClientId(facesContext));
       writer.writeClassAttribute(
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TreeIconRenderer.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TreeIconRenderer.java
index 5d06f96..c999fa1 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TreeIconRenderer.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TreeIconRenderer.java
@@ -92,7 +92,7 @@ public class TreeIconRenderer<T extends AbstractUITreeIcon> extends RendererBase
         TobagoClass.TREE_NODE__TOGGLE,
         component.getCustomClass());
 
-    if (source != null && source.startsWith("fa-")) {
+    if (Icons.matches(source)) {
       writer.startElement(HtmlElements.I);
       writer.writeClassAttribute(Icons.FA, Icons.custom(source));
       if (folder) {
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/HtmlRendererUtils.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/HtmlRendererUtils.java
index efb562c..22c669c 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/HtmlRendererUtils.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/HtmlRendererUtils.java
@@ -81,7 +81,7 @@ public final class HtmlRendererUtils {
 
   public static void encodeIconOrImage(final TobagoResponseWriter writer, final String image) throws IOException {
     if (image != null) {
-      if (image.startsWith("fa-")) {
+      if (Icons.matches(image)) {
         writer.startElement(HtmlElements.I);
         writer.writeClassAttribute(Icons.FA, Icons.custom(image));
         writer.endElement(HtmlElements.I);
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/Icons.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/Icons.java
index a5ea3db..b5e33f2 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/Icons.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/Icons.java
@@ -61,16 +61,21 @@ public enum Icons implements CssItem {
   };
 
   private static final Pattern PATTERN = Pattern.compile("^(fa(-[a-z]+)+)$");
+  private static final String PREFIX = "fa-";
 
-  private String fa;
+  private final String clazz;
 
   Icons() {
-    this.fa = "fa-" + name().toLowerCase().replaceAll("_", "-");
+    this.clazz = PREFIX + name().toLowerCase().replaceAll("_", "-");
   }
 
   @Override
   public String getName() {
-    return fa;
+    return clazz;
+  }
+
+  public static boolean matches(final String value) {
+    return value != null && PATTERN.matcher(value).matches();
   }
 
   public static CssItem custom(final String name) {


[myfaces-tobago] 03/04: TOBAGO-2044: Evaluate use of Bootstrap 5

Posted by lo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

lofwyr pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/myfaces-tobago.git

commit c990cfbd2c112a1b99aabc8742ab66e586c06bf3
Author: Udo Schnurpfeil <ud...@irian.eu>
AuthorDate: Wed Jan 20 17:47:57 2021 +0100

    TOBAGO-2044: Evaluate use of Bootstrap 5
    
    * Nicer way to import JS (popper, bootstrap) - working now!
---
 .../src/main/resources/META-INF/tobago-config.xml                     | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/tobago-config.xml b/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/tobago-config.xml
index 58ae978..b413a5c 100644
--- a/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/tobago-config.xml
+++ b/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/tobago-config.xml
@@ -40,8 +40,6 @@
         <includes>
           <script name="/webjars/webcomponents__custom-elements/1.2.1/custom-elements.min.js"/>
           <script name="/webjars/tether/1.4.0/js/tether.min.js"/>
-          <!-- todo bootstrap js via rollup -->
-<!--          <script name="/tobago/standard/${project.version}/js/bootstrap.bundle.min.js"/>-->
           <script name="/tobago/standard/${project.version}/js/jsf.js"/>
           <script type="module" name="/tobago/standard/${project.version}/js/tobago.min.js"/>
           <style name="/webjars/tether/1.4.0/css/tether.min.css"/>
@@ -53,8 +51,6 @@
         <includes>
           <script name="/webjars/webcomponents__custom-elements/1.2.1/externs/custom-elements.js"/>
           <script name="/webjars/tether/1.4.0/js/tether.js"/>
-          <!-- todo bootstrap js via rollup -->
-<!--          <script name="/tobago/standard/${project.version}/js/bootstrap.bundle.js"/>-->
           <script name="/tobago/standard/${project.version}/js/jsf-development.js"/>
           <script type="module" name="/tobago/standard/${project.version}/js/tobago.js"/>
 <!--


[myfaces-tobago] 01/04: TOBAGO-2044: Evaluate use of Bootstrap 5

Posted by lo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

lofwyr pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/myfaces-tobago.git

commit 13d77430c12e45566838744c9cdb8c094517b3a1
Author: Udo Schnurpfeil <ud...@irian.eu>
AuthorDate: Mon Jan 18 09:24:43 2021 +0100

    TOBAGO-2044: Evaluate use of Bootstrap 5
    
    * Test: Nicer way to import JS - but no working yet!
---
 .../npm/dist/js/tobago-dropdown.js                 |     3 +-
 .../npm/dist/js/tobago-dropdown.js.map             |     2 +-
 .../npm/dist/js/tobago-popover.js                  |    12 +-
 .../npm/dist/js/tobago-popover.js.map              |     2 +-
 .../npm/dist/js/tobago-popup.js                    |     5 +-
 .../npm/dist/js/tobago-popup.js.map                |     2 +-
 .../npm/dist/js/tobago-range.js                    |     4 +-
 .../npm/dist/js/tobago-range.js.map                |     2 +-
 .../tobago-theme-standard/npm/dist/js/tobago.js    | 12566 +++++++++++++------
 .../npm/dist/js/tobago.js.map                      |     2 +-
 .../tobago-theme-standard/npm/package-lock.json    |     3 +-
 .../tobago-theme-standard/npm/package.json         |     4 +-
 .../npm/ts/tobago-dropdown.ts                      |     3 +-
 .../tobago-theme-standard/npm/ts/tobago-popover.ts |    12 +-
 .../tobago-theme-standard/npm/ts/tobago-popup.ts   |     5 +-
 .../tobago-theme-standard/npm/ts/tobago-range.ts   |     5 +-
 .../src/main/resources/META-INF/tobago-config.xml  |     4 +-
 17 files changed, 8905 insertions(+), 3731 deletions(-)

diff --git a/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-dropdown.js b/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-dropdown.js
index e6de088..5d899fb 100644
--- a/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-dropdown.js
+++ b/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-dropdown.js
@@ -14,7 +14,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import { createPopper } from "@popperjs/core/dist/esm/popper";
+import { createPopper } from "@popperjs/core";
+// import {createPopper} from "@popperjs/core/dist/esm/popper";
 const Event = {
     HIDE: "tobago.dropdown.hide",
     HIDDEN: "tobago.dropdown.hidden",
diff --git a/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-dropdown.js.map b/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-dropdown.js.map
index 6c22807..90eec22 100644
--- a/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-dropdown.js.map
+++ b/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-dropdown.js.map
@@ -1 +1 @@
-{"version":3,"file":"tobago-dropdown.js","sourceRoot":"","sources":["../../ts/tobago-dropdown.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAC,YAAY,EAAC,MAAM,gCAAgC,CAAC;AAE5D,MAAM,KAAK,GAAG;IACZ,IAAI,EAAE,sBAAsB;IAC5B,MAAM,EAAE,wBAAwB;IAChC,IAAI,EAAE,sBAAsB;IAC5B,KAAK,EAAE,uBAAuB;CAC/B,CAAC;AAEF,MAAM,QAAS,SAAQ,WAAW;IAIhC;QACE,KAAK,EAAE,CAAC;QAHF,oBAAe,GAAoB,EAAE,CAAC;QAI5C,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,yBAAyB,CAAC,EAAE,EAAE,kBAAkB;YAC3E,MAAM,IAAI,GAAG,IAAI,CA [...]
\ No newline at end of file
+{"version":3,"file":"tobago-dropdown.js","sourceRoot":"","sources":["../../ts/tobago-dropdown.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAC;AAC5C,+DAA+D;AAE/D,MAAM,KAAK,GAAG;IACZ,IAAI,EAAE,sBAAsB;IAC5B,MAAM,EAAE,wBAAwB;IAChC,IAAI,EAAE,sBAAsB;IAC5B,KAAK,EAAE,uBAAuB;CAC/B,CAAC;AAEF,MAAM,QAAS,SAAQ,WAAW;IAIhC;QACE,KAAK,EAAE,CAAC;QAHF,oBAAe,GAAoB,EAAE,CAAC;QAI5C,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,yBAAyB,CAAC,EAAE,EAAE,kBAAkB;YAC3E,MAAM,IAAI [...]
\ No newline at end of file
diff --git a/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-popover.js b/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-popover.js
index dfd6436..a9d56e0 100644
--- a/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-popover.js
+++ b/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-popover.js
@@ -16,16 +16,16 @@
  */
 // XXX which? nothing works...
 // import * as bootstrap from "bootstrap/dist/js/bootstrap";
-// import * as bootstrap from "bootstrap/dist/js/bootstrap.esm";
-// import * as bootstrap from "bootstrap/dist/js/bootstrap.bundle";
+// import Popover from "bootstrap/dist/js/bootstrap.bundle";
 // import {createPopper} from "@popperjs/core/dist/esm/popper";
-class Popover extends HTMLElement {
+import { Popover } from "bootstrap";
+// import {Popover} from "bootstrap/dist/js/bootstrap.bundle";
+class TobagoPopover extends HTMLElement {
     constructor() {
         super();
     }
     connectedCallback() {
-        // @ts-ignore
-        this.popover = new bootstrap.Popover(this.trigger, {
+        this.popover = new Popover(this.trigger, {
             container: this.menuStore
         });
     }
@@ -39,7 +39,7 @@ class Popover extends HTMLElement {
 }
 document.addEventListener("tobago.init", function (event) {
     if (window.customElements.get("tobago-popover") == null) {
-        window.customElements.define("tobago-popover", Popover);
+        window.customElements.define("tobago-popover", TobagoPopover);
     }
 });
 //# sourceMappingURL=tobago-popover.js.map
\ No newline at end of file
diff --git a/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-popover.js.map b/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-popover.js.map
index b39eb6d..bb72ee3 100644
--- a/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-popover.js.map
+++ b/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-popover.js.map
@@ -1 +1 @@
-{"version":3,"file":"tobago-popover.js","sourceRoot":"","sources":["../../ts/tobago-popover.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,8BAA8B;AAC9B,4DAA4D;AAC5D,gEAAgE;AAChE,mEAAmE;AACnE,+DAA+D;AAE/D,MAAM,OAAQ,SAAQ,WAAW;IAI/B;QACE,KAAK,EAAE,CAAC;IACV,CAAC;IAED,iBAAiB;QACf,aAAa;QACb,IAAI,CAAC,OAAO,GAAG,IAAI,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE;YACjD,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B,CAAC,CAAC;IACL,CAAC;IAED,IAAI,OAAO;QACT,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAY,SAAS;QACnB,MAAM,IA [...]
\ No newline at end of file
+{"version":3,"file":"tobago-popover.js","sourceRoot":"","sources":["../../ts/tobago-popover.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,8BAA8B;AAC9B,4DAA4D;AAC5D,4DAA4D;AAC5D,+DAA+D;AAC/D,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAC;AAClC,8DAA8D;AAE9D,MAAM,aAAc,SAAQ,WAAW;IAIrC;QACE,KAAK,EAAE,CAAC;IACV,CAAC;IAED,iBAAiB;QACf,IAAI,CAAC,OAAO,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE;YACvC,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B,CAAC,CAAC;IACL,CAAC;IAED,IAAI,OAAO;QACT,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IA [...]
\ No newline at end of file
diff --git a/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-popup.js b/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-popup.js
index 7e10e50..cb4d0c7 100644
--- a/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-popup.js
+++ b/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-popup.js
@@ -17,14 +17,15 @@
 // import * as bootstrap from "bootstrap/dist/js/bootstrap.esm";
 // import "bootstrap/dist/js/bootstrap.esm";
 // import "bootstrap/dist/js/bootstrap";
+import { Modal } from "bootstrap";
+// import {Modal} from "bootstrap/dist/js/bootstrap.bundle";
 export class Popup extends HTMLElement {
     constructor() {
         super();
     }
     connectedCallback() {
         let options = {};
-        // @ts-ignore
-        this.modal = new bootstrap.Modal(this, options);
+        this.modal = new Modal(this, options);
     }
     show() {
         console.log("show");
diff --git a/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-popup.js.map b/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-popup.js.map
index 2b82367..c59394f 100644
--- a/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-popup.js.map
+++ b/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-popup.js.map
@@ -1 +1 @@
-{"version":3,"file":"tobago-popup.js","sourceRoot":"","sources":["../../ts/tobago-popup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,gEAAgE;AAChE,4CAA4C;AAC5C,wCAAwC;AAExC,MAAM,OAAO,KAAM,SAAQ,WAAW;IAIpC;QACE,KAAK,EAAE,CAAC;IACV,CAAC;IAED,iBAAiB;QAChB,IAAI,OAAO,GAAG,EAAE,CAAC;QAEhB,aAAa;QACb,IAAI,CAAC,KAAK,GAAG,IAAI,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAClD,CAAC;IAED,IAAI;QACF,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACpB,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IACpB,CAAC;IAED, [...]
\ No newline at end of file
+{"version":3,"file":"tobago-popup.js","sourceRoot":"","sources":["../../ts/tobago-popup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,gEAAgE;AAChE,4CAA4C;AAC5C,wCAAwC;AACxC,OAAO,EAAC,KAAK,EAAC,MAAM,WAAW,CAAC;AAChC,4DAA4D;AAE5D,MAAM,OAAO,KAAM,SAAQ,WAAW;IAIpC;QACE,KAAK,EAAE,CAAC;IACV,CAAC;IAED,iBAAiB;QAChB,IAAI,OAAO,GAAG,EAAE,CAAC;QAEhB,IAAI,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACxC,CAAC;IAED,IAAI;QACF,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACpB,IAAI,CAAC,KAAK,CA [...]
\ No newline at end of file
diff --git a/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-range.js b/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-range.js
index 0e81b49..7f61327 100644
--- a/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-range.js
+++ b/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-range.js
@@ -14,13 +14,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+import { Popover } from "bootstrap";
 class TobagoRange extends HTMLElement {
     constructor() {
         super();
     }
     connectedCallback() {
-        // @ts-ignore
-        this.popover = new bootstrap.Popover(this.range, {
+        this.popover = new Popover(this.range, {
             container: this.menuStore,
             content: this.content.bind(this),
             trigger: "input",
diff --git a/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-range.js.map b/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-range.js.map
index 0d89b50..3ec329c 100644
--- a/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-range.js.map
+++ b/tobago-theme/tobago-theme-standard/npm/dist/js/tobago-range.js.map
@@ -1 +1 @@
-{"version":3,"file":"tobago-range.js","sourceRoot":"","sources":["../../ts/tobago-range.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,WAAY,SAAQ,WAAW;IAInC;QACE,KAAK,EAAE,CAAC;IACV,CAAC;IAED,iBAAiB;QACf,aAAa;QACb,IAAI,CAAC,OAAO,GAAG,IAAI,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE;YAC/C,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;YAChC,OAAO,EAAE,OAAO;YAChB,SAAS,EAAE,MAAM;YACjB,KAAK,EAAE;gBACL,IAAI,EAAE,CAAC;gBACP,IAAI,EAAE,GAAG;aACV;SACF,CA [...]
\ No newline at end of file
+{"version":3,"file":"tobago-range.js","sourceRoot":"","sources":["../../ts/tobago-range.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAC;AAElC,MAAM,WAAY,SAAQ,WAAW;IAInC;QACE,KAAK,EAAE,CAAC;IACV,CAAC;IAED,iBAAiB;QACf,IAAI,CAAC,OAAO,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE;YACrC,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;YAChC,OAAO,EAAE,OAAO;YAChB,SAAS,EAAE,MAAM;YACjB,KAAK,EAAE;gBACL,IAAI,EAAE,CAAC;gBACP,IAAI,E [...]
\ No newline at end of file
diff --git a/tobago-theme/tobago-theme-standard/npm/dist/js/tobago.js b/tobago-theme/tobago-theme-standard/npm/dist/js/tobago.js
index c2ccc44..bee44c4 100644
--- a/tobago-theme/tobago-theme-standard/npm/dist/js/tobago.js
+++ b/tobago-theme/tobago-theme-standard/npm/dist/js/tobago.js
@@ -254,18 +254,40 @@
         }
     });
 
-    function getBoundingClientRect(element) {
-      var rect = element.getBoundingClientRect();
-      return {
-        width: rect.width,
-        height: rect.height,
-        top: rect.top,
-        right: rect.right,
-        bottom: rect.bottom,
-        left: rect.left,
-        x: rect.left,
-        y: rect.top
-      };
+    var top = 'top';
+    var bottom = 'bottom';
+    var right = 'right';
+    var left = 'left';
+    var auto = 'auto';
+    var basePlacements = [top, bottom, right, left];
+    var start = 'start';
+    var end = 'end';
+    var clippingParents = 'clippingParents';
+    var viewport = 'viewport';
+    var popper = 'popper';
+    var reference = 'reference';
+    var variationPlacements = /*#__PURE__*/basePlacements.reduce(function (acc, placement) {
+      return acc.concat([placement + "-" + start, placement + "-" + end]);
+    }, []);
+    var placements = /*#__PURE__*/[].concat(basePlacements, [auto]).reduce(function (acc, placement) {
+      return acc.concat([placement, placement + "-" + start, placement + "-" + end]);
+    }, []); // modifiers that need to read the DOM
+
+    var beforeRead = 'beforeRead';
+    var read = 'read';
+    var afterRead = 'afterRead'; // pure-logic modifiers
+
+    var beforeMain = 'beforeMain';
+    var main = 'main';
+    var afterMain = 'afterMain'; // modifier with the purpose to write to the DOM (or write into a framework state)
+
+    var beforeWrite = 'beforeWrite';
+    var write = 'write';
+    var afterWrite = 'afterWrite';
+    var modifierPhases = [beforeRead, read, afterRead, beforeMain, main, afterMain, beforeWrite, write, afterWrite];
+
+    function getNodeName(element) {
+      return element ? (element.nodeName || '').toLowerCase() : null;
     }
 
     /*:: import type { Window } from '../types'; */
@@ -280,16 +302,6 @@
       return node;
     }
 
-    function getWindowScroll(node) {
-      var win = getWindow(node);
-      var scrollLeft = win.pageXOffset;
-      var scrollTop = win.pageYOffset;
-      return {
-        scrollLeft: scrollLeft,
-        scrollTop: scrollTop
-      };
-    }
-
     /*:: declare function isElement(node: mixed): boolean %checks(node instanceof
       Element); */
 
@@ -314,96 +326,90 @@
       return node instanceof OwnElement || node instanceof ShadowRoot;
     }
 
-    function getHTMLElementScroll(element) {
-      return {
-        scrollLeft: element.scrollLeft,
-        scrollTop: element.scrollTop
-      };
-    }
+    // and applies them to the HTMLElements such as popper and arrow
 
-    function getNodeScroll(node) {
-      if (node === getWindow(node) || !isHTMLElement(node)) {
-        return getWindowScroll(node);
-      } else {
-        return getHTMLElementScroll(node);
-      }
-    }
+    function applyStyles(_ref) {
+      var state = _ref.state;
+      Object.keys(state.elements).forEach(function (name) {
+        var style = state.styles[name] || {};
+        var attributes = state.attributes[name] || {};
+        var element = state.elements[name]; // arrow is optional + virtual elements
 
-    function getNodeName(element) {
-      return element ? (element.nodeName || '').toLowerCase() : null;
-    }
+        if (!isHTMLElement(element) || !getNodeName(element)) {
+          return;
+        } // Flow doesn't support to extend this property, but it's the most
+        // effective way to apply styles to an HTMLElement
+        // $FlowFixMe[cannot-write]
 
-    function getDocumentElement(element) {
-      // $FlowFixMe[incompatible-return]: assume body is always available
-      return ((isElement(element) ? element.ownerDocument : // $FlowFixMe[prop-missing]
-      element.document) || window.document).documentElement;
-    }
 
-    function getWindowScrollBarX(element) {
-      // If <html> has a CSS width greater than the viewport, then this will be
-      // incorrect for RTL.
-      // Popper 1 is broken in this case and never had a bug report so let's assume
-      // it's not an issue. I don't think anyone ever specifies width on <html>
-      // anyway.
-      // Browsers where the left scrollbar doesn't cause an issue report `0` for
-      // this (e.g. Edge 2019, IE11, Safari)
-      return getBoundingClientRect(getDocumentElement(element)).left + getWindowScroll(element).scrollLeft;
-    }
+        Object.assign(element.style, style);
+        Object.keys(attributes).forEach(function (name) {
+          var value = attributes[name];
 
-    function getComputedStyle$1(element) {
-      return getWindow(element).getComputedStyle(element);
+          if (value === false) {
+            element.removeAttribute(name);
+          } else {
+            element.setAttribute(name, value === true ? '' : value);
+          }
+        });
+      });
     }
 
-    function isScrollParent(element) {
-      // Firefox wants us to check `-x` and `-y` variations as well
-      var _getComputedStyle = getComputedStyle$1(element),
-          overflow = _getComputedStyle.overflow,
-          overflowX = _getComputedStyle.overflowX,
-          overflowY = _getComputedStyle.overflowY;
+    function effect(_ref2) {
+      var state = _ref2.state;
+      var initialStyles = {
+        popper: {
+          position: state.options.strategy,
+          left: '0',
+          top: '0',
+          margin: '0'
+        },
+        arrow: {
+          position: 'absolute'
+        },
+        reference: {}
+      };
+      Object.assign(state.elements.popper.style, initialStyles.popper);
 
-      return /auto|scroll|overlay|hidden/.test(overflow + overflowY + overflowX);
-    }
+      if (state.elements.arrow) {
+        Object.assign(state.elements.arrow.style, initialStyles.arrow);
+      }
 
-    // Composite means it takes into account transforms as well as layout.
+      return function () {
+        Object.keys(state.elements).forEach(function (name) {
+          var element = state.elements[name];
+          var attributes = state.attributes[name] || {};
+          var styleProperties = Object.keys(state.styles.hasOwnProperty(name) ? state.styles[name] : initialStyles[name]); // Set all values to an empty string to unset them
 
-    function getCompositeRect(elementOrVirtualElement, offsetParent, isFixed) {
-      if (isFixed === void 0) {
-        isFixed = false;
-      }
+          var style = styleProperties.reduce(function (style, property) {
+            style[property] = '';
+            return style;
+          }, {}); // arrow is optional + virtual elements
 
-      var documentElement = getDocumentElement(offsetParent);
-      var rect = getBoundingClientRect(elementOrVirtualElement);
-      var isOffsetParentAnElement = isHTMLElement(offsetParent);
-      var scroll = {
-        scrollLeft: 0,
-        scrollTop: 0
-      };
-      var offsets = {
-        x: 0,
-        y: 0
+          if (!isHTMLElement(element) || !getNodeName(element)) {
+            return;
+          }
+
+          Object.assign(element.style, style);
+          Object.keys(attributes).forEach(function (attribute) {
+            element.removeAttribute(attribute);
+          });
+        });
       };
+    } // eslint-disable-next-line import/no-unused-modules
 
-      if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {
-        if (getNodeName(offsetParent) !== 'body' || // https://github.com/popperjs/popper-core/issues/1078
-        isScrollParent(documentElement)) {
-          scroll = getNodeScroll(offsetParent);
-        }
 
-        if (isHTMLElement(offsetParent)) {
-          offsets = getBoundingClientRect(offsetParent);
-          offsets.x += offsetParent.clientLeft;
-          offsets.y += offsetParent.clientTop;
-        } else if (documentElement) {
-          offsets.x = getWindowScrollBarX(documentElement);
-        }
-      }
+    var applyStyles$1 = {
+      name: 'applyStyles',
+      enabled: true,
+      phase: 'write',
+      fn: applyStyles,
+      effect: effect,
+      requires: ['computeStyles']
+    };
 
-      return {
-        x: rect.left + scroll.scrollLeft - offsets.x,
-        y: rect.top + scroll.scrollTop - offsets.y,
-        width: rect.width,
-        height: rect.height
-      };
+    function getBasePlacement(placement) {
+      return placement.split('-')[0];
     }
 
     // Returns the layout rect of an element relative to its offsetParent. Layout
@@ -417,6 +423,43 @@
       };
     }
 
+    function contains(parent, child) {
+      var rootNode = child.getRootNode && child.getRootNode(); // First, attempt with faster native method
+
+      if (parent.contains(child)) {
+        return true;
+      } // then fallback to custom implementation with Shadow DOM support
+      else if (rootNode && isShadowRoot(rootNode)) {
+          var next = child;
+
+          do {
+            if (next && parent.isSameNode(next)) {
+              return true;
+            } // $FlowFixMe[prop-missing]: need a better way to handle this...
+
+
+            next = next.parentNode || next.host;
+          } while (next);
+        } // Give up, the result is false
+
+
+      return false;
+    }
+
+    function getComputedStyle$1(element) {
+      return getWindow(element).getComputedStyle(element);
+    }
+
+    function isTableElement(element) {
+      return ['table', 'td', 'th'].indexOf(getNodeName(element)) >= 0;
+    }
+
+    function getDocumentElement(element) {
+      // $FlowFixMe[incompatible-return]: assume body is always available
+      return ((isElement(element) ? element.ownerDocument : // $FlowFixMe[prop-missing]
+      element.document) || window.document).documentElement;
+    }
+
     function getParentNode(element) {
       if (getNodeName(element) === 'html') {
         return element;
@@ -435,54 +478,16 @@
       );
     }
 
-    function getScrollParent(node) {
-      if (['html', 'body', '#document'].indexOf(getNodeName(node)) >= 0) {
-        // $FlowFixMe[incompatible-return]: assume body is always available
-        return node.ownerDocument.body;
+    function getTrueOffsetParent(element) {
+      if (!isHTMLElement(element) || // https://github.com/popperjs/popper-core/issues/837
+      getComputedStyle$1(element).position === 'fixed') {
+        return null;
       }
 
-      if (isHTMLElement(node) && isScrollParent(node)) {
-        return node;
-      }
+      var offsetParent = element.offsetParent;
 
-      return getScrollParent(getParentNode(node));
-    }
-
-    /*
-    given a DOM element, return the list of all scroll parents, up the list of ancesors
-    until we get to the top window object. This list is what we attach scroll listeners
-    to, because if any of these parent elements scroll, we'll need to re-calculate the
-    reference element's position.
-    */
-
-    function listScrollParents(element, list) {
-      if (list === void 0) {
-        list = [];
-      }
-
-      var scrollParent = getScrollParent(element);
-      var isBody = getNodeName(scrollParent) === 'body';
-      var win = getWindow(scrollParent);
-      var target = isBody ? [win].concat(win.visualViewport || [], isScrollParent(scrollParent) ? scrollParent : []) : scrollParent;
-      var updatedList = list.concat(target);
-      return isBody ? updatedList : // $FlowFixMe[incompatible-call]: isBody tells us target will be an HTMLElement here
-      updatedList.concat(listScrollParents(getParentNode(target)));
-    }
-
-    function isTableElement(element) {
-      return ['table', 'td', 'th'].indexOf(getNodeName(element)) >= 0;
-    }
-
-    function getTrueOffsetParent(element) {
-      if (!isHTMLElement(element) || // https://github.com/popperjs/popper-core/issues/837
-      getComputedStyle$1(element).position === 'fixed') {
-        return null;
-      }
-
-      var offsetParent = element.offsetParent;
-
-      if (offsetParent) {
-        var html = getDocumentElement(offsetParent);
+      if (offsetParent) {
+        var html = getDocumentElement(offsetParent);
 
         if (getNodeName(offsetParent) === 'body' && getComputedStyle$1(offsetParent).position === 'static' && getComputedStyle$1(html).position !== 'static') {
           return html;
@@ -528,885 +533,905 @@
       return offsetParent || getContainingBlock(element) || window;
     }
 
-    var top = 'top';
-    var bottom = 'bottom';
-    var right = 'right';
-    var left = 'left';
-    var auto = 'auto';
-    var basePlacements = [top, bottom, right, left];
-    var start = 'start';
-    var end = 'end';
-    var clippingParents = 'clippingParents';
-    var viewport = 'viewport';
-    var popper = 'popper';
-    var reference = 'reference';
-    var variationPlacements = /*#__PURE__*/basePlacements.reduce(function (acc, placement) {
-      return acc.concat([placement + "-" + start, placement + "-" + end]);
-    }, []);
-    var placements = /*#__PURE__*/[].concat(basePlacements, [auto]).reduce(function (acc, placement) {
-      return acc.concat([placement, placement + "-" + start, placement + "-" + end]);
-    }, []); // modifiers that need to read the DOM
-
-    var beforeRead = 'beforeRead';
-    var read = 'read';
-    var afterRead = 'afterRead'; // pure-logic modifiers
-
-    var beforeMain = 'beforeMain';
-    var main = 'main';
-    var afterMain = 'afterMain'; // modifier with the purpose to write to the DOM (or write into a framework state)
-
-    var beforeWrite = 'beforeWrite';
-    var write = 'write';
-    var afterWrite = 'afterWrite';
-    var modifierPhases = [beforeRead, read, afterRead, beforeMain, main, afterMain, beforeWrite, write, afterWrite];
+    function getMainAxisFromPlacement(placement) {
+      return ['top', 'bottom'].indexOf(placement) >= 0 ? 'x' : 'y';
+    }
 
-    function order(modifiers) {
-      var map = new Map();
-      var visited = new Set();
-      var result = [];
-      modifiers.forEach(function (modifier) {
-        map.set(modifier.name, modifier);
-      }); // On visiting object, check for its dependencies and visit them recursively
+    function within(min, value, max) {
+      return Math.max(min, Math.min(value, max));
+    }
 
-      function sort(modifier) {
-        visited.add(modifier.name);
-        var requires = [].concat(modifier.requires || [], modifier.requiresIfExists || []);
-        requires.forEach(function (dep) {
-          if (!visited.has(dep)) {
-            var depModifier = map.get(dep);
+    function getFreshSideObject() {
+      return {
+        top: 0,
+        right: 0,
+        bottom: 0,
+        left: 0
+      };
+    }
 
-            if (depModifier) {
-              sort(depModifier);
-            }
-          }
-        });
-        result.push(modifier);
-      }
+    function mergePaddingObject(paddingObject) {
+      return Object.assign(Object.assign({}, getFreshSideObject()), paddingObject);
+    }
 
-      modifiers.forEach(function (modifier) {
-        if (!visited.has(modifier.name)) {
-          // check for visited object
-          sort(modifier);
-        }
-      });
-      return result;
+    function expandToHashMap(value, keys) {
+      return keys.reduce(function (hashMap, key) {
+        hashMap[key] = value;
+        return hashMap;
+      }, {});
     }
 
-    function orderModifiers(modifiers) {
-      // order based on dependencies
-      var orderedModifiers = order(modifiers); // order based on phase
+    function arrow(_ref) {
+      var _state$modifiersData$;
 
-      return modifierPhases.reduce(function (acc, phase) {
-        return acc.concat(orderedModifiers.filter(function (modifier) {
-          return modifier.phase === phase;
-        }));
-      }, []);
-    }
+      var state = _ref.state,
+          name = _ref.name;
+      var arrowElement = state.elements.arrow;
+      var popperOffsets = state.modifiersData.popperOffsets;
+      var basePlacement = getBasePlacement(state.placement);
+      var axis = getMainAxisFromPlacement(basePlacement);
+      var isVertical = [left, right].indexOf(basePlacement) >= 0;
+      var len = isVertical ? 'height' : 'width';
 
-    function debounce(fn) {
-      var pending;
-      return function () {
-        if (!pending) {
-          pending = new Promise(function (resolve) {
-            Promise.resolve().then(function () {
-              pending = undefined;
-              resolve(fn());
-            });
-          });
-        }
+      if (!arrowElement || !popperOffsets) {
+        return;
+      }
 
-        return pending;
-      };
-    }
+      var paddingObject = state.modifiersData[name + "#persistent"].padding;
+      var arrowRect = getLayoutRect(arrowElement);
+      var minProp = axis === 'y' ? top : left;
+      var maxProp = axis === 'y' ? bottom : right;
+      var endDiff = state.rects.reference[len] + state.rects.reference[axis] - popperOffsets[axis] - state.rects.popper[len];
+      var startDiff = popperOffsets[axis] - state.rects.reference[axis];
+      var arrowOffsetParent = getOffsetParent(arrowElement);
+      var clientSize = arrowOffsetParent ? axis === 'y' ? arrowOffsetParent.clientHeight || 0 : arrowOffsetParent.clientWidth || 0 : 0;
+      var centerToReference = endDiff / 2 - startDiff / 2; // Make sure the arrow doesn't overflow the popper if the center point is
+      // outside of the popper bounds
 
-    function getBasePlacement(placement) {
-      return placement.split('-')[0];
+      var min = paddingObject[minProp];
+      var max = clientSize - arrowRect[len] - paddingObject[maxProp];
+      var center = clientSize / 2 - arrowRect[len] / 2 + centerToReference;
+      var offset = within(min, center, max); // Prevents breaking syntax highlighting...
+
+      var axisProp = axis;
+      state.modifiersData[name] = (_state$modifiersData$ = {}, _state$modifiersData$[axisProp] = offset, _state$modifiersData$.centerOffset = offset - center, _state$modifiersData$);
     }
 
-    function mergeByName(modifiers) {
-      var merged = modifiers.reduce(function (merged, current) {
-        var existing = merged[current.name];
-        merged[current.name] = existing ? Object.assign(Object.assign(Object.assign({}, existing), current), {}, {
-          options: Object.assign(Object.assign({}, existing.options), current.options),
-          data: Object.assign(Object.assign({}, existing.data), current.data)
-        }) : current;
-        return merged;
-      }, {}); // IE11 does not support Object.values
+    function effect$1(_ref2) {
+      var state = _ref2.state,
+          options = _ref2.options,
+          name = _ref2.name;
+      var _options$element = options.element,
+          arrowElement = _options$element === void 0 ? '[data-popper-arrow]' : _options$element,
+          _options$padding = options.padding,
+          padding = _options$padding === void 0 ? 0 : _options$padding;
 
-      return Object.keys(merged).map(function (key) {
-        return merged[key];
-      });
-    }
+      if (arrowElement == null) {
+        return;
+      } // CSS selector
 
-    function getViewportRect(element) {
-      var win = getWindow(element);
-      var html = getDocumentElement(element);
-      var visualViewport = win.visualViewport;
-      var width = html.clientWidth;
-      var height = html.clientHeight;
-      var x = 0;
-      var y = 0; // NB: This isn't supported on iOS <= 12. If the keyboard is open, the popper
-      // can be obscured underneath it.
-      // Also, `html.clientHeight` adds the bottom bar height in Safari iOS, even
-      // if it isn't open, so if this isn't available, the popper will be detected
-      // to overflow the bottom of the screen too early.
 
-      if (visualViewport) {
-        width = visualViewport.width;
-        height = visualViewport.height; // Uses Layout Viewport (like Chrome; Safari does not currently)
-        // In Chrome, it returns a value very close to 0 (+/-) but contains rounding
-        // errors due to floating point numbers, so we need to check precision.
-        // Safari returns a number <= 0, usually < -1 when pinch-zoomed
-        // Feature detection fails in mobile emulation mode in Chrome.
-        // Math.abs(win.innerWidth / visualViewport.scale - visualViewport.width) <
-        // 0.001
-        // Fallback here: "Not Safari" userAgent
+      if (typeof arrowElement === 'string') {
+        arrowElement = state.elements.popper.querySelector(arrowElement);
 
-        if (!/^((?!chrome|android).)*safari/i.test(navigator.userAgent)) {
-          x = visualViewport.offsetLeft;
-          y = visualViewport.offsetTop;
+        if (!arrowElement) {
+          return;
         }
       }
 
-      return {
-        width: width,
-        height: height,
-        x: x + getWindowScrollBarX(element),
-        y: y
-      };
-    }
-
-    // of the `<html>` and `<body>` rect bounds if horizontally scrollable
+      if (process.env.NODE_ENV !== "production") {
+        if (!isHTMLElement(arrowElement)) {
+          console.error(['Popper: "arrow" element must be an HTMLElement (not an SVGElement).', 'To use an SVG arrow, wrap it in an HTMLElement that will be used as', 'the arrow.'].join(' '));
+        }
+      }
 
-    function getDocumentRect(element) {
-      var html = getDocumentElement(element);
-      var winScroll = getWindowScroll(element);
-      var body = element.ownerDocument.body;
-      var width = Math.max(html.scrollWidth, html.clientWidth, body ? body.scrollWidth : 0, body ? body.clientWidth : 0);
-      var height = Math.max(html.scrollHeight, html.clientHeight, body ? body.scrollHeight : 0, body ? body.clientHeight : 0);
-      var x = -winScroll.scrollLeft + getWindowScrollBarX(element);
-      var y = -winScroll.scrollTop;
+      if (!contains(state.elements.popper, arrowElement)) {
+        if (process.env.NODE_ENV !== "production") {
+          console.error(['Popper: "arrow" modifier\'s `element` must be a child of the popper', 'element.'].join(' '));
+        }
 
-      if (getComputedStyle$1(body || html).direction === 'rtl') {
-        x += Math.max(html.clientWidth, body ? body.clientWidth : 0) - width;
+        return;
       }
 
-      return {
-        width: width,
-        height: height,
-        x: x,
-        y: y
+      state.elements.arrow = arrowElement;
+      state.modifiersData[name + "#persistent"] = {
+        padding: mergePaddingObject(typeof padding !== 'number' ? padding : expandToHashMap(padding, basePlacements))
       };
-    }
+    } // eslint-disable-next-line import/no-unused-modules
 
-    function contains(parent, child) {
-      var rootNode = child.getRootNode && child.getRootNode(); // First, attempt with faster native method
 
-      if (parent.contains(child)) {
-        return true;
-      } // then fallback to custom implementation with Shadow DOM support
-      else if (rootNode && isShadowRoot(rootNode)) {
-          var next = child;
-
-          do {
-            if (next && parent.isSameNode(next)) {
-              return true;
-            } // $FlowFixMe[prop-missing]: need a better way to handle this...
+    var arrow$1 = {
+      name: 'arrow',
+      enabled: true,
+      phase: 'main',
+      fn: arrow,
+      effect: effect$1,
+      requires: ['popperOffsets'],
+      requiresIfExists: ['preventOverflow']
+    };
 
+    var unsetSides = {
+      top: 'auto',
+      right: 'auto',
+      bottom: 'auto',
+      left: 'auto'
+    }; // Round the offsets to the nearest suitable subpixel based on the DPR.
+    // Zooming can change the DPR, but it seems to report a value that will
+    // cleanly divide the values into the appropriate subpixels.
 
-            next = next.parentNode || next.host;
-          } while (next);
-        } // Give up, the result is false
+    function roundOffsetsByDPR(_ref) {
+      var x = _ref.x,
+          y = _ref.y;
+      var win = window;
+      var dpr = win.devicePixelRatio || 1;
+      return {
+        x: Math.round(x * dpr) / dpr || 0,
+        y: Math.round(y * dpr) / dpr || 0
+      };
+    }
 
+    function mapToStyles(_ref2) {
+      var _Object$assign2;
 
-      return false;
-    }
+      var popper = _ref2.popper,
+          popperRect = _ref2.popperRect,
+          placement = _ref2.placement,
+          offsets = _ref2.offsets,
+          position = _ref2.position,
+          gpuAcceleration = _ref2.gpuAcceleration,
+          adaptive = _ref2.adaptive,
+          roundOffsets = _ref2.roundOffsets;
 
-    function rectToClientRect(rect) {
-      return Object.assign(Object.assign({}, rect), {}, {
-        left: rect.x,
-        top: rect.y,
-        right: rect.x + rect.width,
-        bottom: rect.y + rect.height
-      });
-    }
+      var _ref3 = roundOffsets ? roundOffsetsByDPR(offsets) : offsets,
+          _ref3$x = _ref3.x,
+          x = _ref3$x === void 0 ? 0 : _ref3$x,
+          _ref3$y = _ref3.y,
+          y = _ref3$y === void 0 ? 0 : _ref3$y;
 
-    function getInnerBoundingClientRect(element) {
-      var rect = getBoundingClientRect(element);
-      rect.top = rect.top + element.clientTop;
-      rect.left = rect.left + element.clientLeft;
-      rect.bottom = rect.top + element.clientHeight;
-      rect.right = rect.left + element.clientWidth;
-      rect.width = element.clientWidth;
-      rect.height = element.clientHeight;
-      rect.x = rect.left;
-      rect.y = rect.top;
-      return rect;
-    }
+      var hasX = offsets.hasOwnProperty('x');
+      var hasY = offsets.hasOwnProperty('y');
+      var sideX = left;
+      var sideY = top;
+      var win = window;
 
-    function getClientRectFromMixedType(element, clippingParent) {
-      return clippingParent === viewport ? rectToClientRect(getViewportRect(element)) : isHTMLElement(clippingParent) ? getInnerBoundingClientRect(clippingParent) : rectToClientRect(getDocumentRect(getDocumentElement(element)));
-    } // A "clipping parent" is an overflowable container with the characteristic of
-    // clipping (or hiding) overflowing elements with a position different from
-    // `initial`
+      if (adaptive) {
+        var offsetParent = getOffsetParent(popper);
 
+        if (offsetParent === getWindow(popper)) {
+          offsetParent = getDocumentElement(popper);
+        } // $FlowFixMe[incompatible-cast]: force type refinement, we compare offsetParent with window above, but Flow doesn't detect it
 
-    function getClippingParents(element) {
-      var clippingParents = listScrollParents(getParentNode(element));
-      var canEscapeClipping = ['absolute', 'fixed'].indexOf(getComputedStyle$1(element).position) >= 0;
-      var clipperElement = canEscapeClipping && isHTMLElement(element) ? getOffsetParent(element) : element;
+        /*:: offsetParent = (offsetParent: Element); */
 
-      if (!isElement(clipperElement)) {
-        return [];
-      } // $FlowFixMe[incompatible-return]: https://github.com/facebook/flow/issues/1414
 
+        if (placement === top) {
+          sideY = bottom;
+          y -= offsetParent.clientHeight - popperRect.height;
+          y *= gpuAcceleration ? 1 : -1;
+        }
 
-      return clippingParents.filter(function (clippingParent) {
-        return isElement(clippingParent) && contains(clippingParent, clipperElement) && getNodeName(clippingParent) !== 'body';
-      });
-    } // Gets the maximum area that the element is visible in due to any number of
-    // clipping parents
+        if (placement === left) {
+          sideX = right;
+          x -= offsetParent.clientWidth - popperRect.width;
+          x *= gpuAcceleration ? 1 : -1;
+        }
+      }
 
+      var commonStyles = Object.assign({
+        position: position
+      }, adaptive && unsetSides);
 
-    function getClippingRect(element, boundary, rootBoundary) {
-      var mainClippingParents = boundary === 'clippingParents' ? getClippingParents(element) : [].concat(boundary);
-      var clippingParents = [].concat(mainClippingParents, [rootBoundary]);
-      var firstClippingParent = clippingParents[0];
-      var clippingRect = clippingParents.reduce(function (accRect, clippingParent) {
-        var rect = getClientRectFromMixedType(element, clippingParent);
-        accRect.top = Math.max(rect.top, accRect.top);
-        accRect.right = Math.min(rect.right, accRect.right);
-        accRect.bottom = Math.min(rect.bottom, accRect.bottom);
-        accRect.left = Math.max(rect.left, accRect.left);
-        return accRect;
-      }, getClientRectFromMixedType(element, firstClippingParent));
-      clippingRect.width = clippingRect.right - clippingRect.left;
-      clippingRect.height = clippingRect.bottom - clippingRect.top;
-      clippingRect.x = clippingRect.left;
-      clippingRect.y = clippingRect.top;
-      return clippingRect;
-    }
+      if (gpuAcceleration) {
+        var _Object$assign;
 
-    function getVariation(placement) {
-      return placement.split('-')[1];
-    }
+        return Object.assign(Object.assign({}, commonStyles), {}, (_Object$assign = {}, _Object$assign[sideY] = hasY ? '0' : '', _Object$assign[sideX] = hasX ? '0' : '', _Object$assign.transform = (win.devicePixelRatio || 1) < 2 ? "translate(" + x + "px, " + y + "px)" : "translate3d(" + x + "px, " + y + "px, 0)", _Object$assign));
+      }
 
-    function getMainAxisFromPlacement(placement) {
-      return ['top', 'bottom'].indexOf(placement) >= 0 ? 'x' : 'y';
+      return Object.assign(Object.assign({}, commonStyles), {}, (_Object$assign2 = {}, _Object$assign2[sideY] = hasY ? y + "px" : '', _Object$assign2[sideX] = hasX ? x + "px" : '', _Object$assign2.transform = '', _Object$assign2));
     }
 
-    function computeOffsets(_ref) {
-      var reference = _ref.reference,
-          element = _ref.element,
-          placement = _ref.placement;
-      var basePlacement = placement ? getBasePlacement(placement) : null;
-      var variation = placement ? getVariation(placement) : null;
-      var commonX = reference.x + reference.width / 2 - element.width / 2;
-      var commonY = reference.y + reference.height / 2 - element.height / 2;
-      var offsets;
+    function computeStyles(_ref4) {
+      var state = _ref4.state,
+          options = _ref4.options;
+      var _options$gpuAccelerat = options.gpuAcceleration,
+          gpuAcceleration = _options$gpuAccelerat === void 0 ? true : _options$gpuAccelerat,
+          _options$adaptive = options.adaptive,
+          adaptive = _options$adaptive === void 0 ? true : _options$adaptive,
+          _options$roundOffsets = options.roundOffsets,
+          roundOffsets = _options$roundOffsets === void 0 ? true : _options$roundOffsets;
 
-      switch (basePlacement) {
-        case top:
-          offsets = {
-            x: commonX,
-            y: reference.y - element.height
-          };
-          break;
+      if (process.env.NODE_ENV !== "production") {
+        var transitionProperty = getComputedStyle$1(state.elements.popper).transitionProperty || '';
 
-        case bottom:
-          offsets = {
-            x: commonX,
-            y: reference.y + reference.height
-          };
-          break;
+        if (adaptive && ['transform', 'top', 'right', 'bottom', 'left'].some(function (property) {
+          return transitionProperty.indexOf(property) >= 0;
+        })) {
+          console.warn(['Popper: Detected CSS transitions on at least one of the following', 'CSS properties: "transform", "top", "right", "bottom", "left".', '\n\n', 'Disable the "computeStyles" modifier\'s `adaptive` option to allow', 'for smooth transitions, or remove these properties from the CSS', 'transition declaration on the popper element if only transitioning', 'opacity or background-color for example.', '\n\n', 'We recommend using the popper element as a wrapper around an inne [...]
+        }
+      }
 
-        case right:
-          offsets = {
-            x: reference.x + reference.width,
-            y: commonY
-          };
-          break;
+      var commonStyles = {
+        placement: getBasePlacement(state.placement),
+        popper: state.elements.popper,
+        popperRect: state.rects.popper,
+        gpuAcceleration: gpuAcceleration
+      };
 
-        case left:
-          offsets = {
-            x: reference.x - element.width,
-            y: commonY
-          };
-          break;
+      if (state.modifiersData.popperOffsets != null) {
+        state.styles.popper = Object.assign(Object.assign({}, state.styles.popper), mapToStyles(Object.assign(Object.assign({}, commonStyles), {}, {
+          offsets: state.modifiersData.popperOffsets,
+          position: state.options.strategy,
+          adaptive: adaptive,
+          roundOffsets: roundOffsets
+        })));
+      }
 
-        default:
-          offsets = {
-            x: reference.x,
-            y: reference.y
-          };
+      if (state.modifiersData.arrow != null) {
+        state.styles.arrow = Object.assign(Object.assign({}, state.styles.arrow), mapToStyles(Object.assign(Object.assign({}, commonStyles), {}, {
+          offsets: state.modifiersData.arrow,
+          position: 'absolute',
+          adaptive: false,
+          roundOffsets: roundOffsets
+        })));
       }
 
-      var mainAxis = basePlacement ? getMainAxisFromPlacement(basePlacement) : null;
+      state.attributes.popper = Object.assign(Object.assign({}, state.attributes.popper), {}, {
+        'data-popper-placement': state.placement
+      });
+    } // eslint-disable-next-line import/no-unused-modules
 
-      if (mainAxis != null) {
-        var len = mainAxis === 'y' ? 'height' : 'width';
 
-        switch (variation) {
-          case start:
-            offsets[mainAxis] = offsets[mainAxis] - (reference[len] / 2 - element[len] / 2);
-            break;
+    var computeStyles$1 = {
+      name: 'computeStyles',
+      enabled: true,
+      phase: 'beforeWrite',
+      fn: computeStyles,
+      data: {}
+    };
 
-          case end:
-            offsets[mainAxis] = offsets[mainAxis] + (reference[len] / 2 - element[len] / 2);
-            break;
-        }
-      }
+    var passive = {
+      passive: true
+    };
 
-      return offsets;
-    }
+    function effect$2(_ref) {
+      var state = _ref.state,
+          instance = _ref.instance,
+          options = _ref.options;
+      var _options$scroll = options.scroll,
+          scroll = _options$scroll === void 0 ? true : _options$scroll,
+          _options$resize = options.resize,
+          resize = _options$resize === void 0 ? true : _options$resize;
+      var window = getWindow(state.elements.popper);
+      var scrollParents = [].concat(state.scrollParents.reference, state.scrollParents.popper);
 
-    function getFreshSideObject() {
+      if (scroll) {
+        scrollParents.forEach(function (scrollParent) {
+          scrollParent.addEventListener('scroll', instance.update, passive);
+        });
+      }
+
+      if (resize) {
+        window.addEventListener('resize', instance.update, passive);
+      }
+
+      return function () {
+        if (scroll) {
+          scrollParents.forEach(function (scrollParent) {
+            scrollParent.removeEventListener('scroll', instance.update, passive);
+          });
+        }
+
+        if (resize) {
+          window.removeEventListener('resize', instance.update, passive);
+        }
+      };
+    } // eslint-disable-next-line import/no-unused-modules
+
+
+    var eventListeners = {
+      name: 'eventListeners',
+      enabled: true,
+      phase: 'write',
+      fn: function fn() {},
+      effect: effect$2,
+      data: {}
+    };
+
+    var hash = {
+      left: 'right',
+      right: 'left',
+      bottom: 'top',
+      top: 'bottom'
+    };
+    function getOppositePlacement(placement) {
+      return placement.replace(/left|right|bottom|top/g, function (matched) {
+        return hash[matched];
+      });
+    }
+
+    var hash$1 = {
+      start: 'end',
+      end: 'start'
+    };
+    function getOppositeVariationPlacement(placement) {
+      return placement.replace(/start|end/g, function (matched) {
+        return hash$1[matched];
+      });
+    }
+
+    function getBoundingClientRect(element) {
+      var rect = element.getBoundingClientRect();
       return {
-        top: 0,
-        right: 0,
-        bottom: 0,
-        left: 0
+        width: rect.width,
+        height: rect.height,
+        top: rect.top,
+        right: rect.right,
+        bottom: rect.bottom,
+        left: rect.left,
+        x: rect.left,
+        y: rect.top
       };
     }
 
-    function mergePaddingObject(paddingObject) {
-      return Object.assign(Object.assign({}, getFreshSideObject()), paddingObject);
+    function getWindowScroll(node) {
+      var win = getWindow(node);
+      var scrollLeft = win.pageXOffset;
+      var scrollTop = win.pageYOffset;
+      return {
+        scrollLeft: scrollLeft,
+        scrollTop: scrollTop
+      };
     }
 
-    function expandToHashMap(value, keys) {
-      return keys.reduce(function (hashMap, key) {
-        hashMap[key] = value;
-        return hashMap;
-      }, {});
+    function getWindowScrollBarX(element) {
+      // If <html> has a CSS width greater than the viewport, then this will be
+      // incorrect for RTL.
+      // Popper 1 is broken in this case and never had a bug report so let's assume
+      // it's not an issue. I don't think anyone ever specifies width on <html>
+      // anyway.
+      // Browsers where the left scrollbar doesn't cause an issue report `0` for
+      // this (e.g. Edge 2019, IE11, Safari)
+      return getBoundingClientRect(getDocumentElement(element)).left + getWindowScroll(element).scrollLeft;
     }
 
-    function detectOverflow(state, options) {
-      if (options === void 0) {
-        options = {};
-      }
+    function getViewportRect(element) {
+      var win = getWindow(element);
+      var html = getDocumentElement(element);
+      var visualViewport = win.visualViewport;
+      var width = html.clientWidth;
+      var height = html.clientHeight;
+      var x = 0;
+      var y = 0; // NB: This isn't supported on iOS <= 12. If the keyboard is open, the popper
+      // can be obscured underneath it.
+      // Also, `html.clientHeight` adds the bottom bar height in Safari iOS, even
+      // if it isn't open, so if this isn't available, the popper will be detected
+      // to overflow the bottom of the screen too early.
 
-      var _options = options,
-          _options$placement = _options.placement,
-          placement = _options$placement === void 0 ? state.placement : _options$placement,
-          _options$boundary = _options.boundary,
-          boundary = _options$boundary === void 0 ? clippingParents : _options$boundary,
-          _options$rootBoundary = _options.rootBoundary,
-          rootBoundary = _options$rootBoundary === void 0 ? viewport : _options$rootBoundary,
-          _options$elementConte = _options.elementContext,
-          elementContext = _options$elementConte === void 0 ? popper : _options$elementConte,
-          _options$altBoundary = _options.altBoundary,
-          altBoundary = _options$altBoundary === void 0 ? false : _options$altBoundary,
-          _options$padding = _options.padding,
-          padding = _options$padding === void 0 ? 0 : _options$padding;
-      var paddingObject = mergePaddingObject(typeof padding !== 'number' ? padding : expandToHashMap(padding, basePlacements));
-      var altContext = elementContext === popper ? reference : popper;
-      var referenceElement = state.elements.reference;
-      var popperRect = state.rects.popper;
-      var element = state.elements[altBoundary ? altContext : elementContext];
-      var clippingClientRect = getClippingRect(isElement(element) ? element : element.contextElement || getDocumentElement(state.elements.popper), boundary, rootBoundary);
-      var referenceClientRect = getBoundingClientRect(referenceElement);
-      var popperOffsets = computeOffsets({
-        reference: referenceClientRect,
-        element: popperRect,
-        strategy: 'absolute',
-        placement: placement
-      });
-      var popperClientRect = rectToClientRect(Object.assign(Object.assign({}, popperRect), popperOffsets));
-      var elementClientRect = elementContext === popper ? popperClientRect : referenceClientRect; // positive = overflowing the clipping rect
-      // 0 or negative = within the clipping rect
+      if (visualViewport) {
+        width = visualViewport.width;
+        height = visualViewport.height; // Uses Layout Viewport (like Chrome; Safari does not currently)
+        // In Chrome, it returns a value very close to 0 (+/-) but contains rounding
+        // errors due to floating point numbers, so we need to check precision.
+        // Safari returns a number <= 0, usually < -1 when pinch-zoomed
+        // Feature detection fails in mobile emulation mode in Chrome.
+        // Math.abs(win.innerWidth / visualViewport.scale - visualViewport.width) <
+        // 0.001
+        // Fallback here: "Not Safari" userAgent
 
-      var overflowOffsets = {
-        top: clippingClientRect.top - elementClientRect.top + paddingObject.top,
-        bottom: elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom,
-        left: clippingClientRect.left - elementClientRect.left + paddingObject.left,
-        right: elementClientRect.right - clippingClientRect.right + paddingObject.right
+        if (!/^((?!chrome|android).)*safari/i.test(navigator.userAgent)) {
+          x = visualViewport.offsetLeft;
+          y = visualViewport.offsetTop;
+        }
+      }
+
+      return {
+        width: width,
+        height: height,
+        x: x + getWindowScrollBarX(element),
+        y: y
       };
-      var offsetData = state.modifiersData.offset; // Offsets can be applied only to the popper element
+    }
 
-      if (elementContext === popper && offsetData) {
-        var offset = offsetData[placement];
-        Object.keys(overflowOffsets).forEach(function (key) {
-          var multiply = [right, bottom].indexOf(key) >= 0 ? 1 : -1;
-          var axis = [top, bottom].indexOf(key) >= 0 ? 'y' : 'x';
-          overflowOffsets[key] += offset[axis] * multiply;
-        });
+    // of the `<html>` and `<body>` rect bounds if horizontally scrollable
+
+    function getDocumentRect(element) {
+      var html = getDocumentElement(element);
+      var winScroll = getWindowScroll(element);
+      var body = element.ownerDocument.body;
+      var width = Math.max(html.scrollWidth, html.clientWidth, body ? body.scrollWidth : 0, body ? body.clientWidth : 0);
+      var height = Math.max(html.scrollHeight, html.clientHeight, body ? body.scrollHeight : 0, body ? body.clientHeight : 0);
+      var x = -winScroll.scrollLeft + getWindowScrollBarX(element);
+      var y = -winScroll.scrollTop;
+
+      if (getComputedStyle$1(body || html).direction === 'rtl') {
+        x += Math.max(html.clientWidth, body ? body.clientWidth : 0) - width;
       }
 
-      return overflowOffsets;
+      return {
+        width: width,
+        height: height,
+        x: x,
+        y: y
+      };
     }
 
-    var DEFAULT_OPTIONS = {
-      placement: 'bottom',
-      modifiers: [],
-      strategy: 'absolute'
-    };
+    function isScrollParent(element) {
+      // Firefox wants us to check `-x` and `-y` variations as well
+      var _getComputedStyle = getComputedStyle$1(element),
+          overflow = _getComputedStyle.overflow,
+          overflowX = _getComputedStyle.overflowX,
+          overflowY = _getComputedStyle.overflowY;
 
-    function areValidElements() {
-      for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
-        args[_key] = arguments[_key];
+      return /auto|scroll|overlay|hidden/.test(overflow + overflowY + overflowX);
+    }
+
+    function getScrollParent(node) {
+      if (['html', 'body', '#document'].indexOf(getNodeName(node)) >= 0) {
+        // $FlowFixMe[incompatible-return]: assume body is always available
+        return node.ownerDocument.body;
       }
 
-      return !args.some(function (element) {
-        return !(element && typeof element.getBoundingClientRect === 'function');
-      });
+      if (isHTMLElement(node) && isScrollParent(node)) {
+        return node;
+      }
+
+      return getScrollParent(getParentNode(node));
     }
 
-    function popperGenerator(generatorOptions) {
-      if (generatorOptions === void 0) {
-        generatorOptions = {};
+    /*
+    given a DOM element, return the list of all scroll parents, up the list of ancesors
+    until we get to the top window object. This list is what we attach scroll listeners
+    to, because if any of these parent elements scroll, we'll need to re-calculate the
+    reference element's position.
+    */
+
+    function listScrollParents(element, list) {
+      if (list === void 0) {
+        list = [];
       }
 
-      var _generatorOptions = generatorOptions,
-          _generatorOptions$def = _generatorOptions.defaultModifiers,
-          defaultModifiers = _generatorOptions$def === void 0 ? [] : _generatorOptions$def,
-          _generatorOptions$def2 = _generatorOptions.defaultOptions,
-          defaultOptions = _generatorOptions$def2 === void 0 ? DEFAULT_OPTIONS : _generatorOptions$def2;
-      return function createPopper(reference, popper, options) {
-        if (options === void 0) {
-          options = defaultOptions;
-        }
+      var scrollParent = getScrollParent(element);
+      var isBody = getNodeName(scrollParent) === 'body';
+      var win = getWindow(scrollParent);
+      var target = isBody ? [win].concat(win.visualViewport || [], isScrollParent(scrollParent) ? scrollParent : []) : scrollParent;
+      var updatedList = list.concat(target);
+      return isBody ? updatedList : // $FlowFixMe[incompatible-call]: isBody tells us target will be an HTMLElement here
+      updatedList.concat(listScrollParents(getParentNode(target)));
+    }
 
-        var state = {
-          placement: 'bottom',
-          orderedModifiers: [],
-          options: Object.assign(Object.assign({}, DEFAULT_OPTIONS), defaultOptions),
-          modifiersData: {},
-          elements: {
-            reference: reference,
-            popper: popper
-          },
-          attributes: {},
-          styles: {}
-        };
-        var effectCleanupFns = [];
-        var isDestroyed = false;
-        var instance = {
-          state: state,
-          setOptions: function setOptions(options) {
-            cleanupModifierEffects();
-            state.options = Object.assign(Object.assign(Object.assign({}, defaultOptions), state.options), options);
-            state.scrollParents = {
-              reference: isElement(reference) ? listScrollParents(reference) : reference.contextElement ? listScrollParents(reference.contextElement) : [],
-              popper: listScrollParents(popper)
-            }; // Orders the modifiers based on their dependencies and `phase`
-            // properties
-
-            var orderedModifiers = orderModifiers(mergeByName([].concat(defaultModifiers, state.options.modifiers))); // Strip out disabled modifiers
-
-            state.orderedModifiers = orderedModifiers.filter(function (m) {
-              return m.enabled;
-            }); // Validate the provided modifiers so that the consumer will get warned
+    function rectToClientRect(rect) {
+      return Object.assign(Object.assign({}, rect), {}, {
+        left: rect.x,
+        top: rect.y,
+        right: rect.x + rect.width,
+        bottom: rect.y + rect.height
+      });
+    }
 
-            runModifierEffects();
-            return instance.update();
-          },
-          // Sync update – it will always be executed, even if not necessary. This
-          // is useful for low frequency updates where sync behavior simplifies the
-          // logic.
-          // For high frequency updates (e.g. `resize` and `scroll` events), always
-          // prefer the async Popper#update method
-          forceUpdate: function forceUpdate() {
-            if (isDestroyed) {
-              return;
-            }
+    function getInnerBoundingClientRect(element) {
+      var rect = getBoundingClientRect(element);
+      rect.top = rect.top + element.clientTop;
+      rect.left = rect.left + element.clientLeft;
+      rect.bottom = rect.top + element.clientHeight;
+      rect.right = rect.left + element.clientWidth;
+      rect.width = element.clientWidth;
+      rect.height = element.clientHeight;
+      rect.x = rect.left;
+      rect.y = rect.top;
+      return rect;
+    }
 
-            var _state$elements = state.elements,
-                reference = _state$elements.reference,
-                popper = _state$elements.popper; // Don't proceed if `reference` or `popper` are not valid elements
-            // anymore
+    function getClientRectFromMixedType(element, clippingParent) {
+      return clippingParent === viewport ? rectToClientRect(getViewportRect(element)) : isHTMLElement(clippingParent) ? getInnerBoundingClientRect(clippingParent) : rectToClientRect(getDocumentRect(getDocumentElement(element)));
+    } // A "clipping parent" is an overflowable container with the characteristic of
+    // clipping (or hiding) overflowing elements with a position different from
+    // `initial`
 
-            if (!areValidElements(reference, popper)) {
 
-              return;
-            } // Store the reference and popper rects to be read by modifiers
+    function getClippingParents(element) {
+      var clippingParents = listScrollParents(getParentNode(element));
+      var canEscapeClipping = ['absolute', 'fixed'].indexOf(getComputedStyle$1(element).position) >= 0;
+      var clipperElement = canEscapeClipping && isHTMLElement(element) ? getOffsetParent(element) : element;
 
+      if (!isElement(clipperElement)) {
+        return [];
+      } // $FlowFixMe[incompatible-return]: https://github.com/facebook/flow/issues/1414
 
-            state.rects = {
-              reference: getCompositeRect(reference, getOffsetParent(popper), state.options.strategy === 'fixed'),
-              popper: getLayoutRect(popper)
-            }; // Modifiers have the ability to reset the current update cycle. The
-            // most common use case for this is the `flip` modifier changing the
-            // placement, which then needs to re-run all the modifiers, because the
-            // logic was previously ran for the previous placement and is therefore
-            // stale/incorrect
 
-            state.reset = false;
-            state.placement = state.options.placement; // On each update cycle, the `modifiersData` property for each modifier
-            // is filled with the initial data specified by the modifier. This means
-            // it doesn't persist and is fresh on each update.
-            // To ensure persistent data, use `${name}#persistent`
+      return clippingParents.filter(function (clippingParent) {
+        return isElement(clippingParent) && contains(clippingParent, clipperElement) && getNodeName(clippingParent) !== 'body';
+      });
+    } // Gets the maximum area that the element is visible in due to any number of
+    // clipping parents
 
-            state.orderedModifiers.forEach(function (modifier) {
-              return state.modifiersData[modifier.name] = Object.assign({}, modifier.data);
-            });
 
-            for (var index = 0; index < state.orderedModifiers.length; index++) {
+    function getClippingRect(element, boundary, rootBoundary) {
+      var mainClippingParents = boundary === 'clippingParents' ? getClippingParents(element) : [].concat(boundary);
+      var clippingParents = [].concat(mainClippingParents, [rootBoundary]);
+      var firstClippingParent = clippingParents[0];
+      var clippingRect = clippingParents.reduce(function (accRect, clippingParent) {
+        var rect = getClientRectFromMixedType(element, clippingParent);
+        accRect.top = Math.max(rect.top, accRect.top);
+        accRect.right = Math.min(rect.right, accRect.right);
+        accRect.bottom = Math.min(rect.bottom, accRect.bottom);
+        accRect.left = Math.max(rect.left, accRect.left);
+        return accRect;
+      }, getClientRectFromMixedType(element, firstClippingParent));
+      clippingRect.width = clippingRect.right - clippingRect.left;
+      clippingRect.height = clippingRect.bottom - clippingRect.top;
+      clippingRect.x = clippingRect.left;
+      clippingRect.y = clippingRect.top;
+      return clippingRect;
+    }
 
-              if (state.reset === true) {
-                state.reset = false;
-                index = -1;
-                continue;
-              }
+    function getVariation(placement) {
+      return placement.split('-')[1];
+    }
 
-              var _state$orderedModifie = state.orderedModifiers[index],
-                  fn = _state$orderedModifie.fn,
-                  _state$orderedModifie2 = _state$orderedModifie.options,
-                  _options = _state$orderedModifie2 === void 0 ? {} : _state$orderedModifie2,
-                  name = _state$orderedModifie.name;
+    function computeOffsets(_ref) {
+      var reference = _ref.reference,
+          element = _ref.element,
+          placement = _ref.placement;
+      var basePlacement = placement ? getBasePlacement(placement) : null;
+      var variation = placement ? getVariation(placement) : null;
+      var commonX = reference.x + reference.width / 2 - element.width / 2;
+      var commonY = reference.y + reference.height / 2 - element.height / 2;
+      var offsets;
 
-              if (typeof fn === 'function') {
-                state = fn({
-                  state: state,
-                  options: _options,
-                  name: name,
-                  instance: instance
-                }) || state;
-              }
-            }
-          },
-          // Async and optimistically optimized update – it will not be executed if
-          // not necessary (debounced to run at most once-per-tick)
-          update: debounce(function () {
-            return new Promise(function (resolve) {
-              instance.forceUpdate();
-              resolve(state);
-            });
-          }),
-          destroy: function destroy() {
-            cleanupModifierEffects();
-            isDestroyed = true;
-          }
-        };
+      switch (basePlacement) {
+        case top:
+          offsets = {
+            x: commonX,
+            y: reference.y - element.height
+          };
+          break;
 
-        if (!areValidElements(reference, popper)) {
+        case bottom:
+          offsets = {
+            x: commonX,
+            y: reference.y + reference.height
+          };
+          break;
 
-          return instance;
-        }
+        case right:
+          offsets = {
+            x: reference.x + reference.width,
+            y: commonY
+          };
+          break;
 
-        instance.setOptions(options).then(function (state) {
-          if (!isDestroyed && options.onFirstUpdate) {
-            options.onFirstUpdate(state);
-          }
-        }); // Modifiers have the ability to execute arbitrary code before the first
-        // update cycle runs. They will be executed in the same order as the update
-        // cycle. This is useful when a modifier adds some persistent data that
-        // other modifiers need to use, but the modifier is run after the dependent
-        // one.
+        case left:
+          offsets = {
+            x: reference.x - element.width,
+            y: commonY
+          };
+          break;
 
-        function runModifierEffects() {
-          state.orderedModifiers.forEach(function (_ref3) {
-            var name = _ref3.name,
-                _ref3$options = _ref3.options,
-                options = _ref3$options === void 0 ? {} : _ref3$options,
-                effect = _ref3.effect;
+        default:
+          offsets = {
+            x: reference.x,
+            y: reference.y
+          };
+      }
 
-            if (typeof effect === 'function') {
-              var cleanupFn = effect({
-                state: state,
-                name: name,
-                instance: instance,
-                options: options
-              });
+      var mainAxis = basePlacement ? getMainAxisFromPlacement(basePlacement) : null;
 
-              var noopFn = function noopFn() {};
+      if (mainAxis != null) {
+        var len = mainAxis === 'y' ? 'height' : 'width';
 
-              effectCleanupFns.push(cleanupFn || noopFn);
-            }
-          });
-        }
+        switch (variation) {
+          case start:
+            offsets[mainAxis] = offsets[mainAxis] - (reference[len] / 2 - element[len] / 2);
+            break;
 
-        function cleanupModifierEffects() {
-          effectCleanupFns.forEach(function (fn) {
-            return fn();
-          });
-          effectCleanupFns = [];
+          case end:
+            offsets[mainAxis] = offsets[mainAxis] + (reference[len] / 2 - element[len] / 2);
+            break;
         }
+      }
 
-        return instance;
-      };
+      return offsets;
     }
 
-    var passive = {
-      passive: true
-    };
+    function detectOverflow(state, options) {
+      if (options === void 0) {
+        options = {};
+      }
 
-    function effect(_ref) {
-      var state = _ref.state,
-          instance = _ref.instance,
-          options = _ref.options;
-      var _options$scroll = options.scroll,
-          scroll = _options$scroll === void 0 ? true : _options$scroll,
-          _options$resize = options.resize,
-          resize = _options$resize === void 0 ? true : _options$resize;
-      var window = getWindow(state.elements.popper);
-      var scrollParents = [].concat(state.scrollParents.reference, state.scrollParents.popper);
+      var _options = options,
+          _options$placement = _options.placement,
+          placement = _options$placement === void 0 ? state.placement : _options$placement,
+          _options$boundary = _options.boundary,
+          boundary = _options$boundary === void 0 ? clippingParents : _options$boundary,
+          _options$rootBoundary = _options.rootBoundary,
+          rootBoundary = _options$rootBoundary === void 0 ? viewport : _options$rootBoundary,
+          _options$elementConte = _options.elementContext,
+          elementContext = _options$elementConte === void 0 ? popper : _options$elementConte,
+          _options$altBoundary = _options.altBoundary,
+          altBoundary = _options$altBoundary === void 0 ? false : _options$altBoundary,
+          _options$padding = _options.padding,
+          padding = _options$padding === void 0 ? 0 : _options$padding;
+      var paddingObject = mergePaddingObject(typeof padding !== 'number' ? padding : expandToHashMap(padding, basePlacements));
+      var altContext = elementContext === popper ? reference : popper;
+      var referenceElement = state.elements.reference;
+      var popperRect = state.rects.popper;
+      var element = state.elements[altBoundary ? altContext : elementContext];
+      var clippingClientRect = getClippingRect(isElement(element) ? element : element.contextElement || getDocumentElement(state.elements.popper), boundary, rootBoundary);
+      var referenceClientRect = getBoundingClientRect(referenceElement);
+      var popperOffsets = computeOffsets({
+        reference: referenceClientRect,
+        element: popperRect,
+        strategy: 'absolute',
+        placement: placement
+      });
+      var popperClientRect = rectToClientRect(Object.assign(Object.assign({}, popperRect), popperOffsets));
+      var elementClientRect = elementContext === popper ? popperClientRect : referenceClientRect; // positive = overflowing the clipping rect
+      // 0 or negative = within the clipping rect
 
-      if (scroll) {
-        scrollParents.forEach(function (scrollParent) {
-          scrollParent.addEventListener('scroll', instance.update, passive);
-        });
-      }
+      var overflowOffsets = {
+        top: clippingClientRect.top - elementClientRect.top + paddingObject.top,
+        bottom: elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom,
+        left: clippingClientRect.left - elementClientRect.left + paddingObject.left,
+        right: elementClientRect.right - clippingClientRect.right + paddingObject.right
+      };
+      var offsetData = state.modifiersData.offset; // Offsets can be applied only to the popper element
 
-      if (resize) {
-        window.addEventListener('resize', instance.update, passive);
+      if (elementContext === popper && offsetData) {
+        var offset = offsetData[placement];
+        Object.keys(overflowOffsets).forEach(function (key) {
+          var multiply = [right, bottom].indexOf(key) >= 0 ? 1 : -1;
+          var axis = [top, bottom].indexOf(key) >= 0 ? 'y' : 'x';
+          overflowOffsets[key] += offset[axis] * multiply;
+        });
       }
 
-      return function () {
-        if (scroll) {
-          scrollParents.forEach(function (scrollParent) {
-            scrollParent.removeEventListener('scroll', instance.update, passive);
-          });
-        }
-
-        if (resize) {
-          window.removeEventListener('resize', instance.update, passive);
-        }
-      };
-    } // eslint-disable-next-line import/no-unused-modules
+      return overflowOffsets;
+    }
 
+    /*:: type OverflowsMap = { [ComputedPlacement]: number }; */
 
-    var eventListeners = {
-      name: 'eventListeners',
-      enabled: true,
-      phase: 'write',
-      fn: function fn() {},
-      effect: effect,
-      data: {}
-    };
+    /*;; type OverflowsMap = { [key in ComputedPlacement]: number }; */
+    function computeAutoPlacement(state, options) {
+      if (options === void 0) {
+        options = {};
+      }
 
-    function popperOffsets(_ref) {
-      var state = _ref.state,
-          name = _ref.name;
-      // Offsets are the actual position the popper needs to have to be
-      // properly positioned near its reference element
-      // This is the most basic placement, and will be adjusted by
-      // the modifiers in the next step
-      state.modifiersData[name] = computeOffsets({
-        reference: state.rects.reference,
-        element: state.rects.popper,
-        strategy: 'absolute',
-        placement: state.placement
+      var _options = options,
+          placement = _options.placement,
+          boundary = _options.boundary,
+          rootBoundary = _options.rootBoundary,
+          padding = _options.padding,
+          flipVariations = _options.flipVariations,
+          _options$allowedAutoP = _options.allowedAutoPlacements,
+          allowedAutoPlacements = _options$allowedAutoP === void 0 ? placements : _options$allowedAutoP;
+      var variation = getVariation(placement);
+      var placements$1 = variation ? flipVariations ? variationPlacements : variationPlacements.filter(function (placement) {
+        return getVariation(placement) === variation;
+      }) : basePlacements;
+      var allowedPlacements = placements$1.filter(function (placement) {
+        return allowedAutoPlacements.indexOf(placement) >= 0;
       });
-    } // eslint-disable-next-line import/no-unused-modules
 
+      if (allowedPlacements.length === 0) {
+        allowedPlacements = placements$1;
 
-    var popperOffsets$1 = {
-      name: 'popperOffsets',
-      enabled: true,
-      phase: 'read',
-      fn: popperOffsets,
-      data: {}
-    };
+        if (process.env.NODE_ENV !== "production") {
+          console.error(['Popper: The `allowedAutoPlacements` option did not allow any', 'placements. Ensure the `placement` option matches the variation', 'of the allowed placements.', 'For example, "auto" cannot be used to allow "bottom-start".', 'Use "auto-start" instead.'].join(' '));
+        }
+      } // $FlowFixMe[incompatible-type]: Flow seems to have problems with two array unions...
 
-    var unsetSides = {
-      top: 'auto',
-      right: 'auto',
-      bottom: 'auto',
-      left: 'auto'
-    }; // Round the offsets to the nearest suitable subpixel based on the DPR.
-    // Zooming can change the DPR, but it seems to report a value that will
-    // cleanly divide the values into the appropriate subpixels.
 
-    function roundOffsetsByDPR(_ref) {
-      var x = _ref.x,
-          y = _ref.y;
-      var win = window;
-      var dpr = win.devicePixelRatio || 1;
-      return {
-        x: Math.round(x * dpr) / dpr || 0,
-        y: Math.round(y * dpr) / dpr || 0
-      };
+      var overflows = allowedPlacements.reduce(function (acc, placement) {
+        acc[placement] = detectOverflow(state, {
+          placement: placement,
+          boundary: boundary,
+          rootBoundary: rootBoundary,
+          padding: padding
+        })[getBasePlacement(placement)];
+        return acc;
+      }, {});
+      return Object.keys(overflows).sort(function (a, b) {
+        return overflows[a] - overflows[b];
+      });
     }
 
-    function mapToStyles(_ref2) {
-      var _Object$assign2;
+    function getExpandedFallbackPlacements(placement) {
+      if (getBasePlacement(placement) === auto) {
+        return [];
+      }
 
-      var popper = _ref2.popper,
-          popperRect = _ref2.popperRect,
-          placement = _ref2.placement,
-          offsets = _ref2.offsets,
-          position = _ref2.position,
-          gpuAcceleration = _ref2.gpuAcceleration,
-          adaptive = _ref2.adaptive,
-          roundOffsets = _ref2.roundOffsets;
+      var oppositePlacement = getOppositePlacement(placement);
+      return [getOppositeVariationPlacement(placement), oppositePlacement, getOppositeVariationPlacement(oppositePlacement)];
+    }
 
-      var _ref3 = roundOffsets ? roundOffsetsByDPR(offsets) : offsets,
-          _ref3$x = _ref3.x,
-          x = _ref3$x === void 0 ? 0 : _ref3$x,
-          _ref3$y = _ref3.y,
-          y = _ref3$y === void 0 ? 0 : _ref3$y;
+    function flip(_ref) {
+      var state = _ref.state,
+          options = _ref.options,
+          name = _ref.name;
 
-      var hasX = offsets.hasOwnProperty('x');
-      var hasY = offsets.hasOwnProperty('y');
-      var sideX = left;
-      var sideY = top;
-      var win = window;
+      if (state.modifiersData[name]._skip) {
+        return;
+      }
 
-      if (adaptive) {
-        var offsetParent = getOffsetParent(popper);
+      var _options$mainAxis = options.mainAxis,
+          checkMainAxis = _options$mainAxis === void 0 ? true : _options$mainAxis,
+          _options$altAxis = options.altAxis,
+          checkAltAxis = _options$altAxis === void 0 ? true : _options$altAxis,
+          specifiedFallbackPlacements = options.fallbackPlacements,
+          padding = options.padding,
+          boundary = options.boundary,
+          rootBoundary = options.rootBoundary,
+          altBoundary = options.altBoundary,
+          _options$flipVariatio = options.flipVariations,
+          flipVariations = _options$flipVariatio === void 0 ? true : _options$flipVariatio,
+          allowedAutoPlacements = options.allowedAutoPlacements;
+      var preferredPlacement = state.options.placement;
+      var basePlacement = getBasePlacement(preferredPlacement);
+      var isBasePlacement = basePlacement === preferredPlacement;
+      var fallbackPlacements = specifiedFallbackPlacements || (isBasePlacement || !flipVariations ? [getOppositePlacement(preferredPlacement)] : getExpandedFallbackPlacements(preferredPlacement));
+      var placements = [preferredPlacement].concat(fallbackPlacements).reduce(function (acc, placement) {
+        return acc.concat(getBasePlacement(placement) === auto ? computeAutoPlacement(state, {
+          placement: placement,
+          boundary: boundary,
+          rootBoundary: rootBoundary,
+          padding: padding,
+          flipVariations: flipVariations,
+          allowedAutoPlacements: allowedAutoPlacements
+        }) : placement);
+      }, []);
+      var referenceRect = state.rects.reference;
+      var popperRect = state.rects.popper;
+      var checksMap = new Map();
+      var makeFallbackChecks = true;
+      var firstFittingPlacement = placements[0];
 
-        if (offsetParent === getWindow(popper)) {
-          offsetParent = getDocumentElement(popper);
-        } // $FlowFixMe[incompatible-cast]: force type refinement, we compare offsetParent with window above, but Flow doesn't detect it
+      for (var i = 0; i < placements.length; i++) {
+        var placement = placements[i];
 
-        /*:: offsetParent = (offsetParent: Element); */
+        var _basePlacement = getBasePlacement(placement);
 
+        var isStartVariation = getVariation(placement) === start;
+        var isVertical = [top, bottom].indexOf(_basePlacement) >= 0;
+        var len = isVertical ? 'width' : 'height';
+        var overflow = detectOverflow(state, {
+          placement: placement,
+          boundary: boundary,
+          rootBoundary: rootBoundary,
+          altBoundary: altBoundary,
+          padding: padding
+        });
+        var mainVariationSide = isVertical ? isStartVariation ? right : left : isStartVariation ? bottom : top;
 
-        if (placement === top) {
-          sideY = bottom;
-          y -= offsetParent.clientHeight - popperRect.height;
-          y *= gpuAcceleration ? 1 : -1;
+        if (referenceRect[len] > popperRect[len]) {
+          mainVariationSide = getOppositePlacement(mainVariationSide);
         }
 
-        if (placement === left) {
-          sideX = right;
-          x -= offsetParent.clientWidth - popperRect.width;
-          x *= gpuAcceleration ? 1 : -1;
+        var altVariationSide = getOppositePlacement(mainVariationSide);
+        var checks = [];
+
+        if (checkMainAxis) {
+          checks.push(overflow[_basePlacement] <= 0);
         }
-      }
 
-      var commonStyles = Object.assign({
-        position: position
-      }, adaptive && unsetSides);
+        if (checkAltAxis) {
+          checks.push(overflow[mainVariationSide] <= 0, overflow[altVariationSide] <= 0);
+        }
 
-      if (gpuAcceleration) {
-        var _Object$assign;
+        if (checks.every(function (check) {
+          return check;
+        })) {
+          firstFittingPlacement = placement;
+          makeFallbackChecks = false;
+          break;
+        }
 
-        return Object.assign(Object.assign({}, commonStyles), {}, (_Object$assign = {}, _Object$assign[sideY] = hasY ? '0' : '', _Object$assign[sideX] = hasX ? '0' : '', _Object$assign.transform = (win.devicePixelRatio || 1) < 2 ? "translate(" + x + "px, " + y + "px)" : "translate3d(" + x + "px, " + y + "px, 0)", _Object$assign));
+        checksMap.set(placement, checks);
       }
 
-      return Object.assign(Object.assign({}, commonStyles), {}, (_Object$assign2 = {}, _Object$assign2[sideY] = hasY ? y + "px" : '', _Object$assign2[sideX] = hasX ? x + "px" : '', _Object$assign2.transform = '', _Object$assign2));
-    }
+      if (makeFallbackChecks) {
+        // `2` may be desired in some cases – research later
+        var numberOfChecks = flipVariations ? 3 : 1;
 
-    function computeStyles(_ref4) {
-      var state = _ref4.state,
-          options = _ref4.options;
-      var _options$gpuAccelerat = options.gpuAcceleration,
-          gpuAcceleration = _options$gpuAccelerat === void 0 ? true : _options$gpuAccelerat,
-          _options$adaptive = options.adaptive,
-          adaptive = _options$adaptive === void 0 ? true : _options$adaptive,
-          _options$roundOffsets = options.roundOffsets,
-          roundOffsets = _options$roundOffsets === void 0 ? true : _options$roundOffsets;
+        var _loop = function _loop(_i) {
+          var fittingPlacement = placements.find(function (placement) {
+            var checks = checksMap.get(placement);
 
-      var commonStyles = {
-        placement: getBasePlacement(state.placement),
-        popper: state.elements.popper,
-        popperRect: state.rects.popper,
-        gpuAcceleration: gpuAcceleration
-      };
+            if (checks) {
+              return checks.slice(0, _i).every(function (check) {
+                return check;
+              });
+            }
+          });
 
-      if (state.modifiersData.popperOffsets != null) {
-        state.styles.popper = Object.assign(Object.assign({}, state.styles.popper), mapToStyles(Object.assign(Object.assign({}, commonStyles), {}, {
-          offsets: state.modifiersData.popperOffsets,
-          position: state.options.strategy,
-          adaptive: adaptive,
-          roundOffsets: roundOffsets
-        })));
-      }
+          if (fittingPlacement) {
+            firstFittingPlacement = fittingPlacement;
+            return "break";
+          }
+        };
 
-      if (state.modifiersData.arrow != null) {
-        state.styles.arrow = Object.assign(Object.assign({}, state.styles.arrow), mapToStyles(Object.assign(Object.assign({}, commonStyles), {}, {
-          offsets: state.modifiersData.arrow,
-          position: 'absolute',
-          adaptive: false,
-          roundOffsets: roundOffsets
-        })));
+        for (var _i = numberOfChecks; _i > 0; _i--) {
+          var _ret = _loop(_i);
+
+          if (_ret === "break") break;
+        }
       }
 
-      state.attributes.popper = Object.assign(Object.assign({}, state.attributes.popper), {}, {
-        'data-popper-placement': state.placement
-      });
+      if (state.placement !== firstFittingPlacement) {
+        state.modifiersData[name]._skip = true;
+        state.placement = firstFittingPlacement;
+        state.reset = true;
+      }
     } // eslint-disable-next-line import/no-unused-modules
 
 
-    var computeStyles$1 = {
-      name: 'computeStyles',
+    var flip$1 = {
+      name: 'flip',
       enabled: true,
-      phase: 'beforeWrite',
-      fn: computeStyles,
-      data: {}
+      phase: 'main',
+      fn: flip,
+      requiresIfExists: ['offset'],
+      data: {
+        _skip: false
+      }
     };
 
-    // and applies them to the HTMLElements such as popper and arrow
-
-    function applyStyles(_ref) {
-      var state = _ref.state;
-      Object.keys(state.elements).forEach(function (name) {
-        var style = state.styles[name] || {};
-        var attributes = state.attributes[name] || {};
-        var element = state.elements[name]; // arrow is optional + virtual elements
-
-        if (!isHTMLElement(element) || !getNodeName(element)) {
-          return;
-        } // Flow doesn't support to extend this property, but it's the most
-        // effective way to apply styles to an HTMLElement
-        // $FlowFixMe[cannot-write]
-
+    function getSideOffsets(overflow, rect, preventedOffsets) {
+      if (preventedOffsets === void 0) {
+        preventedOffsets = {
+          x: 0,
+          y: 0
+        };
+      }
 
-        Object.assign(element.style, style);
-        Object.keys(attributes).forEach(function (name) {
-          var value = attributes[name];
+      return {
+        top: overflow.top - rect.height - preventedOffsets.y,
+        right: overflow.right - rect.width + preventedOffsets.x,
+        bottom: overflow.bottom - rect.height + preventedOffsets.y,
+        left: overflow.left - rect.width - preventedOffsets.x
+      };
+    }
 
-          if (value === false) {
-            element.removeAttribute(name);
-          } else {
-            element.setAttribute(name, value === true ? '' : value);
-          }
-        });
+    function isAnySideFullyClipped(overflow) {
+      return [top, right, bottom, left].some(function (side) {
+        return overflow[side] >= 0;
       });
     }
 
-    function effect$1(_ref2) {
-      var state = _ref2.state;
-      var initialStyles = {
-        popper: {
-          position: state.options.strategy,
-          left: '0',
-          top: '0',
-          margin: '0'
-        },
-        arrow: {
-          position: 'absolute'
-        },
-        reference: {}
-      };
-      Object.assign(state.elements.popper.style, initialStyles.popper);
-
-      if (state.elements.arrow) {
-        Object.assign(state.elements.arrow.style, initialStyles.arrow);
-      }
-
-      return function () {
-        Object.keys(state.elements).forEach(function (name) {
-          var element = state.elements[name];
-          var attributes = state.attributes[name] || {};
-          var styleProperties = Object.keys(state.styles.hasOwnProperty(name) ? state.styles[name] : initialStyles[name]); // Set all values to an empty string to unset them
-
-          var style = styleProperties.reduce(function (style, property) {
-            style[property] = '';
-            return style;
-          }, {}); // arrow is optional + virtual elements
-
-          if (!isHTMLElement(element) || !getNodeName(element)) {
-            return;
-          }
-
-          Object.assign(element.style, style);
-          Object.keys(attributes).forEach(function (attribute) {
-            element.removeAttribute(attribute);
-          });
-        });
+    function hide(_ref) {
+      var state = _ref.state,
+          name = _ref.name;
+      var referenceRect = state.rects.reference;
+      var popperRect = state.rects.popper;
+      var preventedOffsets = state.modifiersData.preventOverflow;
+      var referenceOverflow = detectOverflow(state, {
+        elementContext: 'reference'
+      });
+      var popperAltOverflow = detectOverflow(state, {
+        altBoundary: true
+      });
+      var referenceClippingOffsets = getSideOffsets(referenceOverflow, referenceRect);
+      var popperEscapeOffsets = getSideOffsets(popperAltOverflow, popperRect, preventedOffsets);
+      var isReferenceHidden = isAnySideFullyClipped(referenceClippingOffsets);
+      var hasPopperEscaped = isAnySideFullyClipped(popperEscapeOffsets);
+      state.modifiersData[name] = {
+        referenceClippingOffsets: referenceClippingOffsets,
+        popperEscapeOffsets: popperEscapeOffsets,
+        isReferenceHidden: isReferenceHidden,
+        hasPopperEscaped: hasPopperEscaped
       };
+      state.attributes.popper = Object.assign(Object.assign({}, state.attributes.popper), {}, {
+        'data-popper-reference-hidden': isReferenceHidden,
+        'data-popper-escaped': hasPopperEscaped
+      });
     } // eslint-disable-next-line import/no-unused-modules
 
 
-    var applyStyles$1 = {
-      name: 'applyStyles',
+    var hide$1 = {
+      name: 'hide',
       enabled: true,
-      phase: 'write',
-      fn: applyStyles,
-      effect: effect$1,
-      requires: ['computeStyles']
+      phase: 'main',
+      requiresIfExists: ['preventOverflow'],
+      fn: hide
     };
 
     function distanceAndSkiddingToXY(placement, rects, offset) {
@@ -1461,218 +1486,33 @@
       fn: offset
     };
 
-    var hash = {
-      left: 'right',
-      right: 'left',
-      bottom: 'top',
-      top: 'bottom'
-    };
-    function getOppositePlacement(placement) {
-      return placement.replace(/left|right|bottom|top/g, function (matched) {
-        return hash[matched];
+    function popperOffsets(_ref) {
+      var state = _ref.state,
+          name = _ref.name;
+      // Offsets are the actual position the popper needs to have to be
+      // properly positioned near its reference element
+      // This is the most basic placement, and will be adjusted by
+      // the modifiers in the next step
+      state.modifiersData[name] = computeOffsets({
+        reference: state.rects.reference,
+        element: state.rects.popper,
+        strategy: 'absolute',
+        placement: state.placement
       });
-    }
+    } // eslint-disable-next-line import/no-unused-modules
 
-    var hash$1 = {
-      start: 'end',
-      end: 'start'
-    };
-    function getOppositeVariationPlacement(placement) {
-      return placement.replace(/start|end/g, function (matched) {
-        return hash$1[matched];
-      });
-    }
 
-    /*:: type OverflowsMap = { [ComputedPlacement]: number }; */
+    var popperOffsets$1 = {
+      name: 'popperOffsets',
+      enabled: true,
+      phase: 'read',
+      fn: popperOffsets,
+      data: {}
+    };
 
-    /*;; type OverflowsMap = { [key in ComputedPlacement]: number }; */
-    function computeAutoPlacement(state, options) {
-      if (options === void 0) {
-        options = {};
-      }
-
-      var _options = options,
-          placement = _options.placement,
-          boundary = _options.boundary,
-          rootBoundary = _options.rootBoundary,
-          padding = _options.padding,
-          flipVariations = _options.flipVariations,
-          _options$allowedAutoP = _options.allowedAutoPlacements,
-          allowedAutoPlacements = _options$allowedAutoP === void 0 ? placements : _options$allowedAutoP;
-      var variation = getVariation(placement);
-      var placements$1 = variation ? flipVariations ? variationPlacements : variationPlacements.filter(function (placement) {
-        return getVariation(placement) === variation;
-      }) : basePlacements;
-      var allowedPlacements = placements$1.filter(function (placement) {
-        return allowedAutoPlacements.indexOf(placement) >= 0;
-      });
-
-      if (allowedPlacements.length === 0) {
-        allowedPlacements = placements$1;
-      } // $FlowFixMe[incompatible-type]: Flow seems to have problems with two array unions...
-
-
-      var overflows = allowedPlacements.reduce(function (acc, placement) {
-        acc[placement] = detectOverflow(state, {
-          placement: placement,
-          boundary: boundary,
-          rootBoundary: rootBoundary,
-          padding: padding
-        })[getBasePlacement(placement)];
-        return acc;
-      }, {});
-      return Object.keys(overflows).sort(function (a, b) {
-        return overflows[a] - overflows[b];
-      });
-    }
-
-    function getExpandedFallbackPlacements(placement) {
-      if (getBasePlacement(placement) === auto) {
-        return [];
-      }
-
-      var oppositePlacement = getOppositePlacement(placement);
-      return [getOppositeVariationPlacement(placement), oppositePlacement, getOppositeVariationPlacement(oppositePlacement)];
-    }
-
-    function flip(_ref) {
-      var state = _ref.state,
-          options = _ref.options,
-          name = _ref.name;
-
-      if (state.modifiersData[name]._skip) {
-        return;
-      }
-
-      var _options$mainAxis = options.mainAxis,
-          checkMainAxis = _options$mainAxis === void 0 ? true : _options$mainAxis,
-          _options$altAxis = options.altAxis,
-          checkAltAxis = _options$altAxis === void 0 ? true : _options$altAxis,
-          specifiedFallbackPlacements = options.fallbackPlacements,
-          padding = options.padding,
-          boundary = options.boundary,
-          rootBoundary = options.rootBoundary,
-          altBoundary = options.altBoundary,
-          _options$flipVariatio = options.flipVariations,
-          flipVariations = _options$flipVariatio === void 0 ? true : _options$flipVariatio,
-          allowedAutoPlacements = options.allowedAutoPlacements;
-      var preferredPlacement = state.options.placement;
-      var basePlacement = getBasePlacement(preferredPlacement);
-      var isBasePlacement = basePlacement === preferredPlacement;
-      var fallbackPlacements = specifiedFallbackPlacements || (isBasePlacement || !flipVariations ? [getOppositePlacement(preferredPlacement)] : getExpandedFallbackPlacements(preferredPlacement));
-      var placements = [preferredPlacement].concat(fallbackPlacements).reduce(function (acc, placement) {
-        return acc.concat(getBasePlacement(placement) === auto ? computeAutoPlacement(state, {
-          placement: placement,
-          boundary: boundary,
-          rootBoundary: rootBoundary,
-          padding: padding,
-          flipVariations: flipVariations,
-          allowedAutoPlacements: allowedAutoPlacements
-        }) : placement);
-      }, []);
-      var referenceRect = state.rects.reference;
-      var popperRect = state.rects.popper;
-      var checksMap = new Map();
-      var makeFallbackChecks = true;
-      var firstFittingPlacement = placements[0];
-
-      for (var i = 0; i < placements.length; i++) {
-        var placement = placements[i];
-
-        var _basePlacement = getBasePlacement(placement);
-
-        var isStartVariation = getVariation(placement) === start;
-        var isVertical = [top, bottom].indexOf(_basePlacement) >= 0;
-        var len = isVertical ? 'width' : 'height';
-        var overflow = detectOverflow(state, {
-          placement: placement,
-          boundary: boundary,
-          rootBoundary: rootBoundary,
-          altBoundary: altBoundary,
-          padding: padding
-        });
-        var mainVariationSide = isVertical ? isStartVariation ? right : left : isStartVariation ? bottom : top;
-
-        if (referenceRect[len] > popperRect[len]) {
-          mainVariationSide = getOppositePlacement(mainVariationSide);
-        }
-
-        var altVariationSide = getOppositePlacement(mainVariationSide);
-        var checks = [];
-
-        if (checkMainAxis) {
-          checks.push(overflow[_basePlacement] <= 0);
-        }
-
-        if (checkAltAxis) {
-          checks.push(overflow[mainVariationSide] <= 0, overflow[altVariationSide] <= 0);
-        }
-
-        if (checks.every(function (check) {
-          return check;
-        })) {
-          firstFittingPlacement = placement;
-          makeFallbackChecks = false;
-          break;
-        }
-
-        checksMap.set(placement, checks);
-      }
-
-      if (makeFallbackChecks) {
-        // `2` may be desired in some cases – research later
-        var numberOfChecks = flipVariations ? 3 : 1;
-
-        var _loop = function _loop(_i) {
-          var fittingPlacement = placements.find(function (placement) {
-            var checks = checksMap.get(placement);
-
-            if (checks) {
-              return checks.slice(0, _i).every(function (check) {
-                return check;
-              });
-            }
-          });
-
-          if (fittingPlacement) {
-            firstFittingPlacement = fittingPlacement;
-            return "break";
-          }
-        };
-
-        for (var _i = numberOfChecks; _i > 0; _i--) {
-          var _ret = _loop(_i);
-
-          if (_ret === "break") break;
-        }
-      }
-
-      if (state.placement !== firstFittingPlacement) {
-        state.modifiersData[name]._skip = true;
-        state.placement = firstFittingPlacement;
-        state.reset = true;
-      }
-    } // eslint-disable-next-line import/no-unused-modules
-
-
-    var flip$1 = {
-      name: 'flip',
-      enabled: true,
-      phase: 'main',
-      fn: flip,
-      requiresIfExists: ['offset'],
-      data: {
-        _skip: false
-      }
-    };
-
-    function getAltAxis(axis) {
-      return axis === 'x' ? 'y' : 'x';
-    }
-
-    function within(min, value, max) {
-      return Math.max(min, Math.min(value, max));
-    }
+    function getAltAxis(axis) {
+      return axis === 'x' ? 'y' : 'x';
+    }
 
     function preventOverflow(_ref) {
       var state = _ref.state,
@@ -1783,203 +1623,583 @@
       requiresIfExists: ['offset']
     };
 
-    function arrow(_ref) {
-      var _state$modifiersData$;
-
-      var state = _ref.state,
-          name = _ref.name;
-      var arrowElement = state.elements.arrow;
-      var popperOffsets = state.modifiersData.popperOffsets;
-      var basePlacement = getBasePlacement(state.placement);
-      var axis = getMainAxisFromPlacement(basePlacement);
-      var isVertical = [left, right].indexOf(basePlacement) >= 0;
-      var len = isVertical ? 'height' : 'width';
+    function getHTMLElementScroll(element) {
+      return {
+        scrollLeft: element.scrollLeft,
+        scrollTop: element.scrollTop
+      };
+    }
 
-      if (!arrowElement || !popperOffsets) {
-        return;
+    function getNodeScroll(node) {
+      if (node === getWindow(node) || !isHTMLElement(node)) {
+        return getWindowScroll(node);
+      } else {
+        return getHTMLElementScroll(node);
       }
-
-      var paddingObject = state.modifiersData[name + "#persistent"].padding;
-      var arrowRect = getLayoutRect(arrowElement);
-      var minProp = axis === 'y' ? top : left;
-      var maxProp = axis === 'y' ? bottom : right;
-      var endDiff = state.rects.reference[len] + state.rects.reference[axis] - popperOffsets[axis] - state.rects.popper[len];
-      var startDiff = popperOffsets[axis] - state.rects.reference[axis];
-      var arrowOffsetParent = getOffsetParent(arrowElement);
-      var clientSize = arrowOffsetParent ? axis === 'y' ? arrowOffsetParent.clientHeight || 0 : arrowOffsetParent.clientWidth || 0 : 0;
-      var centerToReference = endDiff / 2 - startDiff / 2; // Make sure the arrow doesn't overflow the popper if the center point is
-      // outside of the popper bounds
-
-      var min = paddingObject[minProp];
-      var max = clientSize - arrowRect[len] - paddingObject[maxProp];
-      var center = clientSize / 2 - arrowRect[len] / 2 + centerToReference;
-      var offset = within(min, center, max); // Prevents breaking syntax highlighting...
-
-      var axisProp = axis;
-      state.modifiersData[name] = (_state$modifiersData$ = {}, _state$modifiersData$[axisProp] = offset, _state$modifiersData$.centerOffset = offset - center, _state$modifiersData$);
     }
 
-    function effect$2(_ref2) {
-      var state = _ref2.state,
-          options = _ref2.options,
-          name = _ref2.name;
-      var _options$element = options.element,
-          arrowElement = _options$element === void 0 ? '[data-popper-arrow]' : _options$element,
-          _options$padding = options.padding,
-          padding = _options$padding === void 0 ? 0 : _options$padding;
-
-      if (arrowElement == null) {
-        return;
-      } // CSS selector
+    // Composite means it takes into account transforms as well as layout.
 
+    function getCompositeRect(elementOrVirtualElement, offsetParent, isFixed) {
+      if (isFixed === void 0) {
+        isFixed = false;
+      }
 
-      if (typeof arrowElement === 'string') {
-        arrowElement = state.elements.popper.querySelector(arrowElement);
+      var documentElement = getDocumentElement(offsetParent);
+      var rect = getBoundingClientRect(elementOrVirtualElement);
+      var isOffsetParentAnElement = isHTMLElement(offsetParent);
+      var scroll = {
+        scrollLeft: 0,
+        scrollTop: 0
+      };
+      var offsets = {
+        x: 0,
+        y: 0
+      };
 
-        if (!arrowElement) {
-          return;
+      if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {
+        if (getNodeName(offsetParent) !== 'body' || // https://github.com/popperjs/popper-core/issues/1078
+        isScrollParent(documentElement)) {
+          scroll = getNodeScroll(offsetParent);
         }
-      }
 
-      if (!contains(state.elements.popper, arrowElement)) {
-
-        return;
+        if (isHTMLElement(offsetParent)) {
+          offsets = getBoundingClientRect(offsetParent);
+          offsets.x += offsetParent.clientLeft;
+          offsets.y += offsetParent.clientTop;
+        } else if (documentElement) {
+          offsets.x = getWindowScrollBarX(documentElement);
+        }
       }
 
-      state.elements.arrow = arrowElement;
-      state.modifiersData[name + "#persistent"] = {
-        padding: mergePaddingObject(typeof padding !== 'number' ? padding : expandToHashMap(padding, basePlacements))
+      return {
+        x: rect.left + scroll.scrollLeft - offsets.x,
+        y: rect.top + scroll.scrollTop - offsets.y,
+        width: rect.width,
+        height: rect.height
       };
-    } // eslint-disable-next-line import/no-unused-modules
+    }
 
+    function order(modifiers) {
+      var map = new Map();
+      var visited = new Set();
+      var result = [];
+      modifiers.forEach(function (modifier) {
+        map.set(modifier.name, modifier);
+      }); // On visiting object, check for its dependencies and visit them recursively
 
-    var arrow$1 = {
-      name: 'arrow',
-      enabled: true,
-      phase: 'main',
-      fn: arrow,
-      effect: effect$2,
-      requires: ['popperOffsets'],
-      requiresIfExists: ['preventOverflow']
-    };
+      function sort(modifier) {
+        visited.add(modifier.name);
+        var requires = [].concat(modifier.requires || [], modifier.requiresIfExists || []);
+        requires.forEach(function (dep) {
+          if (!visited.has(dep)) {
+            var depModifier = map.get(dep);
 
-    function getSideOffsets(overflow, rect, preventedOffsets) {
-      if (preventedOffsets === void 0) {
-        preventedOffsets = {
-          x: 0,
-          y: 0
-        };
+            if (depModifier) {
+              sort(depModifier);
+            }
+          }
+        });
+        result.push(modifier);
       }
 
-      return {
-        top: overflow.top - rect.height - preventedOffsets.y,
-        right: overflow.right - rect.width + preventedOffsets.x,
-        bottom: overflow.bottom - rect.height + preventedOffsets.y,
-        left: overflow.left - rect.width - preventedOffsets.x
+      modifiers.forEach(function (modifier) {
+        if (!visited.has(modifier.name)) {
+          // check for visited object
+          sort(modifier);
+        }
+      });
+      return result;
+    }
+
+    function orderModifiers(modifiers) {
+      // order based on dependencies
+      var orderedModifiers = order(modifiers); // order based on phase
+
+      return modifierPhases.reduce(function (acc, phase) {
+        return acc.concat(orderedModifiers.filter(function (modifier) {
+          return modifier.phase === phase;
+        }));
+      }, []);
+    }
+
+    function debounce(fn) {
+      var pending;
+      return function () {
+        if (!pending) {
+          pending = new Promise(function (resolve) {
+            Promise.resolve().then(function () {
+              pending = undefined;
+              resolve(fn());
+            });
+          });
+        }
+
+        return pending;
       };
     }
 
-    function isAnySideFullyClipped(overflow) {
-      return [top, right, bottom, left].some(function (side) {
-        return overflow[side] >= 0;
-      });
+    function format(str) {
+      for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
+        args[_key - 1] = arguments[_key];
+      }
+
+      return [].concat(args).reduce(function (p, c) {
+        return p.replace(/%s/, c);
+      }, str);
     }
 
-    function hide(_ref) {
-      var state = _ref.state,
-          name = _ref.name;
-      var referenceRect = state.rects.reference;
-      var popperRect = state.rects.popper;
-      var preventedOffsets = state.modifiersData.preventOverflow;
-      var referenceOverflow = detectOverflow(state, {
-        elementContext: 'reference'
-      });
-      var popperAltOverflow = detectOverflow(state, {
-        altBoundary: true
+    var INVALID_MODIFIER_ERROR = 'Popper: modifier "%s" provided an invalid %s property, expected %s but got %s';
+    var MISSING_DEPENDENCY_ERROR = 'Popper: modifier "%s" requires "%s", but "%s" modifier is not available';
+    var VALID_PROPERTIES = ['name', 'enabled', 'phase', 'fn', 'effect', 'requires', 'options'];
+    function validateModifiers(modifiers) {
+      modifiers.forEach(function (modifier) {
+        Object.keys(modifier).forEach(function (key) {
+          switch (key) {
+            case 'name':
+              if (typeof modifier.name !== 'string') {
+                console.error(format(INVALID_MODIFIER_ERROR, String(modifier.name), '"name"', '"string"', "\"" + String(modifier.name) + "\""));
+              }
+
+              break;
+
+            case 'enabled':
+              if (typeof modifier.enabled !== 'boolean') {
+                console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"enabled"', '"boolean"', "\"" + String(modifier.enabled) + "\""));
+              }
+
+            case 'phase':
+              if (modifierPhases.indexOf(modifier.phase) < 0) {
+                console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"phase"', "either " + modifierPhases.join(', '), "\"" + String(modifier.phase) + "\""));
+              }
+
+              break;
+
+            case 'fn':
+              if (typeof modifier.fn !== 'function') {
+                console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"fn"', '"function"', "\"" + String(modifier.fn) + "\""));
+              }
+
+              break;
+
+            case 'effect':
+              if (typeof modifier.effect !== 'function') {
+                console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"effect"', '"function"', "\"" + String(modifier.fn) + "\""));
+              }
+
+              break;
+
+            case 'requires':
+              if (!Array.isArray(modifier.requires)) {
+                console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"requires"', '"array"', "\"" + String(modifier.requires) + "\""));
+              }
+
+              break;
+
+            case 'requiresIfExists':
+              if (!Array.isArray(modifier.requiresIfExists)) {
+                console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"requiresIfExists"', '"array"', "\"" + String(modifier.requiresIfExists) + "\""));
+              }
+
+              break;
+
+            case 'options':
+            case 'data':
+              break;
+
+            default:
+              console.error("PopperJS: an invalid property has been provided to the \"" + modifier.name + "\" modifier, valid properties are " + VALID_PROPERTIES.map(function (s) {
+                return "\"" + s + "\"";
+              }).join(', ') + "; but \"" + key + "\" was provided.");
+          }
+
+          modifier.requires && modifier.requires.forEach(function (requirement) {
+            if (modifiers.find(function (mod) {
+              return mod.name === requirement;
+            }) == null) {
+              console.error(format(MISSING_DEPENDENCY_ERROR, String(modifier.name), requirement, requirement));
+            }
+          });
+        });
       });
-      var referenceClippingOffsets = getSideOffsets(referenceOverflow, referenceRect);
-      var popperEscapeOffsets = getSideOffsets(popperAltOverflow, popperRect, preventedOffsets);
-      var isReferenceHidden = isAnySideFullyClipped(referenceClippingOffsets);
-      var hasPopperEscaped = isAnySideFullyClipped(popperEscapeOffsets);
-      state.modifiersData[name] = {
-        referenceClippingOffsets: referenceClippingOffsets,
-        popperEscapeOffsets: popperEscapeOffsets,
-        isReferenceHidden: isReferenceHidden,
-        hasPopperEscaped: hasPopperEscaped
-      };
-      state.attributes.popper = Object.assign(Object.assign({}, state.attributes.popper), {}, {
-        'data-popper-reference-hidden': isReferenceHidden,
-        'data-popper-escaped': hasPopperEscaped
+    }
+
+    function uniqueBy(arr, fn) {
+      var identifiers = new Set();
+      return arr.filter(function (item) {
+        var identifier = fn(item);
+
+        if (!identifiers.has(identifier)) {
+          identifiers.add(identifier);
+          return true;
+        }
       });
-    } // eslint-disable-next-line import/no-unused-modules
+    }
+
+    function mergeByName(modifiers) {
+      var merged = modifiers.reduce(function (merged, current) {
+        var existing = merged[current.name];
+        merged[current.name] = existing ? Object.assign(Object.assign(Object.assign({}, existing), current), {}, {
+          options: Object.assign(Object.assign({}, existing.options), current.options),
+          data: Object.assign(Object.assign({}, existing.data), current.data)
+        }) : current;
+        return merged;
+      }, {}); // IE11 does not support Object.values
 
+      return Object.keys(merged).map(function (key) {
+        return merged[key];
+      });
+    }
 
-    var hide$1 = {
-      name: 'hide',
-      enabled: true,
-      phase: 'main',
-      requiresIfExists: ['preventOverflow'],
-      fn: hide
+    var INVALID_ELEMENT_ERROR = 'Popper: Invalid reference or popper argument provided. They must be either a DOM element or virtual element.';
+    var INFINITE_LOOP_ERROR = 'Popper: An infinite loop in the modifiers cycle has been detected! The cycle has been interrupted to prevent a browser crash.';
+    var DEFAULT_OPTIONS = {
+      placement: 'bottom',
+      modifiers: [],
+      strategy: 'absolute'
     };
 
-    var defaultModifiers = [eventListeners, popperOffsets$1, computeStyles$1, applyStyles$1, offset$1, flip$1, preventOverflow$1, arrow$1, hide$1];
-    var createPopper = /*#__PURE__*/popperGenerator({
-      defaultModifiers: defaultModifiers
-    }); // eslint-disable-next-line import/no-unused-modules
+    function areValidElements() {
+      for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
+        args[_key] = arguments[_key];
+      }
 
-    /*
-     * Licensed to the Apache Software Foundation (ASF) under one or more
-     * contributor license agreements.  See the NOTICE file distributed with
-     * this work for additional information regarding copyright ownership.
-     * The ASF licenses this file to You under the Apache License, Version 2.0
-     * (the "License"); you may not use this file except in compliance with
-     * the License.  You may obtain a copy of the License at
-     *
-     *      http://www.apache.org/licenses/LICENSE-2.0
-     *
-     * Unless required by applicable law or agreed to in writing, software
-     * distributed under the License is distributed on an "AS IS" BASIS,
-     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     * See the License for the specific language governing permissions and
-     * limitations under the License.
-     */
-    const Event$1 = {
-        HIDE: "tobago.dropdown.hide",
-        HIDDEN: "tobago.dropdown.hidden",
-        SHOW: "tobago.dropdown.show",
-        SHOWN: "tobago.dropdown.shown"
-    };
-    class Dropdown extends HTMLElement {
-        constructor() {
-            super();
-            this.dropdownEntries = [];
-            if (!this.classList.contains("tobago-dropdown-submenu")) { // ignore submenus
-                const root = this.getRootNode();
-                this.createDropdownEntries(this.dropdownMenu, null);
-                this.toggleButton.addEventListener("click", this.toggleDropdown.bind(this));
-                root.addEventListener("mouseup", this.mouseupOnDocument.bind(this));
-                root.addEventListener("keydown", this.keydownOnDocument.bind(this));
-            }
-        }
-        connectedCallback() {
-        }
-        toggleDropdown(event) {
-            event.preventDefault();
-            event.stopPropagation();
-            if (this.dropdownVisible()) {
-                this.closeDropdown();
-            }
-            else {
-                this.openDropdown();
-            }
-        }
-        mouseupOnDocument(event) {
-            if (!this.toggleButtonSelected(event) && this.dropdownVisible()
-                && !this.dropdownMenu.contains(event.target)) {
-                this.closeDropdown();
-            }
+      return !args.some(function (element) {
+        return !(element && typeof element.getBoundingClientRect === 'function');
+      });
+    }
+
+    function popperGenerator(generatorOptions) {
+      if (generatorOptions === void 0) {
+        generatorOptions = {};
+      }
+
+      var _generatorOptions = generatorOptions,
+          _generatorOptions$def = _generatorOptions.defaultModifiers,
+          defaultModifiers = _generatorOptions$def === void 0 ? [] : _generatorOptions$def,
+          _generatorOptions$def2 = _generatorOptions.defaultOptions,
+          defaultOptions = _generatorOptions$def2 === void 0 ? DEFAULT_OPTIONS : _generatorOptions$def2;
+      return function createPopper(reference, popper, options) {
+        if (options === void 0) {
+          options = defaultOptions;
         }
-        keydownOnDocument(event) {
+
+        var state = {
+          placement: 'bottom',
+          orderedModifiers: [],
+          options: Object.assign(Object.assign({}, DEFAULT_OPTIONS), defaultOptions),
+          modifiersData: {},
+          elements: {
+            reference: reference,
+            popper: popper
+          },
+          attributes: {},
+          styles: {}
+        };
+        var effectCleanupFns = [];
+        var isDestroyed = false;
+        var instance = {
+          state: state,
+          setOptions: function setOptions(options) {
+            cleanupModifierEffects();
+            state.options = Object.assign(Object.assign(Object.assign({}, defaultOptions), state.options), options);
+            state.scrollParents = {
+              reference: isElement(reference) ? listScrollParents(reference) : reference.contextElement ? listScrollParents(reference.contextElement) : [],
+              popper: listScrollParents(popper)
+            }; // Orders the modifiers based on their dependencies and `phase`
+            // properties
+
+            var orderedModifiers = orderModifiers(mergeByName([].concat(defaultModifiers, state.options.modifiers))); // Strip out disabled modifiers
+
+            state.orderedModifiers = orderedModifiers.filter(function (m) {
+              return m.enabled;
+            }); // Validate the provided modifiers so that the consumer will get warned
+            // if one of the modifiers is invalid for any reason
+
+            if (process.env.NODE_ENV !== "production") {
+              var modifiers = uniqueBy([].concat(orderedModifiers, state.options.modifiers), function (_ref) {
+                var name = _ref.name;
+                return name;
+              });
+              validateModifiers(modifiers);
+
+              if (getBasePlacement(state.options.placement) === auto) {
+                var flipModifier = state.orderedModifiers.find(function (_ref2) {
+                  var name = _ref2.name;
+                  return name === 'flip';
+                });
+
+                if (!flipModifier) {
+                  console.error(['Popper: "auto" placements require the "flip" modifier be', 'present and enabled to work.'].join(' '));
+                }
+              }
+
+              var _getComputedStyle = getComputedStyle$1(popper),
+                  marginTop = _getComputedStyle.marginTop,
+                  marginRight = _getComputedStyle.marginRight,
+                  marginBottom = _getComputedStyle.marginBottom,
+                  marginLeft = _getComputedStyle.marginLeft; // We no longer take into account `margins` on the popper, and it can
+              // cause bugs with positioning, so we'll warn the consumer
+
+
+              if ([marginTop, marginRight, marginBottom, marginLeft].some(function (margin) {
+                return parseFloat(margin);
+              })) {
+                console.warn(['Popper: CSS "margin" styles cannot be used to apply padding', 'between the popper and its reference element or boundary.', 'To replicate margin, use the `offset` modifier, as well as', 'the `padding` option in the `preventOverflow` and `flip`', 'modifiers.'].join(' '));
+              }
+            }
+
+            runModifierEffects();
+            return instance.update();
+          },
+          // Sync update – it will always be executed, even if not necessary. This
+          // is useful for low frequency updates where sync behavior simplifies the
+          // logic.
+          // For high frequency updates (e.g. `resize` and `scroll` events), always
+          // prefer the async Popper#update method
+          forceUpdate: function forceUpdate() {
+            if (isDestroyed) {
+              return;
+            }
+
+            var _state$elements = state.elements,
+                reference = _state$elements.reference,
+                popper = _state$elements.popper; // Don't proceed if `reference` or `popper` are not valid elements
+            // anymore
+
+            if (!areValidElements(reference, popper)) {
+              if (process.env.NODE_ENV !== "production") {
+                console.error(INVALID_ELEMENT_ERROR);
+              }
+
+              return;
+            } // Store the reference and popper rects to be read by modifiers
+
+
+            state.rects = {
+              reference: getCompositeRect(reference, getOffsetParent(popper), state.options.strategy === 'fixed'),
+              popper: getLayoutRect(popper)
+            }; // Modifiers have the ability to reset the current update cycle. The
+            // most common use case for this is the `flip` modifier changing the
+            // placement, which then needs to re-run all the modifiers, because the
+            // logic was previously ran for the previous placement and is therefore
+            // stale/incorrect
+
+            state.reset = false;
+            state.placement = state.options.placement; // On each update cycle, the `modifiersData` property for each modifier
+            // is filled with the initial data specified by the modifier. This means
+            // it doesn't persist and is fresh on each update.
+            // To ensure persistent data, use `${name}#persistent`
+
+            state.orderedModifiers.forEach(function (modifier) {
+              return state.modifiersData[modifier.name] = Object.assign({}, modifier.data);
+            });
+            var __debug_loops__ = 0;
+
+            for (var index = 0; index < state.orderedModifiers.length; index++) {
+              if (process.env.NODE_ENV !== "production") {
+                __debug_loops__ += 1;
+
+                if (__debug_loops__ > 100) {
+                  console.error(INFINITE_LOOP_ERROR);
+                  break;
+                }
+              }
+
+              if (state.reset === true) {
+                state.reset = false;
+                index = -1;
+                continue;
+              }
+
+              var _state$orderedModifie = state.orderedModifiers[index],
+                  fn = _state$orderedModifie.fn,
+                  _state$orderedModifie2 = _state$orderedModifie.options,
+                  _options = _state$orderedModifie2 === void 0 ? {} : _state$orderedModifie2,
+                  name = _state$orderedModifie.name;
+
+              if (typeof fn === 'function') {
+                state = fn({
+                  state: state,
+                  options: _options,
+                  name: name,
+                  instance: instance
+                }) || state;
+              }
+            }
+          },
+          // Async and optimistically optimized update – it will not be executed if
+          // not necessary (debounced to run at most once-per-tick)
+          update: debounce(function () {
+            return new Promise(function (resolve) {
+              instance.forceUpdate();
+              resolve(state);
+            });
+          }),
+          destroy: function destroy() {
+            cleanupModifierEffects();
+            isDestroyed = true;
+          }
+        };
+
+        if (!areValidElements(reference, popper)) {
+          if (process.env.NODE_ENV !== "production") {
+            console.error(INVALID_ELEMENT_ERROR);
+          }
+
+          return instance;
+        }
+
+        instance.setOptions(options).then(function (state) {
+          if (!isDestroyed && options.onFirstUpdate) {
+            options.onFirstUpdate(state);
+          }
+        }); // Modifiers have the ability to execute arbitrary code before the first
+        // update cycle runs. They will be executed in the same order as the update
+        // cycle. This is useful when a modifier adds some persistent data that
+        // other modifiers need to use, but the modifier is run after the dependent
+        // one.
+
+        function runModifierEffects() {
+          state.orderedModifiers.forEach(function (_ref3) {
+            var name = _ref3.name,
+                _ref3$options = _ref3.options,
+                options = _ref3$options === void 0 ? {} : _ref3$options,
+                effect = _ref3.effect;
+
+            if (typeof effect === 'function') {
+              var cleanupFn = effect({
+                state: state,
+                name: name,
+                instance: instance,
+                options: options
+              });
+
+              var noopFn = function noopFn() {};
+
+              effectCleanupFns.push(cleanupFn || noopFn);
+            }
+          });
+        }
+
+        function cleanupModifierEffects() {
+          effectCleanupFns.forEach(function (fn) {
+            return fn();
+          });
+          effectCleanupFns = [];
+        }
+
+        return instance;
+      };
+    }
+    var createPopper = /*#__PURE__*/popperGenerator(); // eslint-disable-next-line import/no-unused-modules
+
+    var defaultModifiers = [eventListeners, popperOffsets$1, computeStyles$1, applyStyles$1];
+    var createPopper$1 = /*#__PURE__*/popperGenerator({
+      defaultModifiers: defaultModifiers
+    }); // eslint-disable-next-line import/no-unused-modules
+
+    var defaultModifiers$1 = [eventListeners, popperOffsets$1, computeStyles$1, applyStyles$1, offset$1, flip$1, preventOverflow$1, arrow$1, hide$1];
+    var createPopper$2 = /*#__PURE__*/popperGenerator({
+      defaultModifiers: defaultModifiers$1
+    }); // eslint-disable-next-line import/no-unused-modules
+
+    var Popper = /*#__PURE__*/Object.freeze({
+        __proto__: null,
+        popperGenerator: popperGenerator,
+        detectOverflow: detectOverflow,
+        createPopperBase: createPopper,
+        createPopper: createPopper$2,
+        createPopperLite: createPopper$1,
+        top: top,
+        bottom: bottom,
+        right: right,
+        left: left,
+        auto: auto,
+        basePlacements: basePlacements,
+        start: start,
+        end: end,
+        clippingParents: clippingParents,
+        viewport: viewport,
+        popper: popper,
+        reference: reference,
+        variationPlacements: variationPlacements,
+        placements: placements,
+        beforeRead: beforeRead,
+        read: read,
+        afterRead: afterRead,
+        beforeMain: beforeMain,
+        main: main,
+        afterMain: afterMain,
+        beforeWrite: beforeWrite,
+        write: write,
+        afterWrite: afterWrite,
+        modifierPhases: modifierPhases,
+        applyStyles: applyStyles$1,
+        arrow: arrow$1,
+        computeStyles: computeStyles$1,
+        eventListeners: eventListeners,
+        flip: flip$1,
+        hide: hide$1,
+        offset: offset$1,
+        popperOffsets: popperOffsets$1,
+        preventOverflow: preventOverflow$1
+    });
+
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *      http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+    // import {createPopper} from "@popperjs/core/dist/esm/popper";
+    const Event$1 = {
+        HIDE: "tobago.dropdown.hide",
+        HIDDEN: "tobago.dropdown.hidden",
+        SHOW: "tobago.dropdown.show",
+        SHOWN: "tobago.dropdown.shown"
+    };
+    class Dropdown extends HTMLElement {
+        constructor() {
+            super();
+            this.dropdownEntries = [];
+            if (!this.classList.contains("tobago-dropdown-submenu")) { // ignore submenus
+                const root = this.getRootNode();
+                this.createDropdownEntries(this.dropdownMenu, null);
+                this.toggleButton.addEventListener("click", this.toggleDropdown.bind(this));
+                root.addEventListener("mouseup", this.mouseupOnDocument.bind(this));
+                root.addEventListener("keydown", this.keydownOnDocument.bind(this));
+            }
+        }
+        connectedCallback() {
+        }
+        toggleDropdown(event) {
+            event.preventDefault();
+            event.stopPropagation();
+            if (this.dropdownVisible()) {
+                this.closeDropdown();
+            }
+            else {
+                this.openDropdown();
+            }
+        }
+        mouseupOnDocument(event) {
+            if (!this.toggleButtonSelected(event) && this.dropdownVisible()
+                && !this.dropdownMenu.contains(event.target)) {
+                this.closeDropdown();
+            }
+        }
+        keydownOnDocument(event) {
             if (this.toggleButtonSelected(event) && !this.dropdownVisible()
                 && (event.code === "ArrowUp" || event.code === "ArrowDown")) {
                 event.preventDefault();
@@ -2058,7 +2278,7 @@
             this.dispatchEvent(new CustomEvent(Event$1.SHOW));
             if (!this.inStickyHeader()) {
                 this.menuStore.appendChild(this.dropdownMenu);
-                createPopper(this.toggleButton, this.dropdownMenu, {
+                createPopper$2(this.toggleButton, this.dropdownMenu, {
                     placement: "bottom-start"
                 });
             }
@@ -2159,2822 +2379,7779 @@
         deactivate(event) {
             this.active = false;
         }
-        get previous() {
-            return this._previous;
+        get previous() {
+            return this._previous;
+        }
+        set previous(value) {
+            this._previous = value;
+        }
+        get next() {
+            return this._next;
+        }
+        set next(value) {
+            this._next = value;
+        }
+        get parent() {
+            return this._parent;
+        }
+        set parent(value) {
+            this._parent = value;
+        }
+        get children() {
+            return this._children;
+        }
+        set children(value) {
+            this._children = value;
+        }
+        get active() {
+            return this._active;
+        }
+        set active(value) {
+            this._active = value;
+        }
+        focus() {
+            var _a, _b;
+            (_a = this.previous) === null || _a === void 0 ? void 0 : _a.clear();
+            (_b = this.next) === null || _b === void 0 ? void 0 : _b.clear();
+            if (this.parent) {
+                this.parent.active = false;
+                this.parent._baseElement.classList.add("tobago-dropdown-open");
+            }
+            for (const child of this.children) {
+                child.clear();
+            }
+            this._baseElement.classList.remove("tobago-dropdown-open");
+            this._baseElement.classList.add("tobago-dropdown-selected");
+            this.active = true;
+            this.focusElement.focus();
+        }
+        clear() {
+            this._baseElement.classList.remove("tobago-dropdown-open");
+            this._baseElement.classList.remove("tobago-dropdown-selected");
+            this.active = false;
+        }
+    }
+    document.addEventListener("tobago.init", function (event) {
+        if (window.customElements.get("tobago-dropdown") == null) {
+            window.customElements.define("tobago-dropdown", Dropdown);
+        }
+    });
+
+    function hasProperty(obj, prop) {
+      return Object.prototype.hasOwnProperty.call(obj, prop);
+    }
+
+    function lastItemOf(arr) {
+      return arr[arr.length - 1];
+    }
+
+    // push only the items not included in the array
+    function pushUnique(arr, ...items) {
+      items.forEach((item) => {
+        if (arr.includes(item)) {
+          return;
+        }
+        arr.push(item);
+      });
+      return arr;
+    }
+
+    function stringToArray(str, separator) {
+      // convert empty string to an empty array
+      return str ? str.split(separator) : [];
+    }
+
+    function isInRange(testVal, min, max) {
+      const minOK = min === undefined || testVal >= min;
+      const maxOK = max === undefined || testVal <= max;
+      return minOK && maxOK;
+    }
+
+    function limitToRange(val, min, max) {
+      if (val < min) {
+        return min;
+      }
+      if (val > max) {
+        return max;
+      }
+      return val;
+    }
+
+    function createTagRepeat(tagName, repeat, attributes = {}, index = 0, html = '') {
+      const openTagSrc = Object.keys(attributes).reduce((src, attr) => {
+        let val = attributes[attr];
+        if (typeof val === 'function') {
+          val = val(index);
+        }
+        return `${src} ${attr}="${val}"`;
+      }, tagName);
+      html += `<${openTagSrc}></${tagName}>`;
+
+      const next = index + 1;
+      return next < repeat
+        ? createTagRepeat(tagName, repeat, attributes, next, html)
+        : html;
+    }
+
+    // Remove the spacing surrounding tags for HTML parser not to create text nodes
+    // before/after elements
+    function optimizeTemplateHTML(html) {
+      return html.replace(/>\s+/g, '>').replace(/\s+</, '<');
+    }
+
+    function stripTime(timeValue) {
+      return new Date(timeValue).setHours(0, 0, 0, 0);
+    }
+
+    function today() {
+      return new Date().setHours(0, 0, 0, 0);
+    }
+
+    // Get the time value of the start of given date or year, month and day
+    function dateValue(...args) {
+      switch (args.length) {
+        case 0:
+          return today();
+        case 1:
+          return stripTime(args[0]);
+      }
+
+      // use setFullYear() to keep 2-digit year from being mapped to 1900-1999
+      const newDate = new Date(0);
+      newDate.setFullYear(...args);
+      return newDate.setHours(0, 0, 0, 0);
+    }
+
+    function addDays(date, amount) {
+      const newDate = new Date(date);
+      return newDate.setDate(newDate.getDate() + amount);
+    }
+
+    function addWeeks(date, amount) {
+      return addDays(date, amount * 7);
+    }
+
+    function addMonths(date, amount) {
+      // If the day of the date is not in the new month, the last day of the new
+      // month will be returned. e.g. Jan 31 + 1 month → Feb 28 (not Mar 03)
+      const newDate = new Date(date);
+      const monthsToSet = newDate.getMonth() + amount;
+      let expectedMonth = monthsToSet % 12;
+      if (expectedMonth < 0) {
+        expectedMonth += 12;
+      }
+
+      const time = newDate.setMonth(monthsToSet);
+      return newDate.getMonth() !== expectedMonth ? newDate.setDate(0) : time;
+    }
+
+    function addYears(date, amount) {
+      // If the date is Feb 29 and the new year is not a leap year, Feb 28 of the
+      // new year will be returned.
+      const newDate = new Date(date);
+      const expectedMonth = newDate.getMonth();
+      const time = newDate.setFullYear(newDate.getFullYear() + amount);
+      return expectedMonth === 1 && newDate.getMonth() === 2 ? newDate.setDate(0) : time;
+    }
+
+    // Calculate the distance bettwen 2 days of the week
+    function dayDiff(day, from) {
+      return (day - from + 7) % 7;
+    }
+
+    // Get the date of the specified day of the week of given base date
+    function dayOfTheWeekOf(baseDate, dayOfWeek, weekStart = 0) {
+      const baseDay = new Date(baseDate).getDay();
+      return addDays(baseDate, dayDiff(dayOfWeek, weekStart) - dayDiff(baseDay, weekStart));
+    }
+
+    // Get the ISO week of a date
+    function getWeek(date) {
+      // start of ISO week is Monday
+      const thuOfTheWeek = dayOfTheWeekOf(date, 4, 1);
+      // 1st week == the week where the 4th of January is in
+      const firstThu = dayOfTheWeekOf(new Date(thuOfTheWeek).setMonth(0, 4), 4, 1);
+      return Math.round((thuOfTheWeek - firstThu) / 604800000) + 1;
+    }
+
+    // Get the start year of the period of years that includes given date
+    // years: length of the year period
+    function startOfYearPeriod(date, years) {
+      /* @see https://en.wikipedia.org/wiki/Year_zero#ISO_8601 */
+      const year = new Date(date).getFullYear();
+      return Math.floor(year / years) * years;
+    }
+
+    // pattern for format parts
+    const reFormatTokens = /dd?|DD?|mm?|MM?|yy?(?:yy)?/;
+    // pattern for non date parts
+    const reNonDateParts = /[\s!-/:-@[-`{-~年月日]+/;
+    // cache for persed formats
+    let knownFormats = {};
+    // parse funtions for date parts
+    const parseFns = {
+      y(date, year) {
+        return new Date(date).setFullYear(parseInt(year, 10));
+      },
+      M: undefined,  // placeholder to maintain the key order
+      m(date, month, locale) {
+        const newDate = new Date(date);
+        let monthIndex = parseInt(month, 10) - 1;
+
+        if (isNaN(monthIndex)) {
+          if (!month) {
+            return NaN;
+          }
+
+          const monthName = month.toLowerCase();
+          const compareNames = name => name.toLowerCase().startsWith(monthName);
+          // compare with both short and full names because some locales have periods
+          // in the short names (not equal to the first X letters of the full names)
+          monthIndex = locale.monthsShort.findIndex(compareNames);
+          if (monthIndex < 0) {
+            monthIndex = locale.months.findIndex(compareNames);
+          }
+          return monthIndex < 0 ? NaN : newDate.setMonth(monthIndex);
+        }
+
+        newDate.setMonth(monthIndex);
+        return newDate.getMonth() !== normalizeMonth(monthIndex)
+          ? newDate.setDate(0)
+          : newDate.getTime();
+      },
+      d(date, day) {
+        return new Date(date).setDate(parseInt(day, 10));
+      },
+    };
+    parseFns.M = parseFns.m;  // make "M" an alias of "m"
+    // format functions for date parts
+    const formatFns = {
+      d(date) {
+        return date.getDate();
+      },
+      dd(date) {
+        return padZero(date.getDate(), 2);
+      },
+      D(date, locale) {
+        return locale.daysShort[date.getDay()];
+      },
+      DD(date, locale) {
+        return locale.days[date.getDay()];
+      },
+      m(date) {
+        return date.getMonth() + 1;
+      },
+      mm(date) {
+        return padZero(date.getMonth() + 1, 2);
+      },
+      M(date, locale) {
+        return locale.monthsShort[date.getMonth()];
+      },
+      MM(date, locale) {
+        return locale.months[date.getMonth()];
+      },
+      y(date) {
+        return date.getFullYear();
+      },
+      yy(date) {
+        return padZero(date.getFullYear(), 2).slice(-2);
+      },
+      yyyy(date) {
+        return padZero(date.getFullYear(), 4);
+      },
+    };
+
+    // get month index in normal range (0 - 11) from any number
+    function normalizeMonth(monthIndex) {
+      return monthIndex > -1 ? monthIndex % 12 : normalizeMonth(monthIndex + 12);
+    }
+
+    function padZero(num, length) {
+      return num.toString().padStart(length, '0');
+    }
+
+    function parseFormatString(format) {
+      if (typeof format !== 'string') {
+        throw new Error("Invalid date format.");
+      }
+      if (format in knownFormats) {
+        return knownFormats[format];
+      }
+
+      // sprit the format string into parts and seprators
+      const separators = format.split(reFormatTokens);
+      const parts = format.match(new RegExp(reFormatTokens, 'g'));
+      if (separators.length === 0 || !parts) {
+        throw new Error("Invalid date format.");
+      }
+
+      // collect format functions used in the format
+      const partFormatters = parts.map(token => formatFns[token]);
+
+      // collect parse functions used in the format
+      // iterate over parseFns' keys in order to keep the order of the keys.
+      const partParsers = Object.keys(parseFns).reduce((parsers, key) => {
+        const token = parts.find(part => part[0] === key);
+        if (!token) {
+          return parsers;
+        }
+        parsers[key] = parseFns[key];
+        return parsers;
+      }, {});
+      const partParserKeys = Object.keys(partParsers);
+
+      return knownFormats[format] = {
+        parser(dateStr, locale) {
+          const dateParts = dateStr.split(reNonDateParts).reduce((dtParts, part, index) => {
+            if (part.length > 0 && parts[index]) {
+              const token = parts[index][0];
+              if (parseFns[token] !== undefined) {
+                dtParts[token] = part;
+              }
+            }
+            return dtParts;
+          }, {});
+
+          // iterate over partParsers' keys so that the parsing is made in the oder
+          // of year, month and day to prevent the day parser from correcting last
+          // day of month wrongly
+          return partParserKeys.reduce((origDate, key) => {
+            const newDate = partParsers[key](origDate, dateParts[key], locale);
+            // ingnore the part failed to parse
+            return isNaN(newDate) ? origDate : newDate;
+          }, today());
+        },
+        formatter(date, locale) {
+          let dateStr = partFormatters.reduce((str, fn, index) => {
+            return str += `${separators[index]}${fn(date, locale)}`;
+          }, '');
+          // separators' length is always parts' length + 1,
+          return dateStr += lastItemOf(separators);
+        },
+      };
+    }
+
+    function parseDate(dateStr, format, locale) {
+      if (dateStr instanceof Date || typeof dateStr === 'number') {
+        const date = stripTime(dateStr);
+        return isNaN(date) ? undefined : date;
+      }
+      if (!dateStr) {
+        return undefined;
+      }
+      if (dateStr === 'today') {
+        return today();
+      }
+
+      if (format && format.toValue) {
+        const date = format.toValue(dateStr, format, locale);
+        return isNaN(date) ? undefined : stripTime(date);
+      }
+
+      return parseFormatString(format).parser(dateStr, locale);
+    }
+
+    function formatDate(date, format, locale) {
+      if (isNaN(date) || (!date && date !== 0)) {
+        return '';
+      }
+
+      const dateObj = typeof date === 'number' ? new Date(date) : date;
+
+      if (format.toDisplay) {
+        return format.toDisplay(dateObj, format, locale);
+      }
+
+      return parseFormatString(format).formatter(dateObj, locale);
+    }
+
+    const listenerRegistry = new WeakMap();
+    const {addEventListener, removeEventListener} = EventTarget.prototype;
+
+    // Register event listeners to a key object
+    // listeners: array of listener definitions;
+    //   - each definition must be a flat array of event target and the arguments
+    //     used to call addEventListener() on the target
+    function registerListeners(keyObj, listeners) {
+      let registered = listenerRegistry.get(keyObj);
+      if (!registered) {
+        registered = [];
+        listenerRegistry.set(keyObj, registered);
+      }
+      listeners.forEach((listener) => {
+        addEventListener.call(...listener);
+        registered.push(listener);
+      });
+    }
+
+    function unregisterListeners(keyObj) {
+      let listeners = listenerRegistry.get(keyObj);
+      if (!listeners) {
+        return;
+      }
+      listeners.forEach((listener) => {
+        removeEventListener.call(...listener);
+      });
+      listenerRegistry.delete(keyObj);
+    }
+
+    // Event.composedPath() polyfill for Edge
+    // based on https://gist.github.com/kleinfreund/e9787d73776c0e3750dcfcdc89f100ec
+    if (!Event.prototype.composedPath) {
+      const getComposedPath = (node, path = []) => {
+        path.push(node);
+
+        let parent;
+        if (node.parentNode) {
+          parent = node.parentNode;
+        } else if (node.host) { // ShadowRoot
+          parent = node.host;
+        } else if (node.defaultView) {  // Document
+          parent = node.defaultView;
+        }
+        return parent ? getComposedPath(parent, path) : path;
+      };
+
+      Event.prototype.composedPath = function () {
+        return getComposedPath(this.target);
+      };
+    }
+
+    function findFromPath(path, criteria, currentTarget, index = 0) {
+      const el = path[index];
+      if (criteria(el)) {
+        return el;
+      } else if (el === currentTarget || !el.parentElement) {
+        // stop when reaching currentTarget or <html>
+        return;
+      }
+      return findFromPath(path, criteria, currentTarget, index + 1);
+    }
+
+    // Search for the actual target of a delegated event
+    function findElementInEventPath(ev, selector) {
+      const criteria = typeof selector === 'function' ? selector : el => el.matches(selector);
+      return findFromPath(ev.composedPath(), criteria, ev.currentTarget);
+    }
+
+    // default locales
+    const locales = {
+      en: {
+        days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
+        daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
+        daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"],
+        months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
+        monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
+        today: "Today",
+        clear: "Clear",
+        titleFormat: "MM y"
+      }
+    };
+
+    // config options updatable by setOptions() and their default values
+    const defaultOptions = {
+      autohide: false,
+      beforeShowDay: null,
+      beforeShowDecade: null,
+      beforeShowMonth: null,
+      beforeShowYear: null,
+      calendarWeeks: false,
+      clearBtn: false,
+      dateDelimiter: ',',
+      datesDisabled: [],
+      daysOfWeekDisabled: [],
+      daysOfWeekHighlighted: [],
+      defaultViewDate: undefined, // placeholder, defaults to today() by the program
+      disableTouchKeyboard: false,
+      format: 'mm/dd/yyyy',
+      language: 'en',
+      maxDate: null,
+      maxNumberOfDates: 1,
+      maxView: 3,
+      minDate: null,
+      nextArrow: '»',
+      orientation: 'auto',
+      pickLevel: 0,
+      prevArrow: '«',
+      showDaysOfWeek: true,
+      showOnClick: true,
+      showOnFocus: true,
+      startView: 0,
+      title: '',
+      todayBtn: false,
+      todayBtnMode: 0,
+      todayHighlight: false,
+      updateOnBlur: true,
+      weekStart: 0,
+    };
+
+    const range = document.createRange();
+
+    function parseHTML(html) {
+      return range.createContextualFragment(html);
+    }
+
+    function hideElement(el) {
+      if (el.style.display === 'none') {
+        return;
+      }
+      // back up the existing display setting in data-style-display
+      if (el.style.display) {
+        el.dataset.styleDisplay = el.style.display;
+      }
+      el.style.display = 'none';
+    }
+
+    function showElement(el) {
+      if (el.style.display !== 'none') {
+        return;
+      }
+      if (el.dataset.styleDisplay) {
+        // restore backed-up dispay property
+        el.style.display = el.dataset.styleDisplay;
+        delete el.dataset.styleDisplay;
+      } else {
+        el.style.display = '';
+      }
+    }
+
+    function emptyChildNodes(el) {
+      if (el.firstChild) {
+        el.removeChild(el.firstChild);
+        emptyChildNodes(el);
+      }
+    }
+
+    function replaceChildNodes(el, newChildNodes) {
+      emptyChildNodes(el);
+      if (newChildNodes instanceof DocumentFragment) {
+        el.appendChild(newChildNodes);
+      } else if (typeof newChildNodes === 'string') {
+        el.appendChild(parseHTML(newChildNodes));
+      } else if (typeof newChildNodes.forEach === 'function') {
+        newChildNodes.forEach((node) => {
+          el.appendChild(node);
+        });
+      }
+    }
+
+    const {
+      language: defaultLang,
+      format: defaultFormat,
+      weekStart: defaultWeekStart,
+    } = defaultOptions;
+
+    // Reducer function to filter out invalid day-of-week from the input
+    function sanitizeDOW(dow, day) {
+      return dow.length < 6 && day >= 0 && day < 7
+        ? pushUnique(dow, day)
+        : dow;
+    }
+
+    function calcEndOfWeek(startOfWeek) {
+      return (startOfWeek + 6) % 7;
+    }
+
+    // validate input date. if invalid, fallback to the original value
+    function validateDate(value, format, locale, origValue) {
+      const date = parseDate(value, format, locale);
+      return date !== undefined ? date : origValue;
+    }
+
+    // Validate viewId. if invalid, fallback to the original value
+    function validateViewId(value, origValue, max = 3) {
+      const viewId = parseInt(value, 10);
+      return viewId >= 0 && viewId <= max ? viewId : origValue;
+    }
+
+    // Create Datepicker configuration to set
+    function processOptions(options, datepicker) {
+      const inOpts = Object.assign({}, options);
+      const config = {};
+      const locales = datepicker.constructor.locales;
+      let {
+        format,
+        language,
+        locale,
+        maxDate,
+        maxView,
+        minDate,
+        pickLevel,
+        startView,
+        weekStart,
+      } = datepicker.config || {};
+
+      if (inOpts.language) {
+        let lang;
+        if (inOpts.language !== language) {
+          if (locales[inOpts.language]) {
+            lang = inOpts.language;
+          } else {
+            // Check if langauge + region tag can fallback to the one without
+            // region (e.g. fr-CA → fr)
+            lang = inOpts.language.split('-')[0];
+            if (locales[lang] === undefined) {
+              lang = false;
+            }
+          }
+        }
+        delete inOpts.language;
+        if (lang) {
+          language = config.language = lang;
+
+          // update locale as well when updating language
+          const origLocale = locale || locales[defaultLang];
+          // use default language's properties for the fallback
+          locale = Object.assign({
+            format: defaultFormat,
+            weekStart: defaultWeekStart
+          }, locales[defaultLang]);
+          if (language !== defaultLang) {
+            Object.assign(locale, locales[language]);
+          }
+          config.locale = locale;
+          // if format and/or weekStart are the same as old locale's defaults,
+          // update them to new locale's defaults
+          if (format === origLocale.format) {
+            format = config.format = locale.format;
+          }
+          if (weekStart === origLocale.weekStart) {
+            weekStart = config.weekStart = locale.weekStart;
+            config.weekEnd = calcEndOfWeek(locale.weekStart);
+          }
+        }
+      }
+
+      if (inOpts.format) {
+        const hasToDisplay = typeof inOpts.format.toDisplay === 'function';
+        const hasToValue = typeof inOpts.format.toValue === 'function';
+        const validFormatString = reFormatTokens.test(inOpts.format);
+        if ((hasToDisplay && hasToValue) || validFormatString) {
+          format = config.format = inOpts.format;
+        }
+        delete inOpts.format;
+      }
+
+      //*** dates ***//
+      // while min and maxDate for "no limit" in the options are better to be null
+      // (especially when updating), the ones in the config have to be undefined
+      // because null is treated as 0 (= unix epoch) when comparing with time value
+      let minDt = minDate;
+      let maxDt = maxDate;
+      if (inOpts.minDate !== undefined) {
+        minDt = inOpts.minDate === null
+          ? dateValue(0, 0, 1)  // set 0000-01-01 to prevent negative values for year
+          : validateDate(inOpts.minDate, format, locale, minDt);
+        delete inOpts.minDate;
+      }
+      if (inOpts.maxDate !== undefined) {
+        maxDt = inOpts.maxDate === null
+          ? undefined
+          : validateDate(inOpts.maxDate, format, locale, maxDt);
+        delete inOpts.maxDate;
+      }
+      if (maxDt < minDt) {
+        minDate = config.minDate = maxDt;
+        maxDate = config.maxDate = minDt;
+      } else {
+        if (minDate !== minDt) {
+          minDate = config.minDate = minDt;
+        }
+        if (maxDate !== maxDt) {
+          maxDate = config.maxDate = maxDt;
+        }
+      }
+
+      if (inOpts.datesDisabled) {
+        config.datesDisabled = inOpts.datesDisabled.reduce((dates, dt) => {
+          const date = parseDate(dt, format, locale);
+          return date !== undefined ? pushUnique(dates, date) : dates;
+        }, []);
+        delete inOpts.datesDisabled;
+      }
+      if (inOpts.defaultViewDate !== undefined) {
+        const viewDate = parseDate(inOpts.defaultViewDate, format, locale);
+        if (viewDate !== undefined) {
+          config.defaultViewDate = viewDate;
+        }
+        delete inOpts.defaultViewDate;
+      }
+
+      //*** days of week ***//
+      if (inOpts.weekStart !== undefined) {
+        const wkStart = Number(inOpts.weekStart) % 7;
+        if (!isNaN(wkStart)) {
+          weekStart = config.weekStart = wkStart;
+          config.weekEnd = calcEndOfWeek(wkStart);
+        }
+        delete inOpts.weekStart;
+      }
+      if (inOpts.daysOfWeekDisabled) {
+        config.daysOfWeekDisabled = inOpts.daysOfWeekDisabled.reduce(sanitizeDOW, []);
+        delete inOpts.daysOfWeekDisabled;
+      }
+      if (inOpts.daysOfWeekHighlighted) {
+        config.daysOfWeekHighlighted = inOpts.daysOfWeekHighlighted.reduce(sanitizeDOW, []);
+        delete inOpts.daysOfWeekHighlighted;
+      }
+
+      //*** multi date ***//
+      if (inOpts.maxNumberOfDates !== undefined) {
+        const maxNumberOfDates = parseInt(inOpts.maxNumberOfDates, 10);
+        if (maxNumberOfDates >= 0) {
+          config.maxNumberOfDates = maxNumberOfDates;
+          config.multidate = maxNumberOfDates !== 1;
+        }
+        delete inOpts.maxNumberOfDates;
+      }
+      if (inOpts.dateDelimiter) {
+        config.dateDelimiter = String(inOpts.dateDelimiter);
+        delete inOpts.dateDelimiter;
+      }
+
+      //*** pick level & view ***//
+      let newPickLevel = pickLevel;
+      if (inOpts.pickLevel !== undefined) {
+        newPickLevel = validateViewId(inOpts.pickLevel, 2);
+        delete inOpts.pickLevel;
+      }
+      if (newPickLevel !== pickLevel) {
+        pickLevel = config.pickLevel = newPickLevel;
+      }
+
+      let newMaxView = maxView;
+      if (inOpts.maxView !== undefined) {
+        newMaxView = validateViewId(inOpts.maxView, maxView);
+        delete inOpts.maxView;
+      }
+      // ensure max view >= pick level
+      newMaxView = pickLevel > newMaxView ? pickLevel : newMaxView;
+      if (newMaxView !== maxView) {
+        maxView = config.maxView = newMaxView;
+      }
+
+      let newStartView = startView;
+      if (inOpts.startView !== undefined) {
+        newStartView = validateViewId(inOpts.startView, newStartView);
+        delete inOpts.startView;
+      }
+      // ensure pick level <= start view <= max view
+      if (newStartView < pickLevel) {
+        newStartView = pickLevel;
+      } else if (newStartView > maxView) {
+        newStartView = maxView;
+      }
+      if (newStartView !== startView) {
+        config.startView = newStartView;
+      }
+
+      //*** template ***//
+      if (inOpts.prevArrow) {
+        const prevArrow = parseHTML(inOpts.prevArrow);
+        if (prevArrow.childNodes.length > 0) {
+          config.prevArrow = prevArrow.childNodes;
+        }
+        delete inOpts.prevArrow;
+      }
+      if (inOpts.nextArrow) {
+        const nextArrow = parseHTML(inOpts.nextArrow);
+        if (nextArrow.childNodes.length > 0) {
+          config.nextArrow = nextArrow.childNodes;
+        }
+        delete inOpts.nextArrow;
+      }
+
+      //*** misc ***//
+      if (inOpts.disableTouchKeyboard !== undefined) {
+        config.disableTouchKeyboard = 'ontouchstart' in document && !!inOpts.disableTouchKeyboard;
+        delete inOpts.disableTouchKeyboard;
+      }
+      if (inOpts.orientation) {
+        const orientation = inOpts.orientation.toLowerCase().split(/\s+/g);
+        config.orientation = {
+          x: orientation.find(x => (x === 'left' || x === 'right')) || 'auto',
+          y: orientation.find(y => (y === 'top' || y === 'bottom')) || 'auto',
+        };
+        delete inOpts.orientation;
+      }
+      if (inOpts.todayBtnMode !== undefined) {
+        switch(inOpts.todayBtnMode) {
+          case 0:
+          case 1:
+            config.todayBtnMode = inOpts.todayBtnMode;
+        }
+        delete inOpts.todayBtnMode;
+      }
+
+      //*** copy the rest ***//
+      Object.keys(inOpts).forEach((key) => {
+        if (inOpts[key] !== undefined && hasProperty(defaultOptions, key)) {
+          config[key] = inOpts[key];
+        }
+      });
+
+      return config;
+    }
+
+    const pickerTemplate = optimizeTemplateHTML(`<div class="datepicker">
+  <div class="datepicker-picker">
+    <div class="datepicker-header">
+      <div class="datepicker-title"></div>
+      <div class="datepicker-controls">
+        <button class="%buttonClass% prev-btn"></button>
+        <button class="%buttonClass% view-switch"></button>
+        <button class="%buttonClass% next-btn"></button>
+      </div>
+    </div>
+    <div class="datepicker-main"></div>
+    <div class="datepicker-footer">
+      <div class="datepicker-controls">
+        <button class="%buttonClass% today-btn"></button>
+        <button class="%buttonClass% clear-btn"></button>
+      </div>
+    </div>
+  </div>
+</div>`);
+
+    const daysTemplate = optimizeTemplateHTML(`<div class="days">
+  <div class="days-of-week">${createTagRepeat('span', 7, {class: 'dow'})}</div>
+  <div class="datepicker-grid">${createTagRepeat('span', 42)}</div>
+</div>`);
+
+    const calendarWeeksTemplate = optimizeTemplateHTML(`<div class="calendar-weeks">
+  <div class="days-of-week"><span class="dow"></span></div>
+  <div class="weeks">${createTagRepeat('span', 6, {class: 'week'})}</div>
+</div>`);
+
+    // Base class of the view classes
+    class View {
+      constructor(picker, config) {
+        Object.assign(this, config, {
+          picker,
+          element: parseHTML(`<div class="datepicker-view"></div>`).firstChild,
+          selected: [],
+        });
+        this.init(this.picker.datepicker.config);
+      }
+
+      init(options) {
+        if (options.pickLevel !== undefined) {
+          this.isMinView = this.id === options.pickLevel;
+        }
+        this.setOptions(options);
+        this.updateFocus();
+        this.updateSelection();
+      }
+
+      // Execute beforeShow() callback and apply the result to the element
+      // args:
+      // - current - current value on the iteration on view rendering
+      // - timeValue - time value of the date to pass to beforeShow()
+      performBeforeHook(el, current, timeValue) {
+        let result = this.beforeShow(new Date(timeValue));
+        switch (typeof result) {
+          case 'boolean':
+            result = {enabled: result};
+            break;
+          case 'string':
+            result = {classes: result};
+        }
+
+        if (result) {
+          if (result.enabled === false) {
+            el.classList.add('disabled');
+            pushUnique(this.disabled, current);
+          }
+          if (result.classes) {
+            const extraClasses = result.classes.split(/\s+/);
+            el.classList.add(...extraClasses);
+            if (extraClasses.includes('disabled')) {
+              pushUnique(this.disabled, current);
+            }
+          }
+          if (result.content) {
+            replaceChildNodes(el, result.content);
+          }
+        }
+      }
+    }
+
+    class DaysView extends View {
+      constructor(picker) {
+        super(picker, {
+          id: 0,
+          name: 'days',
+          cellClass: 'day',
+        });
+      }
+
+      init(options, onConstruction = true) {
+        if (onConstruction) {
+          const inner = parseHTML(daysTemplate).firstChild;
+          this.dow = inner.firstChild;
+          this.grid = inner.lastChild;
+          this.element.appendChild(inner);
+        }
+        super.init(options);
+      }
+
+      setOptions(options) {
+        let updateDOW;
+
+        if (hasProperty(options, 'minDate')) {
+          this.minDate = options.minDate;
+        }
+        if (hasProperty(options, 'maxDate')) {
+          this.maxDate = options.maxDate;
+        }
+        if (options.datesDisabled) {
+          this.datesDisabled = options.datesDisabled;
+        }
+        if (options.daysOfWeekDisabled) {
+          this.daysOfWeekDisabled = options.daysOfWeekDisabled;
+          updateDOW = true;
+        }
+        if (options.daysOfWeekHighlighted) {
+          this.daysOfWeekHighlighted = options.daysOfWeekHighlighted;
+        }
+        if (options.todayHighlight !== undefined) {
+          this.todayHighlight = options.todayHighlight;
+        }
+        if (options.weekStart !== undefined) {
+          this.weekStart = options.weekStart;
+          this.weekEnd = options.weekEnd;
+          updateDOW = true;
+        }
+        if (options.locale) {
+          const locale = this.locale = options.locale;
+          this.dayNames = locale.daysMin;
+          this.switchLabelFormat = locale.titleFormat;
+          updateDOW = true;
+        }
+        if (options.beforeShowDay !== undefined) {
+          this.beforeShow = typeof options.beforeShowDay === 'function'
+            ? options.beforeShowDay
+            : undefined;
+        }
+
+        if (options.calendarWeeks !== undefined) {
+          if (options.calendarWeeks && !this.calendarWeeks) {
+            const weeksElem = parseHTML(calendarWeeksTemplate).firstChild;
+            this.calendarWeeks = {
+              element: weeksElem,
+              dow: weeksElem.firstChild,
+              weeks: weeksElem.lastChild,
+            };
+            this.element.insertBefore(weeksElem, this.element.firstChild);
+          } else if (this.calendarWeeks && !options.calendarWeeks) {
+            this.element.removeChild(this.calendarWeeks.element);
+            this.calendarWeeks = null;
+          }
+        }
+        if (options.showDaysOfWeek !== undefined) {
+          if (options.showDaysOfWeek) {
+            showElement(this.dow);
+            if (this.calendarWeeks) {
+              showElement(this.calendarWeeks.dow);
+            }
+          } else {
+            hideElement(this.dow);
+            if (this.calendarWeeks) {
+              hideElement(this.calendarWeeks.dow);
+            }
+          }
+        }
+
+        // update days-of-week when locale, daysOfweekDisabled or weekStart is changed
+        if (updateDOW) {
+          Array.from(this.dow.children).forEach((el, index) => {
+            const dow = (this.weekStart + index) % 7;
+            el.textContent = this.dayNames[dow];
+            el.className = this.daysOfWeekDisabled.includes(dow) ? 'dow disabled' : 'dow';
+          });
+        }
+      }
+
+      // Apply update on the focused date to view's settings
+      updateFocus() {
+        const viewDate = new Date(this.picker.viewDate);
+        const viewYear = viewDate.getFullYear();
+        const viewMonth = viewDate.getMonth();
+        const firstOfMonth = dateValue(viewYear, viewMonth, 1);
+        const start = dayOfTheWeekOf(firstOfMonth, this.weekStart, this.weekStart);
+
+        this.first = firstOfMonth;
+        this.last = dateValue(viewYear, viewMonth + 1, 0);
+        this.start = start;
+        this.focused = this.picker.viewDate;
+      }
+
+      // Apply update on the selected dates to view's settings
+      updateSelection() {
+        const {dates, rangepicker} = this.picker.datepicker;
+        this.selected = dates;
+        if (rangepicker) {
+          this.range = rangepicker.dates;
+        }
+      }
+
+       // Update the entire view UI
+      render() {
+        // update today marker on ever render
+        this.today = this.todayHighlight ? today() : undefined;
+        // refresh disabled dates on every render in order to clear the ones added
+        // by beforeShow hook at previous render
+        this.disabled = [...this.datesDisabled];
+
+        const switchLabel = formatDate(this.focused, this.switchLabelFormat, this.locale);
+        this.picker.setViewSwitchLabel(switchLabel);
+        this.picker.setPrevBtnDisabled(this.first <= this.minDate);
+        this.picker.setNextBtnDisabled(this.last >= this.maxDate);
+
+        if (this.calendarWeeks) {
+          // start of the UTC week (Monday) of the 1st of the month
+          const startOfWeek = dayOfTheWeekOf(this.first, 1, 1);
+          Array.from(this.calendarWeeks.weeks.children).forEach((el, index) => {
+            el.textContent = getWeek(addWeeks(startOfWeek, index));
+          });
+        }
+        Array.from(this.grid.children).forEach((el, index) => {
+          const classList = el.classList;
+          const current = addDays(this.start, index);
+          const date = new Date(current);
+          const day = date.getDay();
+
+          el.className = `datepicker-cell ${this.cellClass}`;
+          el.dataset.date = current;
+          el.textContent = date.getDate();
+
+          if (current < this.first) {
+            classList.add('prev');
+          } else if (current > this.last) {
+            classList.add('next');
+          }
+          if (this.today === current) {
+            classList.add('today');
+          }
+          if (current < this.minDate || current > this.maxDate || this.disabled.includes(current)) {
+            classList.add('disabled');
+          }
+          if (this.daysOfWeekDisabled.includes(day)) {
+            classList.add('disabled');
+            pushUnique(this.disabled, current);
+          }
+          if (this.daysOfWeekHighlighted.includes(day)) {
+            classList.add('highlighted');
+          }
+          if (this.range) {
+            const [rangeStart, rangeEnd] = this.range;
+            if (current > rangeStart && current < rangeEnd) {
+              classList.add('range');
+            }
+            if (current === rangeStart) {
+              classList.add('range-start');
+            }
+            if (current === rangeEnd) {
+              classList.add('range-end');
+            }
+          }
+          if (this.selected.includes(current)) {
+            classList.add('selected');
+          }
+          if (current === this.focused) {
+            classList.add('focused');
+          }
+
+          if (this.beforeShow) {
+            this.performBeforeHook(el, current, current);
+          }
+        });
+      }
+
+      // Update the view UI by applying the changes of selected and focused items
+      refresh() {
+        const [rangeStart, rangeEnd] = this.range || [];
+        this.grid
+          .querySelectorAll('.range, .range-start, .range-end, .selected, .focused')
+          .forEach((el) => {
+            el.classList.remove('range', 'range-start', 'range-end', 'selected', 'focused');
+          });
+        Array.from(this.grid.children).forEach((el) => {
+          const current = Number(el.dataset.date);
+          const classList = el.classList;
+          if (current > rangeStart && current < rangeEnd) {
+            classList.add('range');
+          }
+          if (current === rangeStart) {
+            classList.add('range-start');
+          }
+          if (current === rangeEnd) {
+            classList.add('range-end');
+          }
+          if (this.selected.includes(current)) {
+            classList.add('selected');
+          }
+          if (current === this.focused) {
+            classList.add('focused');
+          }
+        });
+      }
+
+      // Update the view UI by applying the change of focused item
+      refreshFocus() {
+        const index = Math.round((this.focused - this.start) / 86400000);
+        this.grid.querySelectorAll('.focused').forEach((el) => {
+          el.classList.remove('focused');
+        });
+        this.grid.children[index].classList.add('focused');
+      }
+    }
+
+    function computeMonthRange(range, thisYear) {
+      if (!range || !range[0] || !range[1]) {
+        return;
+      }
+
+      const [[startY, startM], [endY, endM]] = range;
+      if (startY > thisYear || endY < thisYear) {
+        return;
+      }
+      return [
+        startY === thisYear ? startM : -1,
+        endY === thisYear ? endM : 12,
+      ];
+    }
+
+    class MonthsView extends View {
+      constructor(picker) {
+        super(picker, {
+          id: 1,
+          name: 'months',
+          cellClass: 'month',
+        });
+      }
+
+      init(options, onConstruction = true) {
+        if (onConstruction) {
+          this.grid = this.element;
+          this.element.classList.add('months', 'datepicker-grid');
+          this.grid.appendChild(parseHTML(createTagRepeat('span', 12, {'data-month': ix => ix})));
+        }
+        super.init(options);
+      }
+
+      setOptions(options) {
+        if (options.locale) {
+          this.monthNames = options.locale.monthsShort;
+        }
+        if (hasProperty(options, 'minDate')) {
+          if (options.minDate === undefined) {
+            this.minYear = this.minMonth = this.minDate = undefined;
+          } else {
+            const minDateObj = new Date(options.minDate);
+            this.minYear = minDateObj.getFullYear();
+            this.minMonth = minDateObj.getMonth();
+            this.minDate = minDateObj.setDate(1);
+          }
+        }
+        if (hasProperty(options, 'maxDate')) {
+          if (options.maxDate === undefined) {
+            this.maxYear = this.maxMonth = this.maxDate = undefined;
+          } else {
+            const maxDateObj = new Date(options.maxDate);
+            this.maxYear = maxDateObj.getFullYear();
+            this.maxMonth = maxDateObj.getMonth();
+            this.maxDate = dateValue(this.maxYear, this.maxMonth + 1, 0);
+          }
+        }
+        if (options.beforeShowMonth !== undefined) {
+          this.beforeShow = typeof options.beforeShowMonth === 'function'
+            ? options.beforeShowMonth
+            : undefined;
+        }
+      }
+
+      // Update view's settings to reflect the viewDate set on the picker
+      updateFocus() {
+        const viewDate = new Date(this.picker.viewDate);
+        this.year = viewDate.getFullYear();
+        this.focused = viewDate.getMonth();
+      }
+
+      // Update view's settings to reflect the selected dates
+      updateSelection() {
+        const {dates, rangepicker} = this.picker.datepicker;
+        this.selected = dates.reduce((selected, timeValue) => {
+          const date = new Date(timeValue);
+          const year = date.getFullYear();
+          const month = date.getMonth();
+          if (selected[year] === undefined) {
+            selected[year] = [month];
+          } else {
+            pushUnique(selected[year], month);
+          }
+          return selected;
+        }, {});
+        if (rangepicker && rangepicker.dates) {
+          this.range = rangepicker.dates.map(timeValue => {
+            const date = new Date(timeValue);
+            return isNaN(date) ? undefined : [date.getFullYear(), date.getMonth()];
+          });
+        }
+      }
+
+      // Update the entire view UI
+      render() {
+        // refresh disabled months on every render in order to clear the ones added
+        // by beforeShow hook at previous render
+        this.disabled = [];
+
+        this.picker.setViewSwitchLabel(this.year);
+        this.picker.setPrevBtnDisabled(this.year <= this.minYear);
+        this.picker.setNextBtnDisabled(this.year >= this.maxYear);
+
+        const selected = this.selected[this.year] || [];
+        const yrOutOfRange = this.year < this.minYear || this.year > this.maxYear;
+        const isMinYear = this.year === this.minYear;
+        const isMaxYear = this.year === this.maxYear;
+        const range = computeMonthRange(this.range, this.year);
+
+        Array.from(this.grid.children).forEach((el, index) => {
+          const classList = el.classList;
+          const date = dateValue(this.year, index, 1);
+
+          el.className = `datepicker-cell ${this.cellClass}`;
+          if (this.isMinView) {
+            el.dataset.date = date;
+          }
+          // reset text on every render to clear the custom content set
+          // by beforeShow hook at previous render
+          el.textContent = this.monthNames[index];
+
+          if (
+            yrOutOfRange
+            || isMinYear && index < this.minMonth
+            || isMaxYear && index > this.maxMonth
+          ) {
+            classList.add('disabled');
+          }
+          if (range) {
+            const [rangeStart, rangeEnd] = range;
+            if (index > rangeStart && index < rangeEnd) {
+              classList.add('range');
+            }
+            if (index === rangeStart) {
+              classList.add('range-start');
+            }
+            if (index === rangeEnd) {
+              classList.add('range-end');
+            }
+          }
+          if (selected.includes(index)) {
+            classList.add('selected');
+          }
+          if (index === this.focused) {
+            classList.add('focused');
+          }
+
+          if (this.beforeShow) {
+            this.performBeforeHook(el, index, date);
+          }
+        });
+      }
+
+      // Update the view UI by applying the changes of selected and focused items
+      refresh() {
+        const selected = this.selected[this.year] || [];
+        const [rangeStart, rangeEnd] = computeMonthRange(this.range, this.year) || [];
+        this.grid
+          .querySelectorAll('.range, .range-start, .range-end, .selected, .focused')
+          .forEach((el) => {
+            el.classList.remove('range', 'range-start', 'range-end', 'selected', 'focused');
+          });
+        Array.from(this.grid.children).forEach((el, index) => {
+          const classList = el.classList;
+          if (index > rangeStart && index < rangeEnd) {
+            classList.add('range');
+          }
+          if (index === rangeStart) {
+            classList.add('range-start');
+          }
+          if (index === rangeEnd) {
+            classList.add('range-end');
+          }
+          if (selected.includes(index)) {
+            classList.add('selected');
+          }
+          if (index === this.focused) {
+            classList.add('focused');
+          }
+        });
+      }
+
+      // Update the view UI by applying the change of focused item
+      refreshFocus() {
+        this.grid.querySelectorAll('.focused').forEach((el) => {
+          el.classList.remove('focused');
+        });
+        this.grid.children[this.focused].classList.add('focused');
+      }
+    }
+
+    function toTitleCase(word) {
+      return [...word].reduce((str, ch, ix) => str += ix ? ch : ch.toUpperCase(), '');
+    }
+
+    // Class representing the years and decades view elements
+    class YearsView extends View {
+      constructor(picker, config) {
+        super(picker, config);
+      }
+
+      init(options, onConstruction = true) {
+        if (onConstruction) {
+          this.navStep = this.step * 10;
+          this.beforeShowOption = `beforeShow${toTitleCase(this.cellClass)}`;
+          this.grid = this.element;
+          this.element.classList.add(this.name, 'datepicker-grid');
+          this.grid.appendChild(parseHTML(createTagRepeat('span', 12)));
+        }
+        super.init(options);
+      }
+
+      setOptions(options) {
+        if (hasProperty(options, 'minDate')) {
+          if (options.minDate === undefined) {
+            this.minYear = this.minDate = undefined;
+          } else {
+            this.minYear = startOfYearPeriod(options.minDate, this.step);
+            this.minDate = dateValue(this.minYear, 0, 1);
+          }
+        }
+        if (hasProperty(options, 'maxDate')) {
+          if (options.maxDate === undefined) {
+            this.maxYear = this.maxDate = undefined;
+          } else {
+            this.maxYear = startOfYearPeriod(options.maxDate, this.step);
+            this.maxDate = dateValue(this.maxYear, 11, 31);
+          }
+        }
+        if (options[this.beforeShowOption] !== undefined) {
+          const beforeShow = options[this.beforeShowOption];
+          this.beforeShow = typeof beforeShow === 'function' ? beforeShow : undefined;
+        }
+      }
+
+      // Update view's settings to reflect the viewDate set on the picker
+      updateFocus() {
+        const viewDate = new Date(this.picker.viewDate);
+        const first = startOfYearPeriod(viewDate, this.navStep);
+        const last = first + 9 * this.step;
+
+        this.first = first;
+        this.last = last;
+        this.start = first - this.step;
+        this.focused = startOfYearPeriod(viewDate, this.step);
+      }
+
+      // Update view's settings to reflect the selected dates
+      updateSelection() {
+        const {dates, rangepicker} = this.picker.datepicker;
+        this.selected = dates.reduce((years, timeValue) => {
+          return pushUnique(years, startOfYearPeriod(timeValue, this.step));
+        }, []);
+        if (rangepicker && rangepicker.dates) {
+          this.range = rangepicker.dates.map(timeValue => {
+            if (timeValue !== undefined) {
+              return startOfYearPeriod(timeValue, this.step);
+            }
+          });
+        }
+      }
+
+      // Update the entire view UI
+      render() {
+        // refresh disabled years on every render in order to clear the ones added
+        // by beforeShow hook at previous render
+        this.disabled = [];
+
+        this.picker.setViewSwitchLabel(`${this.first}-${this.last}`);
+        this.picker.setPrevBtnDisabled(this.first <= this.minYear);
+        this.picker.setNextBtnDisabled(this.last >= this.maxYear);
+
+        Array.from(this.grid.children).forEach((el, index) => {
+          const classList = el.classList;
+          const current = this.start + (index * this.step);
+          const date = dateValue(current, 0, 1);
+
+          el.className = `datepicker-cell ${this.cellClass}`;
+          if (this.isMinView) {
+            el.dataset.date = date;
+          }
+          el.textContent = el.dataset.year = current;
+
+          if (index === 0) {
+            classList.add('prev');
+          } else if (index === 11) {
+            classList.add('next');
+          }
+          if (current < this.minYear || current > this.maxYear) {
+            classList.add('disabled');
+          }
+          if (this.range) {
+            const [rangeStart, rangeEnd] = this.range;
+            if (current > rangeStart && current < rangeEnd) {
+              classList.add('range');
+            }
+            if (current === rangeStart) {
+              classList.add('range-start');
+            }
+            if (current === rangeEnd) {
+              classList.add('range-end');
+            }
+          }
+          if (this.selected.includes(current)) {
+            classList.add('selected');
+          }
+          if (current === this.focused) {
+            classList.add('focused');
+          }
+
+          if (this.beforeShow) {
+            this.performBeforeHook(el, current, date);
+          }
+        });
+      }
+
+      // Update the view UI by applying the changes of selected and focused items
+      refresh() {
+        const [rangeStart, rangeEnd] = this.range || [];
+        this.grid
+          .querySelectorAll('.range, .range-start, .range-end, .selected, .focused')
+          .forEach((el) => {
+            el.classList.remove('range', 'range-start', 'range-end', 'selected', 'focused');
+          });
+        Array.from(this.grid.children).forEach((el) => {
+          const current = Number(el.textContent);
+          const classList = el.classList;
+          if (current > rangeStart && current < rangeEnd) {
+            classList.add('range');
+          }
+          if (current === rangeStart) {
+            classList.add('range-start');
+          }
+          if (current === rangeEnd) {
+            classList.add('range-end');
+          }
+          if (this.selected.includes(current)) {
+            classList.add('selected');
+          }
+          if (current === this.focused) {
+            classList.add('focused');
+          }
+        });
+      }
+
+      // Update the view UI by applying the change of focused item
+      refreshFocus() {
+        const index = Math.round((this.focused - this.start) / this.step);
+        this.grid.querySelectorAll('.focused').forEach((el) => {
+          el.classList.remove('focused');
+        });
+        this.grid.children[index].classList.add('focused');
+      }
+    }
+
+    function triggerDatepickerEvent(datepicker, type) {
+      const detail = {
+        date: datepicker.getDate(),
+        viewDate: new Date(datepicker.picker.viewDate),
+        viewId: datepicker.picker.currentView.id,
+        datepicker,
+      };
+      datepicker.element.dispatchEvent(new CustomEvent(type, {detail}));
+    }
+
+    // direction: -1 (to previous), 1 (to next)
+    function goToPrevOrNext(datepicker, direction) {
+      const {minDate, maxDate} = datepicker.config;
+      const {currentView, viewDate} = datepicker.picker;
+      let newViewDate;
+      switch (currentView.id) {
+        case 0:
+          newViewDate = addMonths(viewDate, direction);
+          break;
+        case 1:
+          newViewDate = addYears(viewDate, direction);
+          break;
+        default:
+          newViewDate = addYears(viewDate, direction * currentView.navStep);
+      }
+      newViewDate = limitToRange(newViewDate, minDate, maxDate);
+      datepicker.picker.changeFocus(newViewDate).render();
+    }
+
+    function switchView(datepicker) {
+      const viewId = datepicker.picker.currentView.id;
+      if (viewId === datepicker.config.maxView) {
+        return;
+      }
+      datepicker.picker.changeView(viewId + 1).render();
+    }
+
+    function unfocus(datepicker) {
+      if (datepicker.config.updateOnBlur) {
+        datepicker.update({autohide: true});
+      } else {
+        datepicker.refresh('input');
+        datepicker.hide();
+      }
+    }
+
+    function goToSelectedMonthOrYear(datepicker, selection) {
+      const picker = datepicker.picker;
+      const viewDate = new Date(picker.viewDate);
+      const viewId = picker.currentView.id;
+      const newDate = viewId === 1
+        ? addMonths(viewDate, selection - viewDate.getMonth())
+        : addYears(viewDate, selection - viewDate.getFullYear());
+
+      picker.changeFocus(newDate).changeView(viewId - 1).render();
+    }
+
+    function onClickTodayBtn(datepicker) {
+      const picker = datepicker.picker;
+      const currentDate = today();
+      if (datepicker.config.todayBtnMode === 1) {
+        if (datepicker.config.autohide) {
+          datepicker.setDate(currentDate);
+          return;
+        }
+        datepicker.setDate(currentDate, {render: false});
+        picker.update();
+      }
+      if (picker.viewDate !== currentDate) {
+        picker.changeFocus(currentDate);
+      }
+      picker.changeView(0).render();
+    }
+
+    function onClickClearBtn(datepicker) {
+      datepicker.setDate({clear: true});
+    }
+
+    function onClickViewSwitch(datepicker) {
+      switchView(datepicker);
+    }
+
+    function onClickPrevBtn(datepicker) {
+      goToPrevOrNext(datepicker, -1);
+    }
+
+    function onClickNextBtn(datepicker) {
+      goToPrevOrNext(datepicker, 1);
+    }
+
+    // For the picker's main block to delegete the events from `datepicker-cell`s
+    function onClickView(datepicker, ev) {
+      const target = findElementInEventPath(ev, '.datepicker-cell');
+      if (!target || target.classList.contains('disabled')) {
+        return;
+      }
+
+      const {id, isMinView} = datepicker.picker.currentView;
+      if (isMinView) {
+        datepicker.setDate(Number(target.dataset.date));
+      } else if (id === 1) {
+        goToSelectedMonthOrYear(datepicker, Number(target.dataset.month));
+      } else {
+        goToSelectedMonthOrYear(datepicker, Number(target.dataset.year));
+      }
+    }
+
+    function onClickPicker(datepicker) {
+      if (!datepicker.inline && !datepicker.config.disableTouchKeyboard) {
+        datepicker.inputField.focus();
+      }
+    }
+
+    function processPickerOptions(picker, options) {
+      if (options.title !== undefined) {
+        if (options.title) {
+          picker.controls.title.textContent = options.title;
+          showElement(picker.controls.title);
+        } else {
+          picker.controls.title.textContent = '';
+          hideElement(picker.controls.title);
+        }
+      }
+      if (options.prevArrow) {
+        const prevBtn = picker.controls.prevBtn;
+        emptyChildNodes(prevBtn);
+        options.prevArrow.forEach((node) => {
+          prevBtn.appendChild(node.cloneNode(true));
+        });
+      }
+      if (options.nextArrow) {
+        const nextBtn = picker.controls.nextBtn;
+        emptyChildNodes(nextBtn);
+        options.nextArrow.forEach((node) => {
+          nextBtn.appendChild(node.cloneNode(true));
+        });
+      }
+      if (options.locale) {
+        picker.controls.todayBtn.textContent = options.locale.today;
+        picker.controls.clearBtn.textContent = options.locale.clear;
+      }
+      if (options.todayBtn !== undefined) {
+        if (options.todayBtn) {
+          showElement(picker.controls.todayBtn);
+        } else {
+          hideElement(picker.controls.todayBtn);
+        }
+      }
+      if (hasProperty(options, 'minDate') || hasProperty(options, 'maxDate')) {
+        const {minDate, maxDate} = picker.datepicker.config;
+        picker.controls.todayBtn.disabled = !isInRange(today(), minDate, maxDate);
+      }
+      if (options.clearBtn !== undefined) {
+        if (options.clearBtn) {
+          showElement(picker.controls.clearBtn);
+        } else {
+          hideElement(picker.controls.clearBtn);
+        }
+      }
+    }
+
+    // Compute view date to reset, which will be...
+    // - the last item of the selected dates or defaultViewDate if no selection
+    // - limitted to minDate or maxDate if it exceeds the range
+    function computeResetViewDate(datepicker) {
+      const {dates, config} = datepicker;
+      const viewDate = dates.length > 0 ? lastItemOf(dates) : config.defaultViewDate;
+      return limitToRange(viewDate, config.minDate, config.maxDate);
+    }
+
+    // Change current view's view date
+    function setViewDate(picker, newDate) {
+      const oldViewDate = new Date(picker.viewDate);
+      const newViewDate = new Date(newDate);
+      const {id, year, first, last} = picker.currentView;
+      const viewYear = newViewDate.getFullYear();
+
+      picker.viewDate = newDate;
+      if (viewYear !== oldViewDate.getFullYear()) {
+        triggerDatepickerEvent(picker.datepicker, 'changeYear');
+      }
+      if (newViewDate.getMonth() !== oldViewDate.getMonth()) {
+        triggerDatepickerEvent(picker.datepicker, 'changeMonth');
+      }
+
+      // return whether the new date is in different period on time from the one
+      // displayed in the current view
+      // when true, the view needs to be re-rendered on the next UI refresh.
+      switch (id) {
+        case 0:
+          return newDate < first || newDate > last;
+        case 1:
+          return viewYear !== year;
+        default:
+          return viewYear < first || viewYear > last;
+      }
+    }
+
+    function getTextDirection(el) {
+      return window.getComputedStyle(el).direction;
+    }
+
+    // Class representing the picker UI
+    class Picker {
+      constructor(datepicker) {
+        this.datepicker = datepicker;
+
+        const template = pickerTemplate.replace(/%buttonClass%/g, datepicker.config.buttonClass);
+        const element = this.element = parseHTML(template).firstChild;
+        const [header, main, footer] = element.firstChild.children;
+        const title = header.firstElementChild;
+        const [prevBtn, viewSwitch, nextBtn] = header.lastElementChild.children;
+        const [todayBtn, clearBtn] = footer.firstChild.children;
+        const controls = {
+          title,
+          prevBtn,
+          viewSwitch,
+          nextBtn,
+          todayBtn,
+          clearBtn,
+        };
+        this.main = main;
+        this.controls = controls;
+
+        const elementClass = datepicker.inline ? 'inline' : 'dropdown';
+        element.classList.add(`datepicker-${elementClass}`);
+
+        processPickerOptions(this, datepicker.config);
+        this.viewDate = computeResetViewDate(datepicker);
+
+        // set up event listeners
+        registerListeners(datepicker, [
+          [element, 'click', onClickPicker.bind(null, datepicker), {capture: true}],
+          [main, 'click', onClickView.bind(null, datepicker)],
+          [controls.viewSwitch, 'click', onClickViewSwitch.bind(null, datepicker)],
+          [controls.prevBtn, 'click', onClickPrevBtn.bind(null, datepicker)],
+          [controls.nextBtn, 'click', onClickNextBtn.bind(null, datepicker)],
+          [controls.todayBtn, 'click', onClickTodayBtn.bind(null, datepicker)],
+          [controls.clearBtn, 'click', onClickClearBtn.bind(null, datepicker)],
+        ]);
+
+        // set up views
+        this.views = [
+          new DaysView(this),
+          new MonthsView(this),
+          new YearsView(this, {id: 2, name: 'years', cellClass: 'year', step: 1}),
+          new YearsView(this, {id: 3, name: 'decades', cellClass: 'decade', step: 10}),
+        ];
+        this.currentView = this.views[datepicker.config.startView];
+
+        this.currentView.render();
+        this.main.appendChild(this.currentView.element);
+        datepicker.config.container.appendChild(this.element);
+      }
+
+      setOptions(options) {
+        processPickerOptions(this, options);
+        this.views.forEach((view) => {
+          view.init(options, false);
+        });
+        this.currentView.render();
+      }
+
+      detach() {
+        this.datepicker.config.container.removeChild(this.element);
+      }
+
+      show() {
+        if (this.active) {
+          return;
+        }
+        this.element.classList.add('active');
+        this.active = true;
+
+        const datepicker = this.datepicker;
+        if (!datepicker.inline) {
+          // ensure picker's direction matches input's
+          const inputDirection = getTextDirection(datepicker.inputField);
+          if (inputDirection !== getTextDirection(datepicker.config.container)) {
+            this.element.dir = inputDirection;
+          } else if (this.element.dir) {
+            this.element.removeAttribute('dir');
+          }
+
+          this.place();
+          if (datepicker.config.disableTouchKeyboard) {
+            datepicker.inputField.blur();
+          }
+        }
+        triggerDatepickerEvent(datepicker, 'show');
+      }
+
+      hide() {
+        if (!this.active) {
+          return;
+        }
+        this.datepicker.exitEditMode();
+        this.element.classList.remove('active');
+        this.active = false;
+        triggerDatepickerEvent(this.datepicker, 'hide');
+      }
+
+      place() {
+        const {classList, style} = this.element;
+        const {config, inputField} = this.datepicker;
+        const container = config.container;
+        const {
+          width: calendarWidth,
+          height: calendarHeight,
+        } = this.element.getBoundingClientRect();
+        const {
+          left: containerLeft,
+          top: containerTop,
+          width: containerWidth,
+        } = container.getBoundingClientRect();
+        const {
+          left: inputLeft,
+          top: inputTop,
+          width: inputWidth,
+          height: inputHeight
+        } = inputField.getBoundingClientRect();
+        let {x: orientX, y: orientY} = config.orientation;
+        let scrollTop;
+        let left;
+        let top;
+
+        if (container === document.body) {
+          scrollTop = window.scrollY;
+          left = inputLeft + window.scrollX;
+          top = inputTop + scrollTop;
+        } else {
+          scrollTop = container.scrollTop;
+          left = inputLeft - containerLeft;
+          top = inputTop - containerTop + scrollTop;
+        }
+
+        if (orientX === 'auto') {
+          if (left < 0) {
+            // align to the left and move into visible area if input's left edge < window's
+            orientX = 'left';
+            left = 10;
+          } else if (left + calendarWidth > containerWidth) {
+            // align to the right if canlendar's right edge > container's
+            orientX = 'right';
+          } else {
+            orientX = getTextDirection(inputField) === 'rtl' ? 'right' : 'left';
+          }
+        }
+        if (orientX === 'right') {
+          left -= calendarWidth - inputWidth;
+        }
+
+        if (orientY === 'auto') {
+          orientY = top - calendarHeight < scrollTop ? 'bottom' : 'top';
+        }
+        if (orientY === 'top') {
+          top -= calendarHeight;
+        } else {
+          top += inputHeight;
+        }
+
+        classList.remove(
+          'datepicker-orient-top',
+          'datepicker-orient-bottom',
+          'datepicker-orient-right',
+          'datepicker-orient-left'
+        );
+        classList.add(`datepicker-orient-${orientY}`, `datepicker-orient-${orientX}`);
+
+        style.top = top ? `${top}px` : top;
+        style.left = left ? `${left}px` : left;
+      }
+
+      setViewSwitchLabel(labelText) {
+        this.controls.viewSwitch.textContent = labelText;
+      }
+
+      setPrevBtnDisabled(disabled) {
+        this.controls.prevBtn.disabled = disabled;
+      }
+
+      setNextBtnDisabled(disabled) {
+        this.controls.nextBtn.disabled = disabled;
+      }
+
+      changeView(viewId) {
+        const oldView = this.currentView;
+        const newView =  this.views[viewId];
+        if (newView.id !== oldView.id) {
+          this.currentView = newView;
+          this._renderMethod = 'render';
+          triggerDatepickerEvent(this.datepicker, 'changeView');
+          this.main.replaceChild(newView.element, oldView.element);
+        }
+        return this;
+      }
+
+      // Change the focused date (view date)
+      changeFocus(newViewDate) {
+        this._renderMethod = setViewDate(this, newViewDate) ? 'render' : 'refreshFocus';
+        this.views.forEach((view) => {
+          view.updateFocus();
+        });
+        return this;
+      }
+
+      // Apply the change of the selected dates
+      update() {
+        const newViewDate = computeResetViewDate(this.datepicker);
+        this._renderMethod = setViewDate(this, newViewDate) ? 'render' : 'refresh';
+        this.views.forEach((view) => {
+          view.updateFocus();
+          view.updateSelection();
+        });
+        return this;
+      }
+
+      // Refresh the picker UI
+      render(quickRender = true) {
+        const renderMethod = (quickRender && this._renderMethod) || 'render';
+        delete this._renderMethod;
+
+        this.currentView[renderMethod]();
+      }
+    }
+
+    // Find the closest date that doesn't meet the condition for unavailable date
+    // Returns undefined if no available date is found
+    // addFn: function to calculate the next date
+    //   - args: time value, amount
+    // increase: amount to pass to addFn
+    // testFn: function to test the unavailablity of the date
+    //   - args: time value; retun: true if unavailable
+    function findNextAvailableOne(date, addFn, increase, testFn, min, max) {
+      if (!isInRange(date, min, max)) {
+        return;
+      }
+      if (testFn(date)) {
+        const newDate = addFn(date, increase);
+        return findNextAvailableOne(newDate, addFn, increase, testFn, min, max);
+      }
+      return date;
+    }
+
+    // direction: -1 (left/up), 1 (right/down)
+    // vertical: true for up/down, false for left/right
+    function moveByArrowKey(datepicker, ev, direction, vertical) {
+      const picker = datepicker.picker;
+      const currentView = picker.currentView;
+      const step = currentView.step || 1;
+      let viewDate = picker.viewDate;
+      let addFn;
+      let testFn;
+      switch (currentView.id) {
+        case 0:
+          if (vertical) {
+            viewDate = addDays(viewDate, direction * 7);
+          } else if (ev.ctrlKey || ev.metaKey) {
+            viewDate = addYears(viewDate, direction);
+          } else {
+            viewDate = addDays(viewDate, direction);
+          }
+          addFn = addDays;
+          testFn = (date) => currentView.disabled.includes(date);
+          break;
+        case 1:
+          viewDate = addMonths(viewDate, vertical ? direction * 4 : direction);
+          addFn = addMonths;
+          testFn = (date) => {
+            const dt = new Date(date);
+            const {year, disabled} = currentView;
+            return dt.getFullYear() === year && disabled.includes(dt.getMonth());
+          };
+          break;
+        default:
+          viewDate = addYears(viewDate, direction * (vertical ? 4 : 1) * step);
+          addFn = addYears;
+          testFn = date => currentView.disabled.includes(startOfYearPeriod(date, step));
+      }
+      viewDate = findNextAvailableOne(
+        viewDate,
+        addFn,
+        direction < 0 ? -step : step,
+        testFn,
+        currentView.minDate,
+        currentView.maxDate
+      );
+      if (viewDate !== undefined) {
+        picker.changeFocus(viewDate).render();
+      }
+    }
+
+    function onKeydown(datepicker, ev) {
+      if (ev.key === 'Tab') {
+        unfocus(datepicker);
+        return;
+      }
+
+      const picker = datepicker.picker;
+      const {id, isMinView} = picker.currentView;
+      if (!picker.active) {
+        switch (ev.key) {
+          case 'ArrowDown':
+          case 'Escape':
+            picker.show();
+            break;
+          case 'Enter':
+            datepicker.update();
+            break;
+          default:
+            return;
+        }
+      } else if (datepicker.editMode) {
+        switch (ev.key) {
+          case 'Escape':
+            picker.hide();
+            break;
+          case 'Enter':
+            datepicker.exitEditMode({update: true, autohide: datepicker.config.autohide});
+            break;
+          default:
+            return;
+        }
+      } else {
+        switch (ev.key) {
+          case 'Escape':
+            picker.hide();
+            break;
+          case 'ArrowLeft':
+            if (ev.ctrlKey || ev.metaKey) {
+              goToPrevOrNext(datepicker, -1);
+            } else if (ev.shiftKey) {
+              datepicker.enterEditMode();
+              return;
+            } else {
+              moveByArrowKey(datepicker, ev, -1, false);
+            }
+            break;
+          case 'ArrowRight':
+            if (ev.ctrlKey || ev.metaKey) {
+              goToPrevOrNext(datepicker, 1);
+            } else if (ev.shiftKey) {
+              datepicker.enterEditMode();
+              return;
+            } else {
+              moveByArrowKey(datepicker, ev, 1, false);
+            }
+            break;
+          case 'ArrowUp':
+            if (ev.ctrlKey || ev.metaKey) {
+              switchView(datepicker);
+            } else if (ev.shiftKey) {
+              datepicker.enterEditMode();
+              return;
+            } else {
+              moveByArrowKey(datepicker, ev, -1, true);
+            }
+            break;
+          case 'ArrowDown':
+            if (ev.shiftKey && !ev.ctrlKey && !ev.metaKey) {
+              datepicker.enterEditMode();
+              return;
+            }
+            moveByArrowKey(datepicker, ev, 1, true);
+            break;
+          case 'Enter':
+            if (isMinView) {
+              datepicker.setDate(picker.viewDate);
+            } else {
+              picker.changeView(id - 1).render();
+            }
+            break;
+          case 'Backspace':
+          case 'Delete':
+            datepicker.enterEditMode();
+            return;
+          default:
+            if (ev.key.length === 1 && !ev.ctrlKey && !ev.metaKey) {
+              datepicker.enterEditMode();
+            }
+            return;
+        }
+      }
+      ev.preventDefault();
+      ev.stopPropagation();
+    }
+
+    function onFocus(datepicker) {
+      if (datepicker.config.showOnFocus) {
+        datepicker.show();
+      }
+    }
+
+    // for the prevention for entering edit mode while getting focus on click
+    function onMousedown(datepicker, ev) {
+      const el = ev.target;
+      if (datepicker.picker.active || datepicker.config.showOnClick) {
+        el._active = el === document.activeElement;
+        el._clicking = setTimeout(() => {
+          delete el._active;
+          delete el._clicking;
+        }, 2000);
+      }
+    }
+
+    function onClickInput(datepicker, ev) {
+      const el = ev.target;
+      if (!el._clicking) {
+        return;
+      }
+      clearTimeout(el._clicking);
+      delete el._clicking;
+
+      if (el._active) {
+        datepicker.enterEditMode();
+      }
+      delete el._active;
+
+      if (datepicker.config.showOnClick) {
+        datepicker.show();
+      }
+    }
+
+    function onPaste(datepicker, ev) {
+      if (ev.clipboardData.types.includes('text/plain')) {
+        datepicker.enterEditMode();
+      }
+    }
+
+    // for the `document` to delegate the events from outside the picker/input field
+    function onClickOutside(datepicker, ev) {
+      const element = datepicker.element;
+      if (element !== document.activeElement) {
+        return;
+      }
+      const pickerElem = datepicker.picker.element;
+      if (findElementInEventPath(ev, el => el === element || el === pickerElem)) {
+        return;
+      }
+      unfocus(datepicker);
+    }
+
+    function stringifyDates(dates, config) {
+      return dates
+        .map(dt => formatDate(dt, config.format, config.locale))
+        .join(config.dateDelimiter);
+    }
+
+    // parse input dates and create an array of time values for selection
+    // returns undefined if there are no valid dates in inputDates
+    // when origDates (current selection) is passed, the function works to mix
+    // the input dates into the current selection
+    function processInputDates(datepicker, inputDates, clear = false) {
+      const {config, dates: origDates, rangepicker} = datepicker;
+        if (inputDates.length === 0) {
+        // empty input is considered valid unless origiDates is passed
+        return clear ? [] : undefined;
+      }
+
+      const rangeEnd = rangepicker && datepicker === rangepicker.datepickers[1];
+      let newDates = inputDates.reduce((dates, dt) => {
+        let date = parseDate(dt, config.format, config.locale);
+        if (date === undefined) {
+          return dates;
+        }
+        if (config.pickLevel > 0) {
+          // adjust to 1st of the month/Jan 1st of the year
+          // or to the last day of the monh/Dec 31st of the year if the datepicker
+          // is the range-end picker of a rangepicker
+          const dt = new Date(date);
+          if (config.pickLevel === 1) {
+            date = rangeEnd
+              ? dt.setMonth(dt.getMonth() + 1, 0)
+              : dt.setDate(1);
+          } else {
+            date = rangeEnd
+              ? dt.setFullYear(dt.getFullYear() + 1, 0, 0)
+              : dt.setMonth(0, 1);
+          }
+        }
+        if (
+          isInRange(date, config.minDate, config.maxDate)
+          && !dates.includes(date)
+          && !config.datesDisabled.includes(date)
+          && !config.daysOfWeekDisabled.includes(new Date(date).getDay())
+        ) {
+          dates.push(date);
+        }
+        return dates;
+      }, []);
+      if (newDates.length === 0) {
+        return;
+      }
+      if (config.multidate && !clear) {
+        // get the synmetric difference between origDates and newDates
+        newDates = newDates.reduce((dates, date) => {
+          if (!origDates.includes(date)) {
+            dates.push(date);
+          }
+          return dates;
+        }, origDates.filter(date => !newDates.includes(date)));
+      }
+      // do length check always because user can input multiple dates regardless of the mode
+      return config.maxNumberOfDates && newDates.length > config.maxNumberOfDates
+        ? newDates.slice(config.maxNumberOfDates * -1)
+        : newDates;
+    }
+
+    // refresh the UI elements
+    // modes: 1: input only, 2, picker only, 3 both
+    function refreshUI(datepicker, mode = 3, quickRender = true) {
+      const {config, picker, inputField} = datepicker;
+      if (mode & 2) {
+        const newView = picker.active ? config.pickLevel : config.startView;
+        picker.update().changeView(newView).render(quickRender);
+      }
+      if (mode & 1 && inputField) {
+        inputField.value = stringifyDates(datepicker.dates, config);
+      }
+    }
+
+    function setDate(datepicker, inputDates, options) {
+      let {clear, render, autohide} = options;
+      if (render === undefined) {
+        render = true;
+      }
+      if (!render) {
+        autohide = false;
+      } else if (autohide === undefined) {
+        autohide = datepicker.config.autohide;
+      }
+
+      const newDates = processInputDates(datepicker, inputDates, clear);
+      if (!newDates) {
+        return;
+      }
+      if (newDates.toString() !== datepicker.dates.toString()) {
+        datepicker.dates = newDates;
+        refreshUI(datepicker, render ? 3 : 1);
+        triggerDatepickerEvent(datepicker, 'changeDate');
+      } else {
+        refreshUI(datepicker, 1);
+      }
+      if (autohide) {
+        datepicker.hide();
+      }
+    }
+
+    /**
+     * Class representing a date picker
+     */
+    class Datepicker {
+      /**
+       * Create a date picker
+       * @param  {Element} element - element to bind a date picker
+       * @param  {Object} [options] - config options
+       * @param  {DateRangePicker} [rangepicker] - DateRangePicker instance the
+       * date picker belongs to. Use this only when creating date picker as a part
+       * of date range picker
+       */
+      constructor(element, options = {}, rangepicker = undefined) {
+        element.datepicker = this;
+        this.element = element;
+
+        // set up config
+        const config = this.config = Object.assign({
+          buttonClass: (options.buttonClass && String(options.buttonClass)) || 'button',
+          container: document.body,
+          defaultViewDate: today(),
+          maxDate: undefined,
+          minDate: undefined,
+        }, processOptions(defaultOptions, this));
+        this._options = options;
+        Object.assign(config, processOptions(options, this));
+
+        // configure by type
+        const inline = this.inline = element.tagName !== 'INPUT';
+        let inputField;
+        let initialDates;
+
+        if (inline) {
+          config.container = element;
+          initialDates = stringToArray(element.dataset.date, config.dateDelimiter);
+          delete element.dataset.date;
+        } else {
+          const container = options.container ? document.querySelector(options.container) : null;
+          if (container) {
+            config.container = container;
+          }
+          inputField = this.inputField = element;
+          inputField.classList.add('datepicker-input');
+          initialDates = stringToArray(inputField.value, config.dateDelimiter);
+        }
+        if (rangepicker) {
+          // check validiry
+          const index = rangepicker.inputs.indexOf(inputField);
+          const datepickers = rangepicker.datepickers;
+          if (index < 0 || index > 1 || !Array.isArray(datepickers)) {
+            throw Error('Invalid rangepicker object.');
+          }
+          // attach itaelf to the rangepicker here so that processInputDates() can
+          // determine if this is the range-end picker of the rangepicker while
+          // setting inital values when pickLevel > 0
+          datepickers[index] = this;
+          // add getter for rangepicker
+          Object.defineProperty(this, 'rangepicker', {
+            get() {
+              return rangepicker;
+            },
+          });
+        }
+
+        // set initial value
+        this.dates = processInputDates(this, initialDates) || [];
+        if (inputField) {
+          inputField.value = stringifyDates(this.dates, config);
+        }
+
+        const picker = this.picker = new Picker(this);
+
+        if (inline) {
+          this.show();
+        } else {
+          // set up event listeners in other modes
+          const onMousedownDocument = onClickOutside.bind(null, this);
+          const listeners = [
+            [inputField, 'keydown', onKeydown.bind(null, this)],
+            [inputField, 'focus', onFocus.bind(null, this)],
+            [inputField, 'mousedown', onMousedown.bind(null, this)],
+            [inputField, 'click', onClickInput.bind(null, this)],
+            [inputField, 'paste', onPaste.bind(null, this)],
+            [document, 'mousedown', onMousedownDocument],
+            [document, 'touchstart', onMousedownDocument],
+            [window, 'resize', picker.place.bind(picker)]
+          ];
+          registerListeners(this, listeners);
+        }
+      }
+
+      /**
+       * Format Date object or time value in given format and language
+       * @param  {Date|Number} date - date or time value to format
+       * @param  {String|Object} format - format string or object that contains
+       * toDisplay() custom formatter, whose signature is
+       * - args:
+       *   - date: {Date} - Date instance of the date passed to the method
+       *   - format: {Object} - the format object passed to the method
+       *   - locale: {Object} - locale for the language specified by `lang`
+       * - return:
+       *     {String} formatted date
+       * @param  {String} [lang=en] - language code for the locale to use
+       * @return {String} formatted date
+       */
+      static formatDate(date, format, lang) {
+        return formatDate(date, format, lang && locales[lang] || locales.en);
+      }
+
+      /**
+       * Parse date string
+       * @param  {String|Date|Number} dateStr - date string, Date object or time
+       * value to parse
+       * @param  {String|Object} format - format string or object that contains
+       * toValue() custom parser, whose signature is
+       * - args:
+       *   - dateStr: {String|Date|Number} - the dateStr passed to the method
+       *   - format: {Object} - the format object passed to the method
+       *   - locale: {Object} - locale for the language specified by `lang`
+       * - return:
+       *     {Date|Number} parsed date or its time value
+       * @param  {String} [lang=en] - language code for the locale to use
+       * @return {Number} time value of parsed date
+       */
+      static parseDate(dateStr, format, lang) {
+        return parseDate(dateStr, format, lang && locales[lang] || locales.en);
+      }
+
+      /**
+       * @type {Object} - Installed locales in `[languageCode]: localeObject` format
+       * en`:_English (US)_ is pre-installed.
+       */
+      static get locales() {
+        return locales;
+      }
+
+      /**
+       * @type {Boolean} - Whether the picker element is shown. `true` whne shown
+       */
+      get active() {
+        return !!(this.picker && this.picker.active);
+      }
+
+      /**
+       * @type {HTMLDivElement} - DOM object of picker element
+       */
+      get pickerElement() {
+        return this.picker ? this.picker.element : undefined;
+      }
+
+      /**
+       * Set new values to the config options
+       * @param {Object} options - config options to update
+       */
+      setOptions(options) {
+        const picker = this.picker;
+        const newOptions = processOptions(options, this);
+        Object.assign(this._options, options);
+        Object.assign(this.config, newOptions);
+        picker.setOptions(newOptions);
+
+        refreshUI(this, 3);
+      }
+
+      /**
+       * Show the picker element
+       */
+      show() {
+        if (this.inputField && this.inputField.disabled) {
+          return;
+        }
+        this.picker.show();
+      }
+
+      /**
+       * Hide the picker element
+       * Not available on inline picker
+       */
+      hide() {
+        if (this.inline) {
+          return;
+        }
+        this.picker.hide();
+        this.picker.update().changeView(this.config.startView).render();
+      }
+
+      /**
+       * Destroy the Datepicker instance
+       * @return {Detepicker} - the instance destroyed
+       */
+      destroy() {
+        this.hide();
+        unregisterListeners(this);
+        this.picker.detach();
+        if (!this.inline) {
+          this.inputField.classList.remove('datepicker-input');
+        }
+        delete this.element.datepicker;
+        return this;
+      }
+
+      /**
+       * Get the selected date(s)
+       *
+       * The method returns a Date object of selected date by default, and returns
+       * an array of selected dates in multidate mode. If format string is passed,
+       * it returns date string(s) formatted in given format.
+       *
+       * @param  {String} [format] - Format string to stringify the date(s)
+       * @return {Date|String|Date[]|String[]} - selected date(s), or if none is
+       * selected, empty array in multidate mode and untitled in sigledate mode
+       */
+      getDate(format = undefined) {
+        const callback = format
+          ? date => formatDate(date, format, this.config.locale)
+          : date => new Date(date);
+
+        if (this.config.multidate) {
+          return this.dates.map(callback);
+        }
+        if (this.dates.length > 0) {
+          return callback(this.dates[0]);
+        }
+      }
+
+      /**
+       * Set selected date(s)
+       *
+       * In multidate mode, you can pass multiple dates as a series of arguments
+       * or an array. (Since each date is parsed individually, the type of the
+       * dates doesn't have to be the same.)
+       * The given dates are used to toggle the select status of each date. The
+       * number of selected dates is kept from exceeding the length set to
+       * maxNumberOfDates.
+       *
+       * With clear: true option, the method can be used to clear the selection
+       * and to replace the selection instead of toggling in multidate mode.
+       * If the option is passed with no date arguments or an empty dates array,
+       * it works as "clear" (clear the selection then set nothing), and if the
+       * option is passed with new dates to select, it works as "replace" (clear
+       * the selection then set the given dates)
+       *
+       * When render: false option is used, the method omits re-rendering the
+       * picker element. In this case, you need to call refresh() method later in
+       * order for the picker element to reflect the changes. The input field is
+       * refreshed always regardless of this option.
+       *
+       * When invalid (unparsable, repeated, disabled or out-of-range) dates are
+       * passed, the method ignores them and applies only valid ones. In the case
+       * that all the given dates are invalid, which is distinguished from passing
+       * no dates, the method considers it as an error and leaves the selection
+       * untouched.
+       *
+       * @param {...(Date|Number|String)|Array} [dates] - Date strings, Date
+       * objects, time values or mix of those for new selection
+       * @param {Object} [options] - function options
+       * - clear: {boolean} - Whether to clear the existing selection
+       *     defualt: false
+       * - render: {boolean} - Whether to re-render the picker element
+       *     default: true
+       * - autohide: {boolean} - Whether to hide the picker element after re-render
+       *     Ignored when used with render: false
+       *     default: config.autohide
+       */
+      setDate(...args) {
+        const dates = [...args];
+        const opts = {};
+        const lastArg = lastItemOf(args);
+        if (
+          typeof lastArg === 'object'
+          && !Array.isArray(lastArg)
+          && !(lastArg instanceof Date)
+          && lastArg
+        ) {
+          Object.assign(opts, dates.pop());
+        }
+
+        const inputDates = Array.isArray(dates[0]) ? dates[0] : dates;
+        setDate(this, inputDates, opts);
+      }
+
+      /**
+       * Update the selected date(s) with input field's value
+       * Not available on inline picker
+       *
+       * The input field will be refreshed with properly formatted date string.
+       *
+       * @param  {Object} [options] - function options
+       * - autohide: {boolean} - whether to hide the picker element after refresh
+       *     default: false
+       */
+      update(options = undefined) {
+        if (this.inline) {
+          return;
+        }
+
+        const opts = {clear: true, autohide: !!(options && options.autohide)};
+        const inputDates = stringToArray(this.inputField.value, this.config.dateDelimiter);
+        setDate(this, inputDates, opts);
+      }
+
+      /**
+       * Refresh the picker element and the associated input field
+       * @param {String} [target] - target item when refreshing one item only
+       * 'picker' or 'input'
+       * @param {Boolean} [forceRender] - whether to re-render the picker element
+       * regardless of its state instead of optimized refresh
+       */
+      refresh(target = undefined, forceRender = false) {
+        if (target && typeof target !== 'string') {
+          forceRender = target;
+          target = undefined;
+        }
+
+        let mode;
+        if (target === 'picker') {
+          mode = 2;
+        } else if (target === 'input') {
+          mode = 1;
+        } else {
+          mode = 3;
+        }
+        refreshUI(this, mode, !forceRender);
+      }
+
+      /**
+       * Enter edit mode
+       * Not available on inline picker or when the picker element is hidden
+       */
+      enterEditMode() {
+        if (this.inline || !this.picker.active || this.editMode) {
+          return;
+        }
+        this.editMode = true;
+        this.inputField.classList.add('in-edit');
+      }
+
+      /**
+       * Exit from edit mode
+       * Not available on inline picker
+       * @param  {Object} [options] - function options
+       * - update: {boolean} - whether to call update() after exiting
+       *     If false, input field is revert to the existing selection
+       *     default: false
+       */
+      exitEditMode(options = undefined) {
+        if (this.inline || !this.editMode) {
+          return;
+        }
+        const opts = Object.assign({update: false}, options);
+        delete this.editMode;
+        this.inputField.classList.remove('in-edit');
+        if (opts.update) {
+          this.update(opts);
+        }
+      }
+    }
+
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *      http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+    // XXX it might be nice, if this util was in tobago-date.ts, but in that case there are problems
+    // XXX with Jest (UnitTesting)
+    class DateUtils {
+        /*
+        Get the pattern from the "Java world",
+        see https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/text/SimpleDateFormat.html
+        and convert it to 'vanillajs-datepicker', see https://mymth.github.io/vanillajs-datepicker/#/date-string+format
+        Attention: Not every pattern char is supported.
+        */
+        static convertPatternJava2Js(originalPattern) {
+            let pattern;
+            if (!originalPattern || originalPattern.length > 100) {
+                console.warn("Pattern not supported: " + originalPattern);
+                pattern = "";
+            }
+            else {
+                pattern = originalPattern;
+            }
+            let analyzedPattern = "";
+            let nextSegment = "";
+            let escMode = false;
+            for (let i = 0; i < pattern.length; i++) {
+                const currentChar = pattern.charAt(i);
+                if (currentChar == "'" && escMode == false) {
+                    escMode = true;
+                    analyzedPattern += DateUtils.convertPatternPart(nextSegment);
+                    nextSegment = "";
+                }
+                else if (currentChar == "'" && pattern.charAt(i + 1) == "'") {
+                    if (escMode) {
+                        nextSegment += "\\";
+                    }
+                    nextSegment += "'";
+                    i++;
+                }
+                else if (currentChar == "'" && escMode == true) {
+                    escMode = false;
+                    analyzedPattern += nextSegment;
+                    nextSegment = "";
+                }
+                else {
+                    if (escMode) {
+                        nextSegment += "\\";
+                    }
+                    nextSegment += currentChar;
+                }
+            }
+            if (nextSegment != "") {
+                if (escMode) {
+                    analyzedPattern += nextSegment;
+                }
+                else {
+                    analyzedPattern += this.convertPatternPart(nextSegment);
+                }
+            }
+            return analyzedPattern;
+        }
+        static convertPatternPart(originalPattern) {
+            let pattern = originalPattern;
+            if (pattern.search("G") > -1 || pattern.search("W") > -1 || pattern.search("F") > -1
+                || pattern.search("K") > -1 || pattern.search("z") > -1 || pattern.search("X") > -1) {
+                console.warn("Pattern chars 'G', 'W', 'F', 'K', 'z' and 'X' are not supported: " + pattern);
+                pattern = "";
+            }
+            if (pattern.search("y") > -1) {
+                pattern = pattern.replace(/y/g, "y");
+            }
+            if (pattern.search("M") > -1) {
+                pattern = pattern.replace(/M/g, "m");
+            }
+            if (pattern.search("d") > -1) {
+                pattern = pattern.replace(/dd+/g, "dd");
+                pattern = pattern.replace(/\bd\b/g, "d");
+            }
+            return pattern;
+        }
+    }
+
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *      http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+    class Config {
+        static set(key, value) {
+            this.map.set(key, value);
+        }
+        static get(key) {
+            const value = this.map.get(key);
+            if (value) {
+                return value;
+            }
+            else {
+                console.warn("Config.get(" + key + ") = undefined");
+                return 0;
+            }
+        }
+    }
+    Config.map = new Map();
+
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *      http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+    // XXX issue: if a ajax call is scheduled on the same element, the animation arrow will stacking and not desapearing.
+    // XXX issue: "error" is not implemented correctly
+    // see http://localhost:8080/demo-5-snapshot/content/30-concept/50-partial/Partial_Ajax.xhtml to use this feature
+    // XXX todo: check full page transitions
+    class Overlay {
+        constructor(element, ajax = false, error = false, waitOverlayDelay) {
+            /**
+             * Is this overlay for an AJAX request, or an normal submit?
+             * We need this information, because AJAX need to clone the animated image, but for a normal submit
+             * we must not clone it, because the animation stops in some browsers.
+             */
+            this.ajax = true;
+            /**
+             * This boolean indicates, if the overlay is "error" or "wait".
+             */
+            this.error = false;
+            /**
+             * The delay for the wait overlay. If not set the default delay is read from Tobago.Config.
+             */
+            this.waitOverlayDelay = 0;
+            this.element = element;
+            this.ajax = ajax;
+            this.error = error;
+            this.waitOverlayDelay = waitOverlayDelay
+                ? waitOverlayDelay
+                : Config.get(this.ajax ? "Ajax.waitOverlayDelay" : "Tobago.waitOverlayDelay");
+            // create the overlay
+            this.overlay = document.createElement("div");
+            this.overlay.classList.add("tobago-page-overlay");
+            this.overlay.classList.add(this.error ? "tobago-page-overlay-markup-error" : "tobago-page-overlay-markup-wait");
+            let left = "0";
+            let top = "0";
+            if (this.element.matches("body")) {
+                this.overlay.style.position = "fixed";
+                this.overlay.style.zIndex = "1500"; // greater than the bootstrap navbar
+            }
+            else {
+                const rect = this.element.getBoundingClientRect();
+                left = (rect.left + document.body.scrollLeft) + "px";
+                top = (rect.top + document.body.scrollTop) + "px";
+                this.overlay.style.width = this.element.offsetWidth + "px";
+                this.overlay.style.height = this.element.offsetHeight + "px";
+                // tbd: is this still needed?       this.overlay.style.position= "absolute"
+                // XXX is set via class, but seams to be overridden in IE11?
+            }
+            document.getElementsByTagName("body")[0].append(this.overlay);
+            let wait = document.createElement("div");
+            wait.classList.add("tobago-page-overlayCenter");
+            this.overlay.append(wait);
+            let image = document.createElement("i");
+            if (this.error) {
+                image.classList.add("fa", "fa-flash", "fa-3x");
+                wait.classList.add("alert-danger");
+            }
+            else {
+                image.classList.add("fa", "fa-refresh", "fa-3x", "fa-spin");
+                image.style.opacity = "0.4";
+            }
+            wait.append(image);
+            wait.style.display = ""; //XXX ?
+            this.overlay.style.backgroundColor = Page.page(this.element).style.backgroundColor;
+            this.overlay.style.left = left;
+            this.overlay.style.top = top;
+            setTimeout(() => {
+                this.overlay.classList.add("tobago-page-overlay-timeout");
+            }, this.waitOverlayDelay);
+            Overlay.overlayMap.set(element.id, this);
+            console.debug("----> set overlay " + element.id);
+        }
+        static destroy(id) {
+            console.debug("----> get overlay " + id);
+            const overlay = Overlay.overlayMap.get(id);
+            if (overlay) {
+                overlay.overlay.remove();
+                Overlay.overlayMap.delete(id);
+            }
+            else {
+                console.warn("Overlay not found for id='" + id + "'");
+            }
+        }
+    }
+    Overlay.overlayMap = new Map();
+    Config.set("Tobago.waitOverlayDelay", 1000);
+    Config.set("Ajax.waitOverlayDelay", 1000);
+
+    /*!
+      * Bootstrap v5.0.0-beta1 (https://getbootstrap.com/)
+      * Copyright 2011-2020 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
+      * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
+      */
+
+    function _defineProperties(target, props) {
+      for (var i = 0; i < props.length; i++) {
+        var descriptor = props[i];
+        descriptor.enumerable = descriptor.enumerable || false;
+        descriptor.configurable = true;
+        if ("value" in descriptor) descriptor.writable = true;
+        Object.defineProperty(target, descriptor.key, descriptor);
+      }
+    }
+
+    function _createClass(Constructor, protoProps, staticProps) {
+      if (protoProps) _defineProperties(Constructor.prototype, protoProps);
+      if (staticProps) _defineProperties(Constructor, staticProps);
+      return Constructor;
+    }
+
+    function _extends() {
+      _extends = Object.assign || function (target) {
+        for (var i = 1; i < arguments.length; i++) {
+          var source = arguments[i];
+
+          for (var key in source) {
+            if (Object.prototype.hasOwnProperty.call(source, key)) {
+              target[key] = source[key];
+            }
+          }
+        }
+
+        return target;
+      };
+
+      return _extends.apply(this, arguments);
+    }
+
+    function _inheritsLoose(subClass, superClass) {
+      subClass.prototype = Object.create(superClass.prototype);
+      subClass.prototype.constructor = subClass;
+      subClass.__proto__ = superClass;
+    }
+
+    /**
+     * --------------------------------------------------------------------------
+     * Bootstrap (v5.0.0-beta1): util/index.js
+     * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
+     * --------------------------------------------------------------------------
+     */
+    var MAX_UID = 1000000;
+    var MILLISECONDS_MULTIPLIER = 1000;
+    var TRANSITION_END = 'transitionend'; // Shoutout AngusCroll (https://goo.gl/pxwQGp)
+
+    var toType = function toType(obj) {
+      if (obj === null || obj === undefined) {
+        return "" + obj;
+      }
+
+      return {}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCase();
+    };
+    /**
+     * --------------------------------------------------------------------------
+     * Public Util Api
+     * --------------------------------------------------------------------------
+     */
+
+
+    var getUID = function getUID(prefix) {
+      do {
+        prefix += Math.floor(Math.random() * MAX_UID);
+      } while (document.getElementById(prefix));
+
+      return prefix;
+    };
+
+    var getSelector = function getSelector(element) {
+      var selector = element.getAttribute('data-bs-target');
+
+      if (!selector || selector === '#') {
+        var hrefAttr = element.getAttribute('href');
+        selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : null;
+      }
+
+      return selector;
+    };
+
+    var getSelectorFromElement = function getSelectorFromElement(element) {
+      var selector = getSelector(element);
+
+      if (selector) {
+        return document.querySelector(selector) ? selector : null;
+      }
+
+      return null;
+    };
+
+    var getElementFromSelector = function getElementFromSelector(element) {
+      var selector = getSelector(element);
+      return selector ? document.querySelector(selector) : null;
+    };
+
+    var getTransitionDurationFromElement = function getTransitionDurationFromElement(element) {
+      if (!element) {
+        return 0;
+      } // Get transition-duration of the element
+
+
+      var _window$getComputedSt = window.getComputedStyle(element),
+          transitionDuration = _window$getComputedSt.transitionDuration,
+          transitionDelay = _window$getComputedSt.transitionDelay;
+
+      var floatTransitionDuration = Number.parseFloat(transitionDuration);
+      var floatTransitionDelay = Number.parseFloat(transitionDelay); // Return 0 if element or transition duration is not found
+
+      if (!floatTransitionDuration && !floatTransitionDelay) {
+        return 0;
+      } // If multiple durations are defined, take the first
+
+
+      transitionDuration = transitionDuration.split(',')[0];
+      transitionDelay = transitionDelay.split(',')[0];
+      return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER;
+    };
+
+    var triggerTransitionEnd = function triggerTransitionEnd(element) {
+      element.dispatchEvent(new Event(TRANSITION_END));
+    };
+
+    var isElement$1 = function isElement(obj) {
+      return (obj[0] || obj).nodeType;
+    };
+
+    var emulateTransitionEnd = function emulateTransitionEnd(element, duration) {
+      var called = false;
+      var durationPadding = 5;
+      var emulatedDuration = duration + durationPadding;
+
+      function listener() {
+        called = true;
+        element.removeEventListener(TRANSITION_END, listener);
+      }
+
+      element.addEventListener(TRANSITION_END, listener);
+      setTimeout(function () {
+        if (!called) {
+          triggerTransitionEnd(element);
+        }
+      }, emulatedDuration);
+    };
+
+    var typeCheckConfig = function typeCheckConfig(componentName, config, configTypes) {
+      Object.keys(configTypes).forEach(function (property) {
+        var expectedTypes = configTypes[property];
+        var value = config[property];
+        var valueType = value && isElement$1(value) ? 'element' : toType(value);
+
+        if (!new RegExp(expectedTypes).test(valueType)) {
+          throw new Error(componentName.toUpperCase() + ": " + ("Option \"" + property + "\" provided type \"" + valueType + "\" ") + ("but expected type \"" + expectedTypes + "\"."));
+        }
+      });
+    };
+
+    var isVisible = function isVisible(element) {
+      if (!element) {
+        return false;
+      }
+
+      if (element.style && element.parentNode && element.parentNode.style) {
+        var elementStyle = getComputedStyle(element);
+        var parentNodeStyle = getComputedStyle(element.parentNode);
+        return elementStyle.display !== 'none' && parentNodeStyle.display !== 'none' && elementStyle.visibility !== 'hidden';
+      }
+
+      return false;
+    };
+
+    var findShadowRoot = function findShadowRoot(element) {
+      if (!document.documentElement.attachShadow) {
+        return null;
+      } // Can find the shadow root otherwise it'll return the document
+
+
+      if (typeof element.getRootNode === 'function') {
+        var root = element.getRootNode();
+        return root instanceof ShadowRoot ? root : null;
+      }
+
+      if (element instanceof ShadowRoot) {
+        return element;
+      } // when we don't find a shadow root
+
+
+      if (!element.parentNode) {
+        return null;
+      }
+
+      return findShadowRoot(element.parentNode);
+    };
+
+    var noop = function noop() {
+      return function () {};
+    };
+
+    var reflow = function reflow(element) {
+      return element.offsetHeight;
+    };
+
+    var getjQuery = function getjQuery() {
+      var _window = window,
+          jQuery = _window.jQuery;
+
+      if (jQuery && !document.body.hasAttribute('data-bs-no-jquery')) {
+        return jQuery;
+      }
+
+      return null;
+    };
+
+    var onDOMContentLoaded = function onDOMContentLoaded(callback) {
+      if (document.readyState === 'loading') {
+        document.addEventListener('DOMContentLoaded', callback);
+      } else {
+        callback();
+      }
+    };
+
+    var isRTL = document.documentElement.dir === 'rtl';
+
+    /**
+     * --------------------------------------------------------------------------
+     * Bootstrap (v5.0.0-beta1): dom/data.js
+     * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
+     * --------------------------------------------------------------------------
+     */
+
+    /**
+     * ------------------------------------------------------------------------
+     * Constants
+     * ------------------------------------------------------------------------
+     */
+    var mapData = function () {
+      var storeData = {};
+      var id = 1;
+      return {
+        set: function set(element, key, data) {
+          if (typeof element.bsKey === 'undefined') {
+            element.bsKey = {
+              key: key,
+              id: id
+            };
+            id++;
+          }
+
+          storeData[element.bsKey.id] = data;
+        },
+        get: function get(element, key) {
+          if (!element || typeof element.bsKey === 'undefined') {
+            return null;
+          }
+
+          var keyProperties = element.bsKey;
+
+          if (keyProperties.key === key) {
+            return storeData[keyProperties.id];
+          }
+
+          return null;
+        },
+        delete: function _delete(element, key) {
+          if (typeof element.bsKey === 'undefined') {
+            return;
+          }
+
+          var keyProperties = element.bsKey;
+
+          if (keyProperties.key === key) {
+            delete storeData[keyProperties.id];
+            delete element.bsKey;
+          }
+        }
+      };
+    }();
+
+    var Data = {
+      setData: function setData(instance, key, data) {
+        mapData.set(instance, key, data);
+      },
+      getData: function getData(instance, key) {
+        return mapData.get(instance, key);
+      },
+      removeData: function removeData(instance, key) {
+        mapData.delete(instance, key);
+      }
+    };
+
+    /**
+     * --------------------------------------------------------------------------
+     * Bootstrap (v5.0.0-beta1): dom/event-handler.js
+     * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
+     * --------------------------------------------------------------------------
+     */
+    /**
+     * ------------------------------------------------------------------------
+     * Constants
+     * ------------------------------------------------------------------------
+     */
+
+    var namespaceRegex = /[^.]*(?=\..*)\.|.*/;
+    var stripNameRegex = /\..*/;
+    var stripUidRegex = /::\d+$/;
+    var eventRegistry = {}; // Events storage
+
+    var uidEvent = 1;
+    var customEvents = {
+      mouseenter: 'mouseover',
+      mouseleave: 'mouseout'
+    };
+    var nativeEvents = new Set(['click', 'dblclick', 'mouseup', 'mousedown', 'contextmenu', 'mousewheel', 'DOMMouseScroll', 'mouseover', 'mouseout', 'mousemove', 'selectstart', 'selectend', 'keydown', 'keypress', 'keyup', 'orientationchange', 'touchstart', 'touchmove', 'touchend', 'touchcancel', 'pointerdown', 'pointermove', 'pointerup', 'pointerleave', 'pointercancel', 'gesturestart', 'gesturechange', 'gestureend', 'focus', 'blur', 'change', 'reset', 'select', 'submit', 'focusin', 'focu [...]
+    /**
+     * ------------------------------------------------------------------------
+     * Private methods
+     * ------------------------------------------------------------------------
+     */
+
+    function getUidEvent(element, uid) {
+      return uid && uid + "::" + uidEvent++ || element.uidEvent || uidEvent++;
+    }
+
+    function getEvent(element) {
+      var uid = getUidEvent(element);
+      element.uidEvent = uid;
+      eventRegistry[uid] = eventRegistry[uid] || {};
+      return eventRegistry[uid];
+    }
+
+    function bootstrapHandler(element, fn) {
+      return function handler(event) {
+        event.delegateTarget = element;
+
+        if (handler.oneOff) {
+          EventHandler.off(element, event.type, fn);
+        }
+
+        return fn.apply(element, [event]);
+      };
+    }
+
+    function bootstrapDelegationHandler(element, selector, fn) {
+      return function handler(event) {
+        var domElements = element.querySelectorAll(selector);
+
+        for (var target = event.target; target && target !== this; target = target.parentNode) {
+          for (var i = domElements.length; i--;) {
+            if (domElements[i] === target) {
+              event.delegateTarget = target;
+
+              if (handler.oneOff) {
+                EventHandler.off(element, event.type, fn);
+              }
+
+              return fn.apply(target, [event]);
+            }
+          }
+        } // To please ESLint
+
+
+        return null;
+      };
+    }
+
+    function findHandler(events, handler, delegationSelector) {
+      if (delegationSelector === void 0) {
+        delegationSelector = null;
+      }
+
+      var uidEventList = Object.keys(events);
+
+      for (var i = 0, len = uidEventList.length; i < len; i++) {
+        var event = events[uidEventList[i]];
+
+        if (event.originalHandler === handler && event.delegationSelector === delegationSelector) {
+          return event;
+        }
+      }
+
+      return null;
+    }
+
+    function normalizeParams(originalTypeEvent, handler, delegationFn) {
+      var delegation = typeof handler === 'string';
+      var originalHandler = delegation ? delegationFn : handler; // allow to get the native events from namespaced events ('click.bs.button' --> 'click')
+
+      var typeEvent = originalTypeEvent.replace(stripNameRegex, '');
+      var custom = customEvents[typeEvent];
+
+      if (custom) {
+        typeEvent = custom;
+      }
+
+      var isNative = nativeEvents.has(typeEvent);
+
+      if (!isNative) {
+        typeEvent = originalTypeEvent;
+      }
+
+      return [delegation, originalHandler, typeEvent];
+    }
+
+    function addHandler(element, originalTypeEvent, handler, delegationFn, oneOff) {
+      if (typeof originalTypeEvent !== 'string' || !element) {
+        return;
+      }
+
+      if (!handler) {
+        handler = delegationFn;
+        delegationFn = null;
+      }
+
+      var _normalizeParams = normalizeParams(originalTypeEvent, handler, delegationFn),
+          delegation = _normalizeParams[0],
+          originalHandler = _normalizeParams[1],
+          typeEvent = _normalizeParams[2];
+
+      var events = getEvent(element);
+      var handlers = events[typeEvent] || (events[typeEvent] = {});
+      var previousFn = findHandler(handlers, originalHandler, delegation ? handler : null);
+
+      if (previousFn) {
+        previousFn.oneOff = previousFn.oneOff && oneOff;
+        return;
+      }
+
+      var uid = getUidEvent(originalHandler, originalTypeEvent.replace(namespaceRegex, ''));
+      var fn = delegation ? bootstrapDelegationHandler(element, handler, delegationFn) : bootstrapHandler(element, handler);
+      fn.delegationSelector = delegation ? handler : null;
+      fn.originalHandler = originalHandler;
+      fn.oneOff = oneOff;
+      fn.uidEvent = uid;
+      handlers[uid] = fn;
+      element.addEventListener(typeEvent, fn, delegation);
+    }
+
+    function removeHandler(element, events, typeEvent, handler, delegationSelector) {
+      var fn = findHandler(events[typeEvent], handler, delegationSelector);
+
+      if (!fn) {
+        return;
+      }
+
+      element.removeEventListener(typeEvent, fn, Boolean(delegationSelector));
+      delete events[typeEvent][fn.uidEvent];
+    }
+
+    function removeNamespacedHandlers(element, events, typeEvent, namespace) {
+      var storeElementEvent = events[typeEvent] || {};
+      Object.keys(storeElementEvent).forEach(function (handlerKey) {
+        if (handlerKey.includes(namespace)) {
+          var event = storeElementEvent[handlerKey];
+          removeHandler(element, events, typeEvent, event.originalHandler, event.delegationSelector);
+        }
+      });
+    }
+
+    var EventHandler = {
+      on: function on(element, event, handler, delegationFn) {
+        addHandler(element, event, handler, delegationFn, false);
+      },
+      one: function one(element, event, handler, delegationFn) {
+        addHandler(element, event, handler, delegationFn, true);
+      },
+      off: function off(element, originalTypeEvent, handler, delegationFn) {
+        if (typeof originalTypeEvent !== 'string' || !element) {
+          return;
+        }
+
+        var _normalizeParams2 = normalizeParams(originalTypeEvent, handler, delegationFn),
+            delegation = _normalizeParams2[0],
+            originalHandler = _normalizeParams2[1],
+            typeEvent = _normalizeParams2[2];
+
+        var inNamespace = typeEvent !== originalTypeEvent;
+        var events = getEvent(element);
+        var isNamespace = originalTypeEvent.startsWith('.');
+
+        if (typeof originalHandler !== 'undefined') {
+          // Simplest case: handler is passed, remove that listener ONLY.
+          if (!events || !events[typeEvent]) {
+            return;
+          }
+
+          removeHandler(element, events, typeEvent, originalHandler, delegation ? handler : null);
+          return;
+        }
+
+        if (isNamespace) {
+          Object.keys(events).forEach(function (elementEvent) {
+            removeNamespacedHandlers(element, events, elementEvent, originalTypeEvent.slice(1));
+          });
+        }
+
+        var storeElementEvent = events[typeEvent] || {};
+        Object.keys(storeElementEvent).forEach(function (keyHandlers) {
+          var handlerKey = keyHandlers.replace(stripUidRegex, '');
+
+          if (!inNamespace || originalTypeEvent.includes(handlerKey)) {
+            var event = storeElementEvent[keyHandlers];
+            removeHandler(element, events, typeEvent, event.originalHandler, event.delegationSelector);
+          }
+        });
+      },
+      trigger: function trigger(element, event, args) {
+        if (typeof event !== 'string' || !element) {
+          return null;
+        }
+
+        var $ = getjQuery();
+        var typeEvent = event.replace(stripNameRegex, '');
+        var inNamespace = event !== typeEvent;
+        var isNative = nativeEvents.has(typeEvent);
+        var jQueryEvent;
+        var bubbles = true;
+        var nativeDispatch = true;
+        var defaultPrevented = false;
+        var evt = null;
+
+        if (inNamespace && $) {
+          jQueryEvent = $.Event(event, args);
+          $(element).trigger(jQueryEvent);
+          bubbles = !jQueryEvent.isPropagationStopped();
+          nativeDispatch = !jQueryEvent.isImmediatePropagationStopped();
+          defaultPrevented = jQueryEvent.isDefaultPrevented();
+        }
+
+        if (isNative) {
+          evt = document.createEvent('HTMLEvents');
+          evt.initEvent(typeEvent, bubbles, true);
+        } else {
+          evt = new CustomEvent(event, {
+            bubbles: bubbles,
+            cancelable: true
+          });
+        } // merge custom information in our event
+
+
+        if (typeof args !== 'undefined') {
+          Object.keys(args).forEach(function (key) {
+            Object.defineProperty(evt, key, {
+              get: function get() {
+                return args[key];
+              }
+            });
+          });
+        }
+
+        if (defaultPrevented) {
+          evt.preventDefault();
+        }
+
+        if (nativeDispatch) {
+          element.dispatchEvent(evt);
+        }
+
+        if (evt.defaultPrevented && typeof jQueryEvent !== 'undefined') {
+          jQueryEvent.preventDefault();
+        }
+
+        return evt;
+      }
+    };
+
+    /**
+     * ------------------------------------------------------------------------
+     * Constants
+     * ------------------------------------------------------------------------
+     */
+
+    var VERSION = '5.0.0-beta1';
+
+    var BaseComponent = /*#__PURE__*/function () {
+      function BaseComponent(element) {
+        if (!element) {
+          return;
+        }
+
+        this._element = element;
+        Data.setData(element, this.constructor.DATA_KEY, this);
+      }
+
+      var _proto = BaseComponent.prototype;
+
+      _proto.dispose = function dispose() {
+        Data.removeData(this._element, this.constructor.DATA_KEY);
+        this._element = null;
+      }
+      /** Static */
+      ;
+
+      BaseComponent.getInstance = function getInstance(element) {
+        return Data.getData(element, this.DATA_KEY);
+      };
+
+      _createClass(BaseComponent, null, [{
+        key: "VERSION",
+        get: function get() {
+          return VERSION;
+        }
+      }]);
+
+      return BaseComponent;
+    }();
+
+    /**
+     * ------------------------------------------------------------------------
+     * Constants
+     * ------------------------------------------------------------------------
+     */
+
+    var NAME = 'alert';
+    var DATA_KEY = 'bs.alert';
+    var EVENT_KEY = "." + DATA_KEY;
+    var DATA_API_KEY = '.data-api';
+    var SELECTOR_DISMISS = '[data-bs-dismiss="alert"]';
+    var EVENT_CLOSE = "close" + EVENT_KEY;
+    var EVENT_CLOSED = "closed" + EVENT_KEY;
+    var EVENT_CLICK_DATA_API = "click" + EVENT_KEY + DATA_API_KEY;
+    var CLASSNAME_ALERT = 'alert';
+    var CLASSNAME_FADE = 'fade';
+    var CLASSNAME_SHOW = 'show';
+    /**
+     * ------------------------------------------------------------------------
+     * Class Definition
+     * ------------------------------------------------------------------------
+     */
+
+    var Alert = /*#__PURE__*/function (_BaseComponent) {
+      _inheritsLoose(Alert, _BaseComponent);
+
+      function Alert() {
+        return _BaseComponent.apply(this, arguments) || this;
+      }
+
+      var _proto = Alert.prototype;
+
+      // Public
+      _proto.close = function close(element) {
+        var rootElement = element ? this._getRootElement(element) : this._element;
+
+        var customEvent = this._triggerCloseEvent(rootElement);
+
+        if (customEvent === null || customEvent.defaultPrevented) {
+          return;
+        }
+
+        this._removeElement(rootElement);
+      } // Private
+      ;
+
+      _proto._getRootElement = function _getRootElement(element) {
+        return getElementFromSelector(element) || element.closest("." + CLASSNAME_ALERT);
+      };
+
+      _proto._triggerCloseEvent = function _triggerCloseEvent(element) {
+        return EventHandler.trigger(element, EVENT_CLOSE);
+      };
+
+      _proto._removeElement = function _removeElement(element) {
+        var _this = this;
+
+        element.classList.remove(CLASSNAME_SHOW);
+
+        if (!element.classList.contains(CLASSNAME_FADE)) {
+          this._destroyElement(element);
+
+          return;
+        }
+
+        var transitionDuration = getTransitionDurationFromElement(element);
+        EventHandler.one(element, TRANSITION_END, function () {
+          return _this._destroyElement(element);
+        });
+        emulateTransitionEnd(element, transitionDuration);
+      };
+
+      _proto._destroyElement = function _destroyElement(element) {
+        if (element.parentNode) {
+          element.parentNode.removeChild(element);
+        }
+
+        EventHandler.trigger(element, EVENT_CLOSED);
+      } // Static
+      ;
+
+      Alert.jQueryInterface = function jQueryInterface(config) {
+        return this.each(function () {
+          var data = Data.getData(this, DATA_KEY);
+
+          if (!data) {
+            data = new Alert(this);
+          }
+
+          if (config === 'close') {
+            data[config](this);
+          }
+        });
+      };
+
+      Alert.handleDismiss = function handleDismiss(alertInstance) {
+        return function (event) {
+          if (event) {
+            event.preventDefault();
+          }
+
+          alertInstance.close(this);
+        };
+      };
+
+      _createClass(Alert, null, [{
+        key: "DATA_KEY",
+        // Getters
+        get: function get() {
+          return DATA_KEY;
+        }
+      }]);
+
+      return Alert;
+    }(BaseComponent);
+    /**
+     * ------------------------------------------------------------------------
+     * Data Api implementation
+     * ------------------------------------------------------------------------
+     */
+
+
+    EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DISMISS, Alert.handleDismiss(new Alert()));
+    /**
+     * ------------------------------------------------------------------------
+     * jQuery
+     * ------------------------------------------------------------------------
+     * add .Alert to jQuery only if jQuery is present
+     */
+
+    onDOMContentLoaded(function () {
+      var $ = getjQuery();
+      /* istanbul ignore if */
+
+      if ($) {
+        var JQUERY_NO_CONFLICT = $.fn[NAME];
+        $.fn[NAME] = Alert.jQueryInterface;
+        $.fn[NAME].Constructor = Alert;
+
+        $.fn[NAME].noConflict = function () {
+          $.fn[NAME] = JQUERY_NO_CONFLICT;
+          return Alert.jQueryInterface;
+        };
+      }
+    });
+
+    /**
+     * ------------------------------------------------------------------------
+     * Constants
+     * ------------------------------------------------------------------------
+     */
+
+    var NAME$1 = 'button';
+    var DATA_KEY$1 = 'bs.button';
+    var EVENT_KEY$1 = "." + DATA_KEY$1;
+    var DATA_API_KEY$1 = '.data-api';
+    var CLASS_NAME_ACTIVE = 'active';
+    var SELECTOR_DATA_TOGGLE = '[data-bs-toggle="button"]';
+    var EVENT_CLICK_DATA_API$1 = "click" + EVENT_KEY$1 + DATA_API_KEY$1;
+    /**
+     * ------------------------------------------------------------------------
+     * Class Definition
+     * ------------------------------------------------------------------------
+     */
+
+    var Button = /*#__PURE__*/function (_BaseComponent) {
+      _inheritsLoose(Button, _BaseComponent);
+
+      function Button() {
+        return _BaseComponent.apply(this, arguments) || this;
+      }
+
+      var _proto = Button.prototype;
+
+      // Public
+      _proto.toggle = function toggle() {
+        // Toggle class and sync the `aria-pressed` attribute with the return value of the `.toggle()` method
+        this._element.setAttribute('aria-pressed', this._element.classList.toggle(CLASS_NAME_ACTIVE));
+      } // Static
+      ;
+
+      Button.jQueryInterface = function jQueryInterface(config) {
+        return this.each(function () {
+          var data = Data.getData(this, DATA_KEY$1);
+
+          if (!data) {
+            data = new Button(this);
+          }
+
+          if (config === 'toggle') {
+            data[config]();
+          }
+        });
+      };
+
+      _createClass(Button, null, [{
+        key: "DATA_KEY",
+        // Getters
+        get: function get() {
+          return DATA_KEY$1;
+        }
+      }]);
+
+      return Button;
+    }(BaseComponent);
+    /**
+     * ------------------------------------------------------------------------
+     * Data Api implementation
+     * ------------------------------------------------------------------------
+     */
+
+
+    EventHandler.on(document, EVENT_CLICK_DATA_API$1, SELECTOR_DATA_TOGGLE, function (event) {
+      event.preventDefault();
+      var button = event.target.closest(SELECTOR_DATA_TOGGLE);
+      var data = Data.getData(button, DATA_KEY$1);
+
+      if (!data) {
+        data = new Button(button);
+      }
+
+      data.toggle();
+    });
+    /**
+     * ------------------------------------------------------------------------
+     * jQuery
+     * ------------------------------------------------------------------------
+     * add .Button to jQuery only if jQuery is present
+     */
+
+    onDOMContentLoaded(function () {
+      var $ = getjQuery();
+      /* istanbul ignore if */
+
+      if ($) {
+        var JQUERY_NO_CONFLICT = $.fn[NAME$1];
+        $.fn[NAME$1] = Button.jQueryInterface;
+        $.fn[NAME$1].Constructor = Button;
+
+        $.fn[NAME$1].noConflict = function () {
+          $.fn[NAME$1] = JQUERY_NO_CONFLICT;
+          return Button.jQueryInterface;
+        };
+      }
+    });
+
+    /**
+     * --------------------------------------------------------------------------
+     * Bootstrap (v5.0.0-beta1): dom/manipulator.js
+     * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
+     * --------------------------------------------------------------------------
+     */
+    function normalizeData(val) {
+      if (val === 'true') {
+        return true;
+      }
+
+      if (val === 'false') {
+        return false;
+      }
+
+      if (val === Number(val).toString()) {
+        return Number(val);
+      }
+
+      if (val === '' || val === 'null') {
+        return null;
+      }
+
+      return val;
+    }
+
+    function normalizeDataKey(key) {
+      return key.replace(/[A-Z]/g, function (chr) {
+        return "-" + chr.toLowerCase();
+      });
+    }
+
+    var Manipulator = {
+      setDataAttribute: function setDataAttribute(element, key, value) {
+        element.setAttribute("data-bs-" + normalizeDataKey(key), value);
+      },
+      removeDataAttribute: function removeDataAttribute(element, key) {
+        element.removeAttribute("data-bs-" + normalizeDataKey(key));
+      },
+      getDataAttributes: function getDataAttributes(element) {
+        if (!element) {
+          return {};
+        }
+
+        var attributes = {};
+        Object.keys(element.dataset).filter(function (key) {
+          return key.startsWith('bs');
+        }).forEach(function (key) {
+          var pureKey = key.replace(/^bs/, '');
+          pureKey = pureKey.charAt(0).toLowerCase() + pureKey.slice(1, pureKey.length);
+          attributes[pureKey] = normalizeData(element.dataset[key]);
+        });
+        return attributes;
+      },
+      getDataAttribute: function getDataAttribute(element, key) {
+        return normalizeData(element.getAttribute("data-bs-" + normalizeDataKey(key)));
+      },
+      offset: function offset(element) {
+        var rect = element.getBoundingClientRect();
+        return {
+          top: rect.top + document.body.scrollTop,
+          left: rect.left + document.body.scrollLeft
+        };
+      },
+      position: function position(element) {
+        return {
+          top: element.offsetTop,
+          left: element.offsetLeft
+        };
+      }
+    };
+
+    /**
+     * --------------------------------------------------------------------------
+     * Bootstrap (v5.0.0-beta1): dom/selector-engine.js
+     * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
+     * --------------------------------------------------------------------------
+     */
+
+    /**
+     * ------------------------------------------------------------------------
+     * Constants
+     * ------------------------------------------------------------------------
+     */
+    var NODE_TEXT = 3;
+    var SelectorEngine = {
+      matches: function matches(element, selector) {
+        return element.matches(selector);
+      },
+      find: function find(selector, element) {
+        var _ref;
+
+        if (element === void 0) {
+          element = document.documentElement;
+        }
+
+        return (_ref = []).concat.apply(_ref, Element.prototype.querySelectorAll.call(element, selector));
+      },
+      findOne: function findOne(selector, element) {
+        if (element === void 0) {
+          element = document.documentElement;
+        }
+
+        return Element.prototype.querySelector.call(element, selector);
+      },
+      children: function children(element, selector) {
+        var _ref2;
+
+        var children = (_ref2 = []).concat.apply(_ref2, element.children);
+
+        return children.filter(function (child) {
+          return child.matches(selector);
+        });
+      },
+      parents: function parents(element, selector) {
+        var parents = [];
+        var ancestor = element.parentNode;
+
+        while (ancestor && ancestor.nodeType === Node.ELEMENT_NODE && ancestor.nodeType !== NODE_TEXT) {
+          if (this.matches(ancestor, selector)) {
+            parents.push(ancestor);
+          }
+
+          ancestor = ancestor.parentNode;
+        }
+
+        return parents;
+      },
+      prev: function prev(element, selector) {
+        var previous = element.previousElementSibling;
+
+        while (previous) {
+          if (previous.matches(selector)) {
+            return [previous];
+          }
+
+          previous = previous.previousElementSibling;
+        }
+
+        return [];
+      },
+      next: function next(element, selector) {
+        var next = element.nextElementSibling;
+
+        while (next) {
+          if (this.matches(next, selector)) {
+            return [next];
+          }
+
+          next = next.nextElementSibling;
+        }
+
+        return [];
+      }
+    };
+
+    /**
+     * ------------------------------------------------------------------------
+     * Constants
+     * ------------------------------------------------------------------------
+     */
+
+    var NAME$2 = 'carousel';
+    var DATA_KEY$2 = 'bs.carousel';
+    var EVENT_KEY$2 = "." + DATA_KEY$2;
+    var DATA_API_KEY$2 = '.data-api';
+    var ARROW_LEFT_KEY = 'ArrowLeft';
+    var ARROW_RIGHT_KEY = 'ArrowRight';
+    var TOUCHEVENT_COMPAT_WAIT = 500; // Time for mouse compat events to fire after touch
+
+    var SWIPE_THRESHOLD = 40;
+    var Default = {
+      interval: 5000,
+      keyboard: true,
+      slide: false,
+      pause: 'hover',
+      wrap: true,
+      touch: true
+    };
+    var DefaultType = {
+      interval: '(number|boolean)',
+      keyboard: 'boolean',
+      slide: '(boolean|string)',
+      pause: '(string|boolean)',
+      wrap: 'boolean',
+      touch: 'boolean'
+    };
+    var DIRECTION_NEXT = 'next';
+    var DIRECTION_PREV = 'prev';
+    var DIRECTION_LEFT = 'left';
+    var DIRECTION_RIGHT = 'right';
+    var EVENT_SLIDE = "slide" + EVENT_KEY$2;
+    var EVENT_SLID = "slid" + EVENT_KEY$2;
+    var EVENT_KEYDOWN = "keydown" + EVENT_KEY$2;
+    var EVENT_MOUSEENTER = "mouseenter" + EVENT_KEY$2;
+    var EVENT_MOUSELEAVE = "mouseleave" + EVENT_KEY$2;
+    var EVENT_TOUCHSTART = "touchstart" + EVENT_KEY$2;
+    var EVENT_TOUCHMOVE = "touchmove" + EVENT_KEY$2;
+    var EVENT_TOUCHEND = "touchend" + EVENT_KEY$2;
+    var EVENT_POINTERDOWN = "pointerdown" + EVENT_KEY$2;
+    var EVENT_POINTERUP = "pointerup" + EVENT_KEY$2;
+    var EVENT_DRAG_START = "dragstart" + EVENT_KEY$2;
+    var EVENT_LOAD_DATA_API = "load" + EVENT_KEY$2 + DATA_API_KEY$2;
+    var EVENT_CLICK_DATA_API$2 = "click" + EVENT_KEY$2 + DATA_API_KEY$2;
+    var CLASS_NAME_CAROUSEL = 'carousel';
+    var CLASS_NAME_ACTIVE$1 = 'active';
+    var CLASS_NAME_SLIDE = 'slide';
+    var CLASS_NAME_END = 'carousel-item-end';
+    var CLASS_NAME_START = 'carousel-item-start';
+    var CLASS_NAME_NEXT = 'carousel-item-next';
+    var CLASS_NAME_PREV = 'carousel-item-prev';
+    var CLASS_NAME_POINTER_EVENT = 'pointer-event';
+    var SELECTOR_ACTIVE = '.active';
+    var SELECTOR_ACTIVE_ITEM = '.active.carousel-item';
+    var SELECTOR_ITEM = '.carousel-item';
+    var SELECTOR_ITEM_IMG = '.carousel-item img';
+    var SELECTOR_NEXT_PREV = '.carousel-item-next, .carousel-item-prev';
+    var SELECTOR_INDICATORS = '.carousel-indicators';
+    var SELECTOR_DATA_SLIDE = '[data-bs-slide], [data-bs-slide-to]';
+    var SELECTOR_DATA_RIDE = '[data-bs-ride="carousel"]';
+    var PointerType = {
+      TOUCH: 'touch',
+      PEN: 'pen'
+    };
+    /**
+     * ------------------------------------------------------------------------
+     * Class Definition
+     * ------------------------------------------------------------------------
+     */
+
+    var Carousel = /*#__PURE__*/function (_BaseComponent) {
+      _inheritsLoose(Carousel, _BaseComponent);
+
+      function Carousel(element, config) {
+        var _this;
+
+        _this = _BaseComponent.call(this, element) || this;
+        _this._items = null;
+        _this._interval = null;
+        _this._activeElement = null;
+        _this._isPaused = false;
+        _this._isSliding = false;
+        _this.touchTimeout = null;
+        _this.touchStartX = 0;
+        _this.touchDeltaX = 0;
+        _this._config = _this._getConfig(config);
+        _this._indicatorsElement = SelectorEngine.findOne(SELECTOR_INDICATORS, _this._element);
+        _this._touchSupported = 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0;
+        _this._pointerEvent = Boolean(window.PointerEvent);
+
+        _this._addEventListeners();
+
+        return _this;
+      } // Getters
+
+
+      var _proto = Carousel.prototype;
+
+      // Public
+      _proto.next = function next() {
+        if (!this._isSliding) {
+          this._slide(DIRECTION_NEXT);
+        }
+      };
+
+      _proto.nextWhenVisible = function nextWhenVisible() {
+        // Don't call next when the page isn't visible
+        // or the carousel or its parent isn't visible
+        if (!document.hidden && isVisible(this._element)) {
+          this.next();
+        }
+      };
+
+      _proto.prev = function prev() {
+        if (!this._isSliding) {
+          this._slide(DIRECTION_PREV);
+        }
+      };
+
+      _proto.pause = function pause(event) {
+        if (!event) {
+          this._isPaused = true;
+        }
+
+        if (SelectorEngine.findOne(SELECTOR_NEXT_PREV, this._element)) {
+          triggerTransitionEnd(this._element);
+          this.cycle(true);
+        }
+
+        clearInterval(this._interval);
+        this._interval = null;
+      };
+
+      _proto.cycle = function cycle(event) {
+        if (!event) {
+          this._isPaused = false;
+        }
+
+        if (this._interval) {
+          clearInterval(this._interval);
+          this._interval = null;
+        }
+
+        if (this._config && this._config.interval && !this._isPaused) {
+          this._updateInterval();
+
+          this._interval = setInterval((document.visibilityState ? this.nextWhenVisible : this.next).bind(this), this._config.interval);
+        }
+      };
+
+      _proto.to = function to(index) {
+        var _this2 = this;
+
+        this._activeElement = SelectorEngine.findOne(SELECTOR_ACTIVE_ITEM, this._element);
+
+        var activeIndex = this._getItemIndex(this._activeElement);
+
+        if (index > this._items.length - 1 || index < 0) {
+          return;
+        }
+
+        if (this._isSliding) {
+          EventHandler.one(this._element, EVENT_SLID, function () {
+            return _this2.to(index);
+          });
+          return;
+        }
+
+        if (activeIndex === index) {
+          this.pause();
+          this.cycle();
+          return;
+        }
+
+        var direction = index > activeIndex ? DIRECTION_NEXT : DIRECTION_PREV;
+
+        this._slide(direction, this._items[index]);
+      };
+
+      _proto.dispose = function dispose() {
+        _BaseComponent.prototype.dispose.call(this);
+
+        EventHandler.off(this._element, EVENT_KEY$2);
+        this._items = null;
+        this._config = null;
+        this._interval = null;
+        this._isPaused = null;
+        this._isSliding = null;
+        this._activeElement = null;
+        this._indicatorsElement = null;
+      } // Private
+      ;
+
+      _proto._getConfig = function _getConfig(config) {
+        config = _extends({}, Default, config);
+        typeCheckConfig(NAME$2, config, DefaultType);
+        return config;
+      };
+
+      _proto._handleSwipe = function _handleSwipe() {
+        var absDeltax = Math.abs(this.touchDeltaX);
+
+        if (absDeltax <= SWIPE_THRESHOLD) {
+          return;
+        }
+
+        var direction = absDeltax / this.touchDeltaX;
+        this.touchDeltaX = 0; // swipe left
+
+        if (direction > 0) {
+          this.prev();
+        } // swipe right
+
+
+        if (direction < 0) {
+          this.next();
+        }
+      };
+
+      _proto._addEventListeners = function _addEventListeners() {
+        var _this3 = this;
+
+        if (this._config.keyboard) {
+          EventHandler.on(this._element, EVENT_KEYDOWN, function (event) {
+            return _this3._keydown(event);
+          });
+        }
+
+        if (this._config.pause === 'hover') {
+          EventHandler.on(this._element, EVENT_MOUSEENTER, function (event) {
+            return _this3.pause(event);
+          });
+          EventHandler.on(this._element, EVENT_MOUSELEAVE, function (event) {
+            return _this3.cycle(event);
+          });
+        }
+
+        if (this._config.touch && this._touchSupported) {
+          this._addTouchEventListeners();
+        }
+      };
+
+      _proto._addTouchEventListeners = function _addTouchEventListeners() {
+        var _this4 = this;
+
+        var start = function start(event) {
+          if (_this4._pointerEvent && PointerType[event.pointerType.toUpperCase()]) {
+            _this4.touchStartX = event.clientX;
+          } else if (!_this4._pointerEvent) {
+            _this4.touchStartX = event.touches[0].clientX;
+          }
+        };
+
+        var move = function move(event) {
+          // ensure swiping with one touch and not pinching
+          if (event.touches && event.touches.length > 1) {
+            _this4.touchDeltaX = 0;
+          } else {
+            _this4.touchDeltaX = event.touches[0].clientX - _this4.touchStartX;
+          }
+        };
+
+        var end = function end(event) {
+          if (_this4._pointerEvent && PointerType[event.pointerType.toUpperCase()]) {
+            _this4.touchDeltaX = event.clientX - _this4.touchStartX;
+          }
+
+          _this4._handleSwipe();
+
+          if (_this4._config.pause === 'hover') {
+            // If it's a touch-enabled device, mouseenter/leave are fired as
+            // part of the mouse compatibility events on first tap - the carousel
+            // would stop cycling until user tapped out of it;
+            // here, we listen for touchend, explicitly pause the carousel
+            // (as if it's the second time we tap on it, mouseenter compat event
+            // is NOT fired) and after a timeout (to allow for mouse compatibility
+            // events to fire) we explicitly restart cycling
+            _this4.pause();
+
+            if (_this4.touchTimeout) {
+              clearTimeout(_this4.touchTimeout);
+            }
+
+            _this4.touchTimeout = setTimeout(function (event) {
+              return _this4.cycle(event);
+            }, TOUCHEVENT_COMPAT_WAIT + _this4._config.interval);
+          }
+        };
+
+        SelectorEngine.find(SELECTOR_ITEM_IMG, this._element).forEach(function (itemImg) {
+          EventHandler.on(itemImg, EVENT_DRAG_START, function (e) {
+            return e.preventDefault();
+          });
+        });
+
+        if (this._pointerEvent) {
+          EventHandler.on(this._element, EVENT_POINTERDOWN, function (event) {
+            return start(event);
+          });
+          EventHandler.on(this._element, EVENT_POINTERUP, function (event) {
+            return end(event);
+          });
+
+          this._element.classList.add(CLASS_NAME_POINTER_EVENT);
+        } else {
+          EventHandler.on(this._element, EVENT_TOUCHSTART, function (event) {
+            return start(event);
+          });
+          EventHandler.on(this._element, EVENT_TOUCHMOVE, function (event) {
+            return move(event);
+          });
+          EventHandler.on(this._element, EVENT_TOUCHEND, function (event) {
+            return end(event);
+          });
+        }
+      };
+
+      _proto._keydown = function _keydown(event) {
+        if (/input|textarea/i.test(event.target.tagName)) {
+          return;
+        }
+
+        switch (event.key) {
+          case ARROW_LEFT_KEY:
+            event.preventDefault();
+            this.prev();
+            break;
+
+          case ARROW_RIGHT_KEY:
+            event.preventDefault();
+            this.next();
+            break;
+        }
+      };
+
+      _proto._getItemIndex = function _getItemIndex(element) {
+        this._items = element && element.parentNode ? SelectorEngine.find(SELECTOR_ITEM, element.parentNode) : [];
+        return this._items.indexOf(element);
+      };
+
+      _proto._getItemByDirection = function _getItemByDirection(direction, activeElement) {
+        var isNextDirection = direction === DIRECTION_NEXT;
+        var isPrevDirection = direction === DIRECTION_PREV;
+
+        var activeIndex = this._getItemIndex(activeElement);
+
+        var lastItemIndex = this._items.length - 1;
+        var isGoingToWrap = isPrevDirection && activeIndex === 0 || isNextDirection && activeIndex === lastItemIndex;
+
+        if (isGoingToWrap && !this._config.wrap) {
+          return activeElement;
+        }
+
+        var delta = direction === DIRECTION_PREV ? -1 : 1;
+        var itemIndex = (activeIndex + delta) % this._items.length;
+        return itemIndex === -1 ? this._items[this._items.length - 1] : this._items[itemIndex];
+      };
+
+      _proto._triggerSlideEvent = function _triggerSlideEvent(relatedTarget, eventDirectionName) {
+        var targetIndex = this._getItemIndex(relatedTarget);
+
+        var fromIndex = this._getItemIndex(SelectorEngine.findOne(SELECTOR_ACTIVE_ITEM, this._element));
+
+        return EventHandler.trigger(this._element, EVENT_SLIDE, {
+          relatedTarget: relatedTarget,
+          direction: eventDirectionName,
+          from: fromIndex,
+          to: targetIndex
+        });
+      };
+
+      _proto._setActiveIndicatorElement = function _setActiveIndicatorElement(element) {
+        if (this._indicatorsElement) {
+          var indicators = SelectorEngine.find(SELECTOR_ACTIVE, this._indicatorsElement);
+
+          for (var i = 0; i < indicators.length; i++) {
+            indicators[i].classList.remove(CLASS_NAME_ACTIVE$1);
+          }
+
+          var nextIndicator = this._indicatorsElement.children[this._getItemIndex(element)];
+
+          if (nextIndicator) {
+            nextIndicator.classList.add(CLASS_NAME_ACTIVE$1);
+          }
+        }
+      };
+
+      _proto._updateInterval = function _updateInterval() {
+        var element = this._activeElement || SelectorEngine.findOne(SELECTOR_ACTIVE_ITEM, this._element);
+
+        if (!element) {
+          return;
+        }
+
+        var elementInterval = Number.parseInt(element.getAttribute('data-bs-interval'), 10);
+
+        if (elementInterval) {
+          this._config.defaultInterval = this._config.defaultInterval || this._config.interval;
+          this._config.interval = elementInterval;
+        } else {
+          this._config.interval = this._config.defaultInterval || this._config.interval;
+        }
+      };
+
+      _proto._slide = function _slide(direction, element) {
+        var _this5 = this;
+
+        var activeElement = SelectorEngine.findOne(SELECTOR_ACTIVE_ITEM, this._element);
+
+        var activeElementIndex = this._getItemIndex(activeElement);
+
+        var nextElement = element || activeElement && this._getItemByDirection(direction, activeElement);
+
+        var nextElementIndex = this._getItemIndex(nextElement);
+
+        var isCycling = Boolean(this._interval);
+        var directionalClassName;
+        var orderClassName;
+        var eventDirectionName;
+
+        if (direction === DIRECTION_NEXT) {
+          directionalClassName = CLASS_NAME_START;
+          orderClassName = CLASS_NAME_NEXT;
+          eventDirectionName = DIRECTION_LEFT;
+        } else {
+          directionalClassName = CLASS_NAME_END;
+          orderClassName = CLASS_NAME_PREV;
+          eventDirectionName = DIRECTION_RIGHT;
+        }
+
+        if (nextElement && nextElement.classList.contains(CLASS_NAME_ACTIVE$1)) {
+          this._isSliding = false;
+          return;
+        }
+
+        var slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName);
+
+        if (slideEvent.defaultPrevented) {
+          return;
+        }
+
+        if (!activeElement || !nextElement) {
+          // Some weirdness is happening, so we bail
+          return;
+        }
+
+        this._isSliding = true;
+
+        if (isCycling) {
+          this.pause();
+        }
+
+        this._setActiveIndicatorElement(nextElement);
+
+        this._activeElement = nextElement;
+
+        if (this._element.classList.contains(CLASS_NAME_SLIDE)) {
+          nextElement.classList.add(orderClassName);
+          reflow(nextElement);
+          activeElement.classList.add(directionalClassName);
+          nextElement.classList.add(directionalClassName);
+          var transitionDuration = getTransitionDurationFromElement(activeElement);
+          EventHandler.one(activeElement, TRANSITION_END, function () {
+            nextElement.classList.remove(directionalClassName, orderClassName);
+            nextElement.classList.add(CLASS_NAME_ACTIVE$1);
+            activeElement.classList.remove(CLASS_NAME_ACTIVE$1, orderClassName, directionalClassName);
+            _this5._isSliding = false;
+            setTimeout(function () {
+              EventHandler.trigger(_this5._element, EVENT_SLID, {
+                relatedTarget: nextElement,
+                direction: eventDirectionName,
+                from: activeElementIndex,
+                to: nextElementIndex
+              });
+            }, 0);
+          });
+          emulateTransitionEnd(activeElement, transitionDuration);
+        } else {
+          activeElement.classList.remove(CLASS_NAME_ACTIVE$1);
+          nextElement.classList.add(CLASS_NAME_ACTIVE$1);
+          this._isSliding = false;
+          EventHandler.trigger(this._element, EVENT_SLID, {
+            relatedTarget: nextElement,
+            direction: eventDirectionName,
+            from: activeElementIndex,
+            to: nextElementIndex
+          });
+        }
+
+        if (isCycling) {
+          this.cycle();
+        }
+      } // Static
+      ;
+
+      Carousel.carouselInterface = function carouselInterface(element, config) {
+        var data = Data.getData(element, DATA_KEY$2);
+
+        var _config = _extends({}, Default, Manipulator.getDataAttributes(element));
+
+        if (typeof config === 'object') {
+          _config = _extends({}, _config, config);
+        }
+
+        var action = typeof config === 'string' ? config : _config.slide;
+
+        if (!data) {
+          data = new Carousel(element, _config);
+        }
+
+        if (typeof config === 'number') {
+          data.to(config);
+        } else if (typeof action === 'string') {
+          if (typeof data[action] === 'undefined') {
+            throw new TypeError("No method named \"" + action + "\"");
+          }
+
+          data[action]();
+        } else if (_config.interval && _config.ride) {
+          data.pause();
+          data.cycle();
+        }
+      };
+
+      Carousel.jQueryInterface = function jQueryInterface(config) {
+        return this.each(function () {
+          Carousel.carouselInterface(this, config);
+        });
+      };
+
+      Carousel.dataApiClickHandler = function dataApiClickHandler(event) {
+        var target = getElementFromSelector(this);
+
+        if (!target || !target.classList.contains(CLASS_NAME_CAROUSEL)) {
+          return;
+        }
+
+        var config = _extends({}, Manipulator.getDataAttributes(target), Manipulator.getDataAttributes(this));
+
+        var slideIndex = this.getAttribute('data-bs-slide-to');
+
+        if (slideIndex) {
+          config.interval = false;
+        }
+
+        Carousel.carouselInterface(target, config);
+
+        if (slideIndex) {
+          Data.getData(target, DATA_KEY$2).to(slideIndex);
+        }
+
+        event.preventDefault();
+      };
+
+      _createClass(Carousel, null, [{
+        key: "Default",
+        get: function get() {
+          return Default;
+        }
+      }, {
+        key: "DATA_KEY",
+        get: function get() {
+          return DATA_KEY$2;
+        }
+      }]);
+
+      return Carousel;
+    }(BaseComponent);
+    /**
+     * ------------------------------------------------------------------------
+     * Data Api implementation
+     * ------------------------------------------------------------------------
+     */
+
+
+    EventHandler.on(document, EVENT_CLICK_DATA_API$2, SELECTOR_DATA_SLIDE, Carousel.dataApiClickHandler);
+    EventHandler.on(window, EVENT_LOAD_DATA_API, function () {
+      var carousels = SelectorEngine.find(SELECTOR_DATA_RIDE);
+
+      for (var i = 0, len = carousels.length; i < len; i++) {
+        Carousel.carouselInterface(carousels[i], Data.getData(carousels[i], DATA_KEY$2));
+      }
+    });
+    /**
+     * ------------------------------------------------------------------------
+     * jQuery
+     * ------------------------------------------------------------------------
+     * add .Carousel to jQuery only if jQuery is present
+     */
+
+    onDOMContentLoaded(function () {
+      var $ = getjQuery();
+      /* istanbul ignore if */
+
+      if ($) {
+        var JQUERY_NO_CONFLICT = $.fn[NAME$2];
+        $.fn[NAME$2] = Carousel.jQueryInterface;
+        $.fn[NAME$2].Constructor = Carousel;
+
+        $.fn[NAME$2].noConflict = function () {
+          $.fn[NAME$2] = JQUERY_NO_CONFLICT;
+          return Carousel.jQueryInterface;
+        };
+      }
+    });
+
+    /**
+     * ------------------------------------------------------------------------
+     * Constants
+     * ------------------------------------------------------------------------
+     */
+
+    var NAME$3 = 'collapse';
+    var DATA_KEY$3 = 'bs.collapse';
+    var EVENT_KEY$3 = "." + DATA_KEY$3;
+    var DATA_API_KEY$3 = '.data-api';
+    var Default$1 = {
+      toggle: true,
+      parent: ''
+    };
+    var DefaultType$1 = {
+      toggle: 'boolean',
+      parent: '(string|element)'
+    };
+    var EVENT_SHOW = "show" + EVENT_KEY$3;
+    var EVENT_SHOWN = "shown" + EVENT_KEY$3;
+    var EVENT_HIDE = "hide" + EVENT_KEY$3;
+    var EVENT_HIDDEN = "hidden" + EVENT_KEY$3;
+    var EVENT_CLICK_DATA_API$3 = "click" + EVENT_KEY$3 + DATA_API_KEY$3;
+    var CLASS_NAME_SHOW = 'show';
+    var CLASS_NAME_COLLAPSE = 'collapse';
+    var CLASS_NAME_COLLAPSING = 'collapsing';
+    var CLASS_NAME_COLLAPSED = 'collapsed';
+    var WIDTH = 'width';
+    var HEIGHT = 'height';
+    var SELECTOR_ACTIVES = '.show, .collapsing';
+    var SELECTOR_DATA_TOGGLE$1 = '[data-bs-toggle="collapse"]';
+    /**
+     * ------------------------------------------------------------------------
+     * Class Definition
+     * ------------------------------------------------------------------------
+     */
+
+    var Collapse = /*#__PURE__*/function (_BaseComponent) {
+      _inheritsLoose(Collapse, _BaseComponent);
+
+      function Collapse(element, config) {
+        var _this;
+
+        _this = _BaseComponent.call(this, element) || this;
+        _this._isTransitioning = false;
+        _this._config = _this._getConfig(config);
+        _this._triggerArray = SelectorEngine.find(SELECTOR_DATA_TOGGLE$1 + "[href=\"#" + element.id + "\"]," + (SELECTOR_DATA_TOGGLE$1 + "[data-bs-target=\"#" + element.id + "\"]"));
+        var toggleList = SelectorEngine.find(SELECTOR_DATA_TOGGLE$1);
+
+        for (var i = 0, len = toggleList.length; i < len; i++) {
+          var elem = toggleList[i];
+          var selector = getSelectorFromElement(elem);
+          var filterElement = SelectorEngine.find(selector).filter(function (foundElem) {
+            return foundElem === element;
+          });
+
+          if (selector !== null && filterElement.length) {
+            _this._selector = selector;
+
+            _this._triggerArray.push(elem);
+          }
+        }
+
+        _this._parent = _this._config.parent ? _this._getParent() : null;
+
+        if (!_this._config.parent) {
+          _this._addAriaAndCollapsedClass(_this._element, _this._triggerArray);
+        }
+
+        if (_this._config.toggle) {
+          _this.toggle();
         }
-        set previous(value) {
-            this._previous = value;
+
+        return _this;
+      } // Getters
+
+
+      var _proto = Collapse.prototype;
+
+      // Public
+      _proto.toggle = function toggle() {
+        if (this._element.classList.contains(CLASS_NAME_SHOW)) {
+          this.hide();
+        } else {
+          this.show();
         }
-        get next() {
-            return this._next;
+      };
+
+      _proto.show = function show() {
+        var _this2 = this;
+
+        if (this._isTransitioning || this._element.classList.contains(CLASS_NAME_SHOW)) {
+          return;
         }
-        set next(value) {
-            this._next = value;
+
+        var actives;
+        var activesData;
+
+        if (this._parent) {
+          actives = SelectorEngine.find(SELECTOR_ACTIVES, this._parent).filter(function (elem) {
+            if (typeof _this2._config.parent === 'string') {
+              return elem.getAttribute('data-bs-parent') === _this2._config.parent;
+            }
+
+            return elem.classList.contains(CLASS_NAME_COLLAPSE);
+          });
+
+          if (actives.length === 0) {
+            actives = null;
+          }
         }
-        get parent() {
-            return this._parent;
+
+        var container = SelectorEngine.findOne(this._selector);
+
+        if (actives) {
+          var tempActiveData = actives.find(function (elem) {
+            return container !== elem;
+          });
+          activesData = tempActiveData ? Data.getData(tempActiveData, DATA_KEY$3) : null;
+
+          if (activesData && activesData._isTransitioning) {
+            return;
+          }
         }
-        set parent(value) {
-            this._parent = value;
+
+        var startEvent = EventHandler.trigger(this._element, EVENT_SHOW);
+
+        if (startEvent.defaultPrevented) {
+          return;
         }
-        get children() {
-            return this._children;
+
+        if (actives) {
+          actives.forEach(function (elemActive) {
+            if (container !== elemActive) {
+              Collapse.collapseInterface(elemActive, 'hide');
+            }
+
+            if (!activesData) {
+              Data.setData(elemActive, DATA_KEY$3, null);
+            }
+          });
         }
-        set children(value) {
-            this._children = value;
+
+        var dimension = this._getDimension();
+
+        this._element.classList.remove(CLASS_NAME_COLLAPSE);
+
+        this._element.classList.add(CLASS_NAME_COLLAPSING);
+
+        this._element.style[dimension] = 0;
+
+        if (this._triggerArray.length) {
+          this._triggerArray.forEach(function (element) {
+            element.classList.remove(CLASS_NAME_COLLAPSED);
+            element.setAttribute('aria-expanded', true);
+          });
         }
-        get active() {
-            return this._active;
+
+        this.setTransitioning(true);
+
+        var complete = function complete() {
+          _this2._element.classList.remove(CLASS_NAME_COLLAPSING);
+
+          _this2._element.classList.add(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW);
+
+          _this2._element.style[dimension] = '';
+
+          _this2.setTransitioning(false);
+
+          EventHandler.trigger(_this2._element, EVENT_SHOWN);
+        };
+
+        var capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1);
+        var scrollSize = "scroll" + capitalizedDimension;
+        var transitionDuration = getTransitionDurationFromElement(this._element);
+        EventHandler.one(this._element, TRANSITION_END, complete);
+        emulateTransitionEnd(this._element, transitionDuration);
+        this._element.style[dimension] = this._element[scrollSize] + "px";
+      };
+
+      _proto.hide = function hide() {
+        var _this3 = this;
+
+        if (this._isTransitioning || !this._element.classList.contains(CLASS_NAME_SHOW)) {
+          return;
         }
-        set active(value) {
-            this._active = value;
+
+        var startEvent = EventHandler.trigger(this._element, EVENT_HIDE);
+
+        if (startEvent.defaultPrevented) {
+          return;
         }
-        focus() {
-            var _a, _b;
-            (_a = this.previous) === null || _a === void 0 ? void 0 : _a.clear();
-            (_b = this.next) === null || _b === void 0 ? void 0 : _b.clear();
-            if (this.parent) {
-                this.parent.active = false;
-                this.parent._baseElement.classList.add("tobago-dropdown-open");
-            }
-            for (const child of this.children) {
-                child.clear();
+
+        var dimension = this._getDimension();
+
+        this._element.style[dimension] = this._element.getBoundingClientRect()[dimension] + "px";
+        reflow(this._element);
+
+        this._element.classList.add(CLASS_NAME_COLLAPSING);
+
+        this._element.classList.remove(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW);
+
+        var triggerArrayLength = this._triggerArray.length;
+
+        if (triggerArrayLength > 0) {
+          for (var i = 0; i < triggerArrayLength; i++) {
+            var trigger = this._triggerArray[i];
+            var elem = getElementFromSelector(trigger);
+
+            if (elem && !elem.classList.contains(CLASS_NAME_SHOW)) {
+              trigger.classList.add(CLASS_NAME_COLLAPSED);
+              trigger.setAttribute('aria-expanded', false);
             }
-            this._baseElement.classList.remove("tobago-dropdown-open");
-            this._baseElement.classList.add("tobago-dropdown-selected");
-            this.active = true;
-            this.focusElement.focus();
-        }
-        clear() {
-            this._baseElement.classList.remove("tobago-dropdown-open");
-            this._baseElement.classList.remove("tobago-dropdown-selected");
-            this.active = false;
+          }
         }
-    }
-    document.addEventListener("tobago.init", function (event) {
-        if (window.customElements.get("tobago-dropdown") == null) {
-            window.customElements.define("tobago-dropdown", Dropdown);
+
+        this.setTransitioning(true);
+
+        var complete = function complete() {
+          _this3.setTransitioning(false);
+
+          _this3._element.classList.remove(CLASS_NAME_COLLAPSING);
+
+          _this3._element.classList.add(CLASS_NAME_COLLAPSE);
+
+          EventHandler.trigger(_this3._element, EVENT_HIDDEN);
+        };
+
+        this._element.style[dimension] = '';
+        var transitionDuration = getTransitionDurationFromElement(this._element);
+        EventHandler.one(this._element, TRANSITION_END, complete);
+        emulateTransitionEnd(this._element, transitionDuration);
+      };
+
+      _proto.setTransitioning = function setTransitioning(isTransitioning) {
+        this._isTransitioning = isTransitioning;
+      };
+
+      _proto.dispose = function dispose() {
+        _BaseComponent.prototype.dispose.call(this);
+
+        this._config = null;
+        this._parent = null;
+        this._triggerArray = null;
+        this._isTransitioning = null;
+      } // Private
+      ;
+
+      _proto._getConfig = function _getConfig(config) {
+        config = _extends({}, Default$1, config);
+        config.toggle = Boolean(config.toggle); // Coerce string values
+
+        typeCheckConfig(NAME$3, config, DefaultType$1);
+        return config;
+      };
+
+      _proto._getDimension = function _getDimension() {
+        return this._element.classList.contains(WIDTH) ? WIDTH : HEIGHT;
+      };
+
+      _proto._getParent = function _getParent() {
+        var _this4 = this;
+
+        var parent = this._config.parent;
+
+        if (isElement$1(parent)) {
+          // it's a jQuery object
+          if (typeof parent.jquery !== 'undefined' || typeof parent[0] !== 'undefined') {
+            parent = parent[0];
+          }
+        } else {
+          parent = SelectorEngine.findOne(parent);
         }
-    });
 
-    function hasProperty(obj, prop) {
-      return Object.prototype.hasOwnProperty.call(obj, prop);
-    }
+        var selector = SELECTOR_DATA_TOGGLE$1 + "[data-bs-parent=\"" + parent + "\"]";
+        SelectorEngine.find(selector, parent).forEach(function (element) {
+          var selected = getElementFromSelector(element);
 
-    function lastItemOf(arr) {
-      return arr[arr.length - 1];
-    }
+          _this4._addAriaAndCollapsedClass(selected, [element]);
+        });
+        return parent;
+      };
 
-    // push only the items not included in the array
-    function pushUnique(arr, ...items) {
-      items.forEach((item) => {
-        if (arr.includes(item)) {
+      _proto._addAriaAndCollapsedClass = function _addAriaAndCollapsedClass(element, triggerArray) {
+        if (!element || !triggerArray.length) {
           return;
         }
-        arr.push(item);
-      });
-      return arr;
-    }
 
-    function stringToArray(str, separator) {
-      // convert empty string to an empty array
-      return str ? str.split(separator) : [];
-    }
+        var isOpen = element.classList.contains(CLASS_NAME_SHOW);
+        triggerArray.forEach(function (elem) {
+          if (isOpen) {
+            elem.classList.remove(CLASS_NAME_COLLAPSED);
+          } else {
+            elem.classList.add(CLASS_NAME_COLLAPSED);
+          }
 
-    function isInRange(testVal, min, max) {
-      const minOK = min === undefined || testVal >= min;
-      const maxOK = max === undefined || testVal <= max;
-      return minOK && maxOK;
-    }
+          elem.setAttribute('aria-expanded', isOpen);
+        });
+      } // Static
+      ;
 
-    function limitToRange(val, min, max) {
-      if (val < min) {
-        return min;
-      }
-      if (val > max) {
-        return max;
-      }
-      return val;
-    }
+      Collapse.collapseInterface = function collapseInterface(element, config) {
+        var data = Data.getData(element, DATA_KEY$3);
 
-    function createTagRepeat(tagName, repeat, attributes = {}, index = 0, html = '') {
-      const openTagSrc = Object.keys(attributes).reduce((src, attr) => {
-        let val = attributes[attr];
-        if (typeof val === 'function') {
-          val = val(index);
+        var _config = _extends({}, Default$1, Manipulator.getDataAttributes(element), typeof config === 'object' && config ? config : {});
+
+        if (!data && _config.toggle && typeof config === 'string' && /show|hide/.test(config)) {
+          _config.toggle = false;
         }
-        return `${src} ${attr}="${val}"`;
-      }, tagName);
-      html += `<${openTagSrc}></${tagName}>`;
 
-      const next = index + 1;
-      return next < repeat
-        ? createTagRepeat(tagName, repeat, attributes, next, html)
-        : html;
-    }
+        if (!data) {
+          data = new Collapse(element, _config);
+        }
 
-    // Remove the spacing surrounding tags for HTML parser not to create text nodes
-    // before/after elements
-    function optimizeTemplateHTML(html) {
-      return html.replace(/>\s+/g, '>').replace(/\s+</, '<');
-    }
+        if (typeof config === 'string') {
+          if (typeof data[config] === 'undefined') {
+            throw new TypeError("No method named \"" + config + "\"");
+          }
 
-    function stripTime(timeValue) {
-      return new Date(timeValue).setHours(0, 0, 0, 0);
-    }
+          data[config]();
+        }
+      };
 
-    function today() {
-      return new Date().setHours(0, 0, 0, 0);
-    }
+      Collapse.jQueryInterface = function jQueryInterface(config) {
+        return this.each(function () {
+          Collapse.collapseInterface(this, config);
+        });
+      };
 
-    // Get the time value of the start of given date or year, month and day
-    function dateValue(...args) {
-      switch (args.length) {
-        case 0:
-          return today();
-        case 1:
-          return stripTime(args[0]);
+      _createClass(Collapse, null, [{
+        key: "Default",
+        get: function get() {
+          return Default$1;
+        }
+      }, {
+        key: "DATA_KEY",
+        get: function get() {
+          return DATA_KEY$3;
+        }
+      }]);
+
+      return Collapse;
+    }(BaseComponent);
+    /**
+     * ------------------------------------------------------------------------
+     * Data Api implementation
+     * ------------------------------------------------------------------------
+     */
+
+
+    EventHandler.on(document, EVENT_CLICK_DATA_API$3, SELECTOR_DATA_TOGGLE$1, function (event) {
+      // preventDefault only for <a> elements (which change the URL) not inside the collapsible element
+      if (event.target.tagName === 'A') {
+        event.preventDefault();
       }
 
-      // use setFullYear() to keep 2-digit year from being mapped to 1900-1999
-      const newDate = new Date(0);
-      newDate.setFullYear(...args);
-      return newDate.setHours(0, 0, 0, 0);
-    }
+      var triggerData = Manipulator.getDataAttributes(this);
+      var selector = getSelectorFromElement(this);
+      var selectorElements = SelectorEngine.find(selector);
+      selectorElements.forEach(function (element) {
+        var data = Data.getData(element, DATA_KEY$3);
+        var config;
 
-    function addDays(date, amount) {
-      const newDate = new Date(date);
-      return newDate.setDate(newDate.getDate() + amount);
-    }
+        if (data) {
+          // update parent attribute
+          if (data._parent === null && typeof triggerData.parent === 'string') {
+            data._config.parent = triggerData.parent;
+            data._parent = data._getParent();
+          }
 
-    function addWeeks(date, amount) {
-      return addDays(date, amount * 7);
-    }
+          config = 'toggle';
+        } else {
+          config = triggerData;
+        }
 
-    function addMonths(date, amount) {
-      // If the day of the date is not in the new month, the last day of the new
-      // month will be returned. e.g. Jan 31 + 1 month → Feb 28 (not Mar 03)
-      const newDate = new Date(date);
-      const monthsToSet = newDate.getMonth() + amount;
-      let expectedMonth = monthsToSet % 12;
-      if (expectedMonth < 0) {
-        expectedMonth += 12;
+        Collapse.collapseInterface(element, config);
+      });
+    });
+    /**
+     * ------------------------------------------------------------------------
+     * jQuery
+     * ------------------------------------------------------------------------
+     * add .Collapse to jQuery only if jQuery is present
+     */
+
+    onDOMContentLoaded(function () {
+      var $ = getjQuery();
+      /* istanbul ignore if */
+
+      if ($) {
+        var JQUERY_NO_CONFLICT = $.fn[NAME$3];
+        $.fn[NAME$3] = Collapse.jQueryInterface;
+        $.fn[NAME$3].Constructor = Collapse;
+
+        $.fn[NAME$3].noConflict = function () {
+          $.fn[NAME$3] = JQUERY_NO_CONFLICT;
+          return Collapse.jQueryInterface;
+        };
       }
+    });
 
-      const time = newDate.setMonth(monthsToSet);
-      return newDate.getMonth() !== expectedMonth ? newDate.setDate(0) : time;
-    }
+    /**
+     * ------------------------------------------------------------------------
+     * Constants
+     * ------------------------------------------------------------------------
+     */
+
+    var NAME$4 = 'dropdown';
+    var DATA_KEY$4 = 'bs.dropdown';
+    var EVENT_KEY$4 = "." + DATA_KEY$4;
+    var DATA_API_KEY$4 = '.data-api';
+    var ESCAPE_KEY = 'Escape';
+    var SPACE_KEY = 'Space';
+    var TAB_KEY = 'Tab';
+    var ARROW_UP_KEY = 'ArrowUp';
+    var ARROW_DOWN_KEY = 'ArrowDown';
+    var RIGHT_MOUSE_BUTTON = 2; // MouseEvent.button value for the secondary button, usually the right button
+
+    var REGEXP_KEYDOWN = new RegExp(ARROW_UP_KEY + "|" + ARROW_DOWN_KEY + "|" + ESCAPE_KEY);
+    var EVENT_HIDE$1 = "hide" + EVENT_KEY$4;
+    var EVENT_HIDDEN$1 = "hidden" + EVENT_KEY$4;
+    var EVENT_SHOW$1 = "show" + EVENT_KEY$4;
+    var EVENT_SHOWN$1 = "shown" + EVENT_KEY$4;
+    var EVENT_CLICK = "click" + EVENT_KEY$4;
+    var EVENT_CLICK_DATA_API$4 = "click" + EVENT_KEY$4 + DATA_API_KEY$4;
+    var EVENT_KEYDOWN_DATA_API = "keydown" + EVENT_KEY$4 + DATA_API_KEY$4;
+    var EVENT_KEYUP_DATA_API = "keyup" + EVENT_KEY$4 + DATA_API_KEY$4;
+    var CLASS_NAME_DISABLED = 'disabled';
+    var CLASS_NAME_SHOW$1 = 'show';
+    var CLASS_NAME_DROPUP = 'dropup';
+    var CLASS_NAME_DROPEND = 'dropend';
+    var CLASS_NAME_DROPSTART = 'dropstart';
+    var CLASS_NAME_NAVBAR = 'navbar';
+    var SELECTOR_DATA_TOGGLE$2 = '[data-bs-toggle="dropdown"]';
+    var SELECTOR_FORM_CHILD = '.dropdown form';
+    var SELECTOR_MENU = '.dropdown-menu';
+    var SELECTOR_NAVBAR_NAV = '.navbar-nav';
+    var SELECTOR_VISIBLE_ITEMS = '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)';
+    var PLACEMENT_TOP = isRTL ? 'top-end' : 'top-start';
+    var PLACEMENT_TOPEND = isRTL ? 'top-start' : 'top-end';
+    var PLACEMENT_BOTTOM = isRTL ? 'bottom-end' : 'bottom-start';
+    var PLACEMENT_BOTTOMEND = isRTL ? 'bottom-start' : 'bottom-end';
+    var PLACEMENT_RIGHT = isRTL ? 'left-start' : 'right-start';
+    var PLACEMENT_LEFT = isRTL ? 'right-start' : 'left-start';
+    var Default$2 = {
+      offset: 0,
+      flip: true,
+      boundary: 'clippingParents',
+      reference: 'toggle',
+      display: 'dynamic',
+      popperConfig: null
+    };
+    var DefaultType$2 = {
+      offset: '(number|string|function)',
+      flip: 'boolean',
+      boundary: '(string|element)',
+      reference: '(string|element)',
+      display: 'string',
+      popperConfig: '(null|object)'
+    };
+    /**
+     * ------------------------------------------------------------------------
+     * Class Definition
+     * ------------------------------------------------------------------------
+     */
+
+    var Dropdown$1 = /*#__PURE__*/function (_BaseComponent) {
+      _inheritsLoose(Dropdown, _BaseComponent);
+
+      function Dropdown(element, config) {
+        var _this;
 
-    function addYears(date, amount) {
-      // If the date is Feb 29 and the new year is not a leap year, Feb 28 of the
-      // new year will be returned.
-      const newDate = new Date(date);
-      const expectedMonth = newDate.getMonth();
-      const time = newDate.setFullYear(newDate.getFullYear() + amount);
-      return expectedMonth === 1 && newDate.getMonth() === 2 ? newDate.setDate(0) : time;
-    }
+        _this = _BaseComponent.call(this, element) || this;
+        _this._popper = null;
+        _this._config = _this._getConfig(config);
+        _this._menu = _this._getMenuElement();
+        _this._inNavbar = _this._detectNavbar();
 
-    // Calculate the distance bettwen 2 days of the week
-    function dayDiff(day, from) {
-      return (day - from + 7) % 7;
-    }
+        _this._addEventListeners();
 
-    // Get the date of the specified day of the week of given base date
-    function dayOfTheWeekOf(baseDate, dayOfWeek, weekStart = 0) {
-      const baseDay = new Date(baseDate).getDay();
-      return addDays(baseDate, dayDiff(dayOfWeek, weekStart) - dayDiff(baseDay, weekStart));
-    }
+        return _this;
+      } // Getters
 
-    // Get the ISO week of a date
-    function getWeek(date) {
-      // start of ISO week is Monday
-      const thuOfTheWeek = dayOfTheWeekOf(date, 4, 1);
-      // 1st week == the week where the 4th of January is in
-      const firstThu = dayOfTheWeekOf(new Date(thuOfTheWeek).setMonth(0, 4), 4, 1);
-      return Math.round((thuOfTheWeek - firstThu) / 604800000) + 1;
-    }
 
-    // Get the start year of the period of years that includes given date
-    // years: length of the year period
-    function startOfYearPeriod(date, years) {
-      /* @see https://en.wikipedia.org/wiki/Year_zero#ISO_8601 */
-      const year = new Date(date).getFullYear();
-      return Math.floor(year / years) * years;
-    }
+      var _proto = Dropdown.prototype;
 
-    // pattern for format parts
-    const reFormatTokens = /dd?|DD?|mm?|MM?|yy?(?:yy)?/;
-    // pattern for non date parts
-    const reNonDateParts = /[\s!-/:-@[-`{-~年月日]+/;
-    // cache for persed formats
-    let knownFormats = {};
-    // parse funtions for date parts
-    const parseFns = {
-      y(date, year) {
-        return new Date(date).setFullYear(parseInt(year, 10));
-      },
-      M: undefined,  // placeholder to maintain the key order
-      m(date, month, locale) {
-        const newDate = new Date(date);
-        let monthIndex = parseInt(month, 10) - 1;
+      // Public
+      _proto.toggle = function toggle() {
+        if (this._element.disabled || this._element.classList.contains(CLASS_NAME_DISABLED)) {
+          return;
+        }
 
-        if (isNaN(monthIndex)) {
-          if (!month) {
-            return NaN;
-          }
+        var isActive = this._element.classList.contains(CLASS_NAME_SHOW$1);
 
-          const monthName = month.toLowerCase();
-          const compareNames = name => name.toLowerCase().startsWith(monthName);
-          // compare with both short and full names because some locales have periods
-          // in the short names (not equal to the first X letters of the full names)
-          monthIndex = locale.monthsShort.findIndex(compareNames);
-          if (monthIndex < 0) {
-            monthIndex = locale.months.findIndex(compareNames);
-          }
-          return monthIndex < 0 ? NaN : newDate.setMonth(monthIndex);
+        Dropdown.clearMenus();
+
+        if (isActive) {
+          return;
         }
 
-        newDate.setMonth(monthIndex);
-        return newDate.getMonth() !== normalizeMonth(monthIndex)
-          ? newDate.setDate(0)
-          : newDate.getTime();
-      },
-      d(date, day) {
-        return new Date(date).setDate(parseInt(day, 10));
-      },
-    };
-    parseFns.M = parseFns.m;  // make "M" an alias of "m"
-    // format functions for date parts
-    const formatFns = {
-      d(date) {
-        return date.getDate();
-      },
-      dd(date) {
-        return padZero(date.getDate(), 2);
-      },
-      D(date, locale) {
-        return locale.daysShort[date.getDay()];
-      },
-      DD(date, locale) {
-        return locale.days[date.getDay()];
-      },
-      m(date) {
-        return date.getMonth() + 1;
-      },
-      mm(date) {
-        return padZero(date.getMonth() + 1, 2);
-      },
-      M(date, locale) {
-        return locale.monthsShort[date.getMonth()];
-      },
-      MM(date, locale) {
-        return locale.months[date.getMonth()];
-      },
-      y(date) {
-        return date.getFullYear();
-      },
-      yy(date) {
-        return padZero(date.getFullYear(), 2).slice(-2);
-      },
-      yyyy(date) {
-        return padZero(date.getFullYear(), 4);
-      },
-    };
+        this.show();
+      };
 
-    // get month index in normal range (0 - 11) from any number
-    function normalizeMonth(monthIndex) {
-      return monthIndex > -1 ? monthIndex % 12 : normalizeMonth(monthIndex + 12);
-    }
+      _proto.show = function show() {
+        if (this._element.disabled || this._element.classList.contains(CLASS_NAME_DISABLED) || this._menu.classList.contains(CLASS_NAME_SHOW$1)) {
+          return;
+        }
 
-    function padZero(num, length) {
-      return num.toString().padStart(length, '0');
-    }
+        var parent = Dropdown.getParentFromElement(this._element);
+        var relatedTarget = {
+          relatedTarget: this._element
+        };
+        var showEvent = EventHandler.trigger(this._element, EVENT_SHOW$1, relatedTarget);
 
-    function parseFormatString(format) {
-      if (typeof format !== 'string') {
-        throw new Error("Invalid date format.");
-      }
-      if (format in knownFormats) {
-        return knownFormats[format];
-      }
+        if (showEvent.defaultPrevented) {
+          return;
+        } // Totally disable Popper for Dropdowns in Navbar
 
-      // sprit the format string into parts and seprators
-      const separators = format.split(reFormatTokens);
-      const parts = format.match(new RegExp(reFormatTokens, 'g'));
-      if (separators.length === 0 || !parts) {
-        throw new Error("Invalid date format.");
-      }
 
-      // collect format functions used in the format
-      const partFormatters = parts.map(token => formatFns[token]);
+        if (!this._inNavbar) {
+          if (typeof Popper === 'undefined') {
+            throw new TypeError('Bootstrap\'s dropdowns require Popper (https://popper.js.org)');
+          }
 
-      // collect parse functions used in the format
-      // iterate over parseFns' keys in order to keep the order of the keys.
-      const partParsers = Object.keys(parseFns).reduce((parsers, key) => {
-        const token = parts.find(part => part[0] === key);
-        if (!token) {
-          return parsers;
-        }
-        parsers[key] = parseFns[key];
-        return parsers;
-      }, {});
-      const partParserKeys = Object.keys(partParsers);
+          var referenceElement = this._element;
 
-      return knownFormats[format] = {
-        parser(dateStr, locale) {
-          const dateParts = dateStr.split(reNonDateParts).reduce((dtParts, part, index) => {
-            if (part.length > 0 && parts[index]) {
-              const token = parts[index][0];
-              if (parseFns[token] !== undefined) {
-                dtParts[token] = part;
-              }
+          if (this._config.reference === 'parent') {
+            referenceElement = parent;
+          } else if (isElement$1(this._config.reference)) {
+            referenceElement = this._config.reference; // Check if it's jQuery element
+
+            if (typeof this._config.reference.jquery !== 'undefined') {
+              referenceElement = this._config.reference[0];
             }
-            return dtParts;
-          }, {});
+          }
 
-          // iterate over partParsers' keys so that the parsing is made in the oder
-          // of year, month and day to prevent the day parser from correcting last
-          // day of month wrongly
-          return partParserKeys.reduce((origDate, key) => {
-            const newDate = partParsers[key](origDate, dateParts[key], locale);
-            // ingnore the part failed to parse
-            return isNaN(newDate) ? origDate : newDate;
-          }, today());
-        },
-        formatter(date, locale) {
-          let dateStr = partFormatters.reduce((str, fn, index) => {
-            return str += `${separators[index]}${fn(date, locale)}`;
-          }, '');
-          // separators' length is always parts' length + 1,
-          return dateStr += lastItemOf(separators);
-        },
-      };
-    }
+          this._popper = createPopper$2(referenceElement, this._menu, this._getPopperConfig());
+        } // If this is a touch-enabled device we add extra
+        // empty mouseover listeners to the body's immediate children;
+        // only needed because of broken event delegation on iOS
+        // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
 
-    function parseDate(dateStr, format, locale) {
-      if (dateStr instanceof Date || typeof dateStr === 'number') {
-        const date = stripTime(dateStr);
-        return isNaN(date) ? undefined : date;
-      }
-      if (!dateStr) {
-        return undefined;
-      }
-      if (dateStr === 'today') {
-        return today();
-      }
 
-      if (format && format.toValue) {
-        const date = format.toValue(dateStr, format, locale);
-        return isNaN(date) ? undefined : stripTime(date);
-      }
+        if ('ontouchstart' in document.documentElement && !parent.closest(SELECTOR_NAVBAR_NAV)) {
+          var _ref;
 
-      return parseFormatString(format).parser(dateStr, locale);
-    }
+          (_ref = []).concat.apply(_ref, document.body.children).forEach(function (elem) {
+            return EventHandler.on(elem, 'mouseover', null, noop());
+          });
+        }
 
-    function formatDate(date, format, locale) {
-      if (isNaN(date) || (!date && date !== 0)) {
-        return '';
-      }
+        this._element.focus();
 
-      const dateObj = typeof date === 'number' ? new Date(date) : date;
+        this._element.setAttribute('aria-expanded', true);
 
-      if (format.toDisplay) {
-        return format.toDisplay(dateObj, format, locale);
-      }
+        this._menu.classList.toggle(CLASS_NAME_SHOW$1);
 
-      return parseFormatString(format).formatter(dateObj, locale);
-    }
+        this._element.classList.toggle(CLASS_NAME_SHOW$1);
 
-    const listenerRegistry = new WeakMap();
-    const {addEventListener, removeEventListener} = EventTarget.prototype;
+        EventHandler.trigger(parent, EVENT_SHOWN$1, relatedTarget);
+      };
 
-    // Register event listeners to a key object
-    // listeners: array of listener definitions;
-    //   - each definition must be a flat array of event target and the arguments
-    //     used to call addEventListener() on the target
-    function registerListeners(keyObj, listeners) {
-      let registered = listenerRegistry.get(keyObj);
-      if (!registered) {
-        registered = [];
-        listenerRegistry.set(keyObj, registered);
-      }
-      listeners.forEach((listener) => {
-        addEventListener.call(...listener);
-        registered.push(listener);
-      });
-    }
+      _proto.hide = function hide() {
+        if (this._element.disabled || this._element.classList.contains(CLASS_NAME_DISABLED) || !this._menu.classList.contains(CLASS_NAME_SHOW$1)) {
+          return;
+        }
 
-    function unregisterListeners(keyObj) {
-      let listeners = listenerRegistry.get(keyObj);
-      if (!listeners) {
-        return;
-      }
-      listeners.forEach((listener) => {
-        removeEventListener.call(...listener);
-      });
-      listenerRegistry.delete(keyObj);
-    }
+        var parent = Dropdown.getParentFromElement(this._element);
+        var relatedTarget = {
+          relatedTarget: this._element
+        };
+        var hideEvent = EventHandler.trigger(parent, EVENT_HIDE$1, relatedTarget);
 
-    // Event.composedPath() polyfill for Edge
-    // based on https://gist.github.com/kleinfreund/e9787d73776c0e3750dcfcdc89f100ec
-    if (!Event.prototype.composedPath) {
-      const getComposedPath = (node, path = []) => {
-        path.push(node);
+        if (hideEvent.defaultPrevented) {
+          return;
+        }
 
-        let parent;
-        if (node.parentNode) {
-          parent = node.parentNode;
-        } else if (node.host) { // ShadowRoot
-          parent = node.host;
-        } else if (node.defaultView) {  // Document
-          parent = node.defaultView;
+        if (this._popper) {
+          this._popper.destroy();
+        }
+
+        this._menu.classList.toggle(CLASS_NAME_SHOW$1);
+
+        this._element.classList.toggle(CLASS_NAME_SHOW$1);
+
+        EventHandler.trigger(parent, EVENT_HIDDEN$1, relatedTarget);
+      };
+
+      _proto.dispose = function dispose() {
+        _BaseComponent.prototype.dispose.call(this);
+
+        EventHandler.off(this._element, EVENT_KEY$4);
+        this._menu = null;
+
+        if (this._popper) {
+          this._popper.destroy();
+
+          this._popper = null;
         }
-        return parent ? getComposedPath(parent, path) : path;
       };
 
-      Event.prototype.composedPath = function () {
-        return getComposedPath(this.target);
+      _proto.update = function update() {
+        this._inNavbar = this._detectNavbar();
+
+        if (this._popper) {
+          this._popper.update();
+        }
+      } // Private
+      ;
+
+      _proto._addEventListeners = function _addEventListeners() {
+        var _this2 = this;
+
+        EventHandler.on(this._element, EVENT_CLICK, function (event) {
+          event.preventDefault();
+          event.stopPropagation();
+
+          _this2.toggle();
+        });
       };
-    }
 
-    function findFromPath(path, criteria, currentTarget, index = 0) {
-      const el = path[index];
-      if (criteria(el)) {
-        return el;
-      } else if (el === currentTarget || !el.parentElement) {
-        // stop when reaching currentTarget or <html>
-        return;
-      }
-      return findFromPath(path, criteria, currentTarget, index + 1);
-    }
+      _proto._getConfig = function _getConfig(config) {
+        config = _extends({}, this.constructor.Default, Manipulator.getDataAttributes(this._element), config);
+        typeCheckConfig(NAME$4, config, this.constructor.DefaultType);
+        return config;
+      };
 
-    // Search for the actual target of a delegated event
-    function findElementInEventPath(ev, selector) {
-      const criteria = typeof selector === 'function' ? selector : el => el.matches(selector);
-      return findFromPath(ev.composedPath(), criteria, ev.currentTarget);
-    }
+      _proto._getMenuElement = function _getMenuElement() {
+        return SelectorEngine.next(this._element, SELECTOR_MENU)[0];
+      };
 
-    // default locales
-    const locales = {
-      en: {
-        days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
-        daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
-        daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"],
-        months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
-        monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
-        today: "Today",
-        clear: "Clear",
-        titleFormat: "MM y"
-      }
-    };
+      _proto._getPlacement = function _getPlacement() {
+        var parentDropdown = this._element.parentNode;
 
-    // config options updatable by setOptions() and their default values
-    const defaultOptions = {
-      autohide: false,
-      beforeShowDay: null,
-      beforeShowDecade: null,
-      beforeShowMonth: null,
-      beforeShowYear: null,
-      calendarWeeks: false,
-      clearBtn: false,
-      dateDelimiter: ',',
-      datesDisabled: [],
-      daysOfWeekDisabled: [],
-      daysOfWeekHighlighted: [],
-      defaultViewDate: undefined, // placeholder, defaults to today() by the program
-      disableTouchKeyboard: false,
-      format: 'mm/dd/yyyy',
-      language: 'en',
-      maxDate: null,
-      maxNumberOfDates: 1,
-      maxView: 3,
-      minDate: null,
-      nextArrow: '»',
-      orientation: 'auto',
-      pickLevel: 0,
-      prevArrow: '«',
-      showDaysOfWeek: true,
-      showOnClick: true,
-      showOnFocus: true,
-      startView: 0,
-      title: '',
-      todayBtn: false,
-      todayBtnMode: 0,
-      todayHighlight: false,
-      updateOnBlur: true,
-      weekStart: 0,
-    };
+        if (parentDropdown.classList.contains(CLASS_NAME_DROPEND)) {
+          return PLACEMENT_RIGHT;
+        }
 
-    const range = document.createRange();
+        if (parentDropdown.classList.contains(CLASS_NAME_DROPSTART)) {
+          return PLACEMENT_LEFT;
+        } // We need to trim the value because custom properties can also include spaces
 
-    function parseHTML(html) {
-      return range.createContextualFragment(html);
-    }
 
-    function hideElement(el) {
-      if (el.style.display === 'none') {
-        return;
-      }
-      // back up the existing display setting in data-style-display
-      if (el.style.display) {
-        el.dataset.styleDisplay = el.style.display;
-      }
-      el.style.display = 'none';
-    }
+        var isEnd = getComputedStyle(this._menu).getPropertyValue('--bs-position').trim() === 'end';
 
-    function showElement(el) {
-      if (el.style.display !== 'none') {
-        return;
-      }
-      if (el.dataset.styleDisplay) {
-        // restore backed-up dispay property
-        el.style.display = el.dataset.styleDisplay;
-        delete el.dataset.styleDisplay;
-      } else {
-        el.style.display = '';
-      }
-    }
+        if (parentDropdown.classList.contains(CLASS_NAME_DROPUP)) {
+          return isEnd ? PLACEMENT_TOPEND : PLACEMENT_TOP;
+        }
 
-    function emptyChildNodes(el) {
-      if (el.firstChild) {
-        el.removeChild(el.firstChild);
-        emptyChildNodes(el);
-      }
-    }
+        return isEnd ? PLACEMENT_BOTTOMEND : PLACEMENT_BOTTOM;
+      };
 
-    function replaceChildNodes(el, newChildNodes) {
-      emptyChildNodes(el);
-      if (newChildNodes instanceof DocumentFragment) {
-        el.appendChild(newChildNodes);
-      } else if (typeof newChildNodes === 'string') {
-        el.appendChild(parseHTML(newChildNodes));
-      } else if (typeof newChildNodes.forEach === 'function') {
-        newChildNodes.forEach((node) => {
-          el.appendChild(node);
-        });
-      }
-    }
+      _proto._detectNavbar = function _detectNavbar() {
+        return this._element.closest("." + CLASS_NAME_NAVBAR) !== null;
+      };
 
-    const {
-      language: defaultLang,
-      format: defaultFormat,
-      weekStart: defaultWeekStart,
-    } = defaultOptions;
+      _proto._getPopperConfig = function _getPopperConfig() {
+        var popperConfig = {
+          placement: this._getPlacement(),
+          modifiers: [{
+            name: 'preventOverflow',
+            options: {
+              altBoundary: this._config.flip,
+              rootBoundary: this._config.boundary
+            }
+          }]
+        }; // Disable Popper if we have a static display
 
-    // Reducer function to filter out invalid day-of-week from the input
-    function sanitizeDOW(dow, day) {
-      return dow.length < 6 && day >= 0 && day < 7
-        ? pushUnique(dow, day)
-        : dow;
-    }
+        if (this._config.display === 'static') {
+          popperConfig.modifiers = [{
+            name: 'applyStyles',
+            enabled: false
+          }];
+        }
 
-    function calcEndOfWeek(startOfWeek) {
-      return (startOfWeek + 6) % 7;
-    }
+        return _extends({}, popperConfig, this._config.popperConfig);
+      } // Static
+      ;
 
-    // validate input date. if invalid, fallback to the original value
-    function validateDate(value, format, locale, origValue) {
-      const date = parseDate(value, format, locale);
-      return date !== undefined ? date : origValue;
-    }
+      Dropdown.dropdownInterface = function dropdownInterface(element, config) {
+        var data = Data.getData(element, DATA_KEY$4);
 
-    // Validate viewId. if invalid, fallback to the original value
-    function validateViewId(value, origValue, max = 3) {
-      const viewId = parseInt(value, 10);
-      return viewId >= 0 && viewId <= max ? viewId : origValue;
-    }
+        var _config = typeof config === 'object' ? config : null;
 
-    // Create Datepicker configuration to set
-    function processOptions(options, datepicker) {
-      const inOpts = Object.assign({}, options);
-      const config = {};
-      const locales = datepicker.constructor.locales;
-      let {
-        format,
-        language,
-        locale,
-        maxDate,
-        maxView,
-        minDate,
-        pickLevel,
-        startView,
-        weekStart,
-      } = datepicker.config || {};
+        if (!data) {
+          data = new Dropdown(element, _config);
+        }
 
-      if (inOpts.language) {
-        let lang;
-        if (inOpts.language !== language) {
-          if (locales[inOpts.language]) {
-            lang = inOpts.language;
-          } else {
-            // Check if langauge + region tag can fallback to the one without
-            // region (e.g. fr-CA → fr)
-            lang = inOpts.language.split('-')[0];
-            if (locales[lang] === undefined) {
-              lang = false;
-            }
+        if (typeof config === 'string') {
+          if (typeof data[config] === 'undefined') {
+            throw new TypeError("No method named \"" + config + "\"");
           }
+
+          data[config]();
         }
-        delete inOpts.language;
-        if (lang) {
-          language = config.language = lang;
+      };
 
-          // update locale as well when updating language
-          const origLocale = locale || locales[defaultLang];
-          // use default language's properties for the fallback
-          locale = Object.assign({
-            format: defaultFormat,
-            weekStart: defaultWeekStart
-          }, locales[defaultLang]);
-          if (language !== defaultLang) {
-            Object.assign(locale, locales[language]);
+      Dropdown.jQueryInterface = function jQueryInterface(config) {
+        return this.each(function () {
+          Dropdown.dropdownInterface(this, config);
+        });
+      };
+
+      Dropdown.clearMenus = function clearMenus(event) {
+        if (event && (event.button === RIGHT_MOUSE_BUTTON || event.type === 'keyup' && event.key !== TAB_KEY)) {
+          return;
+        }
+
+        var toggles = SelectorEngine.find(SELECTOR_DATA_TOGGLE$2);
+
+        for (var i = 0, len = toggles.length; i < len; i++) {
+          var parent = Dropdown.getParentFromElement(toggles[i]);
+          var context = Data.getData(toggles[i], DATA_KEY$4);
+          var relatedTarget = {
+            relatedTarget: toggles[i]
+          };
+
+          if (event && event.type === 'click') {
+            relatedTarget.clickEvent = event;
           }
-          config.locale = locale;
-          // if format and/or weekStart are the same as old locale's defaults,
-          // update them to new locale's defaults
-          if (format === origLocale.format) {
-            format = config.format = locale.format;
+
+          if (!context) {
+            continue;
           }
-          if (weekStart === origLocale.weekStart) {
-            weekStart = config.weekStart = locale.weekStart;
-            config.weekEnd = calcEndOfWeek(locale.weekStart);
+
+          var dropdownMenu = context._menu;
+
+          if (!toggles[i].classList.contains(CLASS_NAME_SHOW$1)) {
+            continue;
           }
-        }
-      }
 
-      if (inOpts.format) {
-        const hasToDisplay = typeof inOpts.format.toDisplay === 'function';
-        const hasToValue = typeof inOpts.format.toValue === 'function';
-        const validFormatString = reFormatTokens.test(inOpts.format);
-        if ((hasToDisplay && hasToValue) || validFormatString) {
-          format = config.format = inOpts.format;
-        }
-        delete inOpts.format;
-      }
+          if (event && (event.type === 'click' && /input|textarea/i.test(event.target.tagName) || event.type === 'keyup' && event.key === TAB_KEY) && dropdownMenu.contains(event.target)) {
+            continue;
+          }
 
-      //*** dates ***//
-      // while min and maxDate for "no limit" in the options are better to be null
-      // (especially when updating), the ones in the config have to be undefined
-      // because null is treated as 0 (= unix epoch) when comparing with time value
-      let minDt = minDate;
-      let maxDt = maxDate;
-      if (inOpts.minDate !== undefined) {
-        minDt = inOpts.minDate === null
-          ? dateValue(0, 0, 1)  // set 0000-01-01 to prevent negative values for year
-          : validateDate(inOpts.minDate, format, locale, minDt);
-        delete inOpts.minDate;
-      }
-      if (inOpts.maxDate !== undefined) {
-        maxDt = inOpts.maxDate === null
-          ? undefined
-          : validateDate(inOpts.maxDate, format, locale, maxDt);
-        delete inOpts.maxDate;
-      }
-      if (maxDt < minDt) {
-        minDate = config.minDate = maxDt;
-        maxDate = config.maxDate = minDt;
-      } else {
-        if (minDate !== minDt) {
-          minDate = config.minDate = minDt;
+          var hideEvent = EventHandler.trigger(parent, EVENT_HIDE$1, relatedTarget);
+
+          if (hideEvent.defaultPrevented) {
+            continue;
+          } // If this is a touch-enabled device we remove the extra
+          // empty mouseover listeners we added for iOS support
+
+
+          if ('ontouchstart' in document.documentElement) {
+            var _ref2;
+
+            (_ref2 = []).concat.apply(_ref2, document.body.children).forEach(function (elem) {
+              return EventHandler.off(elem, 'mouseover', null, noop());
+            });
+          }
+
+          toggles[i].setAttribute('aria-expanded', 'false');
+
+          if (context._popper) {
+            context._popper.destroy();
+          }
+
+          dropdownMenu.classList.remove(CLASS_NAME_SHOW$1);
+          toggles[i].classList.remove(CLASS_NAME_SHOW$1);
+          EventHandler.trigger(parent, EVENT_HIDDEN$1, relatedTarget);
         }
-        if (maxDate !== maxDt) {
-          maxDate = config.maxDate = maxDt;
+      };
+
+      Dropdown.getParentFromElement = function getParentFromElement(element) {
+        return getElementFromSelector(element) || element.parentNode;
+      };
+
+      Dropdown.dataApiKeydownHandler = function dataApiKeydownHandler(event) {
+        // If not input/textarea:
+        //  - And not a key in REGEXP_KEYDOWN => not a dropdown command
+        // If input/textarea:
+        //  - If space key => not a dropdown command
+        //  - If key is other than escape
+        //    - If key is not up or down => not a dropdown command
+        //    - If trigger inside the menu => not a dropdown command
+        if (/input|textarea/i.test(event.target.tagName) ? event.key === SPACE_KEY || event.key !== ESCAPE_KEY && (event.key !== ARROW_DOWN_KEY && event.key !== ARROW_UP_KEY || event.target.closest(SELECTOR_MENU)) : !REGEXP_KEYDOWN.test(event.key)) {
+          return;
         }
-      }
 
-      if (inOpts.datesDisabled) {
-        config.datesDisabled = inOpts.datesDisabled.reduce((dates, dt) => {
-          const date = parseDate(dt, format, locale);
-          return date !== undefined ? pushUnique(dates, date) : dates;
-        }, []);
-        delete inOpts.datesDisabled;
-      }
-      if (inOpts.defaultViewDate !== undefined) {
-        const viewDate = parseDate(inOpts.defaultViewDate, format, locale);
-        if (viewDate !== undefined) {
-          config.defaultViewDate = viewDate;
+        event.preventDefault();
+        event.stopPropagation();
+
+        if (this.disabled || this.classList.contains(CLASS_NAME_DISABLED)) {
+          return;
         }
-        delete inOpts.defaultViewDate;
-      }
 
-      //*** days of week ***//
-      if (inOpts.weekStart !== undefined) {
-        const wkStart = Number(inOpts.weekStart) % 7;
-        if (!isNaN(wkStart)) {
-          weekStart = config.weekStart = wkStart;
-          config.weekEnd = calcEndOfWeek(wkStart);
+        var parent = Dropdown.getParentFromElement(this);
+        var isActive = this.classList.contains(CLASS_NAME_SHOW$1);
+
+        if (event.key === ESCAPE_KEY) {
+          var button = this.matches(SELECTOR_DATA_TOGGLE$2) ? this : SelectorEngine.prev(this, SELECTOR_DATA_TOGGLE$2)[0];
+          button.focus();
+          Dropdown.clearMenus();
+          return;
         }
-        delete inOpts.weekStart;
-      }
-      if (inOpts.daysOfWeekDisabled) {
-        config.daysOfWeekDisabled = inOpts.daysOfWeekDisabled.reduce(sanitizeDOW, []);
-        delete inOpts.daysOfWeekDisabled;
-      }
-      if (inOpts.daysOfWeekHighlighted) {
-        config.daysOfWeekHighlighted = inOpts.daysOfWeekHighlighted.reduce(sanitizeDOW, []);
-        delete inOpts.daysOfWeekHighlighted;
-      }
 
-      //*** multi date ***//
-      if (inOpts.maxNumberOfDates !== undefined) {
-        const maxNumberOfDates = parseInt(inOpts.maxNumberOfDates, 10);
-        if (maxNumberOfDates >= 0) {
-          config.maxNumberOfDates = maxNumberOfDates;
-          config.multidate = maxNumberOfDates !== 1;
+        if (!isActive || event.key === SPACE_KEY) {
+          Dropdown.clearMenus();
+          return;
         }
-        delete inOpts.maxNumberOfDates;
-      }
-      if (inOpts.dateDelimiter) {
-        config.dateDelimiter = String(inOpts.dateDelimiter);
-        delete inOpts.dateDelimiter;
-      }
 
-      //*** pick level & view ***//
-      let newPickLevel = pickLevel;
-      if (inOpts.pickLevel !== undefined) {
-        newPickLevel = validateViewId(inOpts.pickLevel, 2);
-        delete inOpts.pickLevel;
-      }
-      if (newPickLevel !== pickLevel) {
-        pickLevel = config.pickLevel = newPickLevel;
-      }
+        var items = SelectorEngine.find(SELECTOR_VISIBLE_ITEMS, parent).filter(isVisible);
 
-      let newMaxView = maxView;
-      if (inOpts.maxView !== undefined) {
-        newMaxView = validateViewId(inOpts.maxView, maxView);
-        delete inOpts.maxView;
-      }
-      // ensure max view >= pick level
-      newMaxView = pickLevel > newMaxView ? pickLevel : newMaxView;
-      if (newMaxView !== maxView) {
-        maxView = config.maxView = newMaxView;
-      }
+        if (!items.length) {
+          return;
+        }
 
-      let newStartView = startView;
-      if (inOpts.startView !== undefined) {
-        newStartView = validateViewId(inOpts.startView, newStartView);
-        delete inOpts.startView;
-      }
-      // ensure pick level <= start view <= max view
-      if (newStartView < pickLevel) {
-        newStartView = pickLevel;
-      } else if (newStartView > maxView) {
-        newStartView = maxView;
-      }
-      if (newStartView !== startView) {
-        config.startView = newStartView;
-      }
+        var index = items.indexOf(event.target); // Up
 
-      //*** template ***//
-      if (inOpts.prevArrow) {
-        const prevArrow = parseHTML(inOpts.prevArrow);
-        if (prevArrow.childNodes.length > 0) {
-          config.prevArrow = prevArrow.childNodes;
+        if (event.key === ARROW_UP_KEY && index > 0) {
+          index--;
+        } // Down
+
+
+        if (event.key === ARROW_DOWN_KEY && index < items.length - 1) {
+          index++;
+        } // index is -1 if the first keydown is an ArrowUp
+
+
+        index = index === -1 ? 0 : index;
+        items[index].focus();
+      };
+
+      _createClass(Dropdown, null, [{
+        key: "Default",
+        get: function get() {
+          return Default$2;
         }
-        delete inOpts.prevArrow;
-      }
-      if (inOpts.nextArrow) {
-        const nextArrow = parseHTML(inOpts.nextArrow);
-        if (nextArrow.childNodes.length > 0) {
-          config.nextArrow = nextArrow.childNodes;
+      }, {
+        key: "DefaultType",
+        get: function get() {
+          return DefaultType$2;
         }
-        delete inOpts.nextArrow;
-      }
+      }, {
+        key: "DATA_KEY",
+        get: function get() {
+          return DATA_KEY$4;
+        }
+      }]);
 
-      //*** misc ***//
-      if (inOpts.disableTouchKeyboard !== undefined) {
-        config.disableTouchKeyboard = 'ontouchstart' in document && !!inOpts.disableTouchKeyboard;
-        delete inOpts.disableTouchKeyboard;
-      }
-      if (inOpts.orientation) {
-        const orientation = inOpts.orientation.toLowerCase().split(/\s+/g);
-        config.orientation = {
-          x: orientation.find(x => (x === 'left' || x === 'right')) || 'auto',
-          y: orientation.find(y => (y === 'top' || y === 'bottom')) || 'auto',
+      return Dropdown;
+    }(BaseComponent);
+    /**
+     * ------------------------------------------------------------------------
+     * Data Api implementation
+     * ------------------------------------------------------------------------
+     */
+
+
+    EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_DATA_TOGGLE$2, Dropdown$1.dataApiKeydownHandler);
+    EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_MENU, Dropdown$1.dataApiKeydownHandler);
+    EventHandler.on(document, EVENT_CLICK_DATA_API$4, Dropdown$1.clearMenus);
+    EventHandler.on(document, EVENT_KEYUP_DATA_API, Dropdown$1.clearMenus);
+    EventHandler.on(document, EVENT_CLICK_DATA_API$4, SELECTOR_DATA_TOGGLE$2, function (event) {
+      event.preventDefault();
+      event.stopPropagation();
+      Dropdown$1.dropdownInterface(this, 'toggle');
+    });
+    EventHandler.on(document, EVENT_CLICK_DATA_API$4, SELECTOR_FORM_CHILD, function (e) {
+      return e.stopPropagation();
+    });
+    /**
+     * ------------------------------------------------------------------------
+     * jQuery
+     * ------------------------------------------------------------------------
+     * add .Dropdown to jQuery only if jQuery is present
+     */
+
+    onDOMContentLoaded(function () {
+      var $ = getjQuery();
+      /* istanbul ignore if */
+
+      if ($) {
+        var JQUERY_NO_CONFLICT = $.fn[NAME$4];
+        $.fn[NAME$4] = Dropdown$1.jQueryInterface;
+        $.fn[NAME$4].Constructor = Dropdown$1;
+
+        $.fn[NAME$4].noConflict = function () {
+          $.fn[NAME$4] = JQUERY_NO_CONFLICT;
+          return Dropdown$1.jQueryInterface;
         };
-        delete inOpts.orientation;
-      }
-      if (inOpts.todayBtnMode !== undefined) {
-        switch(inOpts.todayBtnMode) {
-          case 0:
-          case 1:
-            config.todayBtnMode = inOpts.todayBtnMode;
-        }
-        delete inOpts.todayBtnMode;
       }
+    });
 
-      //*** copy the rest ***//
-      Object.keys(inOpts).forEach((key) => {
-        if (inOpts[key] !== undefined && hasProperty(defaultOptions, key)) {
-          config[key] = inOpts[key];
-        }
-      });
+    /**
+     * ------------------------------------------------------------------------
+     * Constants
+     * ------------------------------------------------------------------------
+     */
 
-      return config;
-    }
+    var NAME$5 = 'modal';
+    var DATA_KEY$5 = 'bs.modal';
+    var EVENT_KEY$5 = "." + DATA_KEY$5;
+    var DATA_API_KEY$5 = '.data-api';
+    var ESCAPE_KEY$1 = 'Escape';
+    var Default$3 = {
+      backdrop: true,
+      keyboard: true,
+      focus: true
+    };
+    var DefaultType$3 = {
+      backdrop: '(boolean|string)',
+      keyboard: 'boolean',
+      focus: 'boolean'
+    };
+    var EVENT_HIDE$2 = "hide" + EVENT_KEY$5;
+    var EVENT_HIDE_PREVENTED = "hidePrevented" + EVENT_KEY$5;
+    var EVENT_HIDDEN$2 = "hidden" + EVENT_KEY$5;
+    var EVENT_SHOW$2 = "show" + EVENT_KEY$5;
+    var EVENT_SHOWN$2 = "shown" + EVENT_KEY$5;
+    var EVENT_FOCUSIN = "focusin" + EVENT_KEY$5;
+    var EVENT_RESIZE = "resize" + EVENT_KEY$5;
+    var EVENT_CLICK_DISMISS = "click.dismiss" + EVENT_KEY$5;
+    var EVENT_KEYDOWN_DISMISS = "keydown.dismiss" + EVENT_KEY$5;
+    var EVENT_MOUSEUP_DISMISS = "mouseup.dismiss" + EVENT_KEY$5;
+    var EVENT_MOUSEDOWN_DISMISS = "mousedown.dismiss" + EVENT_KEY$5;
+    var EVENT_CLICK_DATA_API$5 = "click" + EVENT_KEY$5 + DATA_API_KEY$5;
+    var CLASS_NAME_SCROLLBAR_MEASURER = 'modal-scrollbar-measure';
+    var CLASS_NAME_BACKDROP = 'modal-backdrop';
+    var CLASS_NAME_OPEN = 'modal-open';
+    var CLASS_NAME_FADE = 'fade';
+    var CLASS_NAME_SHOW$2 = 'show';
+    var CLASS_NAME_STATIC = 'modal-static';
+    var SELECTOR_DIALOG = '.modal-dialog';
+    var SELECTOR_MODAL_BODY = '.modal-body';
+    var SELECTOR_DATA_TOGGLE$3 = '[data-bs-toggle="modal"]';
+    var SELECTOR_DATA_DISMISS = '[data-bs-dismiss="modal"]';
+    var SELECTOR_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top';
+    var SELECTOR_STICKY_CONTENT = '.sticky-top';
+    /**
+     * ------------------------------------------------------------------------
+     * Class Definition
+     * ------------------------------------------------------------------------
+     */
 
-    const pickerTemplate = optimizeTemplateHTML(`<div class="datepicker">
-  <div class="datepicker-picker">
-    <div class="datepicker-header">
-      <div class="datepicker-title"></div>
-      <div class="datepicker-controls">
-        <button class="%buttonClass% prev-btn"></button>
-        <button class="%buttonClass% view-switch"></button>
-        <button class="%buttonClass% next-btn"></button>
-      </div>
-    </div>
-    <div class="datepicker-main"></div>
-    <div class="datepicker-footer">
-      <div class="datepicker-controls">
-        <button class="%buttonClass% today-btn"></button>
-        <button class="%buttonClass% clear-btn"></button>
-      </div>
-    </div>
-  </div>
-</div>`);
+    var Modal = /*#__PURE__*/function (_BaseComponent) {
+      _inheritsLoose(Modal, _BaseComponent);
 
-    const daysTemplate = optimizeTemplateHTML(`<div class="days">
-  <div class="days-of-week">${createTagRepeat('span', 7, {class: 'dow'})}</div>
-  <div class="datepicker-grid">${createTagRepeat('span', 42)}</div>
-</div>`);
+      function Modal(element, config) {
+        var _this;
 
-    const calendarWeeksTemplate = optimizeTemplateHTML(`<div class="calendar-weeks">
-  <div class="days-of-week"><span class="dow"></span></div>
-  <div class="weeks">${createTagRepeat('span', 6, {class: 'week'})}</div>
-</div>`);
+        _this = _BaseComponent.call(this, element) || this;
+        _this._config = _this._getConfig(config);
+        _this._dialog = SelectorEngine.findOne(SELECTOR_DIALOG, element);
+        _this._backdrop = null;
+        _this._isShown = false;
+        _this._isBodyOverflowing = false;
+        _this._ignoreBackdropClick = false;
+        _this._isTransitioning = false;
+        _this._scrollbarWidth = 0;
+        return _this;
+      } // Getters
 
-    // Base class of the view classes
-    class View {
-      constructor(picker, config) {
-        Object.assign(this, config, {
-          picker,
-          element: parseHTML(`<div class="datepicker-view"></div>`).firstChild,
-          selected: [],
-        });
-        this.init(this.picker.datepicker.config);
-      }
 
-      init(options) {
-        if (options.pickLevel !== undefined) {
-          this.isMinView = this.id === options.pickLevel;
+      var _proto = Modal.prototype;
+
+      // Public
+      _proto.toggle = function toggle(relatedTarget) {
+        return this._isShown ? this.hide() : this.show(relatedTarget);
+      };
+
+      _proto.show = function show(relatedTarget) {
+        var _this2 = this;
+
+        if (this._isShown || this._isTransitioning) {
+          return;
         }
-        this.setOptions(options);
-        this.updateFocus();
-        this.updateSelection();
-      }
 
-      // Execute beforeShow() callback and apply the result to the element
-      // args:
-      // - current - current value on the iteration on view rendering
-      // - timeValue - time value of the date to pass to beforeShow()
-      performBeforeHook(el, current, timeValue) {
-        let result = this.beforeShow(new Date(timeValue));
-        switch (typeof result) {
-          case 'boolean':
-            result = {enabled: result};
-            break;
-          case 'string':
-            result = {classes: result};
+        if (this._element.classList.contains(CLASS_NAME_FADE)) {
+          this._isTransitioning = true;
         }
 
-        if (result) {
-          if (result.enabled === false) {
-            el.classList.add('disabled');
-            pushUnique(this.disabled, current);
-          }
-          if (result.classes) {
-            const extraClasses = result.classes.split(/\s+/);
-            el.classList.add(...extraClasses);
-            if (extraClasses.includes('disabled')) {
-              pushUnique(this.disabled, current);
-            }
-          }
-          if (result.content) {
-            replaceChildNodes(el, result.content);
-          }
+        var showEvent = EventHandler.trigger(this._element, EVENT_SHOW$2, {
+          relatedTarget: relatedTarget
+        });
+
+        if (this._isShown || showEvent.defaultPrevented) {
+          return;
         }
-      }
-    }
 
-    class DaysView extends View {
-      constructor(picker) {
-        super(picker, {
-          id: 0,
-          name: 'days',
-          cellClass: 'day',
+        this._isShown = true;
+
+        this._checkScrollbar();
+
+        this._setScrollbar();
+
+        this._adjustDialog();
+
+        this._setEscapeEvent();
+
+        this._setResizeEvent();
+
+        EventHandler.on(this._element, EVENT_CLICK_DISMISS, SELECTOR_DATA_DISMISS, function (event) {
+          return _this2.hide(event);
+        });
+        EventHandler.on(this._dialog, EVENT_MOUSEDOWN_DISMISS, function () {
+          EventHandler.one(_this2._element, EVENT_MOUSEUP_DISMISS, function (event) {
+            if (event.target === _this2._element) {
+              _this2._ignoreBackdropClick = true;
+            }
+          });
         });
-      }
 
-      init(options, onConstruction = true) {
-        if (onConstruction) {
-          const inner = parseHTML(daysTemplate).firstChild;
-          this.dow = inner.firstChild;
-          this.grid = inner.lastChild;
-          this.element.appendChild(inner);
-        }
-        super.init(options);
-      }
+        this._showBackdrop(function () {
+          return _this2._showElement(relatedTarget);
+        });
+      };
 
-      setOptions(options) {
-        let updateDOW;
+      _proto.hide = function hide(event) {
+        var _this3 = this;
 
-        if (hasProperty(options, 'minDate')) {
-          this.minDate = options.minDate;
+        if (event) {
+          event.preventDefault();
         }
-        if (hasProperty(options, 'maxDate')) {
-          this.maxDate = options.maxDate;
+
+        if (!this._isShown || this._isTransitioning) {
+          return;
         }
-        if (options.datesDisabled) {
-          this.datesDisabled = options.datesDisabled;
+
+        var hideEvent = EventHandler.trigger(this._element, EVENT_HIDE$2);
+
+        if (hideEvent.defaultPrevented) {
+          return;
         }
-        if (options.daysOfWeekDisabled) {
-          this.daysOfWeekDisabled = options.daysOfWeekDisabled;
-          updateDOW = true;
+
+        this._isShown = false;
+
+        var transition = this._element.classList.contains(CLASS_NAME_FADE);
+
+        if (transition) {
+          this._isTransitioning = true;
         }
-        if (options.daysOfWeekHighlighted) {
-          this.daysOfWeekHighlighted = options.daysOfWeekHighlighted;
+
+        this._setEscapeEvent();
+
+        this._setResizeEvent();
+
+        EventHandler.off(document, EVENT_FOCUSIN);
+
+        this._element.classList.remove(CLASS_NAME_SHOW$2);
+
+        EventHandler.off(this._element, EVENT_CLICK_DISMISS);
+        EventHandler.off(this._dialog, EVENT_MOUSEDOWN_DISMISS);
+
+        if (transition) {
+          var transitionDuration = getTransitionDurationFromElement(this._element);
+          EventHandler.one(this._element, TRANSITION_END, function (event) {
+            return _this3._hideModal(event);
+          });
+          emulateTransitionEnd(this._element, transitionDuration);
+        } else {
+          this._hideModal();
         }
-        if (options.todayHighlight !== undefined) {
-          this.todayHighlight = options.todayHighlight;
+      };
+
+      _proto.dispose = function dispose() {
+        [window, this._element, this._dialog].forEach(function (htmlElement) {
+          return EventHandler.off(htmlElement, EVENT_KEY$5);
+        });
+
+        _BaseComponent.prototype.dispose.call(this);
+        /**
+         * `document` has 2 events `EVENT_FOCUSIN` and `EVENT_CLICK_DATA_API`
+         * Do not move `document` in `htmlElements` array
+         * It will remove `EVENT_CLICK_DATA_API` event that should remain
+         */
+
+
+        EventHandler.off(document, EVENT_FOCUSIN);
+        this._config = null;
+        this._dialog = null;
+        this._backdrop = null;
+        this._isShown = null;
+        this._isBodyOverflowing = null;
+        this._ignoreBackdropClick = null;
+        this._isTransitioning = null;
+        this._scrollbarWidth = null;
+      };
+
+      _proto.handleUpdate = function handleUpdate() {
+        this._adjustDialog();
+      } // Private
+      ;
+
+      _proto._getConfig = function _getConfig(config) {
+        config = _extends({}, Default$3, config);
+        typeCheckConfig(NAME$5, config, DefaultType$3);
+        return config;
+      };
+
+      _proto._showElement = function _showElement(relatedTarget) {
+        var _this4 = this;
+
+        var transition = this._element.classList.contains(CLASS_NAME_FADE);
+
+        var modalBody = SelectorEngine.findOne(SELECTOR_MODAL_BODY, this._dialog);
+
+        if (!this._element.parentNode || this._element.parentNode.nodeType !== Node.ELEMENT_NODE) {
+          // Don't move modal's DOM position
+          document.body.appendChild(this._element);
         }
-        if (options.weekStart !== undefined) {
-          this.weekStart = options.weekStart;
-          this.weekEnd = options.weekEnd;
-          updateDOW = true;
+
+        this._element.style.display = 'block';
+
+        this._element.removeAttribute('aria-hidden');
+
+        this._element.setAttribute('aria-modal', true);
+
+        this._element.setAttribute('role', 'dialog');
+
+        this._element.scrollTop = 0;
+
+        if (modalBody) {
+          modalBody.scrollTop = 0;
         }
-        if (options.locale) {
-          const locale = this.locale = options.locale;
-          this.dayNames = locale.daysMin;
-          this.switchLabelFormat = locale.titleFormat;
-          updateDOW = true;
+
+        if (transition) {
+          reflow(this._element);
         }
-        if (options.beforeShowDay !== undefined) {
-          this.beforeShow = typeof options.beforeShowDay === 'function'
-            ? options.beforeShowDay
-            : undefined;
+
+        this._element.classList.add(CLASS_NAME_SHOW$2);
+
+        if (this._config.focus) {
+          this._enforceFocus();
         }
 
-        if (options.calendarWeeks !== undefined) {
-          if (options.calendarWeeks && !this.calendarWeeks) {
-            const weeksElem = parseHTML(calendarWeeksTemplate).firstChild;
-            this.calendarWeeks = {
-              element: weeksElem,
-              dow: weeksElem.firstChild,
-              weeks: weeksElem.lastChild,
-            };
-            this.element.insertBefore(weeksElem, this.element.firstChild);
-          } else if (this.calendarWeeks && !options.calendarWeeks) {
-            this.element.removeChild(this.calendarWeeks.element);
-            this.calendarWeeks = null;
+        var transitionComplete = function transitionComplete() {
+          if (_this4._config.focus) {
+            _this4._element.focus();
           }
+
+          _this4._isTransitioning = false;
+          EventHandler.trigger(_this4._element, EVENT_SHOWN$2, {
+            relatedTarget: relatedTarget
+          });
+        };
+
+        if (transition) {
+          var transitionDuration = getTransitionDurationFromElement(this._dialog);
+          EventHandler.one(this._dialog, TRANSITION_END, transitionComplete);
+          emulateTransitionEnd(this._dialog, transitionDuration);
+        } else {
+          transitionComplete();
         }
-        if (options.showDaysOfWeek !== undefined) {
-          if (options.showDaysOfWeek) {
-            showElement(this.dow);
-            if (this.calendarWeeks) {
-              showElement(this.calendarWeeks.dow);
-            }
-          } else {
-            hideElement(this.dow);
-            if (this.calendarWeeks) {
-              hideElement(this.calendarWeeks.dow);
-            }
+      };
+
+      _proto._enforceFocus = function _enforceFocus() {
+        var _this5 = this;
+
+        EventHandler.off(document, EVENT_FOCUSIN); // guard against infinite focus loop
+
+        EventHandler.on(document, EVENT_FOCUSIN, function (event) {
+          if (document !== event.target && _this5._element !== event.target && !_this5._element.contains(event.target)) {
+            _this5._element.focus();
           }
+        });
+      };
+
+      _proto._setEscapeEvent = function _setEscapeEvent() {
+        var _this6 = this;
+
+        if (this._isShown) {
+          EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS, function (event) {
+            if (_this6._config.keyboard && event.key === ESCAPE_KEY$1) {
+              event.preventDefault();
+
+              _this6.hide();
+            } else if (!_this6._config.keyboard && event.key === ESCAPE_KEY$1) {
+              _this6._triggerBackdropTransition();
+            }
+          });
+        } else {
+          EventHandler.off(this._element, EVENT_KEYDOWN_DISMISS);
         }
+      };
 
-        // update days-of-week when locale, daysOfweekDisabled or weekStart is changed
-        if (updateDOW) {
-          Array.from(this.dow.children).forEach((el, index) => {
-            const dow = (this.weekStart + index) % 7;
-            el.textContent = this.dayNames[dow];
-            el.className = this.daysOfWeekDisabled.includes(dow) ? 'dow disabled' : 'dow';
+      _proto._setResizeEvent = function _setResizeEvent() {
+        var _this7 = this;
+
+        if (this._isShown) {
+          EventHandler.on(window, EVENT_RESIZE, function () {
+            return _this7._adjustDialog();
           });
+        } else {
+          EventHandler.off(window, EVENT_RESIZE);
         }
-      }
+      };
 
-      // Apply update on the focused date to view's settings
-      updateFocus() {
-        const viewDate = new Date(this.picker.viewDate);
-        const viewYear = viewDate.getFullYear();
-        const viewMonth = viewDate.getMonth();
-        const firstOfMonth = dateValue(viewYear, viewMonth, 1);
-        const start = dayOfTheWeekOf(firstOfMonth, this.weekStart, this.weekStart);
+      _proto._hideModal = function _hideModal() {
+        var _this8 = this;
 
-        this.first = firstOfMonth;
-        this.last = dateValue(viewYear, viewMonth + 1, 0);
-        this.start = start;
-        this.focused = this.picker.viewDate;
-      }
+        this._element.style.display = 'none';
 
-      // Apply update on the selected dates to view's settings
-      updateSelection() {
-        const {dates, rangepicker} = this.picker.datepicker;
-        this.selected = dates;
-        if (rangepicker) {
-          this.range = rangepicker.dates;
-        }
-      }
+        this._element.setAttribute('aria-hidden', true);
 
-       // Update the entire view UI
-      render() {
-        // update today marker on ever render
-        this.today = this.todayHighlight ? today() : undefined;
-        // refresh disabled dates on every render in order to clear the ones added
-        // by beforeShow hook at previous render
-        this.disabled = [...this.datesDisabled];
+        this._element.removeAttribute('aria-modal');
 
-        const switchLabel = formatDate(this.focused, this.switchLabelFormat, this.locale);
-        this.picker.setViewSwitchLabel(switchLabel);
-        this.picker.setPrevBtnDisabled(this.first <= this.minDate);
-        this.picker.setNextBtnDisabled(this.last >= this.maxDate);
+        this._element.removeAttribute('role');
 
-        if (this.calendarWeeks) {
-          // start of the UTC week (Monday) of the 1st of the month
-          const startOfWeek = dayOfTheWeekOf(this.first, 1, 1);
-          Array.from(this.calendarWeeks.weeks.children).forEach((el, index) => {
-            el.textContent = getWeek(addWeeks(startOfWeek, index));
-          });
-        }
-        Array.from(this.grid.children).forEach((el, index) => {
-          const classList = el.classList;
-          const current = addDays(this.start, index);
-          const date = new Date(current);
-          const day = date.getDay();
+        this._isTransitioning = false;
 
-          el.className = `datepicker-cell ${this.cellClass}`;
-          el.dataset.date = current;
-          el.textContent = date.getDate();
+        this._showBackdrop(function () {
+          document.body.classList.remove(CLASS_NAME_OPEN);
 
-          if (current < this.first) {
-            classList.add('prev');
-          } else if (current > this.last) {
-            classList.add('next');
-          }
-          if (this.today === current) {
-            classList.add('today');
-          }
-          if (current < this.minDate || current > this.maxDate || this.disabled.includes(current)) {
-            classList.add('disabled');
-          }
-          if (this.daysOfWeekDisabled.includes(day)) {
-            classList.add('disabled');
-            pushUnique(this.disabled, current);
-          }
-          if (this.daysOfWeekHighlighted.includes(day)) {
-            classList.add('highlighted');
-          }
-          if (this.range) {
-            const [rangeStart, rangeEnd] = this.range;
-            if (current > rangeStart && current < rangeEnd) {
-              classList.add('range');
-            }
-            if (current === rangeStart) {
-              classList.add('range-start');
-            }
-            if (current === rangeEnd) {
-              classList.add('range-end');
-            }
-          }
-          if (this.selected.includes(current)) {
-            classList.add('selected');
-          }
-          if (current === this.focused) {
-            classList.add('focused');
-          }
+          _this8._resetAdjustments();
 
-          if (this.beforeShow) {
-            this.performBeforeHook(el, current, current);
-          }
+          _this8._resetScrollbar();
+
+          EventHandler.trigger(_this8._element, EVENT_HIDDEN$2);
         });
-      }
+      };
 
-      // Update the view UI by applying the changes of selected and focused items
-      refresh() {
-        const [rangeStart, rangeEnd] = this.range || [];
-        this.grid
-          .querySelectorAll('.range, .range-start, .range-end, .selected, .focused')
-          .forEach((el) => {
-            el.classList.remove('range', 'range-start', 'range-end', 'selected', 'focused');
-          });
-        Array.from(this.grid.children).forEach((el) => {
-          const current = Number(el.dataset.date);
-          const classList = el.classList;
-          if (current > rangeStart && current < rangeEnd) {
-            classList.add('range');
-          }
-          if (current === rangeStart) {
-            classList.add('range-start');
-          }
-          if (current === rangeEnd) {
-            classList.add('range-end');
-          }
-          if (this.selected.includes(current)) {
-            classList.add('selected');
+      _proto._removeBackdrop = function _removeBackdrop() {
+        this._backdrop.parentNode.removeChild(this._backdrop);
+
+        this._backdrop = null;
+      };
+
+      _proto._showBackdrop = function _showBackdrop(callback) {
+        var _this9 = this;
+
+        var animate = this._element.classList.contains(CLASS_NAME_FADE) ? CLASS_NAME_FADE : '';
+
+        if (this._isShown && this._config.backdrop) {
+          this._backdrop = document.createElement('div');
+          this._backdrop.className = CLASS_NAME_BACKDROP;
+
+          if (animate) {
+            this._backdrop.classList.add(animate);
           }
-          if (current === this.focused) {
-            classList.add('focused');
+
+          document.body.appendChild(this._backdrop);
+          EventHandler.on(this._element, EVENT_CLICK_DISMISS, function (event) {
+            if (_this9._ignoreBackdropClick) {
+              _this9._ignoreBackdropClick = false;
+              return;
+            }
+
+            if (event.target !== event.currentTarget) {
+              return;
+            }
+
+            if (_this9._config.backdrop === 'static') {
+              _this9._triggerBackdropTransition();
+            } else {
+              _this9.hide();
+            }
+          });
+
+          if (animate) {
+            reflow(this._backdrop);
           }
-        });
-      }
 
-      // Update the view UI by applying the change of focused item
-      refreshFocus() {
-        const index = Math.round((this.focused - this.start) / 86400000);
-        this.grid.querySelectorAll('.focused').forEach((el) => {
-          el.classList.remove('focused');
-        });
-        this.grid.children[index].classList.add('focused');
-      }
-    }
+          this._backdrop.classList.add(CLASS_NAME_SHOW$2);
 
-    function computeMonthRange(range, thisYear) {
-      if (!range || !range[0] || !range[1]) {
-        return;
-      }
+          if (!animate) {
+            callback();
+            return;
+          }
 
-      const [[startY, startM], [endY, endM]] = range;
-      if (startY > thisYear || endY < thisYear) {
-        return;
-      }
-      return [
-        startY === thisYear ? startM : -1,
-        endY === thisYear ? endM : 12,
-      ];
-    }
+          var backdropTransitionDuration = getTransitionDurationFromElement(this._backdrop);
+          EventHandler.one(this._backdrop, TRANSITION_END, callback);
+          emulateTransitionEnd(this._backdrop, backdropTransitionDuration);
+        } else if (!this._isShown && this._backdrop) {
+          this._backdrop.classList.remove(CLASS_NAME_SHOW$2);
 
-    class MonthsView extends View {
-      constructor(picker) {
-        super(picker, {
-          id: 1,
-          name: 'months',
-          cellClass: 'month',
-        });
-      }
+          var callbackRemove = function callbackRemove() {
+            _this9._removeBackdrop();
 
-      init(options, onConstruction = true) {
-        if (onConstruction) {
-          this.grid = this.element;
-          this.element.classList.add('months', 'datepicker-grid');
-          this.grid.appendChild(parseHTML(createTagRepeat('span', 12, {'data-month': ix => ix})));
-        }
-        super.init(options);
-      }
+            callback();
+          };
 
-      setOptions(options) {
-        if (options.locale) {
-          this.monthNames = options.locale.monthsShort;
-        }
-        if (hasProperty(options, 'minDate')) {
-          if (options.minDate === undefined) {
-            this.minYear = this.minMonth = this.minDate = undefined;
+          if (this._element.classList.contains(CLASS_NAME_FADE)) {
+            var _backdropTransitionDuration = getTransitionDurationFromElement(this._backdrop);
+
+            EventHandler.one(this._backdrop, TRANSITION_END, callbackRemove);
+            emulateTransitionEnd(this._backdrop, _backdropTransitionDuration);
           } else {
-            const minDateObj = new Date(options.minDate);
-            this.minYear = minDateObj.getFullYear();
-            this.minMonth = minDateObj.getMonth();
-            this.minDate = minDateObj.setDate(1);
+            callbackRemove();
           }
+        } else {
+          callback();
         }
-        if (hasProperty(options, 'maxDate')) {
-          if (options.maxDate === undefined) {
-            this.maxYear = this.maxMonth = this.maxDate = undefined;
-          } else {
-            const maxDateObj = new Date(options.maxDate);
-            this.maxYear = maxDateObj.getFullYear();
-            this.maxMonth = maxDateObj.getMonth();
-            this.maxDate = dateValue(this.maxYear, this.maxMonth + 1, 0);
-          }
+      };
+
+      _proto._triggerBackdropTransition = function _triggerBackdropTransition() {
+        var _this10 = this;
+
+        var hideEvent = EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED);
+
+        if (hideEvent.defaultPrevented) {
+          return;
         }
-        if (options.beforeShowMonth !== undefined) {
-          this.beforeShow = typeof options.beforeShowMonth === 'function'
-            ? options.beforeShowMonth
-            : undefined;
+
+        var isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight;
+
+        if (!isModalOverflowing) {
+          this._element.style.overflowY = 'hidden';
         }
-      }
 
-      // Update view's settings to reflect the viewDate set on the picker
-      updateFocus() {
-        const viewDate = new Date(this.picker.viewDate);
-        this.year = viewDate.getFullYear();
-        this.focused = viewDate.getMonth();
-      }
+        this._element.classList.add(CLASS_NAME_STATIC);
 
-      // Update view's settings to reflect the selected dates
-      updateSelection() {
-        const {dates, rangepicker} = this.picker.datepicker;
-        this.selected = dates.reduce((selected, timeValue) => {
-          const date = new Date(timeValue);
-          const year = date.getFullYear();
-          const month = date.getMonth();
-          if (selected[year] === undefined) {
-            selected[year] = [month];
-          } else {
-            pushUnique(selected[year], month);
+        var modalTransitionDuration = getTransitionDurationFromElement(this._dialog);
+        EventHandler.off(this._element, TRANSITION_END);
+        EventHandler.one(this._element, TRANSITION_END, function () {
+          _this10._element.classList.remove(CLASS_NAME_STATIC);
+
+          if (!isModalOverflowing) {
+            EventHandler.one(_this10._element, TRANSITION_END, function () {
+              _this10._element.style.overflowY = '';
+            });
+            emulateTransitionEnd(_this10._element, modalTransitionDuration);
           }
-          return selected;
-        }, {});
-        if (rangepicker && rangepicker.dates) {
-          this.range = rangepicker.dates.map(timeValue => {
-            const date = new Date(timeValue);
-            return isNaN(date) ? undefined : [date.getFullYear(), date.getMonth()];
-          });
+        });
+        emulateTransitionEnd(this._element, modalTransitionDuration);
+
+        this._element.focus();
+      } // ----------------------------------------------------------------------
+      // the following methods are used to handle overflowing modals
+      // ----------------------------------------------------------------------
+      ;
+
+      _proto._adjustDialog = function _adjustDialog() {
+        var isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight;
+
+        if (!this._isBodyOverflowing && isModalOverflowing && !isRTL || this._isBodyOverflowing && !isModalOverflowing && isRTL) {
+          this._element.style.paddingLeft = this._scrollbarWidth + "px";
         }
-      }
 
-      // Update the entire view UI
-      render() {
-        // refresh disabled months on every render in order to clear the ones added
-        // by beforeShow hook at previous render
-        this.disabled = [];
+        if (this._isBodyOverflowing && !isModalOverflowing && !isRTL || !this._isBodyOverflowing && isModalOverflowing && isRTL) {
+          this._element.style.paddingRight = this._scrollbarWidth + "px";
+        }
+      };
 
-        this.picker.setViewSwitchLabel(this.year);
-        this.picker.setPrevBtnDisabled(this.year <= this.minYear);
-        this.picker.setNextBtnDisabled(this.year >= this.maxYear);
+      _proto._resetAdjustments = function _resetAdjustments() {
+        this._element.style.paddingLeft = '';
+        this._element.style.paddingRight = '';
+      };
 
-        const selected = this.selected[this.year] || [];
-        const yrOutOfRange = this.year < this.minYear || this.year > this.maxYear;
-        const isMinYear = this.year === this.minYear;
-        const isMaxYear = this.year === this.maxYear;
-        const range = computeMonthRange(this.range, this.year);
+      _proto._checkScrollbar = function _checkScrollbar() {
+        var rect = document.body.getBoundingClientRect();
+        this._isBodyOverflowing = Math.round(rect.left + rect.right) < window.innerWidth;
+        this._scrollbarWidth = this._getScrollbarWidth();
+      };
 
-        Array.from(this.grid.children).forEach((el, index) => {
-          const classList = el.classList;
-          const date = dateValue(this.year, index, 1);
+      _proto._setScrollbar = function _setScrollbar() {
+        var _this11 = this;
+
+        if (this._isBodyOverflowing) {
+          // Note: DOMNode.style.paddingRight returns the actual value or '' if not set
+          //   while $(DOMNode).css('padding-right') returns the calculated value or 0 if not set
+          // Adjust fixed content padding
+          SelectorEngine.find(SELECTOR_FIXED_CONTENT).forEach(function (element) {
+            var actualPadding = element.style.paddingRight;
+            var calculatedPadding = window.getComputedStyle(element)['padding-right'];
+            Manipulator.setDataAttribute(element, 'padding-right', actualPadding);
+            element.style.paddingRight = Number.parseFloat(calculatedPadding) + _this11._scrollbarWidth + "px";
+          }); // Adjust sticky content margin
+
+          SelectorEngine.find(SELECTOR_STICKY_CONTENT).forEach(function (element) {
... 3619 lines suppressed ...