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/28 16:48:12 UTC

[myfaces-tobago] branch master updated: use bootstrap-dropdown.js -> rebuild JS/CSS resources after last changes

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


The following commit(s) were added to refs/heads/master by this push:
     new 52e04b1  use bootstrap-dropdown.js -> rebuild JS/CSS resources after last changes
52e04b1 is described below

commit 52e04b12d1444364f2648c7a56d4ba5738d6b181
Author: Udo Schnurpfeil <ud...@irian.eu>
AuthorDate: Thu Jan 28 17:31:45 2021 +0100

    use bootstrap-dropdown.js -> rebuild JS/CSS resources after last changes
---
 .../npm/dist/css/tobago.css                        |    3 +
 .../npm/dist/css/tobago.css.map                    |    2 +-
 .../npm/dist/css/tobago.min.css                    |    2 +-
 .../npm/dist/css/tobago.min.css.map                |    2 +-
 .../npm/dist/css/tobago.css                        |    3 +
 .../npm/dist/css/tobago.css.map                    |    2 +-
 .../npm/dist/css/tobago.min.css                    |    2 +-
 .../npm/dist/css/tobago.min.css.map                |    2 +-
 .../npm/dist/css/tobago.css                        |    3 +
 .../npm/dist/css/tobago.css.map                    |    2 +-
 .../npm/dist/css/tobago.min.css                    |    2 +-
 .../npm/dist/css/tobago.min.css.map                |    2 +-
 .../tobago-theme-speyside/npm/dist/css/tobago.css  |    3 +
 .../npm/dist/css/tobago.css.map                    |    2 +-
 .../npm/dist/css/tobago.min.css                    |    2 +-
 .../npm/dist/css/tobago.min.css.map                |    2 +-
 .../tobago-theme-standard/npm/dist/css/tobago.css  |    3 +
 .../npm/dist/css/tobago.css.map                    |    2 +-
 .../npm/dist/css/tobago.min.css                    |    2 +-
 .../npm/dist/css/tobago.min.css.map                |    2 +-
 .../npm/dist/js/tobago-dropdown.js                 |  250 +-
 .../npm/dist/js/tobago-dropdown.js.map             |    2 +-
 .../tobago-theme-standard/npm/dist/js/tobago.js    | 8045 ++++++++++----------
 .../npm/dist/js/tobago.js.map                      |    2 +-
 24 files changed, 3954 insertions(+), 4390 deletions(-)

diff --git a/tobago-theme/tobago-theme-charlotteville/npm/dist/css/tobago.css b/tobago-theme/tobago-theme-charlotteville/npm/dist/css/tobago.css
index 12b9339..67427e0 100644
--- a/tobago-theme/tobago-theme-charlotteville/npm/dist/css/tobago.css
+++ b/tobago-theme/tobago-theme-charlotteville/npm/dist/css/tobago.css
@@ -11178,6 +11178,9 @@ workaround for Bootstrap Modal (Popup) with vanillajs-datepicker
 }
 
 /* dropdown ------------------------------------------------------- */
+tobago-dropdown {
+  display: inline-block;
+}
 tobago-dropdown .dropdown-menu .form-check {
   /* move form-check components to the right, so checkbox/radio buttons are inside dropdown-menu */
   padding-left: 2.5em;
diff --git a/tobago-theme/tobago-theme-charlotteville/npm/dist/css/tobago.css.map b/tobago-theme/tobago-theme-charlotteville/npm/dist/css/tobago.css.map
index d5cd046..cee2cde 100644
--- a/tobago-theme/tobago-theme-charlotteville/npm/dist/css/tobago.css.map
+++ b/tobago-theme/tobago-theme-charlotteville/npm/dist/css/tobago.css.map
@@ -1 +1 @@
-{"version":3,"sources":["tobago.css","../../scss/tobago-theme.scss","../../scss/_custom.scss","../../node_modules/bootstrap/scss/bootstrap.scss","../../node_modules/bootstrap/scss/_root.scss","../../node_modules/bootstrap/scss/_reboot.scss","../../node_modules/bootstrap/scss/_variables.scss","../../node_modules/bootstrap/scss/vendor/_rfs.scss","../../node_modules/bootstrap/scss/mixins/_border-radius.scss","../../node_modules/bootstrap/scss/_type.scss","../../node_modules/bootstrap/scss/m [...]
\ No newline at end of file
+{"version":3,"sources":["tobago.css","../../scss/tobago-theme.scss","../../scss/_custom.scss","../../node_modules/bootstrap/scss/bootstrap.scss","../../node_modules/bootstrap/scss/_root.scss","../../node_modules/bootstrap/scss/_reboot.scss","../../node_modules/bootstrap/scss/_variables.scss","../../node_modules/bootstrap/scss/vendor/_rfs.scss","../../node_modules/bootstrap/scss/mixins/_border-radius.scss","../../node_modules/bootstrap/scss/_type.scss","../../node_modules/bootstrap/scss/m [...]
\ No newline at end of file
diff --git a/tobago-theme/tobago-theme-charlotteville/npm/dist/css/tobago.min.css b/tobago-theme/tobago-theme-charlotteville/npm/dist/css/tobago.min.css
index f60812a..adde969 100644
--- a/tobago-theme/tobago-theme-charlotteville/npm/dist/css/tobago.min.css
+++ b/tobago-theme/tobago-theme-charlotteville/npm/dist/css/tobago.min.css
@@ -1,2 +1,2 @@
-@charset "UTF-8";:root{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:#6f42c1;--bs-pink:#ff00be;--bs-red:#dc3545;--bs-orange:#fd7e14;--bs-yellow:#ffc107;--bs-green:#198754;--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-white:#ffffff;--bs-gray:#777777;--bs-gray-dark:#323232;--bs-primary:#529696;--bs-secondary:#b2a76d;--bs-success:#abf5ff;--bs-info:#389c30;--bs-warning:#ff00be;--bs-danger:#ff00be;--bs-light:#ffffff;--bs-dark:#529696;--bs-font-sans-serif:system-ui,-apple-system,"Segoe UI",Robo [...]
+@charset "UTF-8";:root{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:#6f42c1;--bs-pink:#ff00be;--bs-red:#dc3545;--bs-orange:#fd7e14;--bs-yellow:#ffc107;--bs-green:#198754;--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-white:#ffffff;--bs-gray:#777777;--bs-gray-dark:#323232;--bs-primary:#529696;--bs-secondary:#b2a76d;--bs-success:#abf5ff;--bs-info:#389c30;--bs-warning:#ff00be;--bs-danger:#ff00be;--bs-light:#ffffff;--bs-dark:#529696;--bs-font-sans-serif:system-ui,-apple-system,"Segoe UI",Robo [...]
 /*# sourceMappingURL=tobago.min.css.map */
\ No newline at end of file
diff --git a/tobago-theme/tobago-theme-charlotteville/npm/dist/css/tobago.min.css.map b/tobago-theme/tobago-theme-charlotteville/npm/dist/css/tobago.min.css.map
index ddd0c21..68581fc 100644
--- a/tobago-theme/tobago-theme-charlotteville/npm/dist/css/tobago.min.css.map
+++ b/tobago-theme/tobago-theme-charlotteville/npm/dist/css/tobago.min.css.map
@@ -1 +1 @@
-{"version":3,"sources":["../../node_modules/bootstrap/scss/_root.scss","../../node_modules/bootstrap/scss/_reboot.scss","dist/css/tobago.css","../../node_modules/bootstrap/scss/vendor/_rfs.scss","../../node_modules/bootstrap/scss/mixins/_border-radius.scss","../../node_modules/bootstrap/scss/_type.scss","../../node_modules/bootstrap/scss/mixins/_lists.scss","../../node_modules/bootstrap/scss/_images.scss","../../node_modules/bootstrap/scss/mixins/_image.scss","../../node_modules/bootstra [...]
\ No newline at end of file
+{"version":3,"sources":["../../node_modules/bootstrap/scss/_root.scss","../../node_modules/bootstrap/scss/_reboot.scss","dist/css/tobago.css","../../node_modules/bootstrap/scss/vendor/_rfs.scss","../../node_modules/bootstrap/scss/mixins/_border-radius.scss","../../node_modules/bootstrap/scss/_type.scss","../../node_modules/bootstrap/scss/mixins/_lists.scss","../../node_modules/bootstrap/scss/_images.scss","../../node_modules/bootstrap/scss/mixins/_image.scss","../../node_modules/bootstra [...]
\ No newline at end of file
diff --git a/tobago-theme/tobago-theme-roxborough/npm/dist/css/tobago.css b/tobago-theme/tobago-theme-roxborough/npm/dist/css/tobago.css
index 2ec6bdc..d5b72d0 100644
--- a/tobago-theme/tobago-theme-roxborough/npm/dist/css/tobago.css
+++ b/tobago-theme/tobago-theme-roxborough/npm/dist/css/tobago.css
@@ -11201,6 +11201,9 @@ workaround for Bootstrap Modal (Popup) with vanillajs-datepicker
 }
 
 /* dropdown ------------------------------------------------------- */
+tobago-dropdown {
+  display: inline-block;
+}
 tobago-dropdown .dropdown-menu .form-check {
   /* move form-check components to the right, so checkbox/radio buttons are inside dropdown-menu */
   padding-left: 2.5em;
diff --git a/tobago-theme/tobago-theme-roxborough/npm/dist/css/tobago.css.map b/tobago-theme/tobago-theme-roxborough/npm/dist/css/tobago.css.map
index 50e17fb..59a7c65 100644
--- a/tobago-theme/tobago-theme-roxborough/npm/dist/css/tobago.css.map
+++ b/tobago-theme/tobago-theme-roxborough/npm/dist/css/tobago.css.map
@@ -1 +1 @@
-{"version":3,"sources":["tobago.css","../../scss/tobago-theme.scss","../../scss/_custom.scss","../../node_modules/bootstrap/scss/bootstrap.scss","../../node_modules/bootstrap/scss/_root.scss","../../node_modules/bootstrap/scss/_reboot.scss","../../node_modules/bootstrap/scss/_variables.scss","../../node_modules/bootstrap/scss/vendor/_rfs.scss","../../node_modules/bootstrap/scss/mixins/_border-radius.scss","../../node_modules/bootstrap/scss/_type.scss","../../node_modules/bootstrap/scss/m [...]
\ No newline at end of file
+{"version":3,"sources":["tobago.css","../../scss/tobago-theme.scss","../../scss/_custom.scss","../../node_modules/bootstrap/scss/bootstrap.scss","../../node_modules/bootstrap/scss/_root.scss","../../node_modules/bootstrap/scss/_reboot.scss","../../node_modules/bootstrap/scss/_variables.scss","../../node_modules/bootstrap/scss/vendor/_rfs.scss","../../node_modules/bootstrap/scss/mixins/_border-radius.scss","../../node_modules/bootstrap/scss/_type.scss","../../node_modules/bootstrap/scss/m [...]
\ No newline at end of file
diff --git a/tobago-theme/tobago-theme-roxborough/npm/dist/css/tobago.min.css b/tobago-theme/tobago-theme-roxborough/npm/dist/css/tobago.min.css
index 5023f2b..1b8020d 100644
--- a/tobago-theme/tobago-theme-roxborough/npm/dist/css/tobago.min.css
+++ b/tobago-theme/tobago-theme-roxborough/npm/dist/css/tobago.min.css
@@ -1,2 +1,2 @@
-@charset "UTF-8";@font-face{font-family:Amaranth;font-style:normal;font-weight:400;src:url(../fonts/Amaranth-Regular.otf) format("opentype")}@font-face{font-family:Amaranth;font-style:normal;font-weight:700;src:url(../fonts/Amaranth-Bold.otf) format("opentype")}@font-face{font-family:Amaranth;font-style:italic;src:url(../fonts/Amaranth-Italic.otf) format("opentype")}@font-face{font-family:Amaranth;font-style:italic;font-weight:700;src:url(../fonts/Amaranth-BoldItalic.otf) format("opentyp [...]
+@charset "UTF-8";@font-face{font-family:Amaranth;font-style:normal;font-weight:400;src:url(../fonts/Amaranth-Regular.otf) format("opentype")}@font-face{font-family:Amaranth;font-style:normal;font-weight:700;src:url(../fonts/Amaranth-Bold.otf) format("opentype")}@font-face{font-family:Amaranth;font-style:italic;src:url(../fonts/Amaranth-Italic.otf) format("opentype")}@font-face{font-family:Amaranth;font-style:italic;font-weight:700;src:url(../fonts/Amaranth-BoldItalic.otf) format("opentyp [...]
 /*# sourceMappingURL=tobago.min.css.map */
\ No newline at end of file
diff --git a/tobago-theme/tobago-theme-roxborough/npm/dist/css/tobago.min.css.map b/tobago-theme/tobago-theme-roxborough/npm/dist/css/tobago.min.css.map
index 69c6cf3..31d6d5b 100644
--- a/tobago-theme/tobago-theme-roxborough/npm/dist/css/tobago.min.css.map
+++ b/tobago-theme/tobago-theme-roxborough/npm/dist/css/tobago.min.css.map
@@ -1 +1 @@
-{"version":3,"sources":["../../scss/_custom.scss","../../node_modules/bootstrap/scss/_root.scss","../../node_modules/bootstrap/scss/_reboot.scss","dist/css/tobago.css","../../node_modules/bootstrap/scss/vendor/_rfs.scss","../../node_modules/bootstrap/scss/mixins/_border-radius.scss","../../node_modules/bootstrap/scss/_type.scss","../../node_modules/bootstrap/scss/mixins/_lists.scss","../../node_modules/bootstrap/scss/_images.scss","../../node_modules/bootstrap/scss/mixins/_image.scss",". [...]
\ No newline at end of file
+{"version":3,"sources":["../../scss/_custom.scss","../../node_modules/bootstrap/scss/_root.scss","../../node_modules/bootstrap/scss/_reboot.scss","dist/css/tobago.css","../../node_modules/bootstrap/scss/vendor/_rfs.scss","../../node_modules/bootstrap/scss/mixins/_border-radius.scss","../../node_modules/bootstrap/scss/_type.scss","../../node_modules/bootstrap/scss/mixins/_lists.scss","../../node_modules/bootstrap/scss/_images.scss","../../node_modules/bootstrap/scss/mixins/_image.scss",". [...]
\ No newline at end of file
diff --git a/tobago-theme/tobago-theme-scarborough/npm/dist/css/tobago.css b/tobago-theme/tobago-theme-scarborough/npm/dist/css/tobago.css
index 36299de..23ec9ff 100644
--- a/tobago-theme/tobago-theme-scarborough/npm/dist/css/tobago.css
+++ b/tobago-theme/tobago-theme-scarborough/npm/dist/css/tobago.css
@@ -11188,6 +11188,9 @@ workaround for Bootstrap Modal (Popup) with vanillajs-datepicker
 }
 
 /* dropdown ------------------------------------------------------- */
+tobago-dropdown {
+  display: inline-block;
+}
 tobago-dropdown .dropdown-menu .form-check {
   /* move form-check components to the right, so checkbox/radio buttons are inside dropdown-menu */
   padding-left: 2.5em;
diff --git a/tobago-theme/tobago-theme-scarborough/npm/dist/css/tobago.css.map b/tobago-theme/tobago-theme-scarborough/npm/dist/css/tobago.css.map
index 80f83cc..c65e676 100644
--- a/tobago-theme/tobago-theme-scarborough/npm/dist/css/tobago.css.map
+++ b/tobago-theme/tobago-theme-scarborough/npm/dist/css/tobago.css.map
@@ -1 +1 @@
-{"version":3,"sources":["tobago.css","../../scss/tobago-theme.scss","../../node_modules/bootstrap/scss/bootstrap.scss","../../node_modules/bootstrap/scss/_root.scss","../../node_modules/bootstrap/scss/_reboot.scss","../../node_modules/bootstrap/scss/_variables.scss","../../node_modules/bootstrap/scss/vendor/_rfs.scss","../../node_modules/bootstrap/scss/mixins/_border-radius.scss","../../node_modules/bootstrap/scss/_type.scss","../../node_modules/bootstrap/scss/mixins/_lists.scss","../../ [...]
\ No newline at end of file
+{"version":3,"sources":["tobago.css","../../scss/tobago-theme.scss","../../node_modules/bootstrap/scss/bootstrap.scss","../../node_modules/bootstrap/scss/_root.scss","../../node_modules/bootstrap/scss/_reboot.scss","../../node_modules/bootstrap/scss/_variables.scss","../../node_modules/bootstrap/scss/vendor/_rfs.scss","../../node_modules/bootstrap/scss/mixins/_border-radius.scss","../../node_modules/bootstrap/scss/_type.scss","../../node_modules/bootstrap/scss/mixins/_lists.scss","../../ [...]
\ No newline at end of file
diff --git a/tobago-theme/tobago-theme-scarborough/npm/dist/css/tobago.min.css b/tobago-theme/tobago-theme-scarborough/npm/dist/css/tobago.min.css
index 3cfb3f5..03ea14a 100644
--- a/tobago-theme/tobago-theme-scarborough/npm/dist/css/tobago.min.css
+++ b/tobago-theme/tobago-theme-scarborough/npm/dist/css/tobago.min.css
@@ -1,2 +1,2 @@
-@charset "UTF-8";:root{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:#6f42c1;--bs-pink:#d63384;--bs-red:#dc3545;--bs-orange:#fd7e14;--bs-yellow:#ffc107;--bs-green:#198754;--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-white:#fff;--bs-gray:#6c757d;--bs-gray-dark:#343a40;--bs-primary:#0d6efd;--bs-secondary:#6c757d;--bs-success:#198754;--bs-info:#0dcaf0;--bs-warning:#ffc107;--bs-danger:#dc3545;--bs-light:#f8f9fa;--bs-dark:#212529;--bs-font-sans-serif:system-ui,-apple-system,"Segoe UI",Roboto, [...]
+@charset "UTF-8";:root{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:#6f42c1;--bs-pink:#d63384;--bs-red:#dc3545;--bs-orange:#fd7e14;--bs-yellow:#ffc107;--bs-green:#198754;--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-white:#fff;--bs-gray:#6c757d;--bs-gray-dark:#343a40;--bs-primary:#0d6efd;--bs-secondary:#6c757d;--bs-success:#198754;--bs-info:#0dcaf0;--bs-warning:#ffc107;--bs-danger:#dc3545;--bs-light:#f8f9fa;--bs-dark:#212529;--bs-font-sans-serif:system-ui,-apple-system,"Segoe UI",Roboto, [...]
 /*# sourceMappingURL=tobago.min.css.map */
\ No newline at end of file
diff --git a/tobago-theme/tobago-theme-scarborough/npm/dist/css/tobago.min.css.map b/tobago-theme/tobago-theme-scarborough/npm/dist/css/tobago.min.css.map
index a1e7a14..d50af3c 100644
--- a/tobago-theme/tobago-theme-scarborough/npm/dist/css/tobago.min.css.map
+++ b/tobago-theme/tobago-theme-scarborough/npm/dist/css/tobago.min.css.map
@@ -1 +1 @@
-{"version":3,"sources":["../../node_modules/bootstrap/scss/_root.scss","../../node_modules/bootstrap/scss/_reboot.scss","dist/css/tobago.css","../../node_modules/bootstrap/scss/vendor/_rfs.scss","../../node_modules/bootstrap/scss/mixins/_border-radius.scss","../../node_modules/bootstrap/scss/_type.scss","../../node_modules/bootstrap/scss/mixins/_lists.scss","../../node_modules/bootstrap/scss/_images.scss","../../node_modules/bootstrap/scss/mixins/_image.scss","../../node_modules/bootstra [...]
\ No newline at end of file
+{"version":3,"sources":["../../node_modules/bootstrap/scss/_root.scss","../../node_modules/bootstrap/scss/_reboot.scss","dist/css/tobago.css","../../node_modules/bootstrap/scss/vendor/_rfs.scss","../../node_modules/bootstrap/scss/mixins/_border-radius.scss","../../node_modules/bootstrap/scss/_type.scss","../../node_modules/bootstrap/scss/mixins/_lists.scss","../../node_modules/bootstrap/scss/_images.scss","../../node_modules/bootstrap/scss/mixins/_image.scss","../../node_modules/bootstra [...]
\ No newline at end of file
diff --git a/tobago-theme/tobago-theme-speyside/npm/dist/css/tobago.css b/tobago-theme/tobago-theme-speyside/npm/dist/css/tobago.css
index 0d5aed6..17dcf2d 100644
--- a/tobago-theme/tobago-theme-speyside/npm/dist/css/tobago.css
+++ b/tobago-theme/tobago-theme-speyside/npm/dist/css/tobago.css
@@ -10888,6 +10888,9 @@ workaround for Bootstrap Modal (Popup) with vanillajs-datepicker
 }
 
 /* dropdown ------------------------------------------------------- */
+tobago-dropdown {
+  display: inline-block;
+}
 tobago-dropdown .dropdown-menu .form-check {
   /* move form-check components to the right, so checkbox/radio buttons are inside dropdown-menu */
   padding-left: 2.5em;
diff --git a/tobago-theme/tobago-theme-speyside/npm/dist/css/tobago.css.map b/tobago-theme/tobago-theme-speyside/npm/dist/css/tobago.css.map
index 4d2b0a1..7cdd094 100644
--- a/tobago-theme/tobago-theme-speyside/npm/dist/css/tobago.css.map
+++ b/tobago-theme/tobago-theme-speyside/npm/dist/css/tobago.css.map
@@ -1 +1 @@
-{"version":3,"sources":["tobago.css","../../scss/tobago-theme.scss","../../scss/_custom.scss","../../node_modules/bootstrap/scss/bootstrap.scss","../../node_modules/bootstrap/scss/_root.scss","../../node_modules/bootstrap/scss/_reboot.scss","../../node_modules/bootstrap/scss/vendor/_rfs.scss","../../node_modules/bootstrap/scss/_variables.scss","../../node_modules/bootstrap/scss/_type.scss","../../node_modules/bootstrap/scss/mixins/_lists.scss","../../node_modules/bootstrap/scss/_images.s [...]
\ No newline at end of file
+{"version":3,"sources":["tobago.css","../../scss/tobago-theme.scss","../../scss/_custom.scss","../../node_modules/bootstrap/scss/bootstrap.scss","../../node_modules/bootstrap/scss/_root.scss","../../node_modules/bootstrap/scss/_reboot.scss","../../node_modules/bootstrap/scss/vendor/_rfs.scss","../../node_modules/bootstrap/scss/_variables.scss","../../node_modules/bootstrap/scss/_type.scss","../../node_modules/bootstrap/scss/mixins/_lists.scss","../../node_modules/bootstrap/scss/_images.s [...]
\ No newline at end of file
diff --git a/tobago-theme/tobago-theme-speyside/npm/dist/css/tobago.min.css b/tobago-theme/tobago-theme-speyside/npm/dist/css/tobago.min.css
index 29beaf1..a2f83e0 100644
--- a/tobago-theme/tobago-theme-speyside/npm/dist/css/tobago.min.css
+++ b/tobago-theme/tobago-theme-speyside/npm/dist/css/tobago.min.css
@@ -1,2 +1,2 @@
-@charset "UTF-8";:root{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:#3a2564;--bs-pink:#d63384;--bs-red:#d30040;--bs-orange:#d90;--bs-yellow:#ffc107;--bs-green:#1da332;--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-white:#fff;--bs-gray:#788c94;--bs-gray-dark:#323232;--bs-primary:#185722;--bs-secondary:#d7d7d7;--bs-success:#1da332;--bs-info:#5bc0de;--bs-warning:#f0ad4e;--bs-danger:#d30040;--bs-light:#f7f7f7;--bs-dark:#323232;--bs-font-sans-serif:verdana,sans-serif;--bs-font-monospace:SFMono [...]
+@charset "UTF-8";:root{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:#3a2564;--bs-pink:#d63384;--bs-red:#d30040;--bs-orange:#d90;--bs-yellow:#ffc107;--bs-green:#1da332;--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-white:#fff;--bs-gray:#788c94;--bs-gray-dark:#323232;--bs-primary:#185722;--bs-secondary:#d7d7d7;--bs-success:#1da332;--bs-info:#5bc0de;--bs-warning:#f0ad4e;--bs-danger:#d30040;--bs-light:#f7f7f7;--bs-dark:#323232;--bs-font-sans-serif:verdana,sans-serif;--bs-font-monospace:SFMono [...]
 /*# sourceMappingURL=tobago.min.css.map */
\ No newline at end of file
diff --git a/tobago-theme/tobago-theme-speyside/npm/dist/css/tobago.min.css.map b/tobago-theme/tobago-theme-speyside/npm/dist/css/tobago.min.css.map
index b946b04..84aa2f4 100644
--- a/tobago-theme/tobago-theme-speyside/npm/dist/css/tobago.min.css.map
+++ b/tobago-theme/tobago-theme-speyside/npm/dist/css/tobago.min.css.map
@@ -1 +1 @@
-{"version":3,"sources":["../../node_modules/bootstrap/scss/_root.scss","../../node_modules/bootstrap/scss/_reboot.scss","dist/css/tobago.css","../../node_modules/bootstrap/scss/vendor/_rfs.scss","../../node_modules/bootstrap/scss/_type.scss","../../node_modules/bootstrap/scss/mixins/_lists.scss","../../node_modules/bootstrap/scss/_images.scss","../../node_modules/bootstrap/scss/mixins/_image.scss","../../node_modules/bootstrap/scss/_containers.scss","../../node_modules/bootstrap/scss/mix [...]
\ No newline at end of file
+{"version":3,"sources":["../../node_modules/bootstrap/scss/_root.scss","../../node_modules/bootstrap/scss/_reboot.scss","dist/css/tobago.css","../../node_modules/bootstrap/scss/vendor/_rfs.scss","../../node_modules/bootstrap/scss/_type.scss","../../node_modules/bootstrap/scss/mixins/_lists.scss","../../node_modules/bootstrap/scss/_images.scss","../../node_modules/bootstrap/scss/mixins/_image.scss","../../node_modules/bootstrap/scss/_containers.scss","../../node_modules/bootstrap/scss/mix [...]
\ No newline at end of file
diff --git a/tobago-theme/tobago-theme-standard/npm/dist/css/tobago.css b/tobago-theme/tobago-theme-standard/npm/dist/css/tobago.css
index e837233..b6e0dee 100644
--- a/tobago-theme/tobago-theme-standard/npm/dist/css/tobago.css
+++ b/tobago-theme/tobago-theme-standard/npm/dist/css/tobago.css
@@ -11158,6 +11158,9 @@ workaround for Bootstrap Modal (Popup) with vanillajs-datepicker
 }
 
 /* dropdown ------------------------------------------------------- */
+tobago-dropdown {
+  display: inline-block;
+}
 tobago-dropdown .dropdown-menu .form-check {
   /* move form-check components to the right, so checkbox/radio buttons are inside dropdown-menu */
   padding-left: 2.5em;
diff --git a/tobago-theme/tobago-theme-standard/npm/dist/css/tobago.css.map b/tobago-theme/tobago-theme-standard/npm/dist/css/tobago.css.map
index f0e5a1d..9573365 100644
--- a/tobago-theme/tobago-theme-standard/npm/dist/css/tobago.css.map
+++ b/tobago-theme/tobago-theme-standard/npm/dist/css/tobago.css.map
@@ -1 +1 @@
-{"version":3,"sources":["tobago.css","../../scss/tobago-theme.scss","../../node_modules/bootstrap/scss/bootstrap.scss","../../node_modules/bootstrap/scss/_root.scss","../../node_modules/bootstrap/scss/_reboot.scss","../../node_modules/bootstrap/scss/_variables.scss","../../node_modules/bootstrap/scss/vendor/_rfs.scss","../../node_modules/bootstrap/scss/mixins/_border-radius.scss","../../node_modules/bootstrap/scss/_type.scss","../../node_modules/bootstrap/scss/mixins/_lists.scss","../../ [...]
\ No newline at end of file
+{"version":3,"sources":["tobago.css","../../scss/tobago-theme.scss","../../node_modules/bootstrap/scss/bootstrap.scss","../../node_modules/bootstrap/scss/_root.scss","../../node_modules/bootstrap/scss/_reboot.scss","../../node_modules/bootstrap/scss/_variables.scss","../../node_modules/bootstrap/scss/vendor/_rfs.scss","../../node_modules/bootstrap/scss/mixins/_border-radius.scss","../../node_modules/bootstrap/scss/_type.scss","../../node_modules/bootstrap/scss/mixins/_lists.scss","../../ [...]
\ No newline at end of file
diff --git a/tobago-theme/tobago-theme-standard/npm/dist/css/tobago.min.css b/tobago-theme/tobago-theme-standard/npm/dist/css/tobago.min.css
index d08b89c..0295e1d 100644
--- a/tobago-theme/tobago-theme-standard/npm/dist/css/tobago.min.css
+++ b/tobago-theme/tobago-theme-standard/npm/dist/css/tobago.min.css
@@ -1,2 +1,2 @@
-@charset "UTF-8";:root{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:#6f42c1;--bs-pink:#d63384;--bs-red:#dc3545;--bs-orange:#fd7e14;--bs-yellow:#ffc107;--bs-green:#198754;--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-white:#fff;--bs-gray:#6c757d;--bs-gray-dark:#343a40;--bs-primary:#0d6efd;--bs-secondary:#6c757d;--bs-success:#198754;--bs-info:#0dcaf0;--bs-warning:#ffc107;--bs-danger:#dc3545;--bs-light:#f8f9fa;--bs-dark:#212529;--bs-font-sans-serif:system-ui,-apple-system,"Segoe UI",Roboto, [...]
+@charset "UTF-8";:root{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:#6f42c1;--bs-pink:#d63384;--bs-red:#dc3545;--bs-orange:#fd7e14;--bs-yellow:#ffc107;--bs-green:#198754;--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-white:#fff;--bs-gray:#6c757d;--bs-gray-dark:#343a40;--bs-primary:#0d6efd;--bs-secondary:#6c757d;--bs-success:#198754;--bs-info:#0dcaf0;--bs-warning:#ffc107;--bs-danger:#dc3545;--bs-light:#f8f9fa;--bs-dark:#212529;--bs-font-sans-serif:system-ui,-apple-system,"Segoe UI",Roboto, [...]
 /*# sourceMappingURL=tobago.min.css.map */
\ No newline at end of file
diff --git a/tobago-theme/tobago-theme-standard/npm/dist/css/tobago.min.css.map b/tobago-theme/tobago-theme-standard/npm/dist/css/tobago.min.css.map
index 63f9c0c..a37138e 100644
--- a/tobago-theme/tobago-theme-standard/npm/dist/css/tobago.min.css.map
+++ b/tobago-theme/tobago-theme-standard/npm/dist/css/tobago.min.css.map
@@ -1 +1 @@
-{"version":3,"sources":["../../node_modules/bootstrap/scss/_root.scss","../../node_modules/bootstrap/scss/_reboot.scss","dist/css/tobago.css","../../node_modules/bootstrap/scss/vendor/_rfs.scss","../../node_modules/bootstrap/scss/mixins/_border-radius.scss","../../node_modules/bootstrap/scss/_type.scss","../../node_modules/bootstrap/scss/mixins/_lists.scss","../../node_modules/bootstrap/scss/_images.scss","../../node_modules/bootstrap/scss/mixins/_image.scss","../../node_modules/bootstra [...]
\ No newline at end of file
+{"version":3,"sources":["../../node_modules/bootstrap/scss/_root.scss","../../node_modules/bootstrap/scss/_reboot.scss","dist/css/tobago.css","../../node_modules/bootstrap/scss/vendor/_rfs.scss","../../node_modules/bootstrap/scss/mixins/_border-radius.scss","../../node_modules/bootstrap/scss/_type.scss","../../node_modules/bootstrap/scss/mixins/_lists.scss","../../node_modules/bootstrap/scss/_images.scss","../../node_modules/bootstrap/scss/mixins/_image.scss","../../node_modules/bootstra [...]
\ No newline at end of file
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 6f4fb1c..d0f2365 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,147 +14,40 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import { createPopper } from "@popperjs/core";
 // import {createPopper} from "@popperjs/core/dist/esm/popper";
-const Event = {
+const TobagoDropdownEvent = {
     HIDE: "tobago.dropdown.hide",
     HIDDEN: "tobago.dropdown.hidden",
     SHOW: "tobago.dropdown.show",
     SHOWN: "tobago.dropdown.shown"
 };
 /**
- * The dropdown implementation of Bootstrap does not support submenus. Therefore we need an own dropdown implementation.
+ * The dropdown implementation of Bootstrap does not move the menu to the tobago-page-menuStore. This behavior is
+ * implemented in this class.
  */
 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));
+            this.addEventListener("shown.bs.dropdown", this.openDropdown.bind(this));
+            this.addEventListener("hidden.bs.dropdown", this.closeDropdown.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();
-            event.stopPropagation();
-            this.openDropdown();
-            const interval = setInterval(() => {
-                if (this.dropdownVisible()) {
-                    if (this.activeDropdownEntry) {
-                        this.activeDropdownEntry.focus();
-                    }
-                    else {
-                        this.dropdownEntries[0].focus();
-                    }
-                    clearInterval(interval);
-                }
-            }, 0);
-        }
-        else if (this.dropdownVisible()
-            && (event.code === "ArrowUp" || event.code === "ArrowDown"
-                || event.code === "ArrowLeft" || event.code === "ArrowRight"
-                || event.code === "Tab")) {
-            event.preventDefault();
-            event.stopPropagation();
-            if (!this.activeDropdownEntry) {
-                this.dropdownEntries[0].focus();
-            }
-            else if (event.code === "ArrowUp" && this.activeDropdownEntry.previous) {
-                this.activeDropdownEntry.previous.focus();
-            }
-            else if (event.code === "ArrowDown" && this.activeDropdownEntry.next) {
-                this.activeDropdownEntry.next.focus();
-            }
-            else if (event.code === "ArrowRight" && this.activeDropdownEntry.children.length > 0) {
-                this.activeDropdownEntry.children[0].focus();
-            }
-            else if (event.code === "ArrowLeft" && this.activeDropdownEntry.parent) {
-                this.activeDropdownEntry.parent.focus();
-            }
-            else if (!event.shiftKey && event.code === "Tab") {
-                if (this.activeDropdownEntry.children.length > 0) {
-                    this.activeDropdownEntry.children[0].focus();
-                }
-                else if (this.activeDropdownEntry.next) {
-                    this.activeDropdownEntry.next.focus();
-                }
-                else {
-                    let parent = this.activeDropdownEntry.parent;
-                    while (parent) {
-                        if (parent.next) {
-                            this.activeDropdownEntry.clear();
-                            parent.next.focus();
-                            break;
-                        }
-                        else {
-                            parent = parent.parent;
-                        }
-                    }
-                }
-            }
-            else if (event.shiftKey && event.code === "Tab") {
-                if (this.activeDropdownEntry.previous) {
-                    this.activeDropdownEntry.previous.focus();
-                }
-                else if (this.activeDropdownEntry.parent) {
-                    this.activeDropdownEntry.parent.focus();
-                }
-            }
-        }
-        else if (this.dropdownVisible() && event.code === "Escape") {
-            event.preventDefault();
-            event.stopPropagation();
-            this.closeDropdown();
-        }
-    }
     openDropdown() {
-        this.dispatchEvent(new CustomEvent(Event.SHOW));
+        this.dispatchEvent(new CustomEvent(TobagoDropdownEvent.SHOW));
         if (!this.inStickyHeader()) {
             this.menuStore.appendChild(this.dropdownMenu);
-            createPopper(this.toggleButton, this.dropdownMenu, {
-                placement: "bottom-start"
-            });
         }
-        for (const dropdownEntry of this.dropdownEntries) {
-            dropdownEntry.clear();
-        }
-        this.dropdownMenu.classList.add("show");
-        this.dispatchEvent(new CustomEvent(Event.SHOWN));
+        this.dispatchEvent(new CustomEvent(TobagoDropdownEvent.SHOWN));
     }
     closeDropdown() {
-        this.dispatchEvent(new CustomEvent(Event.HIDE));
-        this.dropdownMenu.classList.remove("show");
-        this.appendChild(this.dropdownMenu);
-        this.dispatchEvent(new CustomEvent(Event.HIDDEN));
-    }
-    get toggleButton() {
-        return this.querySelector(":scope > button[data-toggle='dropdown']");
-    }
-    toggleButtonSelected(event) {
-        return this.toggleButton.contains(event.target);
+        this.dispatchEvent(new CustomEvent(TobagoDropdownEvent.HIDE));
+        if (!this.inStickyHeader()) {
+            this.appendChild(this.dropdownMenu);
+        }
+        this.dispatchEvent(new CustomEvent(TobagoDropdownEvent.HIDDEN));
     }
     inStickyHeader() {
         return Boolean(this.closest("tobago-header.sticky-top"));
@@ -163,129 +56,10 @@ class Dropdown extends HTMLElement {
         const root = this.getRootNode();
         return root.querySelector(".dropdown-menu[name='" + this.id + "']");
     }
-    dropdownVisible() {
-        return this.dropdownMenu.classList.contains("show");
-    }
     get menuStore() {
         const root = this.getRootNode();
         return root.querySelector(".tobago-page-menuStore");
     }
-    get activeDropdownEntry() {
-        for (const dropdownEntry of this.dropdownEntries) {
-            if (dropdownEntry.active) {
-                return dropdownEntry;
-            }
-        }
-        return null;
-    }
-    createDropdownEntries(dropdownMenu, parent) {
-        let lastDropdownEntry = null;
-        for (const dropdownItem of dropdownMenu.children) {
-            if (dropdownItem.classList.contains("dropdown-item")) {
-                const entry = this.createDropdownEntry(dropdownItem, parent, lastDropdownEntry);
-                lastDropdownEntry = entry;
-                this.dropdownEntries.push(entry);
-                if (dropdownItem.classList.contains("tobago-dropdown-submenu")) {
-                    this.createDropdownEntries(dropdownItem.querySelector(".dropdown-menu"), entry);
-                }
-            }
-            else {
-                const dropdownItems = dropdownItem.querySelectorAll(".dropdown-item");
-                for (const dropdownItem of dropdownItems) {
-                    const entry = this.createDropdownEntry(dropdownItem, parent, lastDropdownEntry);
-                    lastDropdownEntry = entry;
-                    this.dropdownEntries.push(entry);
-                }
-            }
-        }
-    }
-    createDropdownEntry(dropdownItem, parent, previous) {
-        const entry = new DropdownEntry(dropdownItem);
-        if (parent) {
-            entry.parent = parent;
-            parent.children.push(entry);
-        }
-        if (previous) {
-            previous.next = entry;
-            entry.previous = previous;
-        }
-        return entry;
-    }
-}
-class DropdownEntry {
-    constructor(dropdownItem) {
-        this._children = [];
-        this._baseElement = dropdownItem;
-        if (dropdownItem.classList.contains("tobago-dropdown-submenu")) {
-            this.focusElement = dropdownItem.querySelector(".tobago-link");
-        }
-        else if (dropdownItem.tagName === "LABEL") {
-            const root = dropdownItem.getRootNode();
-            this.focusElement = root.getElementById(dropdownItem.getAttribute("for"));
-        }
-        else {
-            this.focusElement = dropdownItem;
-        }
-        this._baseElement.addEventListener("mouseenter", this.activate.bind(this));
-        this._baseElement.addEventListener("mouseleave", this.deactivate.bind(this));
-    }
-    activate(event) {
-        this.active = true;
-    }
-    deactivate(event) {
-        this.active = false;
-    }
-    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) {
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 6b806d9..edd0c6a 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;;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
+{"version":3,"file":"tobago-dropdown.js","sourceRoot":"","sources":["../../ts/tobago-dropdown.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,+DAA+D;AAE/D,MAAM,mBAAmB,GAAG;IAC1B,IAAI,EAAE,sBAAsB;IAC5B,MAAM,EAAE,wBAAwB;IAChC,IAAI,EAAE,sBAAsB;IAC5B,KAAK,EAAE,uBAAuB;CAC/B,CAAC;AAEF;;;GAGG;AACH,MAAM,QAAS,SAAQ,WAAW;IAEhC;QACE,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,yBAAyB,CAAC,EAAE,EAAE,kBAAkB;YAC3E,IAAI,CAAC,gBAAgB,CAAC,mBAAmB,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,I [...]
\ 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 58ac087..8ca10bf 100644
--- a/tobago-theme/tobago-theme-standard/npm/dist/js/tobago.js
+++ b/tobago-theme/tobago-theme-standard/npm/dist/js/tobago.js
@@ -254,1726 +254,2605 @@
         }
     });
 
-    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
+    /*
+     * 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 TobagoDropdownEvent = {
+        HIDE: "tobago.dropdown.hide",
+        HIDDEN: "tobago.dropdown.hidden",
+        SHOW: "tobago.dropdown.show",
+        SHOWN: "tobago.dropdown.shown"
+    };
+    /**
+     * The dropdown implementation of Bootstrap does not move the menu to the tobago-page-menuStore. This behavior is
+     * implemented in this class.
+     */
+    class Dropdown extends HTMLElement {
+        constructor() {
+            super();
+            if (!this.classList.contains("tobago-dropdown-submenu")) { // ignore submenus
+                this.addEventListener("shown.bs.dropdown", this.openDropdown.bind(this));
+                this.addEventListener("hidden.bs.dropdown", this.closeDropdown.bind(this));
+            }
+        }
+        connectedCallback() {
+        }
+        openDropdown() {
+            this.dispatchEvent(new CustomEvent(TobagoDropdownEvent.SHOW));
+            if (!this.inStickyHeader()) {
+                this.menuStore.appendChild(this.dropdownMenu);
+            }
+            this.dispatchEvent(new CustomEvent(TobagoDropdownEvent.SHOWN));
+        }
+        closeDropdown() {
+            this.dispatchEvent(new CustomEvent(TobagoDropdownEvent.HIDE));
+            if (!this.inStickyHeader()) {
+                this.appendChild(this.dropdownMenu);
+            }
+            this.dispatchEvent(new CustomEvent(TobagoDropdownEvent.HIDDEN));
+        }
+        inStickyHeader() {
+            return Boolean(this.closest("tobago-header.sticky-top"));
+        }
+        get dropdownMenu() {
+            const root = this.getRootNode();
+            return root.querySelector(".dropdown-menu[name='" + this.id + "']");
+        }
+        get menuStore() {
+            const root = this.getRootNode();
+            return root.querySelector(".tobago-page-menuStore");
+        }
+    }
+    document.addEventListener("tobago.init", function (event) {
+        if (window.customElements.get("tobago-dropdown") == null) {
+            window.customElements.define("tobago-dropdown", Dropdown);
+        }
+    });
 
-    var beforeRead = 'beforeRead';
-    var read = 'read';
-    var afterRead = 'afterRead'; // pure-logic modifiers
+    function hasProperty(obj, prop) {
+      return Object.prototype.hasOwnProperty.call(obj, prop);
+    }
 
-    var beforeMain = 'beforeMain';
-    var main = 'main';
-    var afterMain = 'afterMain'; // modifier with the purpose to write to the DOM (or write into a framework state)
+    function lastItemOf(arr) {
+      return arr[arr.length - 1];
+    }
 
-    var beforeWrite = 'beforeWrite';
-    var write = 'write';
-    var afterWrite = 'afterWrite';
-    var modifierPhases = [beforeRead, read, afterRead, beforeMain, main, afterMain, beforeWrite, write, afterWrite];
+    // 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 getNodeName(element) {
-      return element ? (element.nodeName || '').toLowerCase() : null;
+    function stringToArray(str, separator) {
+      // convert empty string to an empty array
+      return str ? str.split(separator) : [];
     }
 
-    /*:: import type { Window } from '../types'; */
+    function isInRange(testVal, min, max) {
+      const minOK = min === undefined || testVal >= min;
+      const maxOK = max === undefined || testVal <= max;
+      return minOK && maxOK;
+    }
 
-    /*:: declare function getWindow(node: Node | Window): Window; */
-    function getWindow(node) {
-      if (node.toString() !== '[object Window]') {
-        var ownerDocument = node.ownerDocument;
-        return ownerDocument ? ownerDocument.defaultView || window : window;
+    function limitToRange(val, min, max) {
+      if (val < min) {
+        return min;
       }
-
-      return node;
+      if (val > max) {
+        return max;
+      }
+      return val;
     }
 
-    /*:: declare function isElement(node: mixed): boolean %checks(node instanceof
-      Element); */
+    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}>`;
 
-    function isElement(node) {
-      var OwnElement = getWindow(node).Element;
-      return node instanceof OwnElement || node instanceof Element;
+      const next = index + 1;
+      return next < repeat
+        ? createTagRepeat(tagName, repeat, attributes, next, html)
+        : html;
     }
-    /*:: declare function isHTMLElement(node: mixed): boolean %checks(node instanceof
-      HTMLElement); */
-
 
-    function isHTMLElement(node) {
-      var OwnElement = getWindow(node).HTMLElement;
-      return node instanceof OwnElement || node instanceof HTMLElement;
+    // 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+</, '<');
     }
-    /*:: declare function isShadowRoot(node: mixed): boolean %checks(node instanceof
-      ShadowRoot); */
-
 
-    function isShadowRoot(node) {
-      var OwnElement = getWindow(node).ShadowRoot;
-      return node instanceof OwnElement || node instanceof ShadowRoot;
+    function stripTime(timeValue) {
+      return new Date(timeValue).setHours(0, 0, 0, 0);
     }
 
-    // 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 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]);
+      }
 
-        Object.assign(element.style, style);
-        Object.keys(attributes).forEach(function (name) {
-          var value = attributes[name];
+      // 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);
+    }
 
-          if (value === false) {
-            element.removeAttribute(name);
-          } else {
-            element.setAttribute(name, value === true ? '' : value);
-          }
-        });
-      });
+    function addDays(date, amount) {
+      const newDate = new Date(date);
+      return newDate.setDate(newDate.getDate() + amount);
     }
 
-    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);
+    function addWeeks(date, amount) {
+      return addDays(date, amount * 7);
+    }
 
-      if (state.elements.arrow) {
-        Object.assign(state.elements.arrow.style, initialStyles.arrow);
+    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;
       }
 
-      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
+      const time = newDate.setMonth(monthsToSet);
+      return newDate.getMonth() !== expectedMonth ? newDate.setDate(0) : time;
+    }
 
-          var style = styleProperties.reduce(function (style, property) {
-            style[property] = '';
-            return style;
-          }, {}); // arrow is optional + virtual elements
+    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;
+    }
 
-          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
-
-
-    var applyStyles$1 = {
-      name: 'applyStyles',
-      enabled: true,
-      phase: 'write',
-      fn: applyStyles,
-      effect: effect,
-      requires: ['computeStyles']
-    };
-
-    function getBasePlacement(placement) {
-      return placement.split('-')[0];
+    // Calculate the distance bettwen 2 days of the week
+    function dayDiff(day, from) {
+      return (day - from + 7) % 7;
     }
 
-    // Returns the layout rect of an element relative to its offsetParent. Layout
-    // means it doesn't take into account transforms.
-    function getLayoutRect(element) {
-      return {
-        x: element.offsetLeft,
-        y: element.offsetTop,
-        width: element.offsetWidth,
-        height: element.offsetHeight
-      };
+    // 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));
     }
 
-    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;
+    // 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;
+    }
 
-          do {
-            if (next && parent.isSameNode(next)) {
-              return true;
-            } // $FlowFixMe[prop-missing]: need a better way to handle this...
+    // 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(date, month, locale) {
+        const newDate = new Date(date);
+        let monthIndex = parseInt(month, 10) - 1;
 
-            next = next.parentNode || next.host;
-          } while (next);
-        } // Give up, the result is false
+        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);
+          }
+          if (monthIndex < 0) {
+            return NaN;
+          }
+        }
 
-      return false;
-    }
+        newDate.setMonth(monthIndex);
+        return newDate.getMonth() !== normalizeMonth(monthIndex)
+          ? newDate.setDate(0)
+          : newDate.getTime();
+      },
+      d(date, day) {
+        return new Date(date).setDate(parseInt(day, 10));
+      },
+    };
+    // 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);
+      },
+    };
 
-    function getComputedStyle$1(element) {
-      return getWindow(element).getComputedStyle(element);
+    // get month index in normal range (0 - 11) from any number
+    function normalizeMonth(monthIndex) {
+      return monthIndex > -1 ? monthIndex % 12 : normalizeMonth(monthIndex + 12);
     }
 
-    function isTableElement(element) {
-      return ['table', 'td', 'th'].indexOf(getNodeName(element)) >= 0;
+    function padZero(num, length) {
+      return num.toString().padStart(length, '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 parseFormatString(format) {
+      if (typeof format !== 'string') {
+        throw new Error("Invalid date format.");
+      }
+      if (format in knownFormats) {
+        return knownFormats[format];
+      }
 
-    function getParentNode(element) {
-      if (getNodeName(element) === 'html') {
-        return element;
+      // 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.");
       }
 
-      return (// this is a quicker (but less type safe) way to save quite some bytes from the bundle
-        // $FlowFixMe[incompatible-return]
-        // $FlowFixMe[prop-missing]
-        element.assignedSlot || // step into the shadow DOM of the parent of a slotted node
-        element.parentNode || // DOM Element detected
-        // $FlowFixMe[incompatible-return]: need a better way to handle this...
-        element.host || // ShadowRoot detected
-        // $FlowFixMe[incompatible-call]: HTMLElement is a Node
-        getDocumentElement(element) // fallback
+      // collect format functions used in the format
+      const partFormatters = parts.map(token => formatFns[token]);
 
-      );
+      // collect parse function keys used in the format
+      // iterate over parseFns' keys in order to keep the order of the keys.
+      const partParserKeys = Object.keys(parseFns).reduce((keys, key) => {
+        const token = parts.find(part => part[0] !== 'D' && part[0].toLowerCase() === key);
+        if (token) {
+          keys.push(key);
+        }
+        return keys;
+      }, []);
+
+      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 (token === 'M') {
+                dtParts.m = part;
+              } else if (token !== 'D') {
+                dtParts[token] = part;
+              }
+            }
+            return dtParts;
+          }, {});
+
+          // iterate over partParserkeys 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 = parseFns[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 getTrueOffsetParent(element) {
-      if (!isHTMLElement(element) || // https://github.com/popperjs/popper-core/issues/837
-      getComputedStyle$1(element).position === 'fixed') {
-        return null;
+    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();
       }
 
-      var offsetParent = element.offsetParent;
+      if (format && format.toValue) {
+        const date = format.toValue(dateStr, format, locale);
+        return isNaN(date) ? undefined : stripTime(date);
+      }
 
-      if (offsetParent) {
-        var html = getDocumentElement(offsetParent);
+      return parseFormatString(format).parser(dateStr, locale);
+    }
 
-        if (getNodeName(offsetParent) === 'body' && getComputedStyle$1(offsetParent).position === 'static' && getComputedStyle$1(html).position !== 'static') {
-          return html;
-        }
+    function formatDate(date, format, locale) {
+      if (isNaN(date) || (!date && date !== 0)) {
+        return '';
       }
 
-      return offsetParent;
-    } // `.offsetParent` reports `null` for fixed elements, while absolute elements
-    // return the containing block
-
-
-    function getContainingBlock(element) {
-      var currentNode = getParentNode(element);
-
-      while (isHTMLElement(currentNode) && ['html', 'body'].indexOf(getNodeName(currentNode)) < 0) {
-        var css = getComputedStyle$1(currentNode); // This is non-exhaustive but covers the most common CSS properties that
-        // create a containing block.
+      const dateObj = typeof date === 'number' ? new Date(date) : date;
 
-        if (css.transform !== 'none' || css.perspective !== 'none' || css.willChange && css.willChange !== 'auto') {
-          return currentNode;
-        } else {
-          currentNode = currentNode.parentNode;
-        }
+      if (format.toDisplay) {
+        return format.toDisplay(dateObj, format, locale);
       }
 
-      return null;
-    } // Gets the closest ancestor positioned element. Handles some edge cases,
-    // such as table ancestors and cross browser bugs.
-
+      return parseFormatString(format).formatter(dateObj, locale);
+    }
 
-    function getOffsetParent(element) {
-      var window = getWindow(element);
-      var offsetParent = getTrueOffsetParent(element);
+    const listenerRegistry = new WeakMap();
+    const {addEventListener, removeEventListener} = EventTarget.prototype;
 
-      while (offsetParent && isTableElement(offsetParent) && getComputedStyle$1(offsetParent).position === 'static') {
-        offsetParent = getTrueOffsetParent(offsetParent);
+    // 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);
+      });
+    }
 
-      if (offsetParent && getNodeName(offsetParent) === 'body' && getComputedStyle$1(offsetParent).position === 'static') {
-        return window;
+    function unregisterListeners(keyObj) {
+      let listeners = listenerRegistry.get(keyObj);
+      if (!listeners) {
+        return;
       }
-
-      return offsetParent || getContainingBlock(element) || window;
+      listeners.forEach((listener) => {
+        removeEventListener.call(...listener);
+      });
+      listenerRegistry.delete(keyObj);
     }
 
-    function getMainAxisFromPlacement(placement) {
-      return ['top', 'bottom'].indexOf(placement) >= 0 ? 'x' : 'y';
-    }
+    // Event.composedPath() polyfill for Edge
+    // based on https://gist.github.com/kleinfreund/e9787d73776c0e3750dcfcdc89f100ec
+    if (!Event.prototype.composedPath) {
+      const getComposedPath = (node, path = []) => {
+        path.push(node);
 
-    function within(min, value, max) {
-      return Math.max(min, Math.min(value, max));
-    }
+        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;
+      };
 
-    function getFreshSideObject() {
-      return {
-        top: 0,
-        right: 0,
-        bottom: 0,
-        left: 0
+      Event.prototype.composedPath = function () {
+        return getComposedPath(this.target);
       };
     }
 
-    function mergePaddingObject(paddingObject) {
-      return Object.assign(Object.assign({}, getFreshSideObject()), paddingObject);
+    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);
     }
 
-    function expandToHashMap(value, keys) {
-      return keys.reduce(function (hashMap, key) {
-        hashMap[key] = value;
-        return hashMap;
-      }, {});
+    // 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);
     }
 
-    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';
-
-      if (!arrowElement || !popperOffsets) {
-        return;
+    // 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"
       }
+    };
 
-      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
+    // 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,
+    };
 
-      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...
+    const range = document.createRange();
 
-      var axisProp = axis;
-      state.modifiersData[name] = (_state$modifiersData$ = {}, _state$modifiersData$[axisProp] = offset, _state$modifiersData$.centerOffset = offset - center, _state$modifiersData$);
+    function parseHTML(html) {
+      return range.createContextualFragment(html);
     }
 
-    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;
-
-      if (arrowElement == null) {
+    function hideElement(el) {
+      if (el.style.display === 'none') {
         return;
-      } // CSS selector
-
-
-      if (typeof arrowElement === 'string') {
-        arrowElement = state.elements.popper.querySelector(arrowElement);
-
-        if (!arrowElement) {
-          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';
+    }
 
-      if (!contains(state.elements.popper, arrowElement)) {
-
+    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 = '';
+      }
+    }
 
-      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 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);
+        });
+      }
+    }
 
-    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.
+    const {
+      language: defaultLang,
+      format: defaultFormat,
+      weekStart: defaultWeekStart,
+    } = defaultOptions;
 
-    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
-      };
+    // 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 mapToStyles(_ref2) {
-      var _Object$assign2;
+    function calcEndOfWeek(startOfWeek) {
+      return (startOfWeek + 6) % 7;
+    }
 
-      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;
+    // 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;
+    }
 
-      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;
+    // 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 hasX = offsets.hasOwnProperty('x');
-      var hasY = offsets.hasOwnProperty('y');
-      var sideX = left;
-      var sideY = top;
-      var win = window;
+    // 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 (adaptive) {
-        var offsetParent = getOffsetParent(popper);
+      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;
 
-        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
+          // 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);
+          }
+        }
+      }
 
-        /*:: offsetParent = (offsetParent: Element); */
+      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 (placement === top) {
-          sideY = bottom;
-          y -= offsetParent.clientHeight - popperRect.height;
-          y *= gpuAcceleration ? 1 : -1;
+      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;
+      }
 
-        if (placement === left) {
-          sideX = right;
-          x -= offsetParent.clientWidth - popperRect.width;
-          x *= gpuAcceleration ? 1 : -1;
+      //*** 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;
       }
 
-      var commonStyles = Object.assign({
-        position: position
-      }, adaptive && unsetSides);
+      //*** 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;
+      }
 
-      if (gpuAcceleration) {
-        var _Object$assign;
+      //*** 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;
+      }
 
-        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));
+      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;
       }
 
-      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));
-    }
+      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;
+      }
 
-    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 commonStyles = {
-        placement: getBasePlacement(state.placement),
-        popper: state.elements.popper,
-        popperRect: state.rects.popper,
-        gpuAcceleration: gpuAcceleration
-      };
-
-      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
-        })));
+      //*** 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;
       }
 
-      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
-        })));
+      //*** 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;
       }
 
-      state.attributes.popper = Object.assign(Object.assign({}, state.attributes.popper), {}, {
-        'data-popper-placement': state.placement
+      //*** copy the rest ***//
+      Object.keys(inOpts).forEach((key) => {
+        if (inOpts[key] !== undefined && hasProperty(defaultOptions, key)) {
+          config[key] = inOpts[key];
+        }
       });
-    } // eslint-disable-next-line import/no-unused-modules
 
+      return config;
+    }
 
-    var computeStyles$1 = {
-      name: 'computeStyles',
-      enabled: true,
-      phase: 'beforeWrite',
-      fn: computeStyles,
-      data: {}
-    };
+    const pickerTemplate = optimizeTemplateHTML(`<div class="datepicker">
+  <div class="datepicker-picker">
+    <div class="datepicker-header">
+      <div class="datepicker-title"></div>
+      <div class="datepicker-controls">
+        <button type="button" class="%buttonClass% prev-btn"></button>
+        <button type="button" class="%buttonClass% view-switch"></button>
+        <button type="button" class="%buttonClass% next-btn"></button>
+      </div>
+    </div>
+    <div class="datepicker-main"></div>
+    <div class="datepicker-footer">
+      <div class="datepicker-controls">
+        <button type="button" class="%buttonClass% today-btn"></button>
+        <button type="button" class="%buttonClass% clear-btn"></button>
+      </div>
+    </div>
+  </div>
+</div>`);
 
-    var passive = {
-      passive: true
-    };
+    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 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);
+    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>`);
 
-      if (scroll) {
-        scrollParents.forEach(function (scrollParent) {
-          scrollParent.addEventListener('scroll', instance.update, passive);
+    // 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);
       }
 
-      if (resize) {
-        window.addEventListener('resize', instance.update, passive);
+      init(options) {
+        if (options.pickLevel !== undefined) {
+          this.isMinView = this.id === options.pickLevel;
+        }
+        this.setOptions(options);
+        this.updateFocus();
+        this.updateSelection();
       }
 
-      return function () {
-        if (scroll) {
-          scrollParents.forEach(function (scrollParent) {
-            scrollParent.removeEventListener('scroll', instance.update, passive);
-          });
+      // 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 (resize) {
-          window.removeEventListener('resize', instance.update, passive);
+        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);
+          }
         }
-      };
-    } // 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];
-      });
-    }
+    class DaysView extends View {
+      constructor(picker) {
+        super(picker, {
+          id: 0,
+          name: 'days',
+          cellClass: 'day',
+        });
+      }
 
-    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
-      };
-    }
+      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);
+      }
 
-    function getWindowScroll(node) {
-      var win = getWindow(node);
-      var scrollLeft = win.pageXOffset;
-      var scrollTop = win.pageYOffset;
-      return {
-        scrollLeft: scrollLeft,
-        scrollTop: scrollTop
-      };
-    }
+      setOptions(options) {
+        let updateDOW;
 
-    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 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 (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 (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 (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);
+            }
+          }
+        }
 
-        if (!/^((?!chrome|android).)*safari/i.test(navigator.userAgent)) {
-          x = visualViewport.offsetLeft;
-          y = visualViewport.offsetTop;
+        // 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';
+          });
         }
       }
 
-      return {
-        width: width,
-        height: height,
-        x: x + getWindowScrollBarX(element),
-        y: y
-      };
-    }
-
-    // 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;
+      // 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);
 
-      if (getComputedStyle$1(body || html).direction === 'rtl') {
-        x += Math.max(html.clientWidth, body ? body.clientWidth : 0) - width;
+        this.first = firstOfMonth;
+        this.last = dateValue(viewYear, viewMonth + 1, 0);
+        this.start = start;
+        this.focused = this.picker.viewDate;
       }
 
-      return {
-        width: width,
-        height: height,
-        x: x,
-        y: y
-      };
-    }
-
-    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;
-
-      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;
+      // 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;
+        }
       }
 
-      if (isHTMLElement(node) && isScrollParent(node)) {
-        return node;
-      }
+       // 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];
 
-      return getScrollParent(getParentNode(node));
-    }
+        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);
 
-    /*
-    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.
-    */
+        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();
 
-    function listScrollParents(element, list) {
-      if (list === void 0) {
-        list = [];
-      }
+          el.className = `datepicker-cell ${this.cellClass}`;
+          el.dataset.date = current;
+          el.textContent = date.getDate();
 
-      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)));
-    }
+          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');
+          }
 
-    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
-      });
-    }
+          if (this.beforeShow) {
+            this.performBeforeHook(el, current, current);
+          }
+        });
+      }
 
-    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;
-    }
-
-    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`
-
-
-    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
-
-
-      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
-
-
-    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;
-    }
+      // 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');
+          }
+        });
+      }
 
-    function getVariation(placement) {
-      return placement.split('-')[1];
+      // 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 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 computeMonthRange(range, thisYear) {
+      if (!range || !range[0] || !range[1]) {
+        return;
+      }
 
-      switch (basePlacement) {
-        case top:
-          offsets = {
-            x: commonX,
-            y: reference.y - element.height
-          };
-          break;
+      const [[startY, startM], [endY, endM]] = range;
+      if (startY > thisYear || endY < thisYear) {
+        return;
+      }
+      return [
+        startY === thisYear ? startM : -1,
+        endY === thisYear ? endM : 12,
+      ];
+    }
 
-        case bottom:
-          offsets = {
-            x: commonX,
-            y: reference.y + reference.height
-          };
-          break;
+    class MonthsView extends View {
+      constructor(picker) {
+        super(picker, {
+          id: 1,
+          name: 'months',
+          cellClass: 'month',
+        });
+      }
 
-        case right:
-          offsets = {
-            x: reference.x + reference.width,
-            y: commonY
-          };
-          break;
+      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);
+      }
 
-        case left:
-          offsets = {
-            x: reference.x - element.width,
-            y: commonY
-          };
-          break;
+      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;
+        }
+      }
 
-        default:
-          offsets = {
-            x: reference.x,
-            y: reference.y
-          };
+      // 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();
       }
 
-      var mainAxis = basePlacement ? getMainAxisFromPlacement(basePlacement) : null;
+      // 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()];
+          });
+        }
+      }
 
-      if (mainAxis != null) {
-        var len = mainAxis === 'y' ? 'height' : 'width';
+      // 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 = [];
 
-        switch (variation) {
-          case start:
-            offsets[mainAxis] = offsets[mainAxis] - (reference[len] / 2 - element[len] / 2);
-            break;
+        this.picker.setViewSwitchLabel(this.year);
+        this.picker.setPrevBtnDisabled(this.year <= this.minYear);
+        this.picker.setNextBtnDisabled(this.year >= this.maxYear);
 
-          case end:
-            offsets[mainAxis] = offsets[mainAxis] + (reference[len] / 2 - element[len] / 2);
-            break;
-        }
-      }
+        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);
 
-      return offsets;
-    }
+        Array.from(this.grid.children).forEach((el, index) => {
+          const classList = el.classList;
+          const date = dateValue(this.year, index, 1);
 
-    function detectOverflow(state, options) {
-      if (options === void 0) {
-        options = {};
-      }
+          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];
 
-      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 (
+            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');
+          }
 
-      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 (this.beforeShow) {
+            this.performBeforeHook(el, index, date);
+          }
+        });
+      }
 
-      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;
+      // 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');
+          }
         });
       }
 
-      return overflowOffsets;
+      // 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');
+      }
     }
 
-    /*:: type OverflowsMap = { [ComputedPlacement]: number }; */
+    function toTitleCase(word) {
+      return [...word].reduce((str, ch, ix) => str += ix ? ch : ch.toUpperCase(), '');
+    }
 
-    /*;; type OverflowsMap = { [key in ComputedPlacement]: number }; */
-    function computeAutoPlacement(state, options) {
-      if (options === void 0) {
-        options = {};
+    // Class representing the years and decades view elements
+    class YearsView extends View {
+      constructor(picker, config) {
+        super(picker, config);
       }
 
-      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;
-      });
+      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);
+      }
 
-      if (allowedPlacements.length === 0) {
-        allowedPlacements = placements$1;
-      } // $FlowFixMe[incompatible-type]: Flow seems to have problems with two array unions...
+      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;
 
-      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];
-      });
-    }
+        this.first = first;
+        this.last = last;
+        this.start = first - this.step;
+        this.focused = startOfYearPeriod(viewDate, this.step);
+      }
 
-    function getExpandedFallbackPlacements(placement) {
-      if (getBasePlacement(placement) === auto) {
-        return [];
+      // 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);
+            }
+          });
+        }
       }
 
-      var oppositePlacement = getOppositePlacement(placement);
-      return [getOppositeVariationPlacement(placement), oppositePlacement, getOppositeVariationPlacement(oppositePlacement)];
-    }
+      // 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 = [];
 
-    function flip(_ref) {
-      var state = _ref.state,
-          options = _ref.options,
-          name = _ref.name;
+        this.picker.setViewSwitchLabel(`${this.first}-${this.last}`);
+        this.picker.setPrevBtnDisabled(this.first <= this.minYear);
+        this.picker.setNextBtnDisabled(this.last >= this.maxYear);
 
-      if (state.modifiersData[name]._skip) {
-        return;
-      }
+        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);
 
-      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];
+          el.className = `datepicker-cell ${this.cellClass}`;
+          if (this.isMinView) {
+            el.dataset.date = date;
+          }
+          el.textContent = el.dataset.year = current;
 
-        var _basePlacement = getBasePlacement(placement);
+          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');
+          }
 
-        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
+          if (this.beforeShow) {
+            this.performBeforeHook(el, current, date);
+          }
         });
-        var mainVariationSide = isVertical ? isStartVariation ? right : left : isStartVariation ? bottom : top;
-
-        if (referenceRect[len] > popperRect[len]) {
-          mainVariationSide = getOppositePlacement(mainVariationSide);
-        }
+      }
 
-        var altVariationSide = getOppositePlacement(mainVariationSide);
-        var checks = [];
+      // 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');
+          }
+        });
+      }
 
-        if (checkMainAxis) {
-          checks.push(overflow[_basePlacement] <= 0);
-        }
+      // 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');
+      }
+    }
 
-        if (checkAltAxis) {
-          checks.push(overflow[mainVariationSide] <= 0, overflow[altVariationSide] <= 0);
-        }
+    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}));
+    }
 
-        if (checks.every(function (check) {
-          return check;
-        })) {
-          firstFittingPlacement = placement;
-          makeFallbackChecks = false;
+    // 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;
-        }
-
-        checksMap.set(placement, checks);
+        case 1:
+          newViewDate = addYears(viewDate, direction);
+          break;
+        default:
+          newViewDate = addYears(viewDate, direction * currentView.navStep);
       }
+      newViewDate = limitToRange(newViewDate, minDate, maxDate);
+      datepicker.picker.changeFocus(newViewDate).render();
+    }
 
-      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);
+    function switchView(datepicker) {
+      const viewId = datepicker.picker.currentView.id;
+      if (viewId === datepicker.config.maxView) {
+        return;
+      }
+      datepicker.picker.changeView(viewId + 1).render();
+    }
 
-            if (checks) {
-              return checks.slice(0, _i).every(function (check) {
-                return check;
-              });
-            }
-          });
+    function unfocus(datepicker) {
+      if (datepicker.config.updateOnBlur) {
+        datepicker.update({autohide: true});
+      } else {
+        datepicker.refresh('input');
+        datepicker.hide();
+      }
+    }
 
-          if (fittingPlacement) {
-            firstFittingPlacement = fittingPlacement;
-            return "break";
-          }
-        };
+    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());
 
-        for (var _i = numberOfChecks; _i > 0; _i--) {
-          var _ret = _loop(_i);
+      picker.changeFocus(newDate).changeView(viewId - 1).render();
+    }
 
-          if (_ret === "break") break;
+    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 (state.placement !== firstFittingPlacement) {
-        state.modifiersData[name]._skip = true;
-        state.placement = firstFittingPlacement;
-        state.reset = true;
+      if (picker.viewDate !== currentDate) {
+        picker.changeFocus(currentDate);
       }
-    } // eslint-disable-next-line import/no-unused-modules
+      picker.changeView(0).render();
+    }
 
+    function onClickClearBtn(datepicker) {
+      datepicker.setDate({clear: true});
+    }
 
-    var flip$1 = {
-      name: 'flip',
-      enabled: true,
-      phase: 'main',
-      fn: flip,
-      requiresIfExists: ['offset'],
-      data: {
-        _skip: false
-      }
-    };
+    function onClickViewSwitch(datepicker) {
+      switchView(datepicker);
+    }
 
-    function getSideOffsets(overflow, rect, preventedOffsets) {
-      if (preventedOffsets === void 0) {
-        preventedOffsets = {
-          x: 0,
-          y: 0
-        };
+    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;
       }
 
-      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
-      };
+      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 isAnySideFullyClipped(overflow) {
-      return [top, right, bottom, left].some(function (side) {
-        return overflow[side] >= 0;
-      });
+    function onClickPicker(datepicker) {
+      if (!datepicker.inline && !datepicker.config.disableTouchKeyboard) {
+        datepicker.inputField.focus();
+      }
     }
 
-    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
+    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);
+    }
 
-    var hide$1 = {
-      name: 'hide',
-      enabled: true,
-      phase: 'main',
-      requiresIfExists: ['preventOverflow'],
-      fn: hide
-    };
+    // 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();
 
-    function distanceAndSkiddingToXY(placement, rects, offset) {
-      var basePlacement = getBasePlacement(placement);
-      var invertDistance = [left, top].indexOf(basePlacement) >= 0 ? -1 : 1;
+      picker.viewDate = newDate;
+      if (viewYear !== oldViewDate.getFullYear()) {
+        triggerDatepickerEvent(picker.datepicker, 'changeYear');
+      }
+      if (newViewDate.getMonth() !== oldViewDate.getMonth()) {
+        triggerDatepickerEvent(picker.datepicker, 'changeMonth');
+      }
 
-      var _ref = typeof offset === 'function' ? offset(Object.assign(Object.assign({}, rects), {}, {
-        placement: placement
-      })) : offset,
-          skidding = _ref[0],
-          distance = _ref[1];
+      // 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;
+      }
+    }
 
-      skidding = skidding || 0;
-      distance = (distance || 0) * invertDistance;
-      return [left, right].indexOf(basePlacement) >= 0 ? {
-        x: distance,
-        y: skidding
-      } : {
-        x: skidding,
-        y: distance
-      };
+    function getTextDirection(el) {
+      return window.getComputedStyle(el).direction;
     }
 
-    function offset(_ref2) {
-      var state = _ref2.state,
-          options = _ref2.options,
-          name = _ref2.name;
-      var _options$offset = options.offset,
-          offset = _options$offset === void 0 ? [0, 0] : _options$offset;
-      var data = placements.reduce(function (acc, placement) {
-        acc[placement] = distanceAndSkiddingToXY(placement, state.rects, offset);
-        return acc;
-      }, {});
-      var _data$state$placement = data[state.placement],
-          x = _data$state$placement.x,
-          y = _data$state$placement.y;
+    // Class representing the picker UI
+    class Picker {
+      constructor(datepicker) {
+        this.datepicker = datepicker;
 
-      if (state.modifiersData.popperOffsets != null) {
-        state.modifiersData.popperOffsets.x += x;
-        state.modifiersData.popperOffsets.y += y;
-      }
+        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;
 
-      state.modifiersData[name] = data;
-    } // eslint-disable-next-line import/no-unused-modules
+        const elementClass = datepicker.inline ? 'inline' : 'dropdown';
+        element.classList.add(`datepicker-${elementClass}`);
 
+        processPickerOptions(this, datepicker.config);
+        this.viewDate = computeResetViewDate(datepicker);
 
-    var offset$1 = {
-      name: 'offset',
-      enabled: true,
-      phase: 'main',
-      requires: ['popperOffsets'],
-      fn: offset
-    };
+        // 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)],
+        ]);
 
-    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
+        // 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);
+      }
 
-    var popperOffsets$1 = {
-      name: 'popperOffsets',
-      enabled: true,
-      phase: 'read',
-      fn: popperOffsets,
-      data: {}
-    };
+      setOptions(options) {
+        processPickerOptions(this, options);
+        this.views.forEach((view) => {
+          view.init(options, false);
+        });
+        this.currentView.render();
+      }
 
-    function getAltAxis(axis) {
-      return axis === 'x' ? 'y' : 'x';
-    }
+      detach() {
+        this.datepicker.config.container.removeChild(this.element);
+      }
 
-    function preventOverflow(_ref) {
-      var state = _ref.state,
-          options = _ref.options,
-          name = _ref.name;
-      var _options$mainAxis = options.mainAxis,
-          checkMainAxis = _options$mainAxis === void 0 ? true : _options$mainAxis,
-          _options$altAxis = options.altAxis,
-          checkAltAxis = _options$altAxis === void 0 ? false : _options$altAxis,
-          boundary = options.boundary,
-          rootBoundary = options.rootBoundary,
-          altBoundary = options.altBoundary,
-          padding = options.padding,
-          _options$tether = options.tether,
-          tether = _options$tether === void 0 ? true : _options$tether,
-          _options$tetherOffset = options.tetherOffset,
-          tetherOffset = _options$tetherOffset === void 0 ? 0 : _options$tetherOffset;
-      var overflow = detectOverflow(state, {
-        boundary: boundary,
-        rootBoundary: rootBoundary,
-        padding: padding,
-        altBoundary: altBoundary
-      });
-      var basePlacement = getBasePlacement(state.placement);
-      var variation = getVariation(state.placement);
-      var isBasePlacement = !variation;
-      var mainAxis = getMainAxisFromPlacement(basePlacement);
-      var altAxis = getAltAxis(mainAxis);
-      var popperOffsets = state.modifiersData.popperOffsets;
-      var referenceRect = state.rects.reference;
-      var popperRect = state.rects.popper;
-      var tetherOffsetValue = typeof tetherOffset === 'function' ? tetherOffset(Object.assign(Object.assign({}, state.rects), {}, {
-        placement: state.placement
-      })) : tetherOffset;
-      var data = {
-        x: 0,
-        y: 0
-      };
-
-      if (!popperOffsets) {
-        return;
-      }
-
-      if (checkMainAxis) {
-        var mainSide = mainAxis === 'y' ? top : left;
-        var altSide = mainAxis === 'y' ? bottom : right;
-        var len = mainAxis === 'y' ? 'height' : 'width';
-        var offset = popperOffsets[mainAxis];
-        var min = popperOffsets[mainAxis] + overflow[mainSide];
-        var max = popperOffsets[mainAxis] - overflow[altSide];
-        var additive = tether ? -popperRect[len] / 2 : 0;
-        var minLen = variation === start ? referenceRect[len] : popperRect[len];
-        var maxLen = variation === start ? -popperRect[len] : -referenceRect[len]; // We need to include the arrow in the calculation so the arrow doesn't go
-        // outside the reference bounds
+      show() {
+        if (this.active) {
+          return;
+        }
+        this.element.classList.add('active');
+        this.active = true;
 
-        var arrowElement = state.elements.arrow;
-        var arrowRect = tether && arrowElement ? getLayoutRect(arrowElement) : {
-          width: 0,
-          height: 0
-        };
-        var arrowPaddingObject = state.modifiersData['arrow#persistent'] ? state.modifiersData['arrow#persistent'].padding : getFreshSideObject();
-        var arrowPaddingMin = arrowPaddingObject[mainSide];
-        var arrowPaddingMax = arrowPaddingObject[altSide]; // If the reference length is smaller than the arrow length, we don't want
-        // to include its full size in the calculation. If the reference is small
-        // and near the edge of a boundary, the popper can overflow even if the
-        // reference is not overflowing as well (e.g. virtual elements with no
-        // width or height)
+        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');
+          }
 
-        var arrowLen = within(0, referenceRect[len], arrowRect[len]);
-        var minOffset = isBasePlacement ? referenceRect[len] / 2 - additive - arrowLen - arrowPaddingMin - tetherOffsetValue : minLen - arrowLen - arrowPaddingMin - tetherOffsetValue;
-        var maxOffset = isBasePlacement ? -referenceRect[len] / 2 + additive + arrowLen + arrowPaddingMax + tetherOffsetValue : maxLen + arrowLen + arrowPaddingMax + tetherOffsetValue;
-        var arrowOffsetParent = state.elements.arrow && getOffsetParent(state.elements.arrow);
-        var clientOffset = arrowOffsetParent ? mainAxis === 'y' ? arrowOffsetParent.clientTop || 0 : arrowOffsetParent.clientLeft || 0 : 0;
-        var offsetModifierValue = state.modifiersData.offset ? state.modifiersData.offset[state.placement][mainAxis] : 0;
-        var tetherMin = popperOffsets[mainAxis] + minOffset - offsetModifierValue - clientOffset;
-        var tetherMax = popperOffsets[mainAxis] + maxOffset - offsetModifierValue;
-        var preventedOffset = within(tether ? Math.min(min, tetherMin) : min, offset, tether ? Math.max(max, tetherMax) : max);
-        popperOffsets[mainAxis] = preventedOffset;
-        data[mainAxis] = preventedOffset - offset;
+          this.place();
+          if (datepicker.config.disableTouchKeyboard) {
+            datepicker.inputField.blur();
+          }
+        }
+        triggerDatepickerEvent(datepicker, 'show');
       }
 
-      if (checkAltAxis) {
-        var _mainSide = mainAxis === 'x' ? top : left;
+      hide() {
+        if (!this.active) {
+          return;
+        }
+        this.datepicker.exitEditMode();
+        this.element.classList.remove('active');
+        this.active = false;
+        triggerDatepickerEvent(this.datepicker, 'hide');
+      }
 
-        var _altSide = mainAxis === 'x' ? bottom : right;
+      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;
 
-        var _offset = popperOffsets[altAxis];
+        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;
+        }
 
-        var _min = _offset + overflow[_mainSide];
+        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;
+        }
 
-        var _max = _offset - overflow[_altSide];
+        if (orientY === 'auto') {
+          orientY = top - calendarHeight < scrollTop ? 'bottom' : 'top';
+        }
+        if (orientY === 'top') {
+          top -= calendarHeight;
+        } else {
+          top += inputHeight;
+        }
 
-        var _preventedOffset = within(_min, _offset, _max);
+        classList.remove(
+          'datepicker-orient-top',
+          'datepicker-orient-bottom',
+          'datepicker-orient-right',
+          'datepicker-orient-left'
+        );
+        classList.add(`datepicker-orient-${orientY}`, `datepicker-orient-${orientX}`);
 
-        popperOffsets[altAxis] = _preventedOffset;
-        data[altAxis] = _preventedOffset - _offset;
+        style.top = top ? `${top}px` : top;
+        style.left = left ? `${left}px` : left;
       }
 
-      state.modifiersData[name] = data;
-    } // eslint-disable-next-line import/no-unused-modules
-
-
-    var preventOverflow$1 = {
-      name: 'preventOverflow',
-      enabled: true,
-      phase: 'main',
-      fn: preventOverflow,
-      requiresIfExists: ['offset']
-    };
+      setViewSwitchLabel(labelText) {
+        this.controls.viewSwitch.textContent = labelText;
+      }
 
-    function getHTMLElementScroll(element) {
-      return {
-        scrollLeft: element.scrollLeft,
-        scrollTop: element.scrollTop
-      };
-    }
+      setPrevBtnDisabled(disabled) {
+        this.controls.prevBtn.disabled = disabled;
+      }
 
-    function getNodeScroll(node) {
-      if (node === getWindow(node) || !isHTMLElement(node)) {
-        return getWindowScroll(node);
-      } else {
-        return getHTMLElementScroll(node);
+      setNextBtnDisabled(disabled) {
+        this.controls.nextBtn.disabled = disabled;
       }
-    }
 
-    // Composite means it takes into account transforms as well as layout.
+      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;
+      }
 
-    function getCompositeRect(elementOrVirtualElement, offsetParent, isFixed) {
-      if (isFixed === void 0) {
-        isFixed = false;
+      // Change the focused date (view date)
+      changeFocus(newViewDate) {
+        this._renderMethod = setViewDate(this, newViewDate) ? 'render' : 'refreshFocus';
+        this.views.forEach((view) => {
+          view.updateFocus();
+        });
+        return this;
       }
 
-      var documentElement = getDocumentElement(offsetParent);
-      var rect = getBoundingClientRect(elementOrVirtualElement);
-      var isOffsetParentAnElement = isHTMLElement(offsetParent);
-      var scroll = {
-        scrollLeft: 0,
-        scrollTop: 0
-      };
-      var offsets = {
-        x: 0,
-        y: 0
-      };
+      // 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;
+      }
 
-      if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {
-        if (getNodeName(offsetParent) !== 'body' || // https://github.com/popperjs/popper-core/issues/1078
-        isScrollParent(documentElement)) {
-          scroll = getNodeScroll(offsetParent);
-        }
+      // Refresh the picker UI
+      render(quickRender = true) {
+        const renderMethod = (quickRender && this._renderMethod) || 'render';
+        delete this._renderMethod;
 
-        if (isHTMLElement(offsetParent)) {
-          offsets = getBoundingClientRect(offsetParent);
-          offsets.x += offsetParent.clientLeft;
-          offsets.y += offsetParent.clientTop;
-        } else if (documentElement) {
-          offsets.x = getWindowScrollBarX(documentElement);
-        }
+        this.currentView[renderMethod]();
       }
+    }
 
-      return {
-        x: rect.left + scroll.scrollLeft - offsets.x,
-        y: rect.top + scroll.scrollTop - offsets.y,
-        width: rect.width,
-        height: rect.height
-      };
+    // 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;
     }
 
-    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 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);
-
-            if (depModifier) {
-              sort(depModifier);
-            }
+    // 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);
           }
-        });
-        result.push(modifier);
+          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();
       }
-
-      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 onKeydown(datepicker, ev) {
+      if (ev.key === 'Tab') {
+        unfocus(datepicker);
+        return;
+      }
 
-    function debounce(fn) {
-      var pending;
-      return function () {
-        if (!pending) {
-          pending = new Promise(function (resolve) {
-            Promise.resolve().then(function () {
-              pending = undefined;
-              resolve(fn());
-            });
-          });
+      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;
         }
-
-        return pending;
-      };
+      } 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 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 onFocus(datepicker) {
+      if (datepicker.config.showOnFocus) {
+        datepicker.show();
+      }
+    }
 
-      return Object.keys(merged).map(function (key) {
-        return merged[key];
-      });
+    // 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);
+      }
     }
 
-    var DEFAULT_OPTIONS = {
-      placement: 'bottom',
-      modifiers: [],
-      strategy: 'absolute'
-    };
+    function onClickInput(datepicker, ev) {
+      const el = ev.target;
+      if (!el._clicking) {
+        return;
+      }
+      clearTimeout(el._clicking);
+      delete el._clicking;
 
-    function areValidElements() {
-      for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
-        args[_key] = arguments[_key];
+      if (el._active) {
+        datepicker.enterEditMode();
       }
+      delete el._active;
 
-      return !args.some(function (element) {
-        return !(element && typeof element.getBoundingClientRect === 'function');
-      });
+      if (datepicker.config.showOnClick) {
+        datepicker.show();
+      }
     }
 
-    function popperGenerator(generatorOptions) {
-      if (generatorOptions === void 0) {
-        generatorOptions = {};
+    function onPaste(datepicker, ev) {
+      if (ev.clipboardData.types.includes('text/plain')) {
+        datepicker.enterEditMode();
       }
+    }
 
-      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;
-        }
+    // 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);
+    }
 
-        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
+    function stringifyDates(dates, config) {
+      return dates
+        .map(dt => formatDate(dt, config.format, config.locale))
+        .join(config.dateDelimiter);
+    }
 
-            var orderedModifiers = orderModifiers(mergeByName([].concat(defaultModifiers, state.options.modifiers))); // Strip out disabled modifiers
+    // 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;
+      }
 
-            state.orderedModifiers = orderedModifiers.filter(function (m) {
-              return m.enabled;
-            }); // Validate the provided modifiers so that the consumer will get warned
+      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;
+    }
 
-            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;
-            }
+    // 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);
+      }
+    }
 
-            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 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;
+      }
 
-            if (!areValidElements(reference, popper)) {
+      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();
+      }
+    }
 
-              return;
-            } // Store the reference and popper rects to be read by modifiers
+    /**
+     * 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));
 
-            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
+        // configure by type
+        const inline = this.inline = element.tagName !== 'INPUT';
+        let inputField;
+        let initialDates;
 
-            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`
+        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;
+            },
+          });
+        }
 
-            state.orderedModifiers.forEach(function (modifier) {
-              return state.modifiersData[modifier.name] = Object.assign({}, modifier.data);
-            });
+        // set initial value
+        this.dates = processInputDates(this, initialDates) || [];
+        if (inputField) {
+          inputField.value = stringifyDates(this.dates, config);
+        }
 
-            for (var index = 0; index < state.orderedModifiers.length; index++) {
-
-              if (state.reset === true) {
-                state.reset = false;
-                index = -1;
-                continue;
-              }
+        const picker = this.picker = new Picker(this);
 
-              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 (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);
+        }
+      }
 
-              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;
-          }
-        };
+      /**
+       * 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);
+      }
 
-        if (!areValidElements(reference, popper)) {
+      /**
+       * 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);
+      }
 
-          return instance;
-        }
+      /**
+       * @type {Object} - Installed locales in `[languageCode]: localeObject` format
+       * en`:_English (US)_ is pre-installed.
+       */
+      static get locales() {
+        return locales;
+      }
 
-        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.
+      /**
+       * @type {Boolean} - Whether the picker element is shown. `true` whne shown
+       */
+      get active() {
+        return !!(this.picker && this.picker.active);
+      }
 
-        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;
+      /**
+       * @type {HTMLDivElement} - DOM object of picker element
+       */
+      get pickerElement() {
+        return this.picker ? this.picker.element : undefined;
+      }
 
-            if (typeof effect === 'function') {
-              var cleanupFn = effect({
-                state: state,
-                name: name,
-                instance: instance,
-                options: options
-              });
+      /**
+       * 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);
 
-              var noopFn = function noopFn() {};
+        refreshUI(this, 3);
+      }
 
-              effectCleanupFns.push(cleanupFn || noopFn);
-            }
-          });
+      /**
+       * Show the picker element
+       */
+      show() {
+        if (this.inputField && this.inputField.disabled) {
+          return;
         }
+        this.picker.show();
+      }
 
-        function cleanupModifierEffects() {
-          effectCleanupFns.forEach(function (fn) {
-            return fn();
-          });
-          effectCleanupFns = [];
+      /**
+       * 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();
+      }
 
-        return instance;
-      };
-    }
-    var createPopper = /*#__PURE__*/popperGenerator(); // eslint-disable-next-line import/no-unused-modules
+      /**
+       * 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;
+      }
 
-    var defaultModifiers = [eventListeners, popperOffsets$1, computeStyles$1, applyStyles$1];
-    var createPopper$1 = /*#__PURE__*/popperGenerator({
-      defaultModifiers: defaultModifiers
-    }); // eslint-disable-next-line import/no-unused-modules
+      /**
+       * 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);
 
-    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
+        if (this.config.multidate) {
+          return this.dates.map(callback);
+        }
+        if (this.dates.length > 0) {
+          return callback(this.dates[0]);
+        }
+      }
 
-    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
-    });
+      /**
+       * 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
@@ -1991,3042 +2870,1938 @@
      * 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"
-    };
-    /**
-     * The dropdown implementation of Bootstrap does not support submenus. Therefore we need an own dropdown implementation.
-     */
-    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();
+    // 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 {
-                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();
-                event.stopPropagation();
-                this.openDropdown();
-                const interval = setInterval(() => {
-                    if (this.dropdownVisible()) {
-                        if (this.activeDropdownEntry) {
-                            this.activeDropdownEntry.focus();
-                        }
-                        else {
-                            this.dropdownEntries[0].focus();
-                        }
-                        clearInterval(interval);
-                    }
-                }, 0);
+                pattern = originalPattern;
             }
-            else if (this.dropdownVisible()
-                && (event.code === "ArrowUp" || event.code === "ArrowDown"
-                    || event.code === "ArrowLeft" || event.code === "ArrowRight"
-                    || event.code === "Tab")) {
-                event.preventDefault();
-                event.stopPropagation();
-                if (!this.activeDropdownEntry) {
-                    this.dropdownEntries[0].focus();
-                }
-                else if (event.code === "ArrowUp" && this.activeDropdownEntry.previous) {
-                    this.activeDropdownEntry.previous.focus();
-                }
-                else if (event.code === "ArrowDown" && this.activeDropdownEntry.next) {
-                    this.activeDropdownEntry.next.focus();
-                }
-                else if (event.code === "ArrowRight" && this.activeDropdownEntry.children.length > 0) {
-                    this.activeDropdownEntry.children[0].focus();
-                }
-                else if (event.code === "ArrowLeft" && this.activeDropdownEntry.parent) {
-                    this.activeDropdownEntry.parent.focus();
+            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 (!event.shiftKey && event.code === "Tab") {
-                    if (this.activeDropdownEntry.children.length > 0) {
-                        this.activeDropdownEntry.children[0].focus();
-                    }
-                    else if (this.activeDropdownEntry.next) {
-                        this.activeDropdownEntry.next.focus();
-                    }
-                    else {
-                        let parent = this.activeDropdownEntry.parent;
-                        while (parent) {
-                            if (parent.next) {
-                                this.activeDropdownEntry.clear();
-                                parent.next.focus();
-                                break;
-                            }
-                            else {
-                                parent = parent.parent;
-                            }
-                        }
+                else if (currentChar == "'" && pattern.charAt(i + 1) == "'") {
+                    if (escMode) {
+                        nextSegment += "\\";
                     }
+                    nextSegment += "'";
+                    i++;
                 }
-                else if (event.shiftKey && event.code === "Tab") {
-                    if (this.activeDropdownEntry.previous) {
-                        this.activeDropdownEntry.previous.focus();
-                    }
-                    else if (this.activeDropdownEntry.parent) {
-                        this.activeDropdownEntry.parent.focus();
-                    }
+                else if (currentChar == "'" && escMode == true) {
+                    escMode = false;
+                    analyzedPattern += nextSegment;
+                    nextSegment = "";
                 }
-            }
-            else if (this.dropdownVisible() && event.code === "Escape") {
-                event.preventDefault();
-                event.stopPropagation();
-                this.closeDropdown();
-            }
-        }
-        openDropdown() {
-            this.dispatchEvent(new CustomEvent(Event$1.SHOW));
-            if (!this.inStickyHeader()) {
-                this.menuStore.appendChild(this.dropdownMenu);
-                createPopper$2(this.toggleButton, this.dropdownMenu, {
-                    placement: "bottom-start"
-                });
-            }
-            for (const dropdownEntry of this.dropdownEntries) {
-                dropdownEntry.clear();
-            }
-            this.dropdownMenu.classList.add("show");
-            this.dispatchEvent(new CustomEvent(Event$1.SHOWN));
-        }
-        closeDropdown() {
-            this.dispatchEvent(new CustomEvent(Event$1.HIDE));
-            this.dropdownMenu.classList.remove("show");
-            this.appendChild(this.dropdownMenu);
-            this.dispatchEvent(new CustomEvent(Event$1.HIDDEN));
-        }
-        get toggleButton() {
-            return this.querySelector(":scope > button[data-toggle='dropdown']");
-        }
-        toggleButtonSelected(event) {
-            return this.toggleButton.contains(event.target);
-        }
-        inStickyHeader() {
-            return Boolean(this.closest("tobago-header.sticky-top"));
-        }
-        get dropdownMenu() {
-            const root = this.getRootNode();
-            return root.querySelector(".dropdown-menu[name='" + this.id + "']");
-        }
-        dropdownVisible() {
-            return this.dropdownMenu.classList.contains("show");
-        }
-        get menuStore() {
-            const root = this.getRootNode();
-            return root.querySelector(".tobago-page-menuStore");
-        }
-        get activeDropdownEntry() {
-            for (const dropdownEntry of this.dropdownEntries) {
-                if (dropdownEntry.active) {
-                    return dropdownEntry;
+                else {
+                    if (escMode) {
+                        nextSegment += "\\";
+                    }
+                    nextSegment += currentChar;
                 }
             }
-            return null;
-        }
-        createDropdownEntries(dropdownMenu, parent) {
-            let lastDropdownEntry = null;
-            for (const dropdownItem of dropdownMenu.children) {
-                if (dropdownItem.classList.contains("dropdown-item")) {
-                    const entry = this.createDropdownEntry(dropdownItem, parent, lastDropdownEntry);
-                    lastDropdownEntry = entry;
-                    this.dropdownEntries.push(entry);
-                    if (dropdownItem.classList.contains("tobago-dropdown-submenu")) {
-                        this.createDropdownEntries(dropdownItem.querySelector(".dropdown-menu"), entry);
-                    }
+            if (nextSegment != "") {
+                if (escMode) {
+                    analyzedPattern += nextSegment;
                 }
                 else {
-                    const dropdownItems = dropdownItem.querySelectorAll(".dropdown-item");
-                    for (const dropdownItem of dropdownItems) {
-                        const entry = this.createDropdownEntry(dropdownItem, parent, lastDropdownEntry);
-                        lastDropdownEntry = entry;
-                        this.dropdownEntries.push(entry);
-                    }
+                    analyzedPattern += this.convertPatternPart(nextSegment);
                 }
             }
+            return analyzedPattern;
         }
-        createDropdownEntry(dropdownItem, parent, previous) {
-            const entry = new DropdownEntry(dropdownItem);
-            if (parent) {
-                entry.parent = parent;
-                parent.children.push(entry);
-            }
-            if (previous) {
-                previous.next = entry;
-                entry.previous = previous;
-            }
-            return entry;
-        }
-    }
-    class DropdownEntry {
-        constructor(dropdownItem) {
-            this._children = [];
-            this._baseElement = dropdownItem;
-            if (dropdownItem.classList.contains("tobago-dropdown-submenu")) {
-                this.focusElement = dropdownItem.querySelector(".tobago-link");
+        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 = "";
             }
-            else if (dropdownItem.tagName === "LABEL") {
-                const root = dropdownItem.getRootNode();
-                this.focusElement = root.getElementById(dropdownItem.getAttribute("for"));
+            if (pattern.search("y") > -1) {
+                pattern = pattern.replace(/y/g, "y");
             }
-            else {
-                this.focusElement = dropdownItem;
+            if (pattern.search("M") > -1) {
+                pattern = pattern.replace(/M/g, "m");
             }
-            this._baseElement.addEventListener("mouseenter", this.activate.bind(this));
-            this._baseElement.addEventListener("mouseleave", this.deactivate.bind(this));
-        }
-        activate(event) {
-            this.active = true;
-        }
-        deactivate(event) {
-            this.active = false;
-        }
-        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;
+            if (pattern.search("d") > -1) {
+                pattern = pattern.replace(/dd+/g, "dd");
+                pattern = pattern.replace(/\bd\b/g, "d");
+            }
+            return pattern;
         }
-        get active() {
-            return this._active;
+    }
+
+    /*
+     * 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);
         }
-        set active(value) {
-            this._active = value;
+        static get(key) {
+            const value = this.map.get(key);
+            if (value) {
+                return value;
+            }
+            else {
+                console.warn("Config.get(" + key + ") = undefined");
+                return 0;
+            }
         }
-        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");
+    }
+    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" : null);
+            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");
             }
-            for (const child of this.children) {
-                child.clear();
+            else {
+                image.classList.add("fa", "fa-refresh", "fa-3x", "fa-spin");
+                image.style.opacity = "0.4";
             }
-            this._baseElement.classList.remove("tobago-dropdown-open");
-            this._baseElement.classList.add("tobago-dropdown-selected");
-            this.active = true;
-            this.focusElement.focus();
+            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);
         }
-        clear() {
-            this._baseElement.classList.remove("tobago-dropdown-open");
-            this._baseElement.classList.remove("tobago-dropdown-selected");
-            this.active = false;
+        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 + "'");
+            }
         }
     }
-    document.addEventListener("tobago.init", function (event) {
-        if (window.customElements.get("tobago-dropdown") == null) {
-            window.customElements.define("tobago-dropdown", Dropdown);
-        }
-    });
+    Overlay.overlayMap = new Map();
+    Config.set("Tobago.waitOverlayDelay", 1000);
+    Config.set("Ajax.waitOverlayDelay", 1000);
 
-    function hasProperty(obj, prop) {
-      return Object.prototype.hasOwnProperty.call(obj, prop);
-    }
+    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
 
-    function lastItemOf(arr) {
-      return arr[arr.length - 1];
-    }
+    var beforeRead = 'beforeRead';
+    var read = 'read';
+    var afterRead = 'afterRead'; // pure-logic modifiers
 
-    // 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;
-    }
+    var beforeMain = 'beforeMain';
+    var main = 'main';
+    var afterMain = 'afterMain'; // modifier with the purpose to write to the DOM (or write into a framework state)
 
-    function stringToArray(str, separator) {
-      // convert empty string to an empty array
-      return str ? str.split(separator) : [];
-    }
+    var beforeWrite = 'beforeWrite';
+    var write = 'write';
+    var afterWrite = 'afterWrite';
+    var modifierPhases = [beforeRead, read, afterRead, beforeMain, main, afterMain, beforeWrite, write, afterWrite];
 
-    function isInRange(testVal, min, max) {
-      const minOK = min === undefined || testVal >= min;
-      const maxOK = max === undefined || testVal <= max;
-      return minOK && maxOK;
+    function getNodeName(element) {
+      return element ? (element.nodeName || '').toLowerCase() : null;
     }
 
-    function limitToRange(val, min, max) {
-      if (val < min) {
-        return min;
-      }
-      if (val > max) {
-        return max;
+    /*:: import type { Window } from '../types'; */
+
+    /*:: declare function getWindow(node: Node | Window): Window; */
+    function getWindow(node) {
+      if (node.toString() !== '[object Window]') {
+        var ownerDocument = node.ownerDocument;
+        return ownerDocument ? ownerDocument.defaultView || window : window;
       }
-      return val;
+
+      return node;
     }
 
-    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}>`;
+    /*:: declare function isElement(node: mixed): boolean %checks(node instanceof
+      Element); */
 
-      const next = index + 1;
-      return next < repeat
-        ? createTagRepeat(tagName, repeat, attributes, next, html)
-        : html;
+    function isElement(node) {
+      var OwnElement = getWindow(node).Element;
+      return node instanceof OwnElement || node instanceof Element;
     }
+    /*:: declare function isHTMLElement(node: mixed): boolean %checks(node instanceof
+      HTMLElement); */
 
-    // 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);
+    function isHTMLElement(node) {
+      var OwnElement = getWindow(node).HTMLElement;
+      return node instanceof OwnElement || node instanceof HTMLElement;
     }
+    /*:: declare function isShadowRoot(node: mixed): boolean %checks(node instanceof
+      ShadowRoot); */
 
-    // 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 isShadowRoot(node) {
+      var OwnElement = getWindow(node).ShadowRoot;
+      return node instanceof OwnElement || node instanceof ShadowRoot;
     }
 
-    function addDays(date, amount) {
-      const newDate = new Date(date);
-      return newDate.setDate(newDate.getDate() + amount);
-    }
+    // and applies them to the HTMLElements such as popper and arrow
 
-    function addWeeks(date, amount) {
-      return addDays(date, amount * 7);
-    }
+    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 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;
-      }
+        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]
 
-      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;
-    }
+        Object.assign(element.style, style);
+        Object.keys(attributes).forEach(function (name) {
+          var value = attributes[name];
 
-    // Calculate the distance bettwen 2 days of the week
-    function dayDiff(day, from) {
-      return (day - from + 7) % 7;
+          if (value === false) {
+            element.removeAttribute(name);
+          } else {
+            element.setAttribute(name, value === true ? '' : value);
+          }
+        });
+      });
     }
 
-    // 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));
-    }
+    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);
 
-    // 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;
-    }
+      if (state.elements.arrow) {
+        Object.assign(state.elements.arrow.style, initialStyles.arrow);
+      }
 
-    // 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;
-    }
+      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
 
-    // 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(date, month, locale) {
-        const newDate = new Date(date);
-        let monthIndex = parseInt(month, 10) - 1;
+          var style = styleProperties.reduce(function (style, property) {
+            style[property] = '';
+            return style;
+          }, {}); // arrow is optional + virtual elements
 
-        if (isNaN(monthIndex)) {
-          if (!month) {
-            return NaN;
+          if (!isHTMLElement(element) || !getNodeName(element)) {
+            return;
           }
 
-          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);
-          }
-          if (monthIndex < 0) {
-            return NaN;
-          }
-        }
+          Object.assign(element.style, style);
+          Object.keys(attributes).forEach(function (attribute) {
+            element.removeAttribute(attribute);
+          });
+        });
+      };
+    } // eslint-disable-next-line import/no-unused-modules
 
-        newDate.setMonth(monthIndex);
-        return newDate.getMonth() !== normalizeMonth(monthIndex)
-          ? newDate.setDate(0)
-          : newDate.getTime();
-      },
-      d(date, day) {
-        return new Date(date).setDate(parseInt(day, 10));
-      },
-    };
-    // 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);
-      },
+
+    var applyStyles$1 = {
+      name: 'applyStyles',
+      enabled: true,
+      phase: 'write',
+      fn: applyStyles,
+      effect: effect,
+      requires: ['computeStyles']
     };
 
-    // get month index in normal range (0 - 11) from any number
-    function normalizeMonth(monthIndex) {
-      return monthIndex > -1 ? monthIndex % 12 : normalizeMonth(monthIndex + 12);
+    function getBasePlacement(placement) {
+      return placement.split('-')[0];
     }
 
-    function padZero(num, length) {
-      return num.toString().padStart(length, '0');
+    // Returns the layout rect of an element relative to its offsetParent. Layout
+    // means it doesn't take into account transforms.
+    function getLayoutRect(element) {
+      return {
+        x: element.offsetLeft,
+        y: element.offsetTop,
+        width: element.offsetWidth,
+        height: element.offsetHeight
+      };
     }
 
-    function parseFormatString(format) {
-      if (typeof format !== 'string') {
-        throw new Error("Invalid date format.");
-      }
-      if (format in knownFormats) {
-        return knownFormats[format];
-      }
+    function contains(parent, child) {
+      var rootNode = child.getRootNode && child.getRootNode(); // First, attempt with faster native method
 
-      // 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.");
-      }
+      if (parent.contains(child)) {
+        return true;
+      } // then fallback to custom implementation with Shadow DOM support
+      else if (rootNode && isShadowRoot(rootNode)) {
+          var next = child;
 
-      // collect format functions used in the format
-      const partFormatters = parts.map(token => formatFns[token]);
+          do {
+            if (next && parent.isSameNode(next)) {
+              return true;
+            } // $FlowFixMe[prop-missing]: need a better way to handle this...
 
-      // collect parse function keys used in the format
-      // iterate over parseFns' keys in order to keep the order of the keys.
-      const partParserKeys = Object.keys(parseFns).reduce((keys, key) => {
-        const token = parts.find(part => part[0] !== 'D' && part[0].toLowerCase() === key);
-        if (token) {
-          keys.push(key);
-        }
-        return keys;
-      }, []);
 
-      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 (token === 'M') {
-                dtParts.m = part;
-              } else if (token !== 'D') {
-                dtParts[token] = part;
-              }
-            }
-            return dtParts;
-          }, {});
+            next = next.parentNode || next.host;
+          } while (next);
+        } // Give up, the result is false
 
-          // iterate over partParserkeys 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 = parseFns[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);
-        },
-      };
+
+      return false;
     }
 
-    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();
-      }
+    function getComputedStyle$1(element) {
+      return getWindow(element).getComputedStyle(element);
+    }
 
-      if (format && format.toValue) {
-        const date = format.toValue(dateStr, format, locale);
-        return isNaN(date) ? undefined : stripTime(date);
-      }
+    function isTableElement(element) {
+      return ['table', 'td', 'th'].indexOf(getNodeName(element)) >= 0;
+    }
 
-      return parseFormatString(format).parser(dateStr, locale);
+    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 formatDate(date, format, locale) {
-      if (isNaN(date) || (!date && date !== 0)) {
-        return '';
+    function getParentNode(element) {
+      if (getNodeName(element) === 'html') {
+        return element;
       }
 
-      const dateObj = typeof date === 'number' ? new Date(date) : date;
+      return (// this is a quicker (but less type safe) way to save quite some bytes from the bundle
+        // $FlowFixMe[incompatible-return]
+        // $FlowFixMe[prop-missing]
+        element.assignedSlot || // step into the shadow DOM of the parent of a slotted node
+        element.parentNode || // DOM Element detected
+        // $FlowFixMe[incompatible-return]: need a better way to handle this...
+        element.host || // ShadowRoot detected
+        // $FlowFixMe[incompatible-call]: HTMLElement is a Node
+        getDocumentElement(element) // fallback
 
-      if (format.toDisplay) {
-        return format.toDisplay(dateObj, format, locale);
+      );
+    }
+
+    function getTrueOffsetParent(element) {
+      if (!isHTMLElement(element) || // https://github.com/popperjs/popper-core/issues/837
+      getComputedStyle$1(element).position === 'fixed') {
+        return null;
       }
 
-      return parseFormatString(format).formatter(dateObj, locale);
-    }
+      var offsetParent = element.offsetParent;
 
-    const listenerRegistry = new WeakMap();
-    const {addEventListener, removeEventListener} = EventTarget.prototype;
+      if (offsetParent) {
+        var html = getDocumentElement(offsetParent);
 
-    // 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);
+        if (getNodeName(offsetParent) === 'body' && getComputedStyle$1(offsetParent).position === 'static' && getComputedStyle$1(html).position !== 'static') {
+          return html;
+        }
       }
-      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);
-    }
+      return offsetParent;
+    } // `.offsetParent` reports `null` for fixed elements, while absolute elements
+    // return the containing block
 
-    // 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;
-      };
+    function getContainingBlock(element) {
+      var currentNode = getParentNode(element);
 
-      Event.prototype.composedPath = function () {
-        return getComposedPath(this.target);
-      };
-    }
+      while (isHTMLElement(currentNode) && ['html', 'body'].indexOf(getNodeName(currentNode)) < 0) {
+        var css = getComputedStyle$1(currentNode); // This is non-exhaustive but covers the most common CSS properties that
+        // create a containing block.
 
-    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;
+        if (css.transform !== 'none' || css.perspective !== 'none' || css.willChange && css.willChange !== 'auto') {
+          return currentNode;
+        } else {
+          currentNode = currentNode.parentNode;
+        }
       }
-      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);
-    }
+      return null;
+    } // Gets the closest ancestor positioned element. Handles some edge cases,
+    // such as table ancestors and cross browser bugs.
 
-    // 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"
+
+    function getOffsetParent(element) {
+      var window = getWindow(element);
+      var offsetParent = getTrueOffsetParent(element);
+
+      while (offsetParent && isTableElement(offsetParent) && getComputedStyle$1(offsetParent).position === 'static') {
+        offsetParent = getTrueOffsetParent(offsetParent);
       }
-    };
 
-    // 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 (offsetParent && getNodeName(offsetParent) === 'body' && getComputedStyle$1(offsetParent).position === 'static') {
+        return window;
+      }
 
-    const range = document.createRange();
+      return offsetParent || getContainingBlock(element) || window;
+    }
 
-    function parseHTML(html) {
-      return range.createContextualFragment(html);
+    function getMainAxisFromPlacement(placement) {
+      return ['top', 'bottom'].indexOf(placement) >= 0 ? 'x' : 'y';
     }
 
-    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 within(min, value, max) {
+      return Math.max(min, Math.min(value, max));
     }
 
-    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 getFreshSideObject() {
+      return {
+        top: 0,
+        right: 0,
+        bottom: 0,
+        left: 0
+      };
     }
 
-    function emptyChildNodes(el) {
-      if (el.firstChild) {
-        el.removeChild(el.firstChild);
-        emptyChildNodes(el);
-      }
+    function mergePaddingObject(paddingObject) {
+      return Object.assign(Object.assign({}, getFreshSideObject()), paddingObject);
     }
 
-    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);
-        });
-      }
+    function expandToHashMap(value, keys) {
+      return keys.reduce(function (hashMap, key) {
+        hashMap[key] = value;
+        return hashMap;
+      }, {});
     }
 
-    const {
-      language: defaultLang,
-      format: defaultFormat,
-      weekStart: defaultWeekStart,
-    } = defaultOptions;
+    function arrow(_ref) {
+      var _state$modifiersData$;
 
-    // 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;
-    }
+      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 calcEndOfWeek(startOfWeek) {
-      return (startOfWeek + 6) % 7;
-    }
+      if (!arrowElement || !popperOffsets) {
+        return;
+      }
 
-    // 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;
-    }
+      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
 
-    // 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 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$);
     }
 
-    // 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 || {};
+    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;
 
-      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;
+      if (arrowElement == null) {
+        return;
+      } // CSS selector
 
-          // 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;
-      }
+      if (typeof arrowElement === 'string') {
+        arrowElement = state.elements.popper.querySelector(arrowElement);
 
-      //*** 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 (!arrowElement) {
+          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;
-        }
-        delete inOpts.defaultViewDate;
-      }
+      if (!contains(state.elements.popper, arrowElement)) {
 
-      //*** 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;
+        return;
       }
 
-      //*** 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;
-      }
+      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
 
-      //*** 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;
-      }
+    var arrow$1 = {
+      name: 'arrow',
+      enabled: true,
+      phase: 'main',
+      fn: arrow,
+      effect: effect$1,
+      requires: ['popperOffsets'],
+      requiresIfExists: ['preventOverflow']
+    };
 
-      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 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.
 
-      //*** template ***//
-      if (inOpts.prevArrow) {
-        const prevArrow = parseHTML(inOpts.prevArrow);
-        if (prevArrow.childNodes.length > 0) {
-          config.prevArrow = prevArrow.childNodes;
+    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;
+
+      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 _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;
+
+      var hasX = offsets.hasOwnProperty('x');
+      var hasY = offsets.hasOwnProperty('y');
+      var sideX = left;
+      var sideY = top;
+      var win = window;
+
+      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
+
+        /*:: offsetParent = (offsetParent: Element); */
+
+
+        if (placement === top) {
+          sideY = bottom;
+          y -= offsetParent.clientHeight - popperRect.height;
+          y *= gpuAcceleration ? 1 : -1;
         }
-        delete inOpts.prevArrow;
-      }
-      if (inOpts.nextArrow) {
-        const nextArrow = parseHTML(inOpts.nextArrow);
-        if (nextArrow.childNodes.length > 0) {
-          config.nextArrow = nextArrow.childNodes;
+
+        if (placement === left) {
+          sideX = right;
+          x -= offsetParent.clientWidth - popperRect.width;
+          x *= gpuAcceleration ? 1 : -1;
         }
-        delete inOpts.nextArrow;
       }
 
-      //*** misc ***//
-      if (inOpts.disableTouchKeyboard !== undefined) {
-        config.disableTouchKeyboard = 'ontouchstart' in document && !!inOpts.disableTouchKeyboard;
-        delete inOpts.disableTouchKeyboard;
+      var commonStyles = Object.assign({
+        position: position
+      }, adaptive && unsetSides);
+
+      if (gpuAcceleration) {
+        var _Object$assign;
+
+        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));
       }
-      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;
+
+      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 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 commonStyles = {
+        placement: getBasePlacement(state.placement),
+        popper: state.elements.popper,
+        popperRect: state.rects.popper,
+        gpuAcceleration: gpuAcceleration
+      };
+
+      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 (inOpts.todayBtnMode !== undefined) {
-        switch(inOpts.todayBtnMode) {
-          case 0:
-          case 1:
-            config.todayBtnMode = inOpts.todayBtnMode;
-        }
-        delete inOpts.todayBtnMode;
+
+      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
+        })));
       }
 
-      //*** copy the rest ***//
-      Object.keys(inOpts).forEach((key) => {
-        if (inOpts[key] !== undefined && hasProperty(defaultOptions, key)) {
-          config[key] = inOpts[key];
-        }
+      state.attributes.popper = Object.assign(Object.assign({}, state.attributes.popper), {}, {
+        'data-popper-placement': state.placement
       });
+    } // eslint-disable-next-line import/no-unused-modules
 
-      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 type="button" class="%buttonClass% prev-btn"></button>
-        <button type="button" class="%buttonClass% view-switch"></button>
-        <button type="button" class="%buttonClass% next-btn"></button>
-      </div>
-    </div>
-    <div class="datepicker-main"></div>
-    <div class="datepicker-footer">
-      <div class="datepicker-controls">
-        <button type="button" class="%buttonClass% today-btn"></button>
-        <button type="button" class="%buttonClass% clear-btn"></button>
-      </div>
-    </div>
-  </div>
-</div>`);
+    var computeStyles$1 = {
+      name: 'computeStyles',
+      enabled: true,
+      phase: 'beforeWrite',
+      fn: computeStyles,
+      data: {}
+    };
 
-    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>`);
+    var passive = {
+      passive: true
+    };
 
-    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>`);
+    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);
 
-    // 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: [],
+      if (scroll) {
+        scrollParents.forEach(function (scrollParent) {
+          scrollParent.addEventListener('scroll', instance.update, passive);
         });
-        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();
+      if (resize) {
+        window.addEventListener('resize', instance.update, passive);
       }
 
-      // 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};
+      return function () {
+        if (scroll) {
+          scrollParents.forEach(function (scrollParent) {
+            scrollParent.removeEventListener('scroll', instance.update, passive);
+          });
         }
 
-        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);
-          }
+        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];
+      });
     }
 
-    class DaysView extends View {
-      constructor(picker) {
-        super(picker, {
-          id: 0,
-          name: 'days',
-          cellClass: 'day',
-        });
-      }
+    var hash$1 = {
+      start: 'end',
+      end: 'start'
+    };
+    function getOppositeVariationPlacement(placement) {
+      return placement.replace(/start|end/g, function (matched) {
+        return hash$1[matched];
+      });
+    }
 
-      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);
-      }
+    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
+      };
+    }
 
-      setOptions(options) {
-        let updateDOW;
+    function getWindowScroll(node) {
+      var win = getWindow(node);
+      var scrollLeft = win.pageXOffset;
+      var scrollTop = win.pageYOffset;
+      return {
+        scrollLeft: scrollLeft,
+        scrollTop: scrollTop
+      };
+    }
 
-        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;
-        }
+    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;
+    }
 
-        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);
-            }
-          }
-        }
+    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.
 
-        // 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';
-          });
+      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 (!/^((?!chrome|android).)*safari/i.test(navigator.userAgent)) {
+          x = visualViewport.offsetLeft;
+          y = visualViewport.offsetTop;
         }
       }
 
-      // 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);
+      return {
+        width: width,
+        height: height,
+        x: x + getWindowScrollBarX(element),
+        y: y
+      };
+    }
 
-        this.first = firstOfMonth;
-        this.last = dateValue(viewYear, viewMonth + 1, 0);
-        this.start = start;
-        this.focused = this.picker.viewDate;
-      }
+    // of the `<html>` and `<body>` rect bounds if horizontally scrollable
 
-      // 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;
-        }
+    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;
       }
 
-       // 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];
+      return {
+        width: width,
+        height: height,
+        x: x,
+        y: y
+      };
+    }
 
-        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();
+    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;
 
-          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');
-          }
+      return /auto|scroll|overlay|hidden/.test(overflow + overflowY + overflowX);
+    }
 
-          if (this.beforeShow) {
-            this.performBeforeHook(el, current, current);
-          }
-        });
+    function getScrollParent(node) {
+      if (['html', 'body', '#document'].indexOf(getNodeName(node)) >= 0) {
+        // $FlowFixMe[incompatible-return]: assume body is always available
+        return node.ownerDocument.body;
       }
 
-      // 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');
-          }
-        });
+      if (isHTMLElement(node) && isScrollParent(node)) {
+        return node;
       }
 
-      // 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');
-      }
+      return getScrollParent(getParentNode(node));
     }
 
-    function computeMonthRange(range, thisYear) {
-      if (!range || !range[0] || !range[1]) {
-        return;
-      }
+    /*
+    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.
+    */
 
-      const [[startY, startM], [endY, endM]] = range;
-      if (startY > thisYear || endY < thisYear) {
-        return;
+    function listScrollParents(element, list) {
+      if (list === void 0) {
+        list = [];
       }
-      return [
-        startY === thisYear ? startM : -1,
-        endY === thisYear ? endM : 12,
-      ];
+
+      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)));
     }
 
-    class MonthsView extends View {
-      constructor(picker) {
-        super(picker, {
-          id: 1,
-          name: 'months',
-          cellClass: 'month',
-        });
-      }
+    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
+      });
+    }
 
-      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);
-      }
+    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;
+    }
 
-      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;
-        }
-      }
+    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`
 
-      // 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()];
-          });
-        }
-      }
+    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;
 
-      // 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 (!isElement(clipperElement)) {
+        return [];
+      } // $FlowFixMe[incompatible-return]: https://github.com/facebook/flow/issues/1414
 
-        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);
+      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
 
-        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];
+    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 (
-            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');
-          }
+    function getVariation(placement) {
+      return placement.split('-')[1];
+    }
 
-          if (this.beforeShow) {
-            this.performBeforeHook(el, index, date);
-          }
-        });
-      }
+    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;
 
-      // 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');
-          }
-        });
-      }
+      switch (basePlacement) {
+        case top:
+          offsets = {
+            x: commonX,
+            y: reference.y - element.height
+          };
+          break;
 
-      // 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');
-      }
-    }
+        case bottom:
+          offsets = {
+            x: commonX,
+            y: reference.y + reference.height
+          };
+          break;
 
-    function toTitleCase(word) {
-      return [...word].reduce((str, ch, ix) => str += ix ? ch : ch.toUpperCase(), '');
-    }
+        case right:
+          offsets = {
+            x: reference.x + reference.width,
+            y: commonY
+          };
+          break;
 
-    // Class representing the years and decades view elements
-    class YearsView extends View {
-      constructor(picker, config) {
-        super(picker, config);
-      }
+        case left:
+          offsets = {
+            x: reference.x - element.width,
+            y: commonY
+          };
+          break;
 
-      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);
+        default:
+          offsets = {
+            x: reference.x,
+            y: reference.y
+          };
       }
 
-      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;
-        }
-      }
+      var mainAxis = basePlacement ? getMainAxisFromPlacement(basePlacement) : null;
 
-      // 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;
+      if (mainAxis != null) {
+        var len = mainAxis === 'y' ? 'height' : 'width';
 
-        this.first = first;
-        this.last = last;
-        this.start = first - this.step;
-        this.focused = startOfYearPeriod(viewDate, this.step);
-      }
+        switch (variation) {
+          case start:
+            offsets[mainAxis] = offsets[mainAxis] - (reference[len] / 2 - element[len] / 2);
+            break;
 
-      // 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);
-            }
-          });
+          case end:
+            offsets[mainAxis] = offsets[mainAxis] + (reference[len] / 2 - element[len] / 2);
+            break;
         }
       }
 
-      // 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);
+      return offsets;
+    }
 
-          el.className = `datepicker-cell ${this.cellClass}`;
-          if (this.isMinView) {
-            el.dataset.date = date;
-          }
-          el.textContent = el.dataset.year = current;
+    function detectOverflow(state, options) {
+      if (options === void 0) {
+        options = {};
+      }
 
-          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');
-          }
+      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 (this.beforeShow) {
-            this.performBeforeHook(el, current, date);
-          }
-        });
-      }
+      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
 
-      // 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');
-          }
+      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;
         });
       }
 
-      // 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');
-      }
+      return overflowOffsets;
     }
 
-    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}));
-    }
+    /*:: type OverflowsMap = { [ComputedPlacement]: number }; */
 
-    // 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);
+    /*;; type OverflowsMap = { [key in ComputedPlacement]: number }; */
+    function computeAutoPlacement(state, options) {
+      if (options === void 0) {
+        options = {};
       }
-      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();
-    }
+      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;
+      });
 
-    function unfocus(datepicker) {
-      if (datepicker.config.updateOnBlur) {
-        datepicker.update({autohide: true});
-      } else {
-        datepicker.refresh('input');
-        datepicker.hide();
-      }
-    }
+      if (allowedPlacements.length === 0) {
+        allowedPlacements = placements$1;
+      } // $FlowFixMe[incompatible-type]: Flow seems to have problems with two array unions...
 
-    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();
+      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 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);
+    function getExpandedFallbackPlacements(placement) {
+      if (getBasePlacement(placement) === auto) {
+        return [];
       }
-      picker.changeView(0).render();
-    }
 
-    function onClickClearBtn(datepicker) {
-      datepicker.setDate({clear: true});
-    }
-
-    function onClickViewSwitch(datepicker) {
-      switchView(datepicker);
-    }
-
-    function onClickPrevBtn(datepicker) {
-      goToPrevOrNext(datepicker, -1);
+      var oppositePlacement = getOppositePlacement(placement);
+      return [getOppositeVariationPlacement(placement), oppositePlacement, getOppositeVariationPlacement(oppositePlacement)];
     }
 
-    function onClickNextBtn(datepicker) {
-      goToPrevOrNext(datepicker, 1);
-    }
+    function flip(_ref) {
+      var state = _ref.state,
+          options = _ref.options,
+          name = _ref.name;
 
-    // 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')) {
+      if (state.modifiersData[name]._skip) {
         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));
-      }
-    }
+      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];
 
-    function onClickPicker(datepicker) {
-      if (!datepicker.inline && !datepicker.config.disableTouchKeyboard) {
-        datepicker.inputField.focus();
-      }
-    }
+      for (var i = 0; i < placements.length; i++) {
+        var placement = placements[i];
 
-    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));
+        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
         });
-      }
-      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);
+        var mainVariationSide = isVertical ? isStartVariation ? right : left : isStartVariation ? bottom : top;
+
+        if (referenceRect[len] > popperRect[len]) {
+          mainVariationSide = getOppositePlacement(mainVariationSide);
         }
-      }
-      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);
+
+        var altVariationSide = getOppositePlacement(mainVariationSide);
+        var checks = [];
+
+        if (checkMainAxis) {
+          checks.push(overflow[_basePlacement] <= 0);
         }
-      }
-    }
 
-    // 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);
-    }
+        if (checkAltAxis) {
+          checks.push(overflow[mainVariationSide] <= 0, overflow[altVariationSide] <= 0);
+        }
 
-    // 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();
+        if (checks.every(function (check) {
+          return check;
+        })) {
+          firstFittingPlacement = placement;
+          makeFallbackChecks = false;
+          break;
+        }
 
-      picker.viewDate = newDate;
-      if (viewYear !== oldViewDate.getFullYear()) {
-        triggerDatepickerEvent(picker.datepicker, 'changeYear');
-      }
-      if (newViewDate.getMonth() !== oldViewDate.getMonth()) {
-        triggerDatepickerEvent(picker.datepicker, 'changeMonth');
+        checksMap.set(placement, checks);
       }
 
-      // 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;
-      }
-    }
+      if (makeFallbackChecks) {
+        // `2` may be desired in some cases – research later
+        var numberOfChecks = flipVariations ? 3 : 1;
 
-    function getTextDirection(el) {
-      return window.getComputedStyle(el).direction;
-    }
+        var _loop = function _loop(_i) {
+          var fittingPlacement = placements.find(function (placement) {
+            var checks = checksMap.get(placement);
 
-    // Class representing the picker UI
-    class Picker {
-      constructor(datepicker) {
-        this.datepicker = datepicker;
+            if (checks) {
+              return checks.slice(0, _i).every(function (check) {
+                return check;
+              });
+            }
+          });
 
-        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,
+          if (fittingPlacement) {
+            firstFittingPlacement = fittingPlacement;
+            return "break";
+          }
         };
-        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);
-      }
+        for (var _i = numberOfChecks; _i > 0; _i--) {
+          var _ret = _loop(_i);
 
-      setOptions(options) {
-        processPickerOptions(this, options);
-        this.views.forEach((view) => {
-          view.init(options, false);
-        });
-        this.currentView.render();
+          if (_ret === "break") break;
+        }
       }
 
-      detach() {
-        this.datepicker.config.container.removeChild(this.element);
+      if (state.placement !== firstFittingPlacement) {
+        state.modifiersData[name]._skip = true;
+        state.placement = firstFittingPlacement;
+        state.reset = true;
       }
+    } // eslint-disable-next-line import/no-unused-modules
 
-      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');
+    var flip$1 = {
+      name: 'flip',
+      enabled: true,
+      phase: 'main',
+      fn: flip,
+      requiresIfExists: ['offset'],
+      data: {
+        _skip: false
       }
+    };
 
-      hide() {
-        if (!this.active) {
-          return;
-        }
-        this.datepicker.exitEditMode();
-        this.element.classList.remove('active');
-        this.active = false;
-        triggerDatepickerEvent(this.datepicker, 'hide');
+    function getSideOffsets(overflow, rect, preventedOffsets) {
+      if (preventedOffsets === void 0) {
+        preventedOffsets = {
+          x: 0,
+          y: 0
+        };
       }
 
-      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;
+      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 (container === document.body) {
-          scrollTop = window.scrollY;
-          left = inputLeft + window.scrollX;
-          top = inputTop + scrollTop;
-        } else {
-          scrollTop = container.scrollTop;
-          left = inputLeft - containerLeft;
-          top = inputTop - containerTop + scrollTop;
-        }
+    function isAnySideFullyClipped(overflow) {
+      return [top, right, bottom, left].some(function (side) {
+        return overflow[side] >= 0;
+      });
+    }
 
-        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;
-        }
+    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
 
-        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}`);
+    var hide$1 = {
+      name: 'hide',
+      enabled: true,
+      phase: 'main',
+      requiresIfExists: ['preventOverflow'],
+      fn: hide
+    };
 
-        style.top = top ? `${top}px` : top;
-        style.left = left ? `${left}px` : left;
-      }
+    function distanceAndSkiddingToXY(placement, rects, offset) {
+      var basePlacement = getBasePlacement(placement);
+      var invertDistance = [left, top].indexOf(basePlacement) >= 0 ? -1 : 1;
 
-      setViewSwitchLabel(labelText) {
-        this.controls.viewSwitch.textContent = labelText;
-      }
+      var _ref = typeof offset === 'function' ? offset(Object.assign(Object.assign({}, rects), {}, {
+        placement: placement
+      })) : offset,
+          skidding = _ref[0],
+          distance = _ref[1];
 
-      setPrevBtnDisabled(disabled) {
-        this.controls.prevBtn.disabled = disabled;
-      }
+      skidding = skidding || 0;
+      distance = (distance || 0) * invertDistance;
+      return [left, right].indexOf(basePlacement) >= 0 ? {
+        x: distance,
+        y: skidding
+      } : {
+        x: skidding,
+        y: distance
+      };
+    }
 
-      setNextBtnDisabled(disabled) {
-        this.controls.nextBtn.disabled = disabled;
-      }
+    function offset(_ref2) {
+      var state = _ref2.state,
+          options = _ref2.options,
+          name = _ref2.name;
+      var _options$offset = options.offset,
+          offset = _options$offset === void 0 ? [0, 0] : _options$offset;
+      var data = placements.reduce(function (acc, placement) {
+        acc[placement] = distanceAndSkiddingToXY(placement, state.rects, offset);
+        return acc;
+      }, {});
+      var _data$state$placement = data[state.placement],
+          x = _data$state$placement.x,
+          y = _data$state$placement.y;
 
-      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;
+      if (state.modifiersData.popperOffsets != null) {
+        state.modifiersData.popperOffsets.x += x;
+        state.modifiersData.popperOffsets.y += y;
       }
 
-      // Change the focused date (view date)
-      changeFocus(newViewDate) {
-        this._renderMethod = setViewDate(this, newViewDate) ? 'render' : 'refreshFocus';
-        this.views.forEach((view) => {
-          view.updateFocus();
-        });
-        return this;
-      }
+      state.modifiersData[name] = data;
+    } // eslint-disable-next-line import/no-unused-modules
 
-      // 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;
+    var offset$1 = {
+      name: 'offset',
+      enabled: true,
+      phase: 'main',
+      requires: ['popperOffsets'],
+      fn: offset
+    };
 
-        this.currentView[renderMethod]();
-      }
-    }
+    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
 
-    // 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;
+
+    var popperOffsets$1 = {
+      name: 'popperOffsets',
+      enabled: true,
+      phase: 'read',
+      fn: popperOffsets,
+      data: {}
+    };
+
+    function getAltAxis(axis) {
+      return axis === 'x' ? 'y' : 'x';
     }
 
-    // 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 preventOverflow(_ref) {
+      var state = _ref.state,
+          options = _ref.options,
+          name = _ref.name;
+      var _options$mainAxis = options.mainAxis,
+          checkMainAxis = _options$mainAxis === void 0 ? true : _options$mainAxis,
+          _options$altAxis = options.altAxis,
+          checkAltAxis = _options$altAxis === void 0 ? false : _options$altAxis,
+          boundary = options.boundary,
+          rootBoundary = options.rootBoundary,
+          altBoundary = options.altBoundary,
+          padding = options.padding,
+          _options$tether = options.tether,
+          tether = _options$tether === void 0 ? true : _options$tether,
+          _options$tetherOffset = options.tetherOffset,
+          tetherOffset = _options$tetherOffset === void 0 ? 0 : _options$tetherOffset;
+      var overflow = detectOverflow(state, {
+        boundary: boundary,
+        rootBoundary: rootBoundary,
+        padding: padding,
+        altBoundary: altBoundary
+      });
+      var basePlacement = getBasePlacement(state.placement);
+      var variation = getVariation(state.placement);
+      var isBasePlacement = !variation;
+      var mainAxis = getMainAxisFromPlacement(basePlacement);
+      var altAxis = getAltAxis(mainAxis);
+      var popperOffsets = state.modifiersData.popperOffsets;
+      var referenceRect = state.rects.reference;
+      var popperRect = state.rects.popper;
+      var tetherOffsetValue = typeof tetherOffset === 'function' ? tetherOffset(Object.assign(Object.assign({}, state.rects), {}, {
+        placement: state.placement
+      })) : tetherOffset;
+      var data = {
+        x: 0,
+        y: 0
+      };
 
-    function onKeydown(datepicker, ev) {
-      if (ev.key === 'Tab') {
-        unfocus(datepicker);
+      if (!popperOffsets) {
         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();
-    }
+      if (checkMainAxis) {
+        var mainSide = mainAxis === 'y' ? top : left;
+        var altSide = mainAxis === 'y' ? bottom : right;
+        var len = mainAxis === 'y' ? 'height' : 'width';
+        var offset = popperOffsets[mainAxis];
+        var min = popperOffsets[mainAxis] + overflow[mainSide];
+        var max = popperOffsets[mainAxis] - overflow[altSide];
+        var additive = tether ? -popperRect[len] / 2 : 0;
+        var minLen = variation === start ? referenceRect[len] : popperRect[len];
+        var maxLen = variation === start ? -popperRect[len] : -referenceRect[len]; // We need to include the arrow in the calculation so the arrow doesn't go
+        // outside the reference bounds
 
-    function onFocus(datepicker) {
-      if (datepicker.config.showOnFocus) {
-        datepicker.show();
-      }
-    }
+        var arrowElement = state.elements.arrow;
+        var arrowRect = tether && arrowElement ? getLayoutRect(arrowElement) : {
+          width: 0,
+          height: 0
+        };
+        var arrowPaddingObject = state.modifiersData['arrow#persistent'] ? state.modifiersData['arrow#persistent'].padding : getFreshSideObject();
+        var arrowPaddingMin = arrowPaddingObject[mainSide];
+        var arrowPaddingMax = arrowPaddingObject[altSide]; // If the reference length is smaller than the arrow length, we don't want
+        // to include its full size in the calculation. If the reference is small
+        // and near the edge of a boundary, the popper can overflow even if the
+        // reference is not overflowing as well (e.g. virtual elements with no
+        // width or height)
 
-    // 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);
+        var arrowLen = within(0, referenceRect[len], arrowRect[len]);
+        var minOffset = isBasePlacement ? referenceRect[len] / 2 - additive - arrowLen - arrowPaddingMin - tetherOffsetValue : minLen - arrowLen - arrowPaddingMin - tetherOffsetValue;
+        var maxOffset = isBasePlacement ? -referenceRect[len] / 2 + additive + arrowLen + arrowPaddingMax + tetherOffsetValue : maxLen + arrowLen + arrowPaddingMax + tetherOffsetValue;
+        var arrowOffsetParent = state.elements.arrow && getOffsetParent(state.elements.arrow);
+        var clientOffset = arrowOffsetParent ? mainAxis === 'y' ? arrowOffsetParent.clientTop || 0 : arrowOffsetParent.clientLeft || 0 : 0;
+        var offsetModifierValue = state.modifiersData.offset ? state.modifiersData.offset[state.placement][mainAxis] : 0;
+        var tetherMin = popperOffsets[mainAxis] + minOffset - offsetModifierValue - clientOffset;
+        var tetherMax = popperOffsets[mainAxis] + maxOffset - offsetModifierValue;
+        var preventedOffset = within(tether ? Math.min(min, tetherMin) : min, offset, tether ? Math.max(max, tetherMax) : max);
+        popperOffsets[mainAxis] = preventedOffset;
+        data[mainAxis] = preventedOffset - offset;
       }
-    }
 
-    function onClickInput(datepicker, ev) {
-      const el = ev.target;
-      if (!el._clicking) {
-        return;
-      }
-      clearTimeout(el._clicking);
-      delete el._clicking;
+      if (checkAltAxis) {
+        var _mainSide = mainAxis === 'x' ? top : left;
 
-      if (el._active) {
-        datepicker.enterEditMode();
-      }
-      delete el._active;
+        var _altSide = mainAxis === 'x' ? bottom : right;
 
-      if (datepicker.config.showOnClick) {
-        datepicker.show();
-      }
-    }
+        var _offset = popperOffsets[altAxis];
 
-    function onPaste(datepicker, ev) {
-      if (ev.clipboardData.types.includes('text/plain')) {
-        datepicker.enterEditMode();
-      }
-    }
+        var _min = _offset + overflow[_mainSide];
 
-    // 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);
-    }
+        var _max = _offset - overflow[_altSide];
 
-    function stringifyDates(dates, config) {
-      return dates
-        .map(dt => formatDate(dt, config.format, config.locale))
-        .join(config.dateDelimiter);
-    }
+        var _preventedOffset = within(_min, _offset, _max);
 
-    // 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;
+        popperOffsets[altAxis] = _preventedOffset;
+        data[altAxis] = _preventedOffset - _offset;
       }
 
-      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;
-    }
+      state.modifiersData[name] = data;
+    } // eslint-disable-next-line import/no-unused-modules
 
-    // 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;
-      }
+    var preventOverflow$1 = {
+      name: 'preventOverflow',
+      enabled: true,
+      phase: 'main',
+      fn: preventOverflow,
+      requiresIfExists: ['offset']
+    };
 
-      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');
+    function getHTMLElementScroll(element) {
+      return {
+        scrollLeft: element.scrollLeft,
+        scrollTop: element.scrollTop
+      };
+    }
+
+    function getNodeScroll(node) {
+      if (node === getWindow(node) || !isHTMLElement(node)) {
+        return getWindowScroll(node);
       } else {
-        refreshUI(datepicker, 1);
-      }
-      if (autohide) {
-        datepicker.hide();
+        return getHTMLElementScroll(node);
       }
     }
 
-    /**
-     * 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;
+    // Composite means it takes into account transforms as well as layout.
 
-        // 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));
+    function getCompositeRect(elementOrVirtualElement, offsetParent, isFixed) {
+      if (isFixed === void 0) {
+        isFixed = false;
+      }
 
-        // configure by type
-        const inline = this.inline = element.tagName !== 'INPUT';
-        let inputField;
-        let initialDates;
+      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 (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;
-            },
-          });
+      if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {
+        if (getNodeName(offsetParent) !== 'body' || // https://github.com/popperjs/popper-core/issues/1078
+        isScrollParent(documentElement)) {
+          scroll = getNodeScroll(offsetParent);
         }
 
-        // set initial value
-        this.dates = processInputDates(this, initialDates) || [];
-        if (inputField) {
-          inputField.value = stringifyDates(this.dates, config);
+        if (isHTMLElement(offsetParent)) {
+          offsets = getBoundingClientRect(offsetParent);
+          offsets.x += offsetParent.clientLeft;
+          offsets.y += offsetParent.clientTop;
+        } else if (documentElement) {
+          offsets.x = getWindowScrollBarX(documentElement);
         }
+      }
 
-        const picker = this.picker = new Picker(this);
+      return {
+        x: rect.left + scroll.scrollLeft - offsets.x,
+        y: rect.top + scroll.scrollTop - offsets.y,
+        width: rect.width,
+        height: rect.height
+      };
+    }
 
-        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);
-        }
-      }
+    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
 
-      /**
-       * 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);
+      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);
+
+            if (depModifier) {
+              sort(depModifier);
+            }
+          }
+        });
+        result.push(modifier);
       }
 
-      /**
-       * 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);
-      }
+      modifiers.forEach(function (modifier) {
+        if (!visited.has(modifier.name)) {
+          // check for visited object
+          sort(modifier);
+        }
+      });
+      return result;
+    }
 
-      /**
-       * @type {Object} - Installed locales in `[languageCode]: localeObject` format
-       * en`:_English (US)_ is pre-installed.
-       */
-      static get locales() {
-        return locales;
-      }
+    function orderModifiers(modifiers) {
+      // order based on dependencies
+      var orderedModifiers = order(modifiers); // order based on phase
 
-      /**
-       * @type {Boolean} - Whether the picker element is shown. `true` whne shown
-       */
-      get active() {
-        return !!(this.picker && this.picker.active);
-      }
+      return modifierPhases.reduce(function (acc, phase) {
+        return acc.concat(orderedModifiers.filter(function (modifier) {
+          return modifier.phase === phase;
+        }));
+      }, []);
+    }
 
-      /**
-       * @type {HTMLDivElement} - DOM object of picker element
-       */
-      get pickerElement() {
-        return this.picker ? this.picker.element : undefined;
-      }
+    function debounce(fn) {
+      var pending;
+      return function () {
+        if (!pending) {
+          pending = new Promise(function (resolve) {
+            Promise.resolve().then(function () {
+              pending = undefined;
+              resolve(fn());
+            });
+          });
+        }
 
-      /**
-       * 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);
+        return pending;
+      };
+    }
 
-        refreshUI(this, 3);
-      }
+    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
 
-      /**
-       * Show the picker element
-       */
-      show() {
-        if (this.inputField && this.inputField.disabled) {
-          return;
-        }
-        this.picker.show();
-      }
+      return Object.keys(merged).map(function (key) {
+        return merged[key];
+      });
+    }
 
-      /**
-       * 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();
-      }
+    var DEFAULT_OPTIONS = {
+      placement: 'bottom',
+      modifiers: [],
+      strategy: 'absolute'
+    };
 
-      /**
-       * 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;
+    function areValidElements() {
+      for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
+        args[_key] = arguments[_key];
       }
 
-      /**
-       * 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);
+      return !args.some(function (element) {
+        return !(element && typeof element.getBoundingClientRect === 'function');
+      });
+    }
 
-        if (this.config.multidate) {
-          return this.dates.map(callback);
-        }
-        if (this.dates.length > 0) {
-          return callback(this.dates[0]);
-        }
+    function popperGenerator(generatorOptions) {
+      if (generatorOptions === void 0) {
+        generatorOptions = {};
       }
 
-      /**
-       * 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());
+      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;
         }
 
-        const inputDates = Array.isArray(dates[0]) ? dates[0] : dates;
-        setDate(this, inputDates, opts);
-      }
+        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
 
-      /**
-       * 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;
-        }
+            var orderedModifiers = orderModifiers(mergeByName([].concat(defaultModifiers, state.options.modifiers))); // Strip out disabled modifiers
 
-        const opts = {clear: true, autohide: !!(options && options.autohide)};
-        const inputDates = stringToArray(this.inputField.value, this.config.dateDelimiter);
-        setDate(this, inputDates, opts);
-      }
+            state.orderedModifiers = orderedModifiers.filter(function (m) {
+              return m.enabled;
+            }); // Validate the provided modifiers so that the consumer will get warned
 
-      /**
-       * 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;
-        }
+            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;
+            }
 
-        let mode;
-        if (target === 'picker') {
-          mode = 2;
-        } else if (target === 'input') {
-          mode = 1;
-        } else {
-          mode = 3;
-        }
-        refreshUI(this, mode, !forceRender);
-      }
+            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
 
-      /**
-       * 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');
-      }
+            if (!areValidElements(reference, popper)) {
 
-      /**
-       * 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);
-        }
-      }
-    }
+              return;
+            } // Store the reference and popper rects to be read by modifiers
 
-    /*
-     * 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;
+            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);
+            });
+
+            for (var index = 0; index < state.orderedModifiers.length; index++) {
+
+              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)) {
+
+          return instance;
         }
-    }
-    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" : null);
-            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";
+        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);
             }
-            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 + "'");
-            }
+
+        function cleanupModifierEffects() {
+          effectCleanupFns.forEach(function (fn) {
+            return fn();
+          });
+          effectCleanupFns = [];
         }
+
+        return instance;
+      };
     }
-    Overlay.overlayMap = new Map();
-    Config.set("Tobago.waitOverlayDelay", 1000);
-    Config.set("Ajax.waitOverlayDelay", 1000);
+    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
+    });
 
     /*!
       * Bootstrap v5.0.0-beta1 (https://getbootstrap.com/)
@@ -8347,7 +8122,7 @@
       allowList: DefaultAllowlist,
       popperConfig: null
     };
-    var Event$1$1 = {
+    var Event$1 = {
       HIDE: "hide" + EVENT_KEY$6,
       HIDDEN: "hidden" + EVENT_KEY$6,
       SHOW: "show" + EVENT_KEY$6,
@@ -9018,7 +8793,7 @@
       }, {
         key: "Event",
         get: function get() {
-          return Event$1$1;
+          return Event$1;
         }
       }, {
         key: "EVENT_KEY",
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 669c95d..af569f9 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","tobago-dropdown.js","../../node_modules/vanillajs-datepicker/js/lib/utils.js","../../node_modules/vanillajs-datepicker/js/lib/date.js","../../node_modules/vanillajs-datepicker/js/lib/date-format.js","../../node_modules/vanillajs-datepicker/js/lib/event.js","../../node_modules/vanillajs-datepicker/js/i18n/base-locales.js","../../node_modules/vanillajs-datepicker/js/options/defaultOptions.js" [...]
\ No newline at end of file